portable_atomic/gen/
utils.rs

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")))]
48macro_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")))]
86macro_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]
115mod 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]
142mod 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}