Auto merge of #96946 - WaffleLapkin:ptr_mask, r=scottmcm · rust-lang/rust@1e978a3 (original) (raw)

File tree

10 files changed

lines changed

10 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -577,6 +577,13 @@ fn codegen_regular_intrinsic_call<'tcx>(
577 577 ret.write_cvalue(fx, CValue::by_val(res, base.layout()));
578 578 }
579 579
580 + sym::ptr_mask => {
581 +intrinsic_args!(fx, args => (ptr, mask); intrinsic);
582 +let ptr = ptr.load_scalar(fx);
583 +let mask = mask.load_scalar(fx);
584 + fx.bcx.ins().band(ptr, mask);
585 +}
586 +
580 587 sym::transmute => {
581 588 intrinsic_args!(fx, args => (from); intrinsic);
582 589
Original file line number Diff line number Diff line change
@@ -309,6 +309,18 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
309 309 return;
310 310 }
311 311
312 + sym::ptr_mask => {
313 +let usize_type = self.context.new_type::<usize>();
314 +let void_ptr_type = self.context.new_type::<*const ()>();
315 +
316 +let ptr = args[0].immediate();
317 +let mask = args[1].immediate();
318 +
319 +let addr = self.bitcast(ptr, usize_type);
320 +let masked = self.and(addr, mask);
321 +self.bitcast(masked, void_ptr_type)
322 +},
323 +
312 324 _ if name_str.starts_with("simd_") => {
313 325 match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
314 326 Ok(llval) => llval,
Original file line number Diff line number Diff line change
@@ -886,6 +886,9 @@ impl<'ll> CodegenCx<'ll, '_> {
886 886 ifn!("llvm.dbg.declare", fn(t_metadata, t_metadata) -> void);
887 887 ifn!("llvm.dbg.value", fn(t_metadata, t_i64, t_metadata) -> void);
888 888 }
889 +
890 +ifn!("llvm.ptrmask", fn(i8p, t_isize) -> i8p);
891 +
889 892 None
890 893 }
891 894
Original file line number Diff line number Diff line change
@@ -71,6 +71,7 @@ fn get_simple_intrinsic<'ll>(
71 71 sym::nearbyintf64 => "llvm.nearbyint.f64",
72 72 sym::roundf32 => "llvm.round.f32",
73 73 sym::roundf64 => "llvm.round.f64",
74 + sym::ptr_mask => "llvm.ptrmask",
74 75 _ => return None,
75 76 };
76 77 Some(cx.get_intrinsic(llvm_name))
Original file line number Diff line number Diff line change
@@ -1114,6 +1114,7 @@ symbols! {
1114 1114 ptr,
1115 1115 ptr_guaranteed_eq,
1116 1116 ptr_guaranteed_ne,
1117 + ptr_mask,
1117 1118 ptr_null,
1118 1119 ptr_null_mut,
1119 1120 ptr_offset_from,
Original file line number Diff line number Diff line change
@@ -105,7 +105,8 @@ pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
105 105 | sym::type_name
106 106 | sym::forget
107 107 | sym::black_box
108 - | sym::variant_count => hir::Unsafety::Normal,
108 + | sym::variant_count
109 + | sym::ptr_mask => hir::Unsafety::Normal,
109 110 _ => hir::Unsafety::Unsafe,
110 111 }
111 112 }
@@ -203,6 +204,15 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
203 204 ],
204 205 tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
205 206 ),
207 + sym::ptr_mask => (
208 +1,
209 +vec![
210 + tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
211 + tcx.types.usize,
212 +],
213 + tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
214 +),
215 +
206 216 sym::copy | sym::copy_nonoverlapping => (
207 217 1,
208 218 vec![
Original file line number Diff line number Diff line change
@@ -1287,6 +1287,17 @@ extern "rust-intrinsic" {
1287 1287 #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
1288 1288 pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
1289 1289
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 +
1290 1301 /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
1291 1302 /// a size of `count` * `size_of::()` and an alignment of
1292 1303 /// `min_align_of::()`
Original file line number Diff line number Diff line change
@@ -559,6 +559,21 @@ impl<T: ?Sized> *const T {
559 559 from_raw_parts::<T>(self.cast::<u8>().wrapping_offset(count).cast::<()>(), metadata(self))
560 560 }
561 561
562 +/// Masks out bits of the pointer according to a mask.
563 + ///
564 + /// This is convenience for `ptr.map_addr(|a
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 +
562 577 /// Calculates the distance between two pointers. The returned value is in
563 578 /// units of T: the distance in bytes divided by `mem::size_of::()`.
564 579 ///
Original file line number Diff line number Diff line change
@@ -575,6 +575,21 @@ impl<T: ?Sized> *mut T {
575 575 )
576 576 }
577 577
578 +/// Masks out bits of the pointer according to a mask.
579 + ///
580 + /// This is convenience for `ptr.map_addr(|a
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 +
578 593 /// Returns `None` if the pointer is null, or else returns a unique reference to
579 594 /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_mut`]
580 595 /// must be used instead.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
1 +#![crate_type = "lib"]
2 +#![feature(core_intrinsics)]
3 +
4 +// CHECK-LABEL: @mask_ptr
5 +// CHECK-SAME: [[WORD:i[0-9]+]] %mask
6 +#[no_mangle]
7 +pub fn mask_ptr(ptr: *const u16, mask: usize) -> *const u16 {
8 +// CHECK: call
9 +// CHECK-SAME: @llvm.ptrmask.{{p0|p0i8}}.[[WORD]]({{ptr
10 + core::intrinsics::ptr_mask(ptr, mask)
11 +}