Returning structs in registers - ARM ABI in GCC

前端 未结 4 734
一整个雨季
一整个雨季 2021-01-13 18:01

In the ARM ABI documentation I come across functions defined like:

__value_in_regs struct bar foo(int a, int b) {
    ...
}

but GCC(4.3

相关标签:
4条回答
  • 2021-01-13 18:32

    You can do it for two registers by using "long long", as specified in "Procedure Call Standard for the ARM Architecture" link given in this page.

    long long test(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
    {
        long long ret;
        ret = a+b;
        ret <<= 32;
        ret |= c + d;
        return ret;
    }
    

    will be simply compiled as:

    0002dbb8 <test>:
    2dbb8:       1841            adds    r1, r0, r1
    2dbba:       18d0            adds    r0, r2, r3
    2dbbc:       4770            bx      lr
    

    and the ret & 0xFFFFFFFF and ret >> 32 in your calling function will be replaced seamlessly by r0 and r1.

    It is even possible to do it for registers r0 to r3 by using "Containerized vectors":

    typedef uint32_t uint32x4_t __attribute__ ((vector_size (16)));
    
    uint32x4_t test2(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
    {
        uint32x4_t ret = { a + 1, b + 2, c + 3, d + 4};
        // to access elements: ret[0], ret[1], ...
        return ret;
    }
    

    which is compiled as:

    0002dbb8 <test2>:
    2dbb8:       3001            adds    r0, #1
    2dbba:       3102            adds    r1, #2
    2dbbc:       3203            adds    r2, #3
    2dbbe:       3304            adds    r3, #4
    2dbc0:       4770            bx      lr
    

    Note that it is referenced as a SIMD/NEON feature in the document above, but I just achieved it on a Cortex M0 in Thumb mode, without NEON support.

    0 讨论(0)
  • 2021-01-13 18:39

    Posting as an answer by request:

    If you have to generate a binary that will work with an ABI your compiler doesn't support, you're in for some trouble. There's nothing you can do in C. In this case, you'll need to fall back on assembly language programming and thunk the necessary calls. There are two possibilities:

    1. Calls from your binary into the other binary's ABI.
    2. Calls from the other binary into your binary's ABI.

    Both of these problems are solved similarly. To call out from your code, you'll need to make shim functions in assembly that swizzle around the calling convention to match the external ABI, and then call the external functions from there. The difference to your C code is that now to make external calls, you call your internal assembly routine, and it does whatever it needs to to call out externally, then puts the return value back in a format your C code will understand, and returns.

    To support calls from the external binary into your code, you do the same thing, but in reverse. The entry points to your binary will be little assembly routines that swizzle the external ABI into a format your C code can understand, call your internal function, then put the return values back into a format the external code understands, and return.

    Sometimes there's just no good solution, I'm afraid.

    0 讨论(0)
  • I'm not sure if this will work, but you can try using the pcs function attribute:

    struct bar foo(int a, int b) __attribute__((pcs("aapcs")));
    struct bar foo(int a, int b) {
        ...
    }
    
    0 讨论(0)
  • 2021-01-13 18:45

    The "Procedure Call Standard for the ARM Architecture" specifically says (section 5.4: Result Return):

    "A Composite Type not larger than 4 bytes is returned in R0."

    "A Composite Type larger than 4 bytes ... is stored in memory at an address passed as an extra argument when the function was called ... ."

    I know that some CPUs have several different "standard" ABIs. But I was under the impression that practically all compilers for the ARM used this same ABI.

    Do you have any evidence that GCC doesn't use this standard ABI?

    Would you mind posting a link to any information on a ABI for the ARM that is different from this standard ABI -- the ABI used by the caller, or the called, or both?

    0 讨论(0)
提交回复
热议问题