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 load/store/atomic 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/2023Q1/aapcs64/aapcs64.rst#57pointers
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 = "bpf",
34 target_arch = "loongarch64",
35 target_arch = "mips64",
36 target_arch = "mips64r6",
37 target_arch = "nvptx64",
38 target_arch = "powerpc64",
39 target_arch = "riscv64",
40 target_arch = "s390x",
41 target_arch = "sparc64",
42 target_arch = "wasm64",
43 target_arch = "x86_64",
44 ),
45))]
46macro_rules! ptr_reg {
47 ($ptr:ident) => {{
48 let _: *const _ = $ptr; // ensure $ptr is a pointer (*mut _ or *const _)
49 #[cfg(not(portable_atomic_no_asm_maybe_uninit))]
50 #[allow(clippy::ptr_as_ptr)]
51 {
52 // If we cast to u64 here, the provenance will be lost,
53 // so we convert to MaybeUninit<u64> via zero extend helper.
54 crate::utils::zero_extend64_ptr($ptr as *mut ())
55 }
56 #[cfg(portable_atomic_no_asm_maybe_uninit)]
57 {
58 // Use cast on old rustc because it does not support MaybeUninit
59 // registers. This is still permissive-provenance compatible and
60 // is sound.
61 $ptr as u64
62 }
63 }};
64}
65#[cfg(not(all(
66 target_pointer_width = "32",
67 any(
68 target_arch = "aarch64",
69 target_arch = "bpf",
70 target_arch = "loongarch64",
71 target_arch = "mips64",
72 target_arch = "mips64r6",
73 target_arch = "nvptx64",
74 target_arch = "powerpc64",
75 target_arch = "riscv64",
76 target_arch = "s390x",
77 target_arch = "sparc64",
78 target_arch = "wasm64",
79 target_arch = "x86_64",
80 ),
81)))]
82macro_rules! ptr_reg {
83 ($ptr:ident) => {{
84 let _: *const _ = $ptr; // ensure $ptr is a pointer (*mut _ or *const _)
85 $ptr // cast is unnecessary here.
86 }};
87}
88
89// Some 64-bit architectures have ABI with 32-bit pointer width (e.g., x86_64 X32 ABI,
90// AArch64 ILP32 ABI, MIPS64 N32 ABI). On those targets, AtomicU64 is available
91// and fast, so use it to implement normal sequence lock.
92//
93// See ptr_reg macro for the reason why all known 64-bit architectures are listed.
94#[cfg(feature = "fallback")]
95#[cfg(any(
96 not(any(target_pointer_width = "16", target_pointer_width = "32")), // i.e., 64-bit or greater
97 target_arch = "aarch64",
98 target_arch = "bpf",
99 target_arch = "loongarch64",
100 target_arch = "mips64",
101 target_arch = "mips64r6",
102 target_arch = "nvptx64",
103 target_arch = "powerpc64",
104 target_arch = "riscv64",
105 target_arch = "s390x",
106 target_arch = "sparc64",
107 target_arch = "wasm64",
108 target_arch = "x86_64",
109))]
110#[macro_use]
111mod fast_atomic_64_macros {
112 macro_rules! cfg_has_fast_atomic_64 {
113 ($($tt:tt)*) => {
114 $($tt)*
115 };
116 }
117 macro_rules! cfg_no_fast_atomic_64 {
118 ($($tt:tt)*) => {};
119 }
120}
121#[cfg(feature = "fallback")]
122#[cfg(not(any(
123 not(any(target_pointer_width = "16", target_pointer_width = "32")), // i.e., 64-bit or greater
124 target_arch = "aarch64",
125 target_arch = "bpf",
126 target_arch = "loongarch64",
127 target_arch = "mips64",
128 target_arch = "mips64r6",
129 target_arch = "nvptx64",
130 target_arch = "powerpc64",
131 target_arch = "riscv64",
132 target_arch = "s390x",
133 target_arch = "sparc64",
134 target_arch = "wasm64",
135 target_arch = "x86_64",
136)))]
137#[macro_use]
138mod fast_atomic_64_macros {
139 macro_rules! cfg_has_fast_atomic_64 {
140 ($($tt:tt)*) => {};
141 }
142 macro_rules! cfg_no_fast_atomic_64 {
143 ($($tt:tt)*) => {
144 $($tt)*
145 };
146 }
147}
148