[mingw-users-owner@lists.sourceforge.net: [BUG] x64 ABI is not honoured for 16 byte return values]

classic Classic list List threaded Threaded
1 message Options
s
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[mingw-users-owner@lists.sourceforge.net: [BUG] x64 ABI is not honoured for 16 byte return values]

s
Hi,

I found out a case where mingw gcc does not honour x64 calling convention even
if explicitly asked to use this ABI. Consider a function as simple as this:

```c
__attribute__((ms_abi, noinline)) __int128 passthrough_a_c(__int128 a) {
   return a;
}
```

This assembly gets generated:

```asm
passthrough_a_c:
   movdqa (%rcx), %xmm0
   ret
```

Now, to summarize what happens here: argument `a` is expected to get passed in
as a pointer to caller-allocated stack location. That is correct behaviour as
per strict reading of [this document][ms1]:

> Integer arguments are passed in registers RCX, RDX, R8, and R9. Floating
> point arguments are passed in XMM0L, XMM1L, XMM2L, and XMM3L. 16-byte
> arguments are passed by reference.

Argument `a` is indeed a 16 byte argument and is passed by reference. Great!

Return value, however, gets put into the %xmm0 register and int128 being an…
integer… this is alarming. Turns out, wrong too. A strict reading of [this
document][msdn2] has this to say:

> Otherwise [NB: if a type is in fact a C++03 POD type; which __int128 is],
> the caller assumes the responsibility of allocating memory and passing a
> pointer for the return value as the first argument [NB: that would be
> RCX]. Subsequent arguments are then shifted one argument to the right. The
> same pointer must be returned by the callee in RAX.

So, instead of being compiled as it is currently, the function should be
compiled like this instead (intel syntax):

```asm
passthrough_a_c:
   vmovups     xmm0,xmmword ptr [rdx]
   vmovdqa     xmmword ptr [rcx],xmm0
   mov         rax,rcx
   ret
```

or, alternatively, this:

```asm
passthrough_a_c:
   movq %rcx, %rax
   movq (%rdx), %r9
   movq 8(%rdx), %r10
   movq %r9, (%rcx)
   movq %r10, 8(%rcx)
   ret
```

which is what mingw gcc generates for a slight variation of the original case:

```c
struct i128 { uint64_t a; uint64_t b; };
__attribute__((ms_abi, noinline)) struct i128 passthrough_a_c(struct i128 a) {
   return a;
}
```

[msdn1]: https://msdn.microsoft.com/en-us/library/ms235286.aspx
[msdn2]: https://msdn.microsoft.com/en-us/library/7572ztz4.aspx

Please CC if replying to me, Thanks!

Cheers,
Simonas

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
MinGW-users mailing list
[hidden email]

This list observes the Etiquette found at
http://www.mingw.org/Mailing_Lists.
We ask that you be polite and do the same.  Disregard for the list etiquette may cause your account to be moderated.

_______________________________________________
You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Also: mailto:[hidden email]?subject=unsubscribe
Loading...