Auto merge of #2894 - RalfJung:simd-ptr, r=RalfJung
implement SIMD ptr casts
This commit is contained in:
commit
7750cd93eb
@ -421,14 +421,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
"cast" | "as" => {
|
"cast" | "as" | "cast_ptr" | "expose_addr" | "from_exposed_addr" => {
|
||||||
let [op] = check_arg_count(args)?;
|
let [op] = check_arg_count(args)?;
|
||||||
let (op, op_len) = this.operand_to_simd(op)?;
|
let (op, op_len) = this.operand_to_simd(op)?;
|
||||||
let (dest, dest_len) = this.place_to_simd(dest)?;
|
let (dest, dest_len) = this.place_to_simd(dest)?;
|
||||||
|
|
||||||
assert_eq!(dest_len, op_len);
|
assert_eq!(dest_len, op_len);
|
||||||
|
|
||||||
|
let unsafe_cast = intrinsic_name == "cast";
|
||||||
let safe_cast = intrinsic_name == "as";
|
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 {
|
for i in 0..dest_len {
|
||||||
let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?;
|
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()) {
|
let val = match (op.layout.ty.kind(), dest.layout.ty.kind()) {
|
||||||
// Int-to-(int|float): always safe
|
// 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)?,
|
this.int_to_int_or_float(&op, dest.layout.ty)?,
|
||||||
// Float-to-float: always safe
|
// 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)?,
|
this.float_to_float_or_int(&op, dest.layout.ty)?,
|
||||||
// Float-to-int in safe mode
|
// Float-to-int in safe mode
|
||||||
(ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast =>
|
(ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast =>
|
||||||
this.float_to_float_or_int(&op, dest.layout.ty)?,
|
this.float_to_float_or_int(&op, dest.layout.ty)?,
|
||||||
// Float-to-int in unchecked mode
|
// 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(),
|
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(),
|
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!(
|
throw_unsup_format!(
|
||||||
"Unsupported SIMD cast from element type {from_ty} to {to_ty}",
|
"Unsupported SIMD cast from element type {from_ty} to {to_ty}",
|
||||||
|
12
src/tools/miri/tests/pass/portable-simd-ptrs.rs
Normal file
12
src/tools/miri/tests/pass/portable-simd-ptrs.rs
Normal file
@ -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);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user