]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #1875 - niluxv:volatile_set_memory_intrinsic, r=RalfJung
authorbors <bors@rust-lang.org>
Mon, 23 Aug 2021 10:55:48 +0000 (10:55 +0000)
committerbors <bors@rust-lang.org>
Mon, 23 Aug 2021 10:55:48 +0000 (10:55 +0000)
Add support for the `volatile_set_memory` intrinsic

Add support for the unstable `volatile_set_memory` intrinsic

(Runtime behaviour and soundness requirements for `volatile_set_memory` are identical to those of `write_bytes`, so supporting this intrinsic is trivial.)

src/shims/intrinsics.rs
tests/run-pass/write-bytes.rs

index 5a3a782382dd5253e918c39af901bc4916e9d809..317bba859295884c8cf9d05d969b6a52213d4676 100644 (file)
@@ -66,7 +66,7 @@ fn call_intrinsic(
                 this.copy_op(dest, &place.into())?;
             }
 
-            "write_bytes" => {
+            "write_bytes" | "volatile_set_memory" => {
                 let &[ref ptr, ref val_byte, ref count] = check_arg_count(args)?;
                 let ty = instance.substs.type_at(0);
                 let ty_layout = this.layout_of(ty)?;
@@ -74,7 +74,7 @@ fn call_intrinsic(
                 let ptr = this.read_pointer(ptr)?;
                 let count = this.read_scalar(count)?.to_machine_usize(this)?;
                 let byte_count = ty_layout.size.checked_mul(count, this).ok_or_else(|| {
-                    err_ub_format!("overflow computing total size of `write_bytes`")
+                    err_ub_format!("overflow computing total size of `{}`", intrinsic_name)
                 })?;
                 this.memory
                     .write_bytes(ptr, iter::repeat(val_byte).take(byte_count.bytes() as usize))?;
index 7c9a38fca696dd3e9401c355cb79b5ad00233cc4..b2050c5393e221f2e3874c0828c12fcd7f6650f7 100644 (file)
@@ -1,3 +1,5 @@
+#![feature(core_intrinsics)] // for `volatile_set_memory`
+
 #[repr(C)]
 #[derive(Copy, Clone)]
 struct Foo {
@@ -42,4 +44,42 @@ fn main() {
         assert_eq!(w[idx].b, 0xcdcdcdcdcdcdcdcd);
         assert_eq!(w[idx].c, 0xcdcdcdcdcdcdcdcd);
     }
+
+    // -----
+    // `std::intrinsics::volatile_set_memory` should behave identically
+
+    let mut v: [u64; LENGTH] = [0; LENGTH];
+
+    for idx in 0..LENGTH {
+        assert_eq!(v[idx], 0);
+    }
+
+    unsafe {
+        let p = v.as_mut_ptr();
+        ::std::intrinsics::volatile_set_memory(p, 0xab, LENGTH);
+    }
+
+    for idx in 0..LENGTH {
+        assert_eq!(v[idx], 0xabababababababab);
+    }
+
+    // -----
+
+    let mut w: [Foo; LENGTH] = [Foo { a: 0, b: 0, c: 0 }; LENGTH];
+    for idx in 0..LENGTH {
+        assert_eq!(w[idx].a, 0);
+        assert_eq!(w[idx].b, 0);
+        assert_eq!(w[idx].c, 0);
+    }
+
+    unsafe {
+        let p = w.as_mut_ptr();
+        ::std::intrinsics::volatile_set_memory(p, 0xcd, LENGTH);
+    }
+
+    for idx in 0..LENGTH {
+        assert_eq!(w[idx].a, 0xcdcdcdcdcdcdcdcd);
+        assert_eq!(w[idx].b, 0xcdcdcdcdcdcdcdcd);
+        assert_eq!(w[idx].c, 0xcdcdcdcdcdcdcdcd);
+    }
 }