[llvm-bugs] [Bug 31362] New: ms_abi is implemented incorrectly for larger values (>=16 bytes)
via llvm-bugs
llvm-bugs at lists.llvm.org
Tue Dec 13 10:58:27 PST 2016
https://llvm.org/bugs/show_bug.cgi?id=31362
Bug ID: 31362
Summary: ms_abi is implemented incorrectly for larger values
(>=16 bytes)
Product: clang
Version: 3.9
Hardware: PC
OS: Linux
Status: NEW
Severity: normal
Priority: P
Component: -New Bugs
Assignee: unassignedclangbugs at nondot.org
Reporter: simonas+llvm.org at kazlauskas.me
CC: llvm-bugs at lists.llvm.org
Classification: Unclassified
```c
#include <inttypes.h>
struct i128 { uint64_t a; uint64_t b; };
__attribute__((ms_abi, noinline)) struct i128 passthrough_a_s(struct i128 a) {
return a;
}
__attribute__((ms_abi, noinline)) __int128 passthrough_a(__int128 a) {
return a;
}
```
This code compiles to assembly that looks like this:
```asm
passthrough_a_s:
mov rax, rcx
ret
passthrough_a:
mov rax, rcx
ret
```
As per these two documents:
[msdn1]: https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
[msdn2]: https://msdn.microsoft.com/en-us/library/7572ztz4.aspx
Both of these are wrong and the generated assembly ought to look like this
instead:
```asm
passthrough_a_s:
mov rax, rcx
mov r9, QWORD PTR [rdx]
mov r10, QWORD PTR [rdx+8]
mov QWORD PTR [rcx], r9
mov QWORD PTR [rcx+8], r10
ret
passthrough_a:
mov rax, rcx
mov r9, QWORD PTR [rdx]
mov r10, QWORD PTR [rdx+8]
mov QWORD PTR [rcx], r9
mov QWORD PTR [rcx+8], r10
ret
```
The relevant excerpts:
> A scalar return value that can fit into 64 bits is returned through RAX—this includes __m64 types. Non-scalar types including floats, doubles, and vector types such as __m128, __m128i, __m128d are returned in XMM0. [snip] To be returned by value in RAX, user-defined types must have a length of 1, 2, 4, 8, 16, 32, or 64 bits. [snip] Otherwise, the caller assumes the responsibility of allocating memory and passing a pointer for the return value as the first argument.
> __m128 types, arrays and strings are never passed by immediate value but rather a pointer is passed to memory allocated by the caller. Structs/unions of size 8, 16, 32, or 64 bits and __m64 are passed as if they were integers of the same size. Structs/unions other than these sizes are passed as a pointer to memory allocated by the caller. For these aggregate types passed as a pointer (including __m128), the caller-allocated temporary memory will be 16-byte aligned.
Also from https://msdn.microsoft.com/en-us/library/ms235286.aspx:
> There is no attempt to spread a single argument across multiple registers.
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20161213/ebc9703c/attachment-0001.html>
More information about the llvm-bugs
mailing list