Skip to content

Commit 91238bc

Browse files
committed
Add TBI helpers for AArch64
Adds a trait to `core_arch` for AArch64 to set a value in the top byte of a pointer (which should logically become the canonical address of the allocation), and to retrieve the value stored in the top byte of a pointer, if any.
1 parent fb90dfa commit 91238bc

File tree

3 files changed

+101
-1
lines changed

3 files changed

+101
-1
lines changed

crates/core_arch/src/aarch64/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
//! [arm_ref]: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0073a/IHI0073A_arm_neon_intrinsics_ref.pdf
77
//! [arm_dat]: https://developer.arm.com/technologies/neon/intrinsics
88
9+
mod tbi;
10+
#[unstable(feature = "stdarch_aarch64_tbi", issue = "none")]
11+
pub use self::tbi::*;
12+
913
// NEON intrinsics are currently broken on big-endian, so don't expose them. (#1484)
1014
#[cfg(target_endian = "little")]
1115
mod neon;

crates/core_arch/src/aarch64/tbi.rs

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/// Provides additional methods on pointers to get and set any values set in the top byte of the pointer,
2+
/// as per AArch64's Top-Byte Ignore (TBI) feature.
3+
#[unstable(feature = "stdarch_aarch64_tbi", issue = "none")]
4+
pub trait TBIPointer: Sized {
5+
/// Returns a new pointer with the top byte set to a given value, invalidating the original pointer.
6+
///
7+
/// Continuing to use the pointer passed in to this function is Undefined Behavior; you should replace it with the returned pointer instead.
8+
#[unstable(feature = "stdarch_aarch64_tbi", issue = "none")]
9+
fn with_top_byte(self, b: u8) -> Self;
10+
11+
/// Returns the value (if any) stored in the top byte of the pointer.
12+
#[unstable(feature = "stdarch_aarch64_tbi", issue = "none")]
13+
fn top_byte(&self) -> u8;
14+
}
15+
16+
macro_rules! tbi_ptr_impl {
17+
() => {
18+
fn with_top_byte(self, b: u8) -> Self {
19+
// We can't actually call `realloc` here as we don't have `std`, and the pointer may not be valid for `realloc` anyway (if the value's stored on the stack, for example).
20+
let addr = self.addr() & 0x00ffffffffffffff;
21+
let p = addr | ((b as usize) << 56);
22+
self.with_addr(p)
23+
}
24+
25+
fn top_byte(&self) -> u8 {
26+
(self.addr() >> 56) as u8
27+
}
28+
};
29+
}
30+
31+
#[unstable(feature = "stdarch_aarch64_tbi", issue = "none")]
32+
impl<T> TBIPointer for *const T {
33+
tbi_ptr_impl!();
34+
}
35+
36+
#[unstable(feature = "stdarch_aarch64_tbi", issue = "none")]
37+
impl<T> TBIPointer for *mut T {
38+
tbi_ptr_impl!();
39+
}
40+
41+
#[unstable(feature = "stdarch_aarch64_tbi", issue = "none")]
42+
impl<T> TBIPointer for *const [T] {
43+
tbi_ptr_impl!();
44+
}
45+
46+
#[unstable(feature = "stdarch_aarch64_tbi", issue = "none")]
47+
impl<T> TBIPointer for *mut [T] {
48+
tbi_ptr_impl!();
49+
}
50+
51+
#[cfg(test)]
52+
mod test {
53+
use super::*;
54+
55+
#[test]
56+
fn tbi_const() {
57+
let value: u32 = 10;
58+
let mut address = &value as *const u32;
59+
address = address.with_top_byte(0x80);
60+
assert_eq!(address.top_byte(), 0x80);
61+
assert_eq!(unsafe { *address }, 10);
62+
}
63+
64+
#[test]
65+
fn tbi_mut() {
66+
let mut value: u32 = 10;
67+
let mut address = &mut value as *mut u32;
68+
address = address.with_top_byte(0x80);
69+
assert_eq!(address.top_byte(), 0x80);
70+
assert_eq!(unsafe { *address }, 10);
71+
unsafe { *address = 255 };
72+
assert_eq!(unsafe { *address }, 255);
73+
}
74+
75+
#[test]
76+
fn tbi_const_array() {
77+
let value: [u32; 4] = [10, 255, 65535, 0xffffffff];
78+
let mut address = &value as *const [u32; 4];
79+
address = address.with_top_byte(0x80);
80+
assert_eq!(address.top_byte(), 0x80);
81+
assert_eq!(unsafe { *address }, [10, 255, 65535, 0xffffffff]);
82+
}
83+
84+
#[test]
85+
fn tbi_mut_array() {
86+
let mut value: [u32; 4] = [10, 255, 65535, 0xffffffff];
87+
let mut address = &mut value as *mut [u32; 4];
88+
address = address.with_top_byte(0x80);
89+
assert_eq!(address.top_byte(), 0x80);
90+
assert_eq!(unsafe { *address }, [10, 255, 65535, 0xffffffff]);
91+
unsafe { (*address)[0] = 25 };
92+
assert_eq!(unsafe { *address }, [25, 255, 65535, 0xffffffff]);
93+
}
94+
}

crates/core_arch/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
generic_arg_infer,
3636
asm_experimental_arch,
3737
sha512_sm_x86,
38-
f16
38+
f16,
39+
ptr_metadata,
40+
strict_provenance
3941
)]
4042
#![cfg_attr(test, feature(test, abi_vectorcall, stdarch_internal))]
4143
#![deny(clippy::missing_inline_in_public_items)]

0 commit comments

Comments
 (0)