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

Stefan Kanthak via cfe-dev cfe-dev at lists.llvm.org
Thu Sep 3 14:01:50 PDT 2020


"Anton Korobeynikov" <anton at korobeynikov.info> wrote:

>> --- llvm-bug.c ---Any argument
            that doesn't fit in 8 bytes, or isn't 1, 2, 4, or 8 bytes, must be
            passed by reference.
>> #ifndef __clang__
>> typedef struct {
>>     unsigned __int64 low;
>>     unsigned __int64 high;
>> } __uint128_t;
>> #else
>> __attribute__((ms_abi))
>> #endif
>>
> These are different types. __uint128_t is not a struct of two 64-bit
> integers.

This is irrelavent here: clang's builtin type __uint128_t doesn't fit in
64-bit, so it MUST be returned by reference through a hidden first argument!
Please read the specification of the Microsoft ABI
<https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention>

| User-defined types can be returned by value from global functions and
| static member functions. To return a user-defined type by value in RAX,
| it must have a length of 1, 2, 4, 8, 16, 32, or 64 bits. [...]
| Otherwise, the caller must allocate memory for the return value and
| pass a pointer to it as the first argument. The remaining arguments
| are then shifted one argument to the right. The same pointer must be
| returned by the callee in RAX.

Since MSVC does NOT support an (unsigned) __int128 data type, __uint128_t
is a user-defined type there, for which the cited specs clearly state how
to return it.

> If you'd modify the source so it would pass / return struct of two 64 bit
> integers, then you will see that clang will generate the same code as MSVC.

Who said "these are different types"? See above!

Additionally I recommend to take a thorough look into the SystemV ABI for
the AMD64 platform:

| For classification purposes __int128 is treated as if it were implemented as:
| typedef struct {
| long low, high;
| } __int128;

> NOT A BUG. USER ERROR.

WRONG: interoperability and developer error!
<https://blog.llvm.org/2018/03/clang-is-now-used-to-build-chrome-for.html>
puts up the FALSE claim:

| Clang is the first-ever open-source C++ compiler that's ABI-compatible with
| Microsoft Visual C++ (MSVC) - meaning you can build some parts of your
| program (for example, system libraries) with the MSVC compiler ("cl.exe"),
| other parts with Clang, and when linked together (either by MSVC's linker,
| "link.exe", or LLD, the LLVM project's linker - see below) the parts will form
| a working program.

Due to clang's non-conforming parameter and return value passing this does
NOT hold for code which uses __uint128_t: either fix the compiler and the
functions shipped in clang_rt.builtins-x86_64.lib, or remove the claim
"ABI-compatible" from the blog post.

Stefan


More information about the cfe-dev mailing list