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: unassignedclangb...@nondot.org Reporter: simonas+llvm....@kazlauskas.me CC: llvm-bugs@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.
_______________________________________________ llvm-bugs mailing list llvm-bugs@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs