[llvm-dev] BUG: complete misunterstanding of the MS-ABI

Craig Topper via llvm-dev llvm-dev at lists.llvm.org
Tue Sep 8 12:27:23 PDT 2020


__uint128_t isn't getting the usual x86 handling. I think the usual
handling for i128 return would be rdx:rax. Instead I believe it's being
coerced to v2i64 by this code in clang/lib/CodeGen/TargetInfo.cpp

      // Mingw64 GCC returns i128 in XMM0. Coerce to v2i64 to handle that.
      // Clang matches them for compatibility.
      return ABIArgInfo::getDirect(llvm::FixedVectorType::get(
          llvm::Type::getInt64Ty(getVMContext()), 2));


~Craig


On Tue, Sep 8, 2020 at 11:57 AM Reid Kleckner via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

> The code that you have has a large `#ifndef __clang__` block in it, and
> IMO that explains the ABI difference.
>
> As you note, MSVC does not have native support for 128 bit integers, so
> there is no reason for Clang to attempt to be ABI compatible.
>
> The __uint128_t arguments are passed indirectly because MSVC has a rule
> that requires arguments larger than 64 bits to be passed indirectly by
> address. I believe exceptions to that rule, such as vector arguments, are
> made on a case-by-case basis. No such rule exists for return values, so we
> get the usual i128 handling for x86 instead.
>
> ---
>
> I see that you are interested in using compiler-rt, presumably on Windows,
> and maybe from MSVC compiled objects. I think the proper fix for your use
> case is to change compiler-rt to use a union when passing these types by
> value.
>
> On Thu, Sep 3, 2020 at 5:35 PM Stefan Kanthak via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
>
>> Objects compiled for the MS-ABI don't conform to it!
>>
>> Data types beyond 64 bit MUST BE returned by the callee via the
>> hidden first argument allocated by the caller, NOT in XMM0!
>>
>> Demo/proof: from this source
>>
>> --- llvm-bug.c ---
>> #ifndef __clang__
>> typedef struct {
>>     unsigned __int64 low;
>>     unsigned __int64 high;
>> } __uint128_t;
>> #else
>> __attribute__((ms_abi))
>> #endif
>> __uint128_t __udivmodti4(__uint128_t dividend, __uint128_t divisor,
>> __uint128_t *remainder) {
>>     if (remainder != 0)
>>         *remainder = divisor;
>>     return dividend;
>> }
>> --- EOF ---
>>
>> clang -c -O1 generates the following INCOMPATIBLE and WRONG code:
>>
>> __udivmodti4 proc public
>>         movaps  xmm0, xmmword ptr [rcx]
>>         test    r8, r8
>>         jz      0f
>>         movaps  xmm1, xmmword ptr [rdx]
>>         movaps  xmmword ptr [r8], xmm1
>> 0:      ret
>> __udivmodti4 endp
>>
>>
>> clang's misunderstanding of the MS-ABI can be clearly seen here:
>>
>> - RCX holds the address of the return value, NOT the address
>>   of the dividend;
>>
>> - RDX holds the address of the dividend, NOT the address of
>>   the divisor;
>>
>> - R8 holds the address of the divisor, NOT the address of the
>>   remainder;
>>
>> - R9 holds the address of the remainder;
>>
>> - aggregate data types are NOT returned in XMM0, but via the
>>   hidden first argument addressed by RCX;
>>
>> - the address of the hidden first argument is returned in RAX!
>>
>> JFTR: an 128-bit integer data type is not supported by MS.
>>       clang is also rather confused here: why is the return
>>       value mapped to an XMM register, but not the arguments?
>>
>>
>> Microsoft's CL.EXE -c -Ox generates the following (of course)
>> CONFORMANT code:
>>
>> __udivmodti4 proc public
>> ; Line 10
>>         test    r9, r9
>>         je      SHORT $LN1 at udivmodti4
>> ; Line 11
>>         mov     rax, QWORD PTR [r8]
>>         mov     QWORD PTR [r9], rax
>>         mov     rax, QWORD PTR [r8+8]
>>         mov     QWORD PTR [r9+8], rax
>> $LN1 at udivmodti4:
>> ; Line 12
>>         mov     rax, QWORD PTR [rdx]
>>         mov     QWORD PTR [rcx], rax
>>         mov     rax, QWORD PTR [rdx+8]
>>         mov     QWORD PTR [rcx+8], rax
>>         mov     rax, rcx
>> ; Line 13
>>         ret     0
>> __udivmodti4 endp
>>
>>
>> NOT AMUSED
>> Stefan
>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200908/d1bb1a5d/attachment.html>


More information about the llvm-dev mailing list