diff options
| author | bors <bors@rust-lang.org> | 2022-08-28 01:34:47 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-08-28 01:34:47 +0000 |
| commit | 1e978a3627bd65064164af3548c585fb25eef9d2 (patch) | |
| tree | d36b93e40e37cd26a0f15a200435c511ed21c0bd /library | |
| parent | eaadb8947b850a025404082f6297766c4680a42a (diff) | |
| parent | ca753124088c0d57ca6728ee093363cbc1db5274 (diff) | |
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 https://github.com/rust-lang/rust/pull/95643#issuecomment-1121562352
cc `@Gankra` `@scottmcm` `@RalfJung`
r? rust-lang/libs-api
Diffstat (limited to 'library')
| -rw-r--r-- | library/core/src/intrinsics.rs | 11 | ||||
| -rw-r--r-- | library/core/src/ptr/const_ptr.rs | 15 | ||||
| -rw-r--r-- | library/core/src/ptr/mut_ptr.rs | 15 |
3 files changed, 41 insertions, 0 deletions
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 50ee97e980c..5f8e6efa0cf 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1287,6 +1287,17 @@ extern "rust-intrinsic" { #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T; + /// Masks out bits of the pointer according to a mask. + /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// + /// Consider using [`pointer::mask`] instead. + #[cfg(not(bootstrap))] + pub fn ptr_mask<T>(ptr: *const T, mask: usize) -> *const T; + /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with /// a size of `count` * `size_of::<T>()` and an alignment of /// `min_align_of::<T>()` diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index b8486af0018..3f3eb3b3c5c 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -559,6 +559,21 @@ impl<T: ?Sized> *const T { from_raw_parts::<T>(self.cast::<u8>().wrapping_offset(count).cast::<()>(), metadata(self)) } + /// Masks out bits of the pointer according to a mask. + /// + /// This is convenience for `ptr.map_addr(|a| a & mask)`. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[cfg(not(bootstrap))] + #[unstable(feature = "ptr_mask", issue = "98290")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[inline(always)] + pub fn mask(self, mask: usize) -> *const T { + let this = intrinsics::ptr_mask(self.cast::<()>(), mask); + from_raw_parts::<T>(this, metadata(self)) + } + /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes divided by `mem::size_of::<T>()`. /// diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index a1836140559..03ee879f7da 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -575,6 +575,21 @@ impl<T: ?Sized> *mut T { ) } + /// Masks out bits of the pointer according to a mask. + /// + /// This is convenience for `ptr.map_addr(|a| a & mask)`. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[cfg(not(bootstrap))] + #[unstable(feature = "ptr_mask", issue = "98290")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[inline(always)] + pub fn mask(self, mask: usize) -> *mut T { + let this = intrinsics::ptr_mask(self.cast::<()>(), mask) as *mut (); + from_raw_parts_mut::<T>(this, metadata(self)) + } + /// Returns `None` if the pointer is null, or else returns a unique reference to /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_mut`] /// must be used instead. |
