#296 reverse order of arguments

open
None
5
2011-06-08
2010-09-23
No

There should be a way to reverse the order in which function arguments are stored to the stack.

e.g. something like

__reversed_args f(int a, int b);

This would be useful for interfacing to existing routines e.g. written in asm or residing in some BIOS.

Philipp

Discussion

  • This has been implemented partially. However so far it works for function declarations only, not definition and doesn't work with function pointers yet:

    void f(int, int) __optlink;
    void h(int, int);
    void (*p)(int, int) __optlink;
    void (*q)(int, int);

    void g(void)
    {
    f(1, 2); // OK - parameters passed in reverse order
    h(1, 2); // OK - parameters passed in normal order
    (*p)(1, 2); // Broken
    (*q)(1, 2); // OK
    }

    Philipp

     
    • assigned_to: nobody --> spth
     
  • __optlink now works for function pointers, too.

     
  • Maarten Brock
    Maarten Brock
    2011-06-08

    How does this work with varargs?

     
  • It works the same for varargs as for any other functions:

    void g1(int i, ...);
    void g2(int i, ...) __optlink;

    void f(void)
    {
    g1(1, 2, 3);
    g2(1, 2, 3);
    }

    results in

    ld hl,#0x0003
    push hl
    ld l, #0x02
    push hl
    ld l, #0x01
    push hl
    call _g1
    pop af
    pop af
    pop af
    ld hl,#0x0001
    push hl
    ld l, #0x02
    push hl
    ld l, #0x03
    push hl
    call _g2
    pop af
    pop af
    pop af

    Philipp

     
  • Maarten Brock
    Maarten Brock
    2011-06-08

    Ehm, I meant at the receiving end. How does the callee know how far back on the stack the first argument is placed?

     
  • The short answear: It works the same for varargs as for any other functions: It doesn't.

    The long answear: It seems to me that sccz80 passes the number of variable arguments in the register A, and we should probably do the same. Unfortunately, this is a port-specific solution.

    The motivation for introducing __optlink is this: z88dk people are considering using sdcc instead of the compiler they currently use (z88dk is basically a simple compiler with lots of peepholes and lots and lots of support libraries for Z80-based platforms). However they have a large amount of asm code that expects parameters in reverse order. Using __optlink they would only have to change some headers, and legacy code calling these asm routines would not require further changes. I do not even know if there are varargs in that use-case.

    Philipp

     
  • Maarten Brock
    Maarten Brock
    2011-06-08

    Ok, so this means it can never be a command line option or pragma to make it default behaviour, which is fine by me.

    I have one more question: Why is it called __optlink? When I search for that it seems to always mean a right-to-left calling convention and not left-to-right. Usually (always?) the pascal calling convention is left-to-right.

     
  • It seems I remembered optlink incorrectly. You're right, we need to rename this. Unfortunately the pascal calling convention is a callee-clean-up convention, while this is a caller-clen-up convention, so we can't call it __pascal.
    So far I have not found a right-to-left caller-clears-the-stack calling convention name. If nothing better turns up today or tomorrow, I'd propose to rename it __sccz80.

    Philipp

     
  • Bodo Wenzel
    Bodo Wenzel
    2011-06-08

    __sccz80 sounds good, because also the number of args is in A - or am I wrong? This also means that all arguments have to be of equal size, otherwise the value is useless. ;-) In the end, this is a very special way to pass varargs just for z88dk.

     
  • The handling of A isn't even implemented yet. I haven't looked at it in detail, it could be that a number of bytes of arguments is passed there, not the number of arguments. The interesting part here isn't varargs - the z88dk people don't have many vararg functions, and AFAIK all of them are written in C anyway (so we don't have to use some specific calling convention).
    This calling convention is mostly needed for "normal" functions, of which there are many in existing libraries, not written in C.

    Philipp

     
  • I renamed __optlink to __smallc since AFAIK the Small-C compiler (and derivatives such as z88dk) is the only one using this calling convention.

    Philipp