@@ -18,3 +18,70 @@ pub type uint16_t = u16;
1818pub type uint32_t = u32 ;
1919#[ deprecated( since = "0.2.55" , note = "Use u64 instead." ) ]
2020pub type uint64_t = u64 ;
21+
22+ cfg_if ! {
23+ if #[ cfg( all( target_arch = "aarch64" ,
24+ any( target_os = "android" , target_os="macos" , target_os = "ios" ) ) ) ] {
25+ // This introduces partial support for FFI with __int128 and
26+ // equivalent types on platforms where Rust's definition is validated
27+ // to match the standard C ABI of that platform.
28+ //
29+ // Rust does not guarantee u128/i128 are sound for FFI, and its
30+ // definitions are in fact known to be incompatible. [0]
31+ //
32+ // However these problems aren't fundamental, and are just platform
33+ // inconsistencies. Specifically at the time of this writing:
34+ //
35+ // * For x64 SysV ABIs (everything but Windows), the types are underaligned.
36+ // * For all Windows ABIs, Microsoft doesn't actually officially define __int128,
37+ // and as a result different implementations don't actually agree on its ABI.
38+ //
39+ // But on the major aarch64 platforms (android, macos, ios) we have validated
40+ // that rustc has the right ABI for these types. This is important because
41+ // aarch64 uses these types in some fundamental OS types like user_fpsimd_struct,
42+ // which represents saved simd registers.
43+ //
44+ // Any API which uses these types will need to `#[ignore(improper_ctypes)]`
45+ // until the upstream rust issue is resolved, but this at least lets us make
46+ // progress on platforms where this type is important.
47+ //
48+ // The supported architectures and OSes is intentionally very restricted,
49+ // as careful work needs to be done to verify that a particular platform
50+ // has a conformant ABI.
51+ //
52+ // [0]: https://github.com/rust-lang/rust/issues/54341
53+
54+ /// C `__int128` (a GCC extension that's part of many ABIs)
55+ pub type __int128 = i128 ;
56+ /// C `unsigned __int128` (a GCC extension that's part of many ABIs)
57+ pub type __uint128 = u128 ;
58+ /// C __int128_t (alternate name for [__int128][])
59+ pub type __int128_t = i128 ;
60+ /// C __uint128_t (alternate name for [__uint128][])
61+ pub type __uint128_t = u128 ;
62+
63+ // NOTE: if you add more platforms to here, you made need to cfg
64+ // these consts. They should always match the platform's values
65+ // for `sizeof(__int128)` and `_Alignof(__int128)`.
66+ const SIZE_128 : usize = 16 ;
67+ const ALIGN_128 : usize = 16 ;
68+
69+ /// Since Rust doesn't officially guarantee that these types
70+ /// have compatible ABIs, we const assert that these values have the
71+ /// known size/align of the target platform's libc. If rustc ever
72+ /// tries to regress things, it will cause a compilation error.
73+ const _ASSERT_128_COMPAT: ( ) = {
74+ assert!( std:: mem:: size_of:: <__int128>( ) == SIZE_128 ) ;
75+ assert!( std:: mem:: align_of:: <__int128>( ) == ALIGN_128 ) ;
76+
77+ assert!( std:: mem:: size_of:: <__uint128>( ) == SIZE_128 ) ;
78+ assert!( std:: mem:: align_of:: <__uint128>( ) == ALIGN_128 ) ;
79+
80+ assert!( std:: mem:: size_of:: <__int128_t>( ) == SIZE_128 ) ;
81+ assert!( std:: mem:: align_of:: <__int128_t>( ) == ALIGN_128 ) ;
82+
83+ assert!( std:: mem:: size_of:: <__uint128_t>( ) == SIZE_128 ) ;
84+ assert!( std:: mem:: align_of:: <__uint128_t>( ) == ALIGN_128 ) ;
85+ } ;
86+ }
87+ }
0 commit comments