llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.35k stars 12.14k forks source link

ABI issue in i686 mingw + libstdc++ when using std::optional #75411

Open gbaraldi opened 11 months ago

gbaraldi commented 11 months ago

In summary, std::optional when compiled from clang is returned from a function using edx and eax, while gcc and msvc expect the selector bit to be on the stack.

The setup is a bit annoying because one needs a clang + libstdc++ 32 bit mingw toolchain. But once one has that it's simple to see the difference.

#include <optional>

std::optional<const char *> foo(int a){
    if (a)
        return std::nullopt;
    return std::optional<const char *>("a");
} 

clang assembly:

Disassembly of section .text:

64f01400 <__Z3fooi>:
64f01400: 31 d2                         xorl    %edx, %edx
64f01402: 83 7c 24 04 00                cmpl    $0x0, 0x4(%esp)
64f01407: 0f 94 c2                      sete    %dl
64f0140a: b8 00 40 f0 64                movl    $0x64f04000, %eax       # imm = 0x64F04000
64f0140f: c3                            retl

gcc assembly:


Disassembly of section .text:

651414e0 <__Z3fooi>:
651414e0: 8b 54 24 08                   movl    0x8(%esp), %edx
651414e4: 8b 44 24 04                   movl    0x4(%esp), %eax
651414e8: 85 d2                         testl   %edx, %edx
651414ea: 74 0c                         je      0x651414f8 <__Z3fooi+0x18>
651414ec: c6 40 04 00                   movb    $0x0, 0x4(%eax)
651414f0: c3                            retl
651414f1: 8d b4 26 00 00 00 00          leal    (%esi,%eiz), %esi
651414f8: c7 00 44 40 14 65             movl    $0x65144044, (%eax)     # imm = 0x65144044
651414fe: c6 40 04 01                   movb    $0x1, 0x4(%eax)
65141502: c3                            retl

note the sete %dl vs the movb $0x0, 0x4(%eax)

gbaraldi commented 11 months ago

The call to clang looks something like

clang++-17 --target=i686-w64-mingw32 -isystem /usr/lib/gcc/i686-w64-mingw32/10-posix/include/c++ -isystem /usr/lib/gcc/i686-w64-mingw32/10-posix/include/c++/i686-w64-mingw32 -isystem /usr/lib/gcc/i686-w64-mingw32/10-posix/include/c++/backward -isystem /usr/lib/gcc/i686-w64-mingw32/10-posix/include -isystem /usr/lib/gcc/i686-w64-mingw32
/10-posix/../../../../i686-w64-mingw32/include -L -L/usr/lib/gcc/i686-w64-mingw32/10-posix -L/usr/lib/gcc/i686-w64-mingw32/10-posix/../../../../i686-w64-mingw32/lib/../lib -L/usr/lib/gcc/i686-w64-mingw32/10-posix/../../../../i686-w64-mingw32/lib -stdlib=libstdc++ -L/usr/lib/gcc/i686-w64-mingw32/10-win32/ test.cpp -shared -v -o clang17.dl
l -O3

Paths might differ on gcc version and other things

pinskia commented 11 months ago

GCC does have ABI issues too that has not been fixed yet: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105932 for an example.

vtjnash commented 10 months ago

Yes, but just to point out that in this case, this seems to be a clang bug, since it is clang that disagrees with msvc, while gcc uses the same ABI as clang for this particular C++ API.