diff options
| -rw-r--r-- | src/tools/miri/src/shims/intrinsics/simd.rs | 26 | ||||
| -rw-r--r-- | src/tools/miri/tests/pass/portable-simd-ptrs.rs | 12 |
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); +} |
