Multiple return values...

Iain Buclaw ibuclaw at ubuntu.com
Mon Mar 12 09:59:50 PDT 2012


On 12 March 2012 01:37, Andrew Wiley <wiley.andrew.j at gmail.com> wrote:
> On Sun, Mar 11, 2012 at 7:44 PM, Manu <turkeyman at gmail.com> wrote:
>> On 12 March 2012 00:58, Robert Jacques <sandford at jhu.edu> wrote:
>>>
>>> That's an argument for using the right register for the job. And we can /
>>> will be doing this on x86-64, as other compilers have already done. Manu was
>>> arguing that MRV were somehow special and had mystical optimization
>>> potential. That's simply not true.
>>
>>
>> Here's some tests for you:
>>
>> // first test that the argument registers allocate as expected...
>> int gprtest(int x, int y, int z)
>> {
>> return x+y+z;
>> }
>>
>>    Perfect, ints pass in register sequence, return in r0, no memory access
>> add r0, r0, r1
>> add r0, r0, r2
>> bx lr
>>
>> float fptest(float x, float y, float z)
>> {
>> return x+y+z;
>> }
>>
>>    Same for floats
>> fadds s0, s0, s1
>> fadds s0, s0, s2
>> bx lr
>>
>>
>> // Some MRV tests...
>> auto mrv1(int x, int z)
>> {
>> return Tuple!(int, int)(x, z);
>> }
>>
>>   Simple case, 2 ints
>>   FAIL, stores the 2 arguments it received in regs straight to output struct
>> pointer supplied
>> stmia r0, {r1, r2}
>> bx lr
>>
>>
>> auto mrv2(int x, float y, byte z)
>> {
>> return Tuple!(int, float, byte)(x, y, z);
>> }
>>
>>   Different typed things
>>   EPIC FAIL
>> stmfd sp!, {r4, r5}
>> mov ip, #0
>> sub sp, sp, #24
>> mov r4, r2
>> str ip, [sp, #12]
>> str ip, [sp, #20]
>> ldr r2, .L27
>> add ip, sp, #24
>> mov r3, r0
>> mov r5, r1
>> str r2, [sp, #16] @ float
>> ldmdb ip, {r0, r1, r2}
>> stmia r3, {r0, r1, r2}
>> fsts s0, [r3, #4]
>> stmia sp, {r0, r1, r2}
>> str r5, [r3, #0]
>> strb r4, [r3, #8]
>> mov r0, r3
>> add sp, sp, #24
>> ldmfd sp!, {r4, r5}
>> bx lr
>>
>>
>> auto range(int *p)
>> {
>> return p[0..1];
>> }
>>
>>   Range
>>   SURPRISE FAIL, even a range is returned as a struct! O_O
>> mov r2, #1
>> str r2, [r0, #0]
>> str r1, [r0, #4]
>> bx lr
>>
>>
>> So the D ABI is a complete shambles on ARM!
>> Unsurprisingly, it all just follows the return struct by-val ABI, which is
>> to write it to the stack unconditionally. And sadly, it even thinks the
>> internal types like range+delegate are just a struct by-val, and completely
>> ruins those!
>>
>> Let's try again with x86...
>>
>>
>> auto mrv1(int x, int z)
>> {
>> return Tuple!(int, int)(x, z);
>> }
>>
>> Returns in eax/edx as expected
>>  movl 4(%esp), %eax
>>  movl 8(%esp), %edx
>>
>>
>> auto mrv2(int x, float y, int z)
>> {
>> return Tuple!(int, float, int)(x, y, z);
>> }
>>
>> FAIL! All written to a struct rather than returning in eax,edx,st0 .. This
>> is C ABI baggage, D can do better.
>>  movl 4(%esp), %eax
>>  movl 8(%esp), %edx
>>  movl %edx, (%eax)
>>  movl 12(%esp), %edx
>>  movl %edx, 4(%eax)
>>  movl 16(%esp), %edx
>>  movl %edx, 8(%eax)
>>  ret $4
>>
>>
>> auto range(int *p)
>> {
>> return p[0..1];
>> }
>>
>> Obviously, the small struct optimisation allows this to work properly
>>  movl $1, %eax
>>  movl 4(%esp), %edx
>>  ret
>>
>>
>> All that said, x86 isn't a good test case, since all args are ALWAYS passed
>> on the stack. x64 would be a much better test since it actually has arg
>> registers, but I'm on windows, so no x64 for me...
>
> I assume this is with GDC? Pretty sure GDC doesn't match D's official
> ABI anyway because Iain didn't want to try to push D ABI support into
> GCC along with GDC.
> You're probably still right, but be aware that GDC is a bit different here.

Well, this is taken off the D ABI documentation.

The extern (C) and extern (D) calling convention matches the C calling
convention used by the supported C compiler on the host system. Except
that the extern (D) calling convention for Windows x86 is described
here.


Examining it in a literal sense, I can say that GDC is compliant with
the spec (except on x86 Windows, which it uses stdcall rather than the
calling convention described on the page).

-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';


More information about the Digitalmars-d mailing list