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