about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/miri/src/shims/intrinsics/simd.rs26
-rw-r--r--src/tools/miri/tests/pass/portable-simd-ptrs.rs12
2 files changed, 33 insertions, 5 deletions
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index d101f8d3111..114c66253f7 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -421,14 +421,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 }
             }
             #[rustfmt::skip]
-            "cast" | "as" => {
+            "cast" | "as" | "cast_ptr" | "expose_addr" | "from_exposed_addr" => {
                 let [op] = check_arg_count(args)?;
                 let (op, op_len) = this.operand_to_simd(op)?;
                 let (dest, dest_len) = this.place_to_simd(dest)?;
 
                 assert_eq!(dest_len, op_len);
 
+                let unsafe_cast = intrinsic_name == "cast";
                 let safe_cast = intrinsic_name == "as";
+                let ptr_cast = intrinsic_name == "cast_ptr";
+                let expose_cast = intrinsic_name == "expose_addr";
+                let from_exposed_cast = intrinsic_name == "from_exposed_addr";
 
                 for i in 0..dest_len {
                     let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?;
@@ -436,19 +440,31 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
                     let val = match (op.layout.ty.kind(), dest.layout.ty.kind()) {
                         // Int-to-(int|float): always safe
-                        (ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) =>
+                        (ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) if safe_cast || unsafe_cast =>
                             this.int_to_int_or_float(&op, dest.layout.ty)?,
                         // Float-to-float: always safe
-                        (ty::Float(_), ty::Float(_)) =>
+                        (ty::Float(_), ty::Float(_)) if safe_cast || unsafe_cast =>
                             this.float_to_float_or_int(&op, dest.layout.ty)?,
                         // Float-to-int in safe mode
                         (ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast =>
                             this.float_to_float_or_int(&op, dest.layout.ty)?,
                         // Float-to-int in unchecked mode
-                        (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if !safe_cast =>
+                        (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast =>
                             this.float_to_int_unchecked(op.to_scalar().to_f32()?, dest.layout.ty)?.into(),
-                        (ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if !safe_cast =>
+                        (ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast =>
                             this.float_to_int_unchecked(op.to_scalar().to_f64()?, dest.layout.ty)?.into(),
+                        // Ptr-to-ptr cast
+                        (ty::RawPtr(..), ty::RawPtr(..)) if ptr_cast => {
+                            this.ptr_to_ptr(&op, dest.layout.ty)?
+                        }
+                        // Ptr/Int casts
+                        (ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast => {
+                            this.pointer_expose_address_cast(&op, dest.layout.ty)?
+                        }
+                        (ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast => {
+                            this.pointer_from_exposed_address_cast(&op, dest.layout.ty)?
+                        }
+                        // Error otherwise
                         _ =>
                             throw_unsup_format!(
                                 "Unsupported SIMD cast from element type {from_ty} to {to_ty}",
diff --git a/src/tools/miri/tests/pass/portable-simd-ptrs.rs b/src/tools/miri/tests/pass/portable-simd-ptrs.rs
new file mode 100644
index 00000000000..303c99834f5
--- /dev/null
+++ b/src/tools/miri/tests/pass/portable-simd-ptrs.rs
@@ -0,0 +1,12 @@
+// Separate test without strict provenance
+//@compile-flags: -Zmiri-permissive-provenance
+#![feature(portable_simd, platform_intrinsics)]
+use std::ptr;
+use std::simd::*;
+
+fn main() {
+    // Pointer casts
+    let _val: Simd<*const u8, 4> = Simd::<*const i32, 4>::splat(ptr::null()).cast_ptr();
+    let addrs = Simd::<*const i32, 4>::splat(ptr::null()).expose_addr();
+    let _ptrs = Simd::<*const i32, 4>::from_exposed_addr(addrs);
+}