diff --git a/build.rs b/build.rs index 61acba646dca0..47eef2f802633 100644 --- a/build.rs +++ b/build.rs @@ -60,6 +60,11 @@ fn main() { println!("cargo:rustc-cfg=libc_align"); } + // Rust >= 1.26 supports i128 and u128: + if rustc_minor_ver >= 26 || rustc_dep_of_std { + println!("cargo:rustc-cfg=libc_int128"); + } + // Rust >= 1.30 supports `core::ffi::c_void`, so libc can just re-export it. // Otherwise, it defines an incompatible type to retaining // backwards-compatibility. @@ -82,6 +87,11 @@ fn main() { println!("cargo:rustc-cfg=libc_ptr_addr_of"); } + // Rust >= 1.57.0 allows assert! (and panics in general) in constants. + if rustc_minor_ver >= 57 || rustc_dep_of_std { + println!("cargo:rustc-cfg=libc_const_assert"); + } + // #[thread_local] is currently unstable if rustc_dep_of_std { println!("cargo:rustc-cfg=libc_thread_local"); diff --git a/libc-test/semver/android-aarch64.txt b/libc-test/semver/android-aarch64.txt index 0036c2d743906..7a8868aa2c5de 100644 --- a/libc-test/semver/android-aarch64.txt +++ b/libc-test/semver/android-aarch64.txt @@ -12,3 +12,4 @@ SYS_syscalls SYS_fcntl __system_property_wait user_regs_struct +user_fpsimd_struct diff --git a/libc-test/semver/linux-aarch64.txt b/libc-test/semver/linux-aarch64.txt index 18fa63fed70b5..27416915d265a 100644 --- a/libc-test/semver/linux-aarch64.txt +++ b/libc-test/semver/linux-aarch64.txt @@ -91,3 +91,4 @@ max_align_t mcontext_t ucontext_t user_regs_struct +user_fpsimd_struct diff --git a/src/fixed_width_ints.rs b/src/fixed_width_ints.rs index 014640855fa30..44cf8b592ea6c 100644 --- a/src/fixed_width_ints.rs +++ b/src/fixed_width_ints.rs @@ -18,3 +18,78 @@ pub type uint16_t = u16; pub type uint32_t = u32; #[deprecated(since = "0.2.55", note = "Use u64 instead.")] pub type uint64_t = u64; + +cfg_if! { + if #[cfg(all(libc_int128, target_arch = "aarch64", not(target_os = "windows")))] { + // This introduces partial support for FFI with __int128 and + // equivalent types on platforms where Rust's definition is validated + // to match the standard C ABI of that platform. + // + // Rust does not guarantee u128/i128 are sound for FFI, and its + // definitions are in fact known to be incompatible. [0] + // + // However these problems aren't fundamental, and are just platform + // inconsistencies. Specifically at the time of this writing: + // + // * For x64 SysV ABIs (everything but Windows), the types are underaligned. + // * For all Windows ABIs, Microsoft doesn't actually officially define __int128, + // and as a result different implementations don't actually agree on its ABI. + // + // But on the other major aarch64 platforms (android, linux, ios, macos) we have + // validated that rustc has the right ABI for these types. This is important because + // aarch64 uses these types in some fundamental OS types like user_fpsimd_struct, + // which represents saved simd registers. + // + // Any API which uses these types will need to `#[ignore(improper_ctypes)]` + // until the upstream rust issue is resolved, but this at least lets us make + // progress on platforms where this type is important. + // + // The supported architectures and OSes is intentionally very restricted, + // as careful work needs to be done to verify that a particular platform + // has a conformant ABI. + // + // [0]: https://github.com/rust-lang/rust/issues/54341 + + /// C `__int128` (a GCC extension that's part of many ABIs) + pub type __int128 = i128; + /// C `unsigned __int128` (a GCC extension that's part of many ABIs) + pub type __uint128 = u128; + /// C __int128_t (alternate name for [__int128][]) + pub type __int128_t = i128; + /// C __uint128_t (alternate name for [__uint128][]) + pub type __uint128_t = u128; + + cfg_if! { + if #[cfg(libc_const_assert)] { + // NOTE: if you add more platforms to here, you may need to cfg + // these consts. They should always match the platform's values + // for `sizeof(__int128)` and `_Alignof(__int128)`. + const _SIZE_128: usize = 16; + const _ALIGN_128: usize = 16; + + /// Since Rust doesn't officially guarantee that these types + /// have compatible ABIs, we const assert that these values have the + /// known size/align of the target platform's libc. If rustc ever + /// tries to regress things, it will cause a compilation error. + /// + /// This isn't a bullet-proof solution because e.g. it doesn't + /// catch the fact that llvm and gcc disagree on how x64 __int128 + /// is actually *passed* on the stack (clang underaligns it for + /// the same reason that rustc *never* properly aligns it). + const _ASSERT_128_COMPAT: () = { + assert!(core::mem::size_of::<__int128>() == _SIZE_128); + assert!(core::mem::align_of::<__int128>() == _ALIGN_128); + + assert!(core::mem::size_of::<__uint128>() == _SIZE_128); + assert!(core::mem::align_of::<__uint128>() == _ALIGN_128); + + assert!(core::mem::size_of::<__int128_t>() == _SIZE_128); + assert!(core::mem::align_of::<__int128_t>() == _ALIGN_128); + + assert!(core::mem::size_of::<__uint128_t>() == _SIZE_128); + assert!(core::mem::align_of::<__uint128_t>() == _ALIGN_128); + }; + } + } + } +} diff --git a/src/unix/bsd/apple/b64/aarch64/align.rs b/src/unix/bsd/apple/b64/aarch64/align.rs index 10d55039dfa7a..131e15b69ad94 100644 --- a/src/unix/bsd/apple/b64/aarch64/align.rs +++ b/src/unix/bsd/apple/b64/aarch64/align.rs @@ -39,8 +39,15 @@ s! { pub __pad: u32, } - #[repr(align(16))] + // This type natively uses a uint128, but for a while we hacked + // it in with repr(align) and `[u64; 2]`. uint128 isn't available + // all the way back to our earliest supported versions so we + // preserver the old shim. + #[cfg_attr(not(libc_int128), repr(align(16)))] pub struct __darwin_arm_neon_state64 { + #[cfg(libc_int128)] + pub __v: [::__uint128_t; 32], + #[cfg(not(libc_int128))] pub __v: [[u64; 2]; 32], pub __fpsr: u32, pub __fpcr: u32, diff --git a/src/unix/linux_like/android/b64/aarch64/int128.rs b/src/unix/linux_like/android/b64/aarch64/int128.rs new file mode 100644 index 0000000000000..4535e73eeddf1 --- /dev/null +++ b/src/unix/linux_like/android/b64/aarch64/int128.rs @@ -0,0 +1,7 @@ +s! { + pub struct user_fpsimd_struct { + pub vregs: [::__uint128_t; 32], + pub fpsr: u32, + pub fpcr: u32, + } +} diff --git a/src/unix/linux_like/android/b64/aarch64/mod.rs b/src/unix/linux_like/android/b64/aarch64/mod.rs index 0416267c2859f..c4d4420600283 100644 --- a/src/unix/linux_like/android/b64/aarch64/mod.rs +++ b/src/unix/linux_like/android/b64/aarch64/mod.rs @@ -382,3 +382,10 @@ cfg_if! { pub use self::align::*; } } + +cfg_if! { + if #[cfg(libc_int128)] { + mod int128; + pub use self::int128::*; + } +} diff --git a/src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs b/src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs new file mode 100644 index 0000000000000..4535e73eeddf1 --- /dev/null +++ b/src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs @@ -0,0 +1,7 @@ +s! { + pub struct user_fpsimd_struct { + pub vregs: [::__uint128_t; 32], + pub fpsr: u32, + pub fpcr: u32, + } +} diff --git a/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs b/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs index 5cc0a5a4906d5..513f6acd1c8bb 100644 --- a/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs +++ b/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs @@ -897,3 +897,10 @@ cfg_if! { pub use self::align::*; } } + +cfg_if! { + if #[cfg(libc_int128)] { + mod int128; + pub use self::int128::*; + } +} diff --git a/src/unix/linux_like/linux/musl/b64/aarch64/int128.rs b/src/unix/linux_like/linux/musl/b64/aarch64/int128.rs new file mode 100644 index 0000000000000..4535e73eeddf1 --- /dev/null +++ b/src/unix/linux_like/linux/musl/b64/aarch64/int128.rs @@ -0,0 +1,7 @@ +s! { + pub struct user_fpsimd_struct { + pub vregs: [::__uint128_t; 32], + pub fpsr: u32, + pub fpcr: u32, + } +} diff --git a/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs b/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs index 1b8045341c64a..845707dcd9ab5 100644 --- a/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs +++ b/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs @@ -642,3 +642,10 @@ cfg_if! { pub use self::align::*; } } + +cfg_if! { + if #[cfg(libc_int128)] { + mod int128; + pub use self::int128::*; + } +}