-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create optionally-available __int128 typedefs and use them for ARM64 definitions. #2719
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @Amanieu (or someone else) soon. Please see the contribution instructions for more information. |
See rust-lang/rust#54341 (comment) for details on my investigation into this. I will happily fill in more OS/arches if anyone can run https://github.com/Gankra/abi-checker on that target and get full passes. I only have access to aarch64 Android (phone) and macOS (coworker). I'm kinda blindly assuming iOS is the same as macOS here. |
For context, properly defining these types is important for saving a crashing process' registers (i.e. when generating a breakpad-style minidump, which I am currently working on porting to Rust for Android). |
In the upstream issue nagisa notes that rust uniformly has this repr on all aarch64 targets -- but I'd still like to verify that the primary C compilers for those targets agree. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work! I think this was sorely needed.
src/fixed_width_ints.rs
Outdated
|
||
cfg_if! { | ||
if #[cfg(all(target_arch = "aarch64", | ||
any(target_os = "android", target_os="macos", target_os = "ios")))] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would feel comfortable just doing not(windows)
here. That way all non-Windows platforms automatically get support and this is confirmed by the static assert.
So since putting up this PR I spent a bit more time digging into what can be done to polyfill this type on x64 (since SysV actually passes structs the same as ints, in general). Unfortunately on x64 (linux, at least) clang and gcc actually disagree on the pass-on-stack convention for https://twitter.com/Gankra_/status/1502320041315946499 x64 SysV fails to specify what "pushing" a value actually means and so clang packs __int128 while gcc properly aligns it. This can introduce padding and differences and completely desynchronize the offsets to args. In discussing this on Twitter some Apple engineers also pointed out that clang actually has macos-specific ABI differences for backcompat with itself (details vague, no documentation for this in general). Similarly a coworker noted that stuff like this is a problem for clang plugins when the plugin and compiler weren't both consistently built by clang or gcc. This now has me increasingly paranoid about claiming u128/i128 are ABI-compatible on ARM64 without any way for me to properly compare gcc and clang both targetting these platforms. And also makes me less inclined to willy-nilly declare that Rust agrees with C compilers for "all non-windows OSes". Even asserting they agree on size and align isn't sufficient because the compilers can still disagree on how the value is pushed to the stack. :( I'm not sure what libc's policy is on divergent impls for one platform, and how to declare one "canonical" over the others. Unfortunately I can't really test this stuff out better -- the "gcc" on my phone's termux is just an alias for clang, and similarly I expect that will be the case for m1 macbooks. If anyone has better access to arm64 platforms and can setup clang/gcc properly, they can test this out by checking out: https://github.com/Gankra/abi-checker and running
This will compare CC to rustc and CC to itself. That is a good start for rust matching the "canonical" implementation. To exhaustively try out all the combos of clang+gcc+rust to check if the ABI is actually consistent between all impls, you can do:
Otherwise you can manually do something like this godbolt. |
I ran your ABI checker on AArch64 Linux, all the tests pass:
|
Oh nice!! that helps my confidence with going forward with this a lot. I'll clean this up on monday. |
Also lmao @ rustc actually managing to do something on linux when you ask it to fastcall/stdcall with itself, I hadn't actually every tested that. |
Applied review requests and squashed. |
@bors r+ |
📌 Commit 3741d52 has been approved by |
Create optionally-available __int128 typedefs and use them for ARM64 definitions. Potentially fixes #2524, see the comments in the patch for details.
💔 Test failed - checks-actions |
src/fixed_width_ints.rs
Outdated
/// is actually *passed* on the stack (clang underaligns it for | ||
/// the same reason that rustc *never* properly aligns it). | ||
const _ASSERT_128_COMPAT: () = { | ||
assert!(std::mem::size_of::<__int128>() == SIZE_128); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should use core
instead of std
.
@@ -55,6 +55,12 @@ s! { | |||
pub pc: u64, | |||
pub pstate: u64, | |||
} | |||
|
|||
pub struct user_fpsimd_struct { | |||
pub vregs: [__uint128_t; 32], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type needs to be imported:
pub vregs: [__uint128_t; 32], | |
pub vregs: [::__uint128_t; 32], |
ok!!! this one actually seems to work and satisfy the nightmare cfg macro rube-goldberg machine (remaining failures are the pre-existing ones in the repo itself). |
💔 Test failed - checks-actions |
@bors r+ |
📌 Commit 127542f has been approved by |
Create optionally-available __int128 typedefs and use them for ARM64 definitions. Potentially fixes #2524, see the comments in the patch for details.
💔 Test failed - checks-actions |
…definitions. This adds the following types to fixed_width_ints behind appropriate platform cfgs: * __int128 * __int128_t * __uint128 * __uint128_t and user_fpsimd_struct to arm64 android and linux.
ok coming back to this with a fresh mind and the design of libc i think now has congealed into a coherent form for me. Hopefully this works now... |
@bors try |
Create optionally-available __int128 typedefs and use them for ARM64 definitions. Potentially fixes #2524, see the comments in the patch for details.
@bors r+ |
📌 Commit adfa385 has been approved by |
☀️ Test successful - checks-actions, checks-cirrus-freebsd-11, checks-cirrus-freebsd-12, checks-cirrus-freebsd-13 |
Two improvements of the latest i128 numbers change Two improvements of #2719: * First, a typo/grammar fix * Second, a fix to avoid usage of the anti pattern of `==` inside an `assert` macro. Since a few releases, `assert` is usable inside `const` expressions, but for the purpose of `==`, superior alternatives exist that also work at compile time but print the two values at a mismatch. `assert_eq` is not yet usable in const contexts due to formatting.
Two improvements of the latest i128 numbers change Two improvements of #2719: * First, a typo/grammar fix * Second, a fix to avoid usage of the anti pattern of `==` inside an `assert` macro. Since a few releases, `assert` is usable inside `const` expressions, but for the purpose of `==`, superior alternatives exist that also work at compile time but print the two values at a mismatch. `assert_eq` is not yet usable in const contexts due to formatting.
Potentially fixes #2524, see the comments in the patch for details.