Skip to content

Commit 098f1b4

Browse files
committed
Auto merge of #96946 - WaffleLapkin:ptr_mask, r=scottmcm
Add pointer masking convenience functions This PR adds the following public API: ```rust impl<T: ?Sized> *const T { fn mask(self, mask: usize) -> *const T; } impl<T: ?Sized> *mut T { fn mask(self, mask: usize) -> *const T; } // mod intrinsics fn mask<T>(ptr: *const T, mask: usize) -> *const T ``` This is equivalent to `ptr.map_addr(|a| a & mask)` but also uses a cool llvm intrinsic. Proposed in rust-lang/rust#95643 (comment) cc `@Gankra` `@scottmcm` `@RalfJung` r? rust-lang/libs-api
2 parents ada17f4 + 5e5c59e commit 098f1b4

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

core/src/intrinsics.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,17 @@ extern "rust-intrinsic" {
12871287
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
12881288
pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
12891289

1290+
/// Masks out bits of the pointer according to a mask.
1291+
///
1292+
/// Note that, unlike most intrinsics, this is safe to call;
1293+
/// it does not require an `unsafe` block.
1294+
/// Therefore, implementations must not require the user to uphold
1295+
/// any safety invariants.
1296+
///
1297+
/// Consider using [`pointer::mask`] instead.
1298+
#[cfg(not(bootstrap))]
1299+
pub fn ptr_mask<T>(ptr: *const T, mask: usize) -> *const T;
1300+
12901301
/// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
12911302
/// a size of `count` * `size_of::<T>()` and an alignment of
12921303
/// `min_align_of::<T>()`

core/src/ptr/const_ptr.rs

+15
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,21 @@ impl<T: ?Sized> *const T {
559559
from_raw_parts::<T>(self.cast::<u8>().wrapping_offset(count).cast::<()>(), metadata(self))
560560
}
561561

562+
/// Masks out bits of the pointer according to a mask.
563+
///
564+
/// This is convenience for `ptr.map_addr(|a| a & mask)`.
565+
///
566+
/// For non-`Sized` pointees this operation changes only the data pointer,
567+
/// leaving the metadata untouched.
568+
#[cfg(not(bootstrap))]
569+
#[unstable(feature = "ptr_mask", issue = "98290")]
570+
#[must_use = "returns a new pointer rather than modifying its argument"]
571+
#[inline(always)]
572+
pub fn mask(self, mask: usize) -> *const T {
573+
let this = intrinsics::ptr_mask(self.cast::<()>(), mask);
574+
from_raw_parts::<T>(this, metadata(self))
575+
}
576+
562577
/// Calculates the distance between two pointers. The returned value is in
563578
/// units of T: the distance in bytes divided by `mem::size_of::<T>()`.
564579
///

core/src/ptr/mut_ptr.rs

+15
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,21 @@ impl<T: ?Sized> *mut T {
575575
)
576576
}
577577

578+
/// Masks out bits of the pointer according to a mask.
579+
///
580+
/// This is convenience for `ptr.map_addr(|a| a & mask)`.
581+
///
582+
/// For non-`Sized` pointees this operation changes only the data pointer,
583+
/// leaving the metadata untouched.
584+
#[cfg(not(bootstrap))]
585+
#[unstable(feature = "ptr_mask", issue = "98290")]
586+
#[must_use = "returns a new pointer rather than modifying its argument"]
587+
#[inline(always)]
588+
pub fn mask(self, mask: usize) -> *mut T {
589+
let this = intrinsics::ptr_mask(self.cast::<()>(), mask) as *mut ();
590+
from_raw_parts_mut::<T>(this, metadata(self))
591+
}
592+
578593
/// Returns `None` if the pointer is null, or else returns a unique reference to
579594
/// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_mut`]
580595
/// must be used instead.

0 commit comments

Comments
 (0)