64-bit specifics

deadwood · 1032

deadwood

  • AROS Developer
  • Legendary Member
  • *****
    • Posts: 1524
    • Karma: +118/-0
on: January 20, 2022, 02:45:59 AM
Moving from another thread

Here is another question.  How do I correctly implement a function that takes variable number of arguments on AROS?

Here is a sample program:
Code: [Select]
#include <stdio.h>
#include <stdarg.h>
#include <libraries/mui.h>
#include <proto/muimaster.h>
#include <proto/intuition.h>
#include <proto/exec.h>

#define VARARGS68K __stackparm

struct Library *MUIMasterBase = NULL;

static void VARARGS68K ask(Object *app, const char *fmt, ...)
{
    va_list va;

    va_start(va, fmt);
    MUI_Request(app, NULL, 0, "Requester", "*Ok", fmt,
            (APTR)va->overflow_arg_area);
    va_end(va);
}

int main(void)
{
    MUIMasterBase = OpenLibrary((STRPTR)MUIMASTER_NAME, 0);
    if (MUIMasterBase == NULL) {
        printf("No MUI\n");
        return 10;
    }

    Object *app = ApplicationObject, End;

    ask(app, "6 * 7 = %d", 42);

    MUI_DisposeObject(app);

    CloseLibrary(MUIMasterBase);

    return 0;
}

When running this on x86-64-v11 I get the funny result: "6 * 7 = 22160"  :(


Varargs on 64-bit ABIs are passed via combination of registers and stack. There specification is quite complex. The "overflow_area" probably works on m68k and i386 but won't work on 64-bit (also on linux). I'll dig into AROS sources if what you want to do is even possible as MUI_Request takes an array of IPTR as "params" parameter if I'm not mistaking.



deadwood

  • AROS Developer
  • Legendary Member
  • *****
    • Posts: 1524
    • Karma: +118/-0
Reply #1 on: January 20, 2022, 01:17:52 PM
Here is something that might help you. Essentially what your code does is trying to forward varargs (...) into a varargs function (...). This is generally not supported in standard, but works on some architectures which use stack for passing arguments. I dug into AROS sources and have two solutions which should work on any architecture. Both involve variadic argument macros, which might not be available on old compilers.

Code: [Select]
#include <proto/exec.h>
#include <libraries/mui.h>
#include <proto/muimaster.h>

#include <stdio.h>

struct Library *MUIMasterBase = NULL;

#define SOLUTION2

#ifdef ORIGINAL
#define VARARGS68K

static void VARARGS68K ask(Object *app, const char *fmt, ...)
{
    va_list va;

    va_start(va, fmt);
    MUI_Request(app, NULL, 0, "Requester", "*Ok", fmt,
            (APTR)va->overflow_arg_area);
    va_end(va);
}
#endif

#ifdef SOLUTION1
#define ask(app, fmt, ...) \
({\
    MUI_Request(app, NULL, 0, "S1", "*Ok", fmt, __VA_ARGS__); \
})
#endif

#ifdef SOLUTION2
#define ask(app, fmt, ...) \
({ \
    IPTR __args[] = { AROS_PP_VARIADIC_CAST2IPTR(__VA_ARGS__) }; \
    MUI_RequestA((app), NULL, 0, "S2", "*Ok", fmt, __args); \
})
#endif

int main(void)
{
    MUIMasterBase = OpenLibrary((STRPTR)MUIMASTER_NAME, 0);
    if (MUIMasterBase == NULL) {
        printf("No MUI\n");
        return 10;
    }

    Object *app = ApplicationObject, End;

    ask(app, "6 * 7 = %d", 42);

    MUI_DisposeObject(app);

    CloseLibrary(MUIMasterBase);

    return 0;
}



muibase

  • Newbie
  • *
    • Posts: 26
    • Karma: +65/-0
Reply #2 on: January 21, 2022, 12:02:44 AM
Thanks, I like the 2nd solution as it allows to keep the macro smaller.

BTW, I also tried these AROS_SLOWSTACKFORMAT macros (they are used in various places in the AROS source tree), but it does not seem to work.  Here is an example (I get "6 * 7 = 21824'):

Code: [Select]
static void ask(Object *app, const char *fmt, ...)
{
    AROS_SLOWSTACKFORMAT_PRE(fmt);

    MUI_Request(app, NULL, 0, "Requester", "*Ok", fmt,
            AROS_SLOWSTACKFORMAT_ARG(fmt));
    AROS_SLOWSTACKFORMAT_POST(fmt);
}



deadwood

  • AROS Developer
  • Legendary Member
  • *****
    • Posts: 1524
    • Karma: +118/-0
Reply #3 on: January 21, 2022, 02:52:33 AM
As far I as I know AROS_SLOWSTACKFORMAT "repackage" C-like varargs (...) into Amiga-like varargs (called RAWARG under AROS - simply a stream of values with different sizes allocated on stack). In your case, you are "repacking" C-like varargs into C-like varargs (that's what MUI_Request accepts as last parameter) do that's why AROS_SLOWSTACKFORMAT won't work.



muibase

  • Newbie
  • *
    • Posts: 26
    • Karma: +65/-0
Reply #4 on: January 21, 2022, 10:58:01 AM
I am not really understanding this.  Maybe, let's look at a case where this is used.  C/Mount uses it here: https://github.com/deadw00d/AROS/blob/e75800b801d18415f3a316dc6cb9cd694702b073/workbench/c/Mount.c#L1853

If this code is correct then I don't see why it also wouldn't work for MUI_Request.



deadwood

  • AROS Developer
  • Legendary Member
  • *****
    • Posts: 1524
    • Karma: +118/-0
Reply #5 on: January 21, 2022, 01:34:32 PM
What I mean is that if you look at VPrintf and EasyRequestargs they both take RAWARG as last parameter, while MUI_Request takes "...".



muibase

  • Newbie
  • *
    • Posts: 26
    • Karma: +65/-0
Reply #6 on: January 21, 2022, 03:19:50 PM
Ah, my bad, I meant to use MUI_RequestA.

The following also works correctly now (but the one using va->overflow_arg_area doesn't, which is okay):

Code: [Select]
static void ask(Object *app, const char *fmt, ...)
{
    AROS_SLOWSTACKFORMAT_PRE(fmt);

    MUI_RequestA(app, NULL, 0, "Requester", "*Ok", fmt,
            AROS_SLOWSTACKFORMAT_ARG(fmt));
    AROS_SLOWSTACKFORMAT_POST(fmt);
}

Of course the macro version is preferable since everything is inlined and there is no memory allocation that can fail (other then running out of stack space that is).



deadwood

  • AROS Developer
  • Legendary Member
  • *****
    • Posts: 1524
    • Karma: +118/-0
Reply #7 on: January 21, 2022, 11:29:36 PM
Good we had this sorted out :) Any more 64-bit issues in MUIBase?
« Last Edit: January 22, 2022, 12:31:28 AM by deadwood »



muibase

  • Newbie
  • *
    • Posts: 26
    • Karma: +65/-0
Reply #8 on: January 22, 2022, 01:01:06 AM
Yup, you can find MUIbase 4.4.1 which includes a x86_64-v11-aros version here: https://muibase.sourceforge.io/files/amiga/



deadwood

  • AROS Developer
  • Legendary Member
  • *****
    • Posts: 1524
    • Karma: +118/-0
Reply #9 on: January 22, 2022, 01:48:55 AM
Nice thx! If the code is already 64-bit compliant we can try building also AxRuntime version (for native Linux version of MUIBase) once I fix AxRuntime. Seems it is broken under newer linuxes (right-click menu crashes application).



Amiwell

  • Legendary Member
  • *****
    • Posts: 2616
    • Karma: +35/-4
  • Peace
Reply #10 on: January 22, 2022, 05:35:23 AM
Yup, you can find MUIbase 4.4.1 which includes a x86_64-v11-aros version here: https://muibase.sourceforge.io/files/amiga/

thank you Steffen :)