]> git.lizzy.rs Git - rust.git/commitdiff
Implement `ptr_mask` intrinsic
authorMaybe Waffle <waffle.lapkin@gmail.com>
Thu, 27 Oct 2022 18:23:58 +0000 (22:23 +0400)
committerMaybe Waffle <waffle.lapkin@gmail.com>
Thu, 27 Oct 2022 19:47:50 +0000 (23:47 +0400)
src/tools/miri/src/shims/intrinsics/mod.rs
src/tools/miri/tests/pass/shims/ptr_mask.rs [new file with mode: 0644]

index e0985ace5be7da3d8c2f0c3c3f0933013845cc76..6004e2078ad4fb6edf21e811f8c12daf25a8e1b4 100644 (file)
@@ -11,7 +11,7 @@
     mir,
     ty::{self, FloatTy, Ty},
 };
-use rustc_target::abi::Integer;
+use rustc_target::abi::{Integer, Size};
 
 use crate::*;
 use atomic::EvalContextExt as _;
@@ -120,6 +120,17 @@ fn emulate_intrinsic_by_name(
                 this.write_bytes_ptr(ptr, iter::repeat(val_byte).take(byte_count.bytes_usize()))?;
             }
 
+            "ptr_mask" => {
+                let [ptr, mask] = check_arg_count(args)?;
+
+                let ptr = this.read_pointer(ptr)?;
+                let mask = this.read_scalar(mask)?.to_machine_usize(this)?;
+
+                let masked_addr = Size::from_bytes(ptr.addr().bytes() & mask);
+
+                this.write_pointer(Pointer::new(ptr.provenance, masked_addr), dest)?;
+            }
+
             // Floating-point operations
             "fabsf32" => {
                 let [f] = check_arg_count(args)?;
diff --git a/src/tools/miri/tests/pass/shims/ptr_mask.rs b/src/tools/miri/tests/pass/shims/ptr_mask.rs
new file mode 100644 (file)
index 0000000..fb8bb6b
--- /dev/null
@@ -0,0 +1,18 @@
+#![feature(ptr_mask)]
+#![feature(strict_provenance)]
+
+fn main() {
+    let v: u32 = 0xABCDABCD;
+    let ptr: *const u32 = &v;
+
+    // u32 is 4 aligned,
+    // so the lower `log2(4) = 2` bits of the address are always 0
+    assert_eq!(ptr.addr() & 0b11, 0);
+
+    let tagged_ptr = ptr.map_addr(|a| a | 0b11);
+    let tag = tagged_ptr.addr() & 0b11;
+    let masked_ptr = tagged_ptr.mask(!0b11);
+
+    assert_eq!(tag, 0b11);
+    assert_eq!(unsafe { *masked_ptr }, 0xABCDABCD);
+}