1 //! This module contains type aliases for C's platform-specific types 2 //! and fixed-width integer types. 3 //! 4 //! The platform-specific types definitions were taken from rust-lang/rust in 5 //! library/core/src/ffi/primitives.rs 6 //! 7 //! The fixed-width integer aliases are deprecated: use the Rust types instead. 8 9 pub type c_schar = i8; 10 pub type c_uchar = u8; 11 pub type c_short = i16; 12 pub type c_ushort = u16; 13 14 pub type c_longlong = i64; 15 pub type c_ulonglong = u64; 16 17 pub type c_float = f32; 18 pub type c_double = f64; 19 20 cfg_if! { 21 if #[cfg(all( 22 not(windows), 23 // FIXME(ctest): just use `target_vendor` = "apple"` once `ctest` supports it 24 not(any( 25 target_os = "macos", 26 target_os = "ios", 27 target_os = "tvos", 28 target_os = "watchos", 29 target_os = "visionos", 30 )), 31 not(target_os = "vita"), 32 any( 33 target_arch = "aarch64", 34 target_arch = "arm", 35 target_arch = "csky", 36 target_arch = "hexagon", 37 target_arch = "msp430", 38 target_arch = "powerpc", 39 target_arch = "powerpc64", 40 target_arch = "riscv32", 41 target_arch = "riscv64", 42 target_arch = "s390x", 43 target_arch = "xtensa", 44 ) 45 ))] { 46 pub type c_char = u8; 47 } else { 48 // On every other target, c_char is signed. 49 pub type c_char = i8; 50 } 51 } 52 53 cfg_if! { 54 if #[cfg(any(target_arch = "avr", target_arch = "msp430"))] { 55 pub type c_int = i16; 56 pub type c_uint = u16; 57 } else { 58 pub type c_int = i32; 59 pub type c_uint = u32; 60 } 61 } 62 63 cfg_if! { 64 if #[cfg(all(target_pointer_width = "64", not(windows)))] { 65 pub type c_long = i64; 66 pub type c_ulong = u64; 67 } else { 68 // The minimal size of `long` in the C standard is 32 bits 69 pub type c_long = i32; 70 pub type c_ulong = u32; 71 } 72 } 73 74 #[deprecated(since = "0.2.55", note = "Use i8 instead.")] 75 pub type int8_t = i8; 76 #[deprecated(since = "0.2.55", note = "Use i16 instead.")] 77 pub type int16_t = i16; 78 #[deprecated(since = "0.2.55", note = "Use i32 instead.")] 79 pub type int32_t = i32; 80 #[deprecated(since = "0.2.55", note = "Use i64 instead.")] 81 pub type int64_t = i64; 82 #[deprecated(since = "0.2.55", note = "Use u8 instead.")] 83 pub type uint8_t = u8; 84 #[deprecated(since = "0.2.55", note = "Use u16 instead.")] 85 pub type uint16_t = u16; 86 #[deprecated(since = "0.2.55", note = "Use u32 instead.")] 87 pub type uint32_t = u32; 88 #[deprecated(since = "0.2.55", note = "Use u64 instead.")] 89 pub type uint64_t = u64; 90 91 cfg_if! { 92 if #[cfg(all(target_arch = "aarch64", not(target_os = "windows")))] { 93 // This introduces partial support for FFI with __int128 and 94 // equivalent types on platforms where Rust's definition is validated 95 // to match the standard C ABI of that platform. 96 // 97 // Rust does not guarantee u128/i128 are sound for FFI, and its 98 // definitions are in fact known to be incompatible. [0] 99 // 100 // However these problems aren't fundamental, and are just platform 101 // inconsistencies. Specifically at the time of this writing: 102 // 103 // * For x64 SysV ABIs (everything but Windows), the types are underaligned. 104 // * For all Windows ABIs, Microsoft doesn't actually officially define __int128, 105 // and as a result different implementations don't actually agree on its ABI. 106 // 107 // But on the other major aarch64 platforms (android, linux, ios, macos) we have 108 // validated that rustc has the right ABI for these types. This is important because 109 // aarch64 uses these types in some fundamental OS types like user_fpsimd_struct, 110 // which represents saved simd registers. 111 // 112 // Any API which uses these types will need to `#[ignore(improper_ctypes)]` 113 // until the upstream rust issue is resolved, but this at least lets us make 114 // progress on platforms where this type is important. 115 // 116 // The list of supported architectures and OSes is intentionally very restricted, 117 // as careful work needs to be done to verify that a particular platform 118 // has a conformant ABI. 119 // 120 // [0]: https://github.com/rust-lang/rust/issues/54341 121 122 /// C `__int128` (a GCC extension that's part of many ABIs) 123 pub type __int128 = i128; 124 /// C `unsigned __int128` (a GCC extension that's part of many ABIs) 125 pub type __uint128 = u128; 126 /// C __int128_t (alternate name for [__int128][]) 127 pub type __int128_t = i128; 128 /// C __uint128_t (alternate name for [__uint128][]) 129 pub type __uint128_t = u128; 130 131 // NOTE: if you add more platforms to here, you may need to cfg 132 // these consts. They should always match the platform's values 133 // for `sizeof(__int128)` and `_Alignof(__int128)`. 134 const _SIZE_128: usize = 16; 135 const _ALIGN_128: usize = 16; 136 137 // FIXME(ctest): ctest doesn't handle `_` as an identifier so these tests are temporarily 138 // disabled. 139 // macro_rules! static_assert_eq { 140 // ($a:expr, $b:expr) => { 141 // const _: [(); $a] = [(); $b]; 142 // }; 143 // } 144 // 145 // // Since Rust doesn't officially guarantee that these types 146 // // have compatible ABIs, we const assert that these values have the 147 // // known size/align of the target platform's libc. If rustc ever 148 // // tries to regress things, it will cause a compilation error. 149 // // 150 // // This isn't a bullet-proof solution because e.g. it doesn't 151 // // catch the fact that llvm and gcc disagree on how x64 __int128 152 // // is actually *passed* on the stack (clang underaligns it for 153 // // the same reason that rustc *never* properly aligns it). 154 // static_assert_eq!(core::mem::size_of::<__int128>(), _SIZE_128); 155 // static_assert_eq!(core::mem::align_of::<__int128>(), _ALIGN_128); 156 157 // static_assert_eq!(core::mem::size_of::<__uint128>(), _SIZE_128); 158 // static_assert_eq!(core::mem::align_of::<__uint128>(), _ALIGN_128); 159 160 // static_assert_eq!(core::mem::size_of::<__int128_t>(), _SIZE_128); 161 // static_assert_eq!(core::mem::align_of::<__int128_t>(), _ALIGN_128); 162 163 // static_assert_eq!(core::mem::size_of::<__uint128_t>(), _SIZE_128); 164 // static_assert_eq!(core::mem::align_of::<__uint128_t>(), _ALIGN_128); 165 } 166 } 167