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