Skip to content

Instantly share code, notes, and snippets.

@Gankra
Last active September 4, 2022 16:54
Show Gist options
  • Save Gankra/990c44f87477df7aac8af24e9e940e4b to your computer and use it in GitHub Desktop.
Save Gankra/990c44f87477df7aac8af24e9e940e4b to your computer and use it in GitHub Desktop.
The Clang/GCC int128 issue

Clang and GCC disagree on the ABI of __int128 (and its various unsigned/_t variants) on x64 linux (at least).

The issue is that when pushing __int128 to the stack, clang only aligns to 8, even though in structs it's aligned to 16. This causes Clang and GCC to disagree on the offset for by-value __int128 arguments that need padding to be 16-aligned.

The following function signature demonstrates this in practice:

void i128_val_in_0_perturbed_small(
  uint8_t arg0, 
  __int128_t arg1,
  __int128_t arg2, 
  __int128_t arg3,
  __int128_t arg4, 
  float arg5
);

Clang is pretty clearly in the wrong, but the root cause is llvm, which only aligns i128 to 8 on x64 (on arm64 it correctly aligns to 16!). Clang attempts to work around the llvm issue in the frontend by adding an alignment attribute, but this only half works, because that attribute seems to "fall off" when llvm implicitly pushes an i128 to the stack as part of a calling convention. This makes Clang incompatible with GCC AND other llvm compilers like rustc at the same time (worst of both worlds, imo).

(This might bethe relevant clang code but I don't know anything about clang, and am going off of descriptions from others on the precise impl details.)

History

  • rust issue filed because i128 isn't usable for FFI with C __int128 rust-lang/rust#54341

    • At the time, the clang workaround is known, but folks seem to believe it Works and that rustc could copy it
    • but we agree that the upstream fix to llvm is Ideal/Best
  • rust devs provide fix for llvm: https://reviews.llvm.org/D28990

    • change is merged, but then backed out for breaking some tests/tooling(?)
    • backout was "temporary" in 2017, no movement since
  • another dev attempts to fix the issue with more of the supporting changes needed: https://reviews.llvm.org/D86310

    • again logistical issues are brought up and the change isn't landed
  • In an attempt to make progress I propose rustc adopts clang's hack, but there's lack of clarity on what the ABI should be on various platforms

  • I write my ABI-checker tool to investigate on which platforms i128 is usable for FFI, if any: https://github.com/Gankra/abi-checker

    • I reproduce the original rust issue
    • But then also discover that clang and gcc fail to interop: rust-lang/rust#54341 (comment)
    • (I do however demonstrate that everyone agrees on arm64 and expose i128 ffi on that platform)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment