@@ -87,3 +87,108 @@ pub type uint16_t = u16;
87
87
pub type uint32_t = u32 ;
88
88
#[ deprecated( since = "0.2.55" , note = "Use u64 instead." ) ]
89
89
pub type uint64_t = u64 ;
90
+
91
+ cfg_if ! {
92
+ if #[ cfg( all(
93
+ target_arch = "aarch64" ,
94
+ not( any(
95
+ target_os = "windows" ,
96
+ target_os = "macos" ,
97
+ target_os = "ios" ,
98
+ target_os = "tvos" ,
99
+ target_os = "watchos"
100
+ ) )
101
+ ) ) ] {
102
+ // This introduces partial support for FFI with __int128 and
103
+ // equivalent types on platforms where Rust's definition is validated
104
+ // to match the standard C ABI of that platform.
105
+ //
106
+ // Rust does not guarantee u128/i128 are sound for FFI, and its
107
+ // definitions are in fact known to be incompatible. [0]
108
+ //
109
+ // However these problems aren't fundamental, and are just platform
110
+ // inconsistencies. Specifically at the time of this writing:
111
+ //
112
+ // * For x64 SysV ABIs (everything but Windows), the types are underaligned.
113
+ // * For all Windows ABIs, Microsoft doesn't actually officially define __int128,
114
+ // and as a result different implementations don't actually agree on its ABI.
115
+ //
116
+ // But on the other major aarch64 platforms (android, linux, ios, macos) we have
117
+ // validated that rustc has the right ABI for these types. This is important because
118
+ // aarch64 uses these types in some fundamental OS types like user_fpsimd_struct,
119
+ // which represents saved simd registers.
120
+ //
121
+ // Any API which uses these types will need to `#[ignore(improper_ctypes)]`
122
+ // until the upstream rust issue is resolved, but this at least lets us make
123
+ // progress on platforms where this type is important.
124
+ //
125
+ // The list of supported architectures and OSes is intentionally very restricted,
126
+ // as careful work needs to be done to verify that a particular platform
127
+ // has a conformant ABI.
128
+ //
129
+ // [0]: https://github.com/rust-lang/rust/issues/54341
130
+
131
+ /// C `__int128` (a GCC extension that's part of many ABIs)
132
+ #[ deprecated( since = "1.0" , note = "Use i128 instead." ) ]
133
+ pub type __int128 = i128 ;
134
+ /// C `unsigned __int128` (a GCC extension that's part of many ABIs)
135
+ #[ deprecated( since = "1.0" , note = "Use u128 instead." ) ]
136
+ pub type __uint128 = u128 ;
137
+ /// C __int128_t (alternate name for [__int128][])
138
+ #[ deprecated( since = "1.0" , note = "Use i128 instead." ) ]
139
+ pub type __int128_t = i128 ;
140
+ /// C __uint128_t (alternate name for [__uint128][])
141
+ #[ deprecated( since = "1.0" , note = "Use u128 instead." ) ]
142
+ pub type __uint128_t = u128 ;
143
+
144
+ // NOTE: if you add more platforms to here, you may need to cfg
145
+ // these consts. They should always match the platform's values
146
+ // for `sizeof(__int128)` and `_Alignof(__int128)`.
147
+ const _SIZE_128: usize = 16 ;
148
+ const _ALIGN_128: usize = 16 ;
149
+
150
+ // FIXME(ctest): ctest doesn't handle `_` as an identifier so these tests are temporarily
151
+ // disabled.
152
+ // macro_rules! static_assert_eq {
153
+ // ($a:expr, $b:expr) => {
154
+ // const _: [(); $a] = [(); $b];
155
+ // };
156
+ // }
157
+ //
158
+ // // Since Rust doesn't officially guarantee that these types
159
+ // // have compatible ABIs, we const assert that these values have the
160
+ // // known size/align of the target platform's libc. If rustc ever
161
+ // // tries to regress things, it will cause a compilation error.
162
+ // //
163
+ // // This isn't a bullet-proof solution because e.g. it doesn't
164
+ // // catch the fact that llvm and gcc disagree on how x64 __int128
165
+ // // is actually *passed* on the stack (clang underaligns it for
166
+ // // the same reason that rustc *never* properly aligns it).
167
+ // static_assert_eq!(core::mem::size_of::<__int128>(), _SIZE_128);
168
+ // static_assert_eq!(core::mem::align_of::<__int128>(), _ALIGN_128);
169
+
170
+ // static_assert_eq!(core::mem::size_of::<__uint128>(), _SIZE_128);
171
+ // static_assert_eq!(core::mem::align_of::<__uint128>(), _ALIGN_128);
172
+
173
+ // static_assert_eq!(core::mem::size_of::<__int128_t>(), _SIZE_128);
174
+ // static_assert_eq!(core::mem::align_of::<__int128_t>(), _ALIGN_128);
175
+
176
+ // static_assert_eq!(core::mem::size_of::<__uint128_t>(), _SIZE_128);
177
+ // static_assert_eq!(core::mem::align_of::<__uint128_t>(), _ALIGN_128);
178
+ } else if #[ cfg( all(
179
+ target_arch = "aarch64" ,
180
+ any(
181
+ target_os = "macos" ,
182
+ target_os = "ios" ,
183
+ target_os = "tvos" ,
184
+ target_os = "watchos"
185
+ )
186
+ ) ) ] {
187
+ /// C `__int128_t`
188
+ #[ deprecated( since = "1.0" , note = "Use i128 instead." ) ]
189
+ pub type __int128_t = i128 ;
190
+ /// C `__uint128_t`
191
+ #[ deprecated( since = "1.0" , note = "Use ux128 instead." ) ]
192
+ pub type __uint128_t = u128 ;
193
+ }
194
+ }
0 commit comments