1 | // SPDX-License-Identifier: Apache-2.0 OR MIT |
2 | // This file is @generated by target_spec.sh. |
3 | // It is not intended for manual editing. |
4 | |
5 | #![allow (unused_macros)] |
6 | |
7 | // On AArch64, the base register of memory-related instructions must be 64-bit. |
8 | // Passing a 32-bit value to `in(reg)` on AArch64 results in the upper bits |
9 | // having an undefined value, but to work correctly with ILP32 ABI, the upper |
10 | // bits must be zero, which is handled here by casting to u64. Another way to |
11 | // handle this is to pass it as a pointer and clear the upper bits inside asm, |
12 | // but it is easier to overlook than cast, which can catch overlooks by |
13 | // asm_sub_register lint. |
14 | // See also https://github.com/ARM-software/abi-aa/blob/2024Q3/aapcs64/aapcs64.rst#pointers |
15 | // |
16 | // Except for x86_64, which can use 32-bit registers in the destination operand |
17 | // (on x86_64, we use the ptr_modifier macro to handle this), we need to do the |
18 | // same for ILP32 ABI on other 64-bit architectures. (At least, as far as I can |
19 | // see from the assembly generated by LLVM, this is also required for MIPS64 N32 |
20 | // ABI. I don't know about the RISC-V s64ilp32 ABI for which a patch was |
21 | // recently submitted to the kernel, but in any case, this should be a safe |
22 | // default for such ABIs). |
23 | // |
24 | // Known architectures that have such ABI are x86_64 (X32), AArch64 (ILP32), |
25 | // mips64 (N32), and riscv64 (s64ilp32, not merged yet though). (As of |
26 | // 2023-06-05, only the former two are supported by rustc.) However, we list all |
27 | // known 64-bit architectures because similar ABIs may exist or future added for |
28 | // other architectures. |
29 | #[cfg (all( |
30 | target_pointer_width = "32" , |
31 | any( |
32 | target_arch = "aarch64" , |
33 | target_arch = "arm64ec" , |
34 | target_arch = "bpf" , |
35 | target_arch = "loongarch64" , |
36 | target_arch = "mips64" , |
37 | target_arch = "mips64r6" , |
38 | target_arch = "nvptx64" , |
39 | target_arch = "powerpc64" , |
40 | target_arch = "riscv64" , |
41 | target_arch = "s390x" , |
42 | target_arch = "sparc64" , |
43 | target_arch = "wasm64" , |
44 | target_arch = "x86_64" , |
45 | ), |
46 | ))] |
47 | #[cfg (not(any(target_arch = "x86" , target_arch = "x86_64" )))] |
48 | macro_rules! ptr_reg { |
49 | ($ptr:ident) => {{ |
50 | let _: *const _ = $ptr; // ensure $ptr is a pointer (*mut _ or *const _) |
51 | #[cfg(not(portable_atomic_no_asm_maybe_uninit))] |
52 | #[allow(clippy::ptr_as_ptr)] |
53 | { |
54 | // If we cast to u64 here, the provenance will be lost, |
55 | // so we convert to MaybeUninit<u64> via zero extend helper. |
56 | crate::utils::zero_extend64_ptr($ptr as *mut ()) |
57 | } |
58 | #[cfg(portable_atomic_no_asm_maybe_uninit)] |
59 | { |
60 | // Use cast on old rustc because it does not support MaybeUninit |
61 | // registers. This is still permissive-provenance compatible and |
62 | // is sound. |
63 | $ptr as u64 |
64 | } |
65 | }}; |
66 | } |
67 | #[cfg (not(all( |
68 | target_pointer_width = "32" , |
69 | any( |
70 | target_arch = "aarch64" , |
71 | target_arch = "arm64ec" , |
72 | target_arch = "bpf" , |
73 | target_arch = "loongarch64" , |
74 | target_arch = "mips64" , |
75 | target_arch = "mips64r6" , |
76 | target_arch = "nvptx64" , |
77 | target_arch = "powerpc64" , |
78 | target_arch = "riscv64" , |
79 | target_arch = "s390x" , |
80 | target_arch = "sparc64" , |
81 | target_arch = "wasm64" , |
82 | target_arch = "x86_64" , |
83 | ), |
84 | )))] |
85 | #[cfg (not(any(target_arch = "x86" , target_arch = "x86_64" )))] |
86 | macro_rules! ptr_reg { |
87 | ($ptr:ident) => {{ |
88 | let _: *const _ = $ptr; // ensure $ptr is a pointer (*mut _ or *const _) |
89 | $ptr // cast is unnecessary here. |
90 | }}; |
91 | } |
92 | |
93 | // Some 64-bit architectures have ABI with 32-bit pointer width (e.g., x86_64 X32 ABI, |
94 | // AArch64 ILP32 ABI, MIPS64 N32 ABI). On those targets, AtomicU64 is available |
95 | // and fast, so use it to implement normal sequence lock. |
96 | // |
97 | // See ptr_reg macro for the reason why all known 64-bit architectures are listed. |
98 | #[cfg (any( |
99 | not(any(target_pointer_width = "16" , target_pointer_width = "32" )), // i.e., 64-bit or greater |
100 | target_arch = "aarch64" , |
101 | target_arch = "arm64ec" , |
102 | target_arch = "bpf" , |
103 | target_arch = "loongarch64" , |
104 | target_arch = "mips64" , |
105 | target_arch = "mips64r6" , |
106 | target_arch = "nvptx64" , |
107 | target_arch = "powerpc64" , |
108 | target_arch = "riscv64" , |
109 | target_arch = "s390x" , |
110 | target_arch = "sparc64" , |
111 | target_arch = "wasm64" , |
112 | target_arch = "x86_64" , |
113 | ))] |
114 | #[macro_use ] |
115 | mod fast_atomic_64_macros { |
116 | macro_rules! cfg_has_fast_atomic_64 { |
117 | ($($tt:tt)*) => { |
118 | $($tt)* |
119 | }; |
120 | } |
121 | macro_rules! cfg_no_fast_atomic_64 { |
122 | ($($tt:tt)*) => {}; |
123 | } |
124 | } |
125 | #[cfg (not(any( |
126 | not(any(target_pointer_width = "16" , target_pointer_width = "32" )), // i.e., 64-bit or greater |
127 | target_arch = "aarch64" , |
128 | target_arch = "arm64ec" , |
129 | target_arch = "bpf" , |
130 | target_arch = "loongarch64" , |
131 | target_arch = "mips64" , |
132 | target_arch = "mips64r6" , |
133 | target_arch = "nvptx64" , |
134 | target_arch = "powerpc64" , |
135 | target_arch = "riscv64" , |
136 | target_arch = "s390x" , |
137 | target_arch = "sparc64" , |
138 | target_arch = "wasm64" , |
139 | target_arch = "x86_64" , |
140 | )))] |
141 | #[macro_use ] |
142 | mod fast_atomic_64_macros { |
143 | macro_rules! cfg_has_fast_atomic_64 { |
144 | ($($tt:tt)*) => {}; |
145 | } |
146 | macro_rules! cfg_no_fast_atomic_64 { |
147 | ($($tt:tt)*) => { |
148 | $($tt)* |
149 | }; |
150 | } |
151 | } |
152 | |