lvc / abi-compliance-checker

A tool for checking backward API/ABI compatibility of a C/C++ library
https://lvc.github.io/abi-compliance-checker/
GNU Lesser General Public License v2.1
621 stars 76 forks source link

Doesn't detect change to x64 ABI calling convention due to C++ struct definition change #128

Open unwiredben opened 3 months ago

unwiredben commented 3 months ago

Here's a fun issue that I found recently.

In the x64 System V ABI, the calling convention used to pass structs via registers as opposed to via pointers to memory depends on if the struct is considered trivial according to the Itanium C++ ABI.

This means that if you define this struct

struct v {
    float a, b;
};

it can be passed in a single SSE register. However, if you add an empty destructor

struct v {
    float a, b;
    ~v() { }
};

then the class becomes non-trivial and it has to be passed via a pointer instead.

This didn't affect ARM32 compilation (the struct was too large for a register) or MIPS32 compilation (only uses pointers), but broke when build for a desktop simulator.

abi-tests.zip

unwiredben commented 3 months ago

References: https://gitlab.com/x86-psABIs/x86-64-ABI/-/jobs/artifacts/master/raw/x86-64-ABI/abi.pdf?job=build part 3.2.3 and https://itanium-cxx-abi.github.io/cxx-abi/abi.html (search for "non-trivial for the purposes of calls") and https://godbolt.org/z/4n45r6hMq