libffi_sys/
arch.rs

1//! This module defines the different ffi_abi values for each platform.
2//!
3//! This module is set-up to define all the constants for each platform, but only export those which
4//! are actually relevant to the target arch. This is done as a compile check to ensure the code
5//! paths in less utilized architectures largely continue to compile.
6
7#![allow(unused)]
8
9/// From libffi:src/x86/ffitarget.h.
10/// See: <https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/x86/ffitarget.h#L83>
11mod x86 {
12    pub mod x86_win64 {
13        use crate::ffi_abi;
14
15        pub const ffi_abi_FFI_FIRST_ABI: ffi_abi = 0;
16        pub const ffi_abi_FFI_WIN64: ffi_abi = 1;
17        pub const ffi_abi_FFI_GNUW64: ffi_abi = 2;
18        pub const ffi_abi_FFI_LAST_ABI: ffi_abi = 3;
19
20        mod gnu {
21            pub const ffi_abi_FFI_DEFAULT_ABI: crate::ffi_abi = super::ffi_abi_FFI_GNUW64;
22        }
23
24        mod msvc {
25            pub const ffi_abi_FFI_DEFAULT_ABI: crate::ffi_abi = super::ffi_abi_FFI_WIN64;
26        }
27
28        #[cfg(target_env = "gnu")]
29        pub use gnu::*;
30        #[cfg(target_env = "msvc")]
31        pub use msvc::*;
32
33        // See: https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/x86/ffitarget.h#L140
34        pub const FFI_TRAMPOLINE_SIZE: usize = 32;
35        pub const FFI_NATIVE_RAW_API: u32 = 0;
36    }
37
38    pub mod x86_64 {
39        use crate::ffi_abi;
40
41        pub const ffi_abi_FFI_FIRST_ABI: ffi_abi = 1;
42        pub const ffi_abi_FFI_UNIX64: ffi_abi = 2;
43        pub const ffi_abi_FFI_WIN64: ffi_abi = 3;
44        pub const ffi_abi_FFI_EFI64: ffi_abi = ffi_abi_FFI_WIN64;
45        pub const ffi_abi_FFI_GNUW64: ffi_abi = 4;
46        pub const ffi_abi_FFI_LAST_ABI: ffi_abi = 5;
47        pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi = ffi_abi_FFI_UNIX64;
48
49        // See: https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/x86/ffitarget.h#L140
50        pub const FFI_TRAMPOLINE_SIZE: usize = 32;
51        pub const FFI_NATIVE_RAW_API: u32 = 0;
52    }
53
54    pub mod x86_win32 {
55        use crate::ffi_abi;
56
57        pub const ffi_abi_FFI_FIRST_ABI: ffi_abi = 0;
58        pub const ffi_abi_FFI_SYSV: ffi_abi = 1;
59        pub const ffi_abi_FFI_STDCALL: ffi_abi = 2;
60        pub const ffi_abi_FFI_THISCALL: ffi_abi = 3;
61        pub const ffi_abi_FFI_FASTCALL: ffi_abi = 4;
62        pub const ffi_abi_FFI_MS_CDECL: ffi_abi = 5;
63        pub const ffi_abi_FFI_PASCAL: ffi_abi = 6;
64        pub const ffi_abi_FFI_REGISTER: ffi_abi = 7;
65        pub const ffi_abi_FFI_LAST_ABI: ffi_abi = 8;
66        pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi = ffi_abi_FFI_MS_CDECL;
67
68        // See: https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/x86/ffitarget.h#L149
69        pub const FFI_TRAMPOLINE_SIZE: usize = 16;
70        pub const FFI_NATIVE_RAW_API: u32 = 1;
71    }
72
73    pub mod x86 {
74        use crate::ffi_abi;
75
76        pub const ffi_abi_FFI_FIRST_ABI: ffi_abi = 0;
77        pub const ffi_abi_FFI_SYSV: ffi_abi = 1;
78        pub const ffi_abi_FFI_THISCALL: ffi_abi = 3;
79        pub const ffi_abi_FFI_FASTCALL: ffi_abi = 4;
80        pub const ffi_abi_FFI_STDCALL: ffi_abi = 5;
81        pub const ffi_abi_FFI_PASCAL: ffi_abi = 6;
82        pub const ffi_abi_FFI_REGISTER: ffi_abi = 7;
83        pub const ffi_abi_FFI_MS_CDECL: ffi_abi = 8;
84        pub const ffi_abi_FFI_LAST_ABI: ffi_abi = 9;
85        pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi = ffi_abi_FFI_SYSV;
86
87        // See: https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/x86/ffitarget.h#L149
88        pub const FFI_TRAMPOLINE_SIZE: usize = 16;
89        pub const FFI_NATIVE_RAW_API: u32 = 1;
90    }
91
92    pub const FFI_GO_CLOSURES: u32 = 1;
93}
94
95#[cfg(all(target_arch = "x86_64", windows))]
96pub use x86::x86_win64::*;
97
98#[cfg(all(target_arch = "x86_64", unix))]
99pub use x86::x86_64::*;
100
101#[cfg(all(target_arch = "x86", windows))]
102pub use x86::x86_win32::*;
103
104#[cfg(all(target_arch = "x86", unix))]
105pub use x86::x86::*;
106
107/// From libffi:src/arm/ffitarget.h.
108/// See: <https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/arm/ffitarget.h#L41>
109mod arm {
110    use crate::ffi_abi;
111
112    pub const ffi_abi_FFI_FIRST_ABI: ffi_abi = 0;
113    pub const ffi_abi_FFI_SYSV: ffi_abi = 1;
114    pub const ffi_abi_FFI_VFP: ffi_abi = 2;
115    pub const ffi_abi_FFI_LAST_ABI: ffi_abi = 3;
116
117    // On systems with a hard(ware) float ("hf"), ffi_abi_FFI_VPF is the default ABI.
118    #[cfg(target_abi = "eabihf")]
119    pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi = ffi_abi_FFI_VFP;
120    #[cfg(not(target_abi = "eabihf"))]
121    pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi = ffi_abi_FFI_SYSV;
122
123    // See: <https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/arm/ffitarget.h#L84>
124    pub const FFI_GO_CLOSURES: u32 = 1;
125    pub const FFI_TRAMPOLINE_SIZE: usize = 12;
126    pub const FFI_NATIVE_RAW_API: u32 = 0;
127}
128
129#[cfg(target_arch = "arm")]
130pub use arm::*;
131
132/// From libffi:src/aarch64/ffitarget.h.
133/// See: <https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/aarch64/ffitarget.h#L44>
134mod aarch64 {
135    use crate::ffi_abi;
136
137    pub const ffi_abi_FFI_FIRST_ABI: ffi_abi = 0;
138    pub const ffi_abi_FFI_SYSV: ffi_abi = 1;
139    pub const ffi_abi_FFI_WIN64: ffi_abi = 2;
140    pub const ffi_abi_FFI_LAST_ABI: ffi_abi = 3;
141
142    #[cfg(unix)]
143    pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi = ffi_abi_FFI_SYSV;
144    #[cfg(windows)]
145    pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi = ffi_abi_FFI_WIN64;
146
147    pub const FFI_NATIVE_RAW_API: u32 = 0;
148
149    // See: <https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/aarch64/ffitarget.h#L66>
150    #[cfg(target_vendor = "apple")]
151    pub const FFI_TRAMPOLINE_SIZE: usize = 16;
152
153    // See: <https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/aarch64/ffitarget.h#L66>
154    #[cfg(not(target_vendor = "apple"))]
155    pub const FFI_TRAMPOLINE_SIZE: usize = 24;
156
157    // No GO_CLOSURES on iOS or Windows
158    #[cfg(not(any(target_os = "windows", target_vendor = "apple")))]
159    pub const FFI_GO_CLOSURES: u32 = 1;
160}
161
162#[cfg(target_arch = "aarch64")]
163pub use aarch64::*;
164
165/// From libffi:src/powerpc/ffitarget.h.
166/// See: <https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/powerpc/ffitarget.h#L60>
167mod powerpc {
168    pub mod powerpc {
169        use crate::ffi_abi;
170
171        pub const ffi_abi_FFI_FIRST_ABI: ffi_abi = 0;
172        pub const ffi_abi_FFI_SYSV_SOFT_FLOAT: ffi_abi = 0b00_0001;
173        pub const ffi_abi_FFI_SYSV_STRUCT_RET: ffi_abi = 0b00_0010;
174        pub const ffi_abi_FFI_SYSV_IBM_LONG_DOUBLE: ffi_abi = 0b00_0100;
175        pub const ffi_abi_FFI_SYSV: ffi_abi = 0b00_1000;
176        pub const ffi_abi_FFI_SYSV_LONG_DOUBLE_128: ffi_abi = 0b01_0000;
177
178        mod fprs {
179            pub const SOFT_FLOAT_FLAG: crate::ffi_abi = 0b0;
180        }
181
182        mod no_fprs {
183            pub const SOFT_FLOAT_FLAG: crate::ffi_abi = super::ffi_abi_FFI_SYSV_SOFT_FLOAT;
184        }
185
186        #[cfg(target_abi = "spe")]
187        use no_fprs::*;
188
189        #[cfg(not(target_abi = "spe"))]
190        use fprs::*;
191
192        mod struct_ret {
193            pub const STRUCT_RET_FLAG: crate::ffi_abi = super::ffi_abi_FFI_SYSV_STRUCT_RET;
194        }
195
196        mod no_struct_ret {
197            pub const STRUCT_RET_FLAG: crate::ffi_abi = 0b0;
198        }
199
200        #[cfg(target_os = "netbsd")]
201        use struct_ret::*;
202
203        #[cfg(not(target_os = "netbsd"))]
204        use no_struct_ret::*;
205
206        mod long_double_64 {
207            pub const LONG_DOUBLE_128_FLAG: crate::ffi_abi = 0b0;
208        }
209
210        mod long_double_128 {
211            pub const LONG_DOUBLE_128_FLAG: crate::ffi_abi =
212                super::ffi_abi_FFI_SYSV_LONG_DOUBLE_128;
213        }
214
215        // IEEE128 is not supported on BSD or when targeting musl:
216        // https://github.com/rust-lang/llvm-project/blob/cb7f903994646c5b9223e0bb6cee3792190991f7/clang/lib/Basic/Targets/PPC.h#L379
217
218        #[cfg(any(target_os = "netbsd", target_os = "freebsd", target_env = "musl"))]
219        use long_double_64::*;
220
221        #[cfg(not(any(target_os = "netbsd", target_os = "freebsd", target_env = "musl")))]
222        use long_double_128::*;
223
224        pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi = ffi_abi_FFI_SYSV
225            | ffi_abi_FFI_SYSV_IBM_LONG_DOUBLE
226            | SOFT_FLOAT_FLAG
227            | STRUCT_RET_FLAG
228            | LONG_DOUBLE_128_FLAG;
229
230        pub const FFI_TRAMPOLINE_SIZE: usize = 40;
231        pub const FFI_NATIVE_RAW_API: u32 = 0;
232        pub const FFI_GO_CLOSURES: u32 = 1;
233    }
234
235    pub mod powerpc64 {
236        use crate::ffi_abi;
237
238        pub const ffi_abi_FFI_FIRST_ABI: ffi_abi = 0;
239        pub const ffi_abi_FFI_LINUX_STRUCT_ALIGN: ffi_abi = 0b00_0001;
240        pub const ffi_abi_FFI_LINUX_LONG_DOUBLE_128: ffi_abi = 0b00_0010;
241        pub const ffi_abi_FFI_LINUX_LONG_DOUBLE_IEEE128: ffi_abi = 0b00_0100;
242        pub const ffi_abi_FFI_LINUX: ffi_abi = 0b00_1000;
243
244        mod elfv1 {
245            pub const FFI_TRAMPOLINE_SIZE: usize = 24;
246        }
247
248        mod elfv2 {
249            pub const FFI_TRAMPOLINE_SIZE: usize = 32;
250        }
251
252        // I think this should be something like `target_abi = "elf_v2"`, but that's not yet
253        // supported.
254        // Discussion: https://github.com/rust-lang/rust/issues/60617
255        // RFC: https://github.com/rust-lang/rfcs/pull/2992
256        //
257        // Instead, this is based on the current defaults at the time of this writing:
258        // https://github.com/rust-lang/rust/blob/50d2c3abd59af8cbed7e001b5b4e2f6a9a011112/src/librustc_target/abi/call/powerpc64.rs#L122
259
260        #[cfg(any(
261            // ELFv1 is the used for powerpc64 when not targeting musl
262            all(target_arch = "powerpc64", target_endian="big", not(target_env = "musl")),
263            // Use empty flags when targeting a non-PowerPC target, too, just so code compiles.
264            not(target_arch = "powerpc64")
265        ))]
266        mod elf {
267            pub use super::elfv1::*;
268        }
269
270        // ELFv2 is used for Little-Endian powerpc64 and with musl
271        #[cfg(any(
272            all(target_arch = "powerpc64", target_endian = "big", target_env = "musl"),
273            all(target_arch = "powerpc64", target_endian = "little")
274        ))]
275        mod elf {
276            pub use super::elfv2::*;
277        }
278
279        pub use elf::FFI_TRAMPOLINE_SIZE;
280
281        mod long_double_64 {
282            pub const LONG_DOUBLE_128_FLAG: crate::ffi_abi = 0b0;
283        }
284
285        mod long_double_128 {
286            pub const LONG_DOUBLE_128_FLAG: crate::ffi_abi =
287                super::ffi_abi_FFI_LINUX_LONG_DOUBLE_128;
288        }
289
290        // IEEE128 is not supported on BSD or when targeting musl:
291        // https://github.com/rust-lang/llvm-project/blob/cb7f903994646c5b9223e0bb6cee3792190991f7/clang/lib/Basic/Targets/PPC.h#L417
292
293        #[cfg(any(target_os = "netbsd", target_os = "freebsd", target_env = "musl"))]
294        use long_double_64::*;
295
296        #[cfg(not(any(target_os = "netbsd", target_os = "freebsd", target_env = "musl")))]
297        use long_double_128::*;
298
299        pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi =
300            ffi_abi_FFI_LINUX | ffi_abi_FFI_LINUX_STRUCT_ALIGN | LONG_DOUBLE_128_FLAG;
301
302        pub const FFI_NATIVE_RAW_API: u32 = 0;
303        pub const FFI_GO_CLOSURES: u32 = 1;
304    }
305}
306
307#[cfg(target_arch = "powerpc")]
308pub use powerpc::powerpc::*;
309
310#[cfg(target_arch = "powerpc64")]
311pub use powerpc::powerpc64::*;
312
313/// From libffi:src/riscv/ffitarget.h
314/// See: <https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/riscv/ffitarget.h#L46>
315mod riscv {
316    use crate::ffi_abi;
317
318    pub const ffi_abi_FFI_FIRST_ABI: ffi_abi = 0;
319    pub const ffi_abi_FFI_SYSV: ffi_abi = 1;
320    pub const ffi_abi_FFI_UNUSED_1: ffi_abi = 2;
321    pub const ffi_abi_FFI_UNUSED_2: ffi_abi = 3;
322    pub const ffi_abi_FFI_UNUSED_3: ffi_abi = 4;
323    pub const ffi_abi_LAST_ABI: ffi_abi = 5;
324    pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi = ffi_abi_FFI_SYSV;
325
326    /// See: <https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/riscv/ffitarget.h#L63>
327    pub const FFI_GO_CLOSURES: u32 = 1;
328    pub const FFI_TRAMPOLINE_SIZE: usize = 24;
329    pub const FFI_NATIVE_RAW_API: u32 = 0;
330}
331
332#[cfg(target_arch = "riscv32")]
333pub use riscv::*;
334
335#[cfg(target_arch = "riscv64")]
336pub use riscv::*;
337
338/// From libffi:src/s390/ffitarget.h
339/// See: <https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/s390/ffitarget.h#L47>
340mod s390x {
341    use crate::ffi_abi;
342
343    pub const ffi_abi_FFI_FIRST_ABI: ffi_abi = 0;
344    pub const ffi_abi_FFI_SYSV: ffi_abi = 1;
345    pub const ffi_abi_LAST_ABI: ffi_abi = 2;
346    pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi = ffi_abi_FFI_SYSV;
347
348    pub const FFI_GO_CLOSURES: u32 = 1;
349    pub const FFI_TRAMPOLINE_SIZE: usize = 32;
350    pub const FFI_NATIVE_RAW_API: u32 = 0;
351}
352
353#[cfg(target_arch = "s390x")]
354pub use s390x::*;
355
356/// From libffi:src/sparc/ffitarget.h
357/// See <https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/sparc/ffitarget.h#L47>
358mod sparcv9 {
359    use crate::ffi_abi;
360
361    pub const ffi_abi_FFI_FIRST_ABI: ffi_abi = 0;
362    pub const ffi_abi_FFI_V9: ffi_abi = 1;
363    pub const ffi_abi_LAST_ABI: ffi_abi = 2;
364    pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi = ffi_abi_FFI_V9;
365
366    pub const FFI_GO_CLOSURES: u32 = 1;
367    pub const FFI_TRAMPOLINE_SIZE: usize = 24;
368    pub const FFI_NATIVE_RAW_API: u32 = 0;
369}
370
371#[cfg(target_arch = "sparc64")]
372pub use sparcv9::*;
373
374/// From libffi:src/loongarch64/ffitarget.h.
375/// See: <https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/loongarch64/ffitarget.h#L47>
376mod loongarch64 {
377    use crate::ffi_abi;
378
379    pub const ffi_abi_FFI_FIRST_ABI: ffi_abi = 0;
380    pub const ffi_abi_FFI_LP64S: ffi_abi = 1;
381    pub const ffi_abi_FFI_LP64F: ffi_abi = 2;
382    pub const ffi_abi_FFI_LP64D: ffi_abi = 3;
383    pub const ffi_abi_FFI_LAST_ABI: ffi_abi = 4;
384    pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi = ffi_abi_FFI_LP64D;
385
386    pub const FFI_GO_CLOSURES: u32 = 1;
387    pub const FFI_TRAMPOLINE_SIZE: usize = 24;
388    pub const FFI_NATIVE_RAW_API: u32 = 0;
389}
390
391#[cfg(target_arch = "loongarch64")]
392pub use loongarch64::*;
393
394/// From libffi:src/mips/ffitarget.h
395/// See: <https://github.com/libffi/libffi/blob/252c0f463641e6100169c3f0a4a590d7df438278/src/mips/ffitarget.h#L201>
396mod mips {
397    mod common {
398        use crate::ffi_abi;
399        pub const ffi_abi_FFI_FIRST_ABI: ffi_abi = 0;
400        pub const ffi_abi_FFI_O32: ffi_abi = 1;
401        pub const ffi_abi_FFI_N32: ffi_abi = 2;
402        pub const ffi_abi_FFI_N64: ffi_abi = 3;
403        pub const ffi_abi_FFI_O32_SOFT_FLOAT: ffi_abi = 4;
404        pub const ffi_abi_FFI_N32_SOFT_FLOAT: ffi_abi = 5;
405        pub const ffi_abi_FFI_N64_SOFT_FLOAT: ffi_abi = 6;
406        pub const ffi_abi_FFI_LAST_ABI: ffi_abi = 7;
407
408        pub const FFI_CLOSURES: u32 = 1;
409        pub const FFI_GO_CLOSURES: u32 = 1;
410        pub const FFI_NATIVE_RAW_ABI: u32 = 0;
411    }
412
413    pub mod mips {
414        use crate::ffi_abi;
415
416        pub use super::common::*;
417
418        pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi = ffi_abi_FFI_O32;
419
420        pub const FFI_TRAMPOLINE_SIZE: usize = 20;
421    }
422
423    pub mod mips64 {
424        use crate::ffi_abi;
425
426        pub use super::common::*;
427
428        pub const ffi_abi_FFI_DEFAULT_ABI: ffi_abi = ffi_abi_FFI_N64;
429
430        pub const FFI_TRAMPOLINE_SIZE: usize = 56;
431    }
432}
433
434#[cfg(any(target_arch = "mips", target_arch = "mips32r6"))]
435pub use mips::mips::*;
436
437#[cfg(any(target_arch = "mips64", target_arch = "mips64r6"))]
438pub use mips::mips64::*;
439
440#[cfg(all(test, feature = "std"))]
441mod test {
442    use core::ffi::c_uint;
443
444    use super::*;
445
446    // `ffi_get_default_abi` was added in libffi v3.5.0. This test cannot be
447    // executed without the function, so it is disabled when performing dynamic
448    // linking to libffi until version 3.5.0. is required for dynamic linking by
449    // libffi-rs.
450    #[cfg(not(feature = "system"))]
451    #[test]
452    fn verify_default_abi() {
453        extern "C" {
454            fn ffi_get_default_abi() -> c_uint;
455        }
456
457        unsafe { assert_eq!(ffi_abi_FFI_DEFAULT_ABI, ffi_get_default_abi()) }
458    }
459}