[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