Skip to content

Commit

Permalink
Add zero_extend64_ptr helper
Browse files Browse the repository at this point in the history
For 64-bit architecture's 32-bit ABI (e.g., AArch64 ILP32 ABI).
  • Loading branch information
taiki-e committed Sep 27, 2023
1 parent 8681e27 commit 29831ca
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 2 deletions.
4 changes: 4 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ fn main() {
if !version.probe(64, 2022, 7, 18) {
println!("cargo:rustc-cfg=portable_atomic_no_stronger_failure_ordering");
}
// https://github.com/rust-lang/rust/pull/114790 merged in nightly-2023-08-24
if !version.probe(74, 2023, 8, 23) {
println!("cargo:rustc-cfg=portable_atomic_no_asm_maybe_uninit");
}

// asm stabilized in Rust 1.59 (nightly-2021-12-16): https://github.com/rust-lang/rust/pull/91728
let no_asm = !version.probe(59, 2021, 12, 15);
Expand Down
15 changes: 14 additions & 1 deletion src/gen/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,20 @@
macro_rules! ptr_reg {
($ptr:ident) => {{
let _: *const _ = $ptr; // ensure $ptr is a pointer (*mut _ or *const _)
$ptr as u64
#[cfg(not(portable_atomic_no_asm_maybe_uninit))]
#[allow(clippy::ptr_as_ptr)]
{
// If we cast to u64 here, the provenance will be lost,
// so we convert to MaybeUninit<u64> via zero extend helper.
crate::utils::zero_extend64_ptr($ptr as *mut ())
}
#[cfg(portable_atomic_no_asm_maybe_uninit)]
{
// Use cast on old rustc because it does not support MaybeUninit
// registers. This is still permissive-provenance compatible and
// is sound.
$ptr as u64
}
}};
}
#[cfg(not(all(
Expand Down
31 changes: 31 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ mod gen;

use core::sync::atomic::Ordering;

#[cfg(not(portable_atomic_no_asm_maybe_uninit))]
#[cfg(target_pointer_width = "32")]
use core::mem::{self, MaybeUninit};

macro_rules! static_assert {
($cond:expr $(,)?) => {{
let [] = [(); true as usize - $crate::utils::_assert_is_bool($cond) as usize];
Expand Down Expand Up @@ -751,6 +755,33 @@ pub(crate) fn upgrade_success_ordering(success: Ordering, failure: Ordering) ->
}
}

/// Zero-extends the given 32-bit pointer to `MaybeUninit<u64>`.
/// This is used for 64-bit architecture's 32-bit ABI (e.g., AArch64 ILP32 ABI).
/// See ptr_reg! macro in src/gen/utils.rs for details.
#[cfg(not(portable_atomic_no_asm_maybe_uninit))]
#[cfg(target_pointer_width = "32")]
#[allow(dead_code)]
#[inline]
pub(crate) fn zero_extend64_ptr(v: *mut ()) -> MaybeUninit<u64> {
// SAFETY: we can safely transmute any 64-bit value to MaybeUninit<u64>.
unsafe {
mem::transmute(ZeroExtended::<*mut (), 1> {
v: MaybeUninit::new(v),
pad: [core::ptr::null_mut(); 1],
})
}
}
#[cfg(not(portable_atomic_no_asm_maybe_uninit))]
#[cfg(target_pointer_width = "32")]
#[repr(C)]
struct ZeroExtended<T, const N: usize> {
#[cfg(target_endian = "big")]
pad: [T; N],
v: MaybeUninit<T>,
#[cfg(target_endian = "little")]
pad: [T; N],
}

#[allow(dead_code)]
#[cfg(any(
target_arch = "aarch64",
Expand Down
15 changes: 14 additions & 1 deletion tools/target_spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,20 @@ $(sed <<<"${known_64_bit_arch[*]}" -E 's/^/ target_arch = "/g; s/$/",/g')
macro_rules! ptr_reg {
(\$ptr:ident) => {{
let _: *const _ = \$ptr; // ensure \$ptr is a pointer (*mut _ or *const _)
\$ptr as u64
#[cfg(not(portable_atomic_no_asm_maybe_uninit))]
#[allow(clippy::ptr_as_ptr)]
{
// If we cast to u64 here, the provenance will be lost,
// so we convert to MaybeUninit<u64> via zero extend helper.
crate::utils::zero_extend64_ptr(\$ptr as *mut ())
}
#[cfg(portable_atomic_no_asm_maybe_uninit)]
{
// Use cast on old rustc because it does not support MaybeUninit
// registers. This is still permissive-provenance compatible and
// is sound.
\$ptr as u64
}
}};
}
#[cfg(not(all(
Expand Down

0 comments on commit 29831ca

Please sign in to comment.