about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-09-06 21:49:16 +0200
committerLukas Wirth <lukastw97@gmail.com>2023-09-06 21:49:16 +0200
commitf13b184eb3ab0e9ec59c1671b2cfb027d8745ef0 (patch)
tree7e4cc92ca86e4ec996f2fd700ef01b794c8ce12d
parentf29867bd26ec0ed34a8c26cd39fc02df657a13f8 (diff)
downloadrust-f13b184eb3ab0e9ec59c1671b2cfb027d8745ef0.tar.gz
rust-f13b184eb3ab0e9ec59c1671b2cfb027d8745ef0.zip
Implement `write_via_move` intrinsic for mir-eval
-rw-r--r--crates/hir-ty/src/consteval/tests/intrinsics.rs18
-rw-r--r--crates/hir-ty/src/mir/eval/shim.rs16
2 files changed, 34 insertions, 0 deletions
diff --git a/crates/hir-ty/src/consteval/tests/intrinsics.rs b/crates/hir-ty/src/consteval/tests/intrinsics.rs
index cc3a43fd9ae..44a4ac27af0 100644
--- a/crates/hir-ty/src/consteval/tests/intrinsics.rs
+++ b/crates/hir-ty/src/consteval/tests/intrinsics.rs
@@ -587,6 +587,24 @@ fn write_bytes() {
 }
 
 #[test]
+fn write_via_move() {
+    check_number(
+        r#"
+        extern "rust-intrinsic" {
+            fn write_via_move<T>(ptr: *mut T, value: T);
+        }
+
+        const GOAL: i32 = unsafe {
+            let mut x = 2;
+            write_via_move(&mut x, 100);
+            x
+        };
+        "#,
+        100,
+    );
+}
+
+#[test]
 fn copy() {
     check_number(
         r#"
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index 18396638940..803ef631f1e 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -1200,6 +1200,22 @@ impl Evaluator<'_> {
                 let addr = Address::from_bytes(arg.interval.get(self)?)?;
                 destination.write_from_interval(self, Interval { addr, size: destination.size })
             }
+            "write_via_move" => {
+                let [ptr, val] = args else {
+                    return Err(MirEvalError::TypeError("write_via_move args are not provided"));
+                };
+                let dst = Address::from_bytes(ptr.get(self)?)?;
+                let Some(ty) =
+                    generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
+                else {
+                    return Err(MirEvalError::TypeError(
+                        "write_via_copy generic arg is not provided",
+                    ));
+                };
+                let size = self.size_of_sized(ty, locals, "write_via_move ptr type")?;
+                Interval { addr: dst, size }.write_from_interval(self, val.interval)?;
+                Ok(())
+            }
             "write_bytes" => {
                 let [dst, val, count] = args else {
                     return Err(MirEvalError::TypeError("write_bytes args are not provided"));