mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Add const-eval support for SIMD types, insert, and extract
This commit is contained in:
parent
ef906d0e3c
commit
03ac54aed6
@ -239,7 +239,25 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
"transmute" => {
|
||||
self.copy_op_transmute(args[0], dest)?;
|
||||
}
|
||||
|
||||
"simd_insert" => {
|
||||
let mut vector = self.read_vector(args[0])?;
|
||||
let index = self.read_scalar(args[1])?.to_u32()? as usize;
|
||||
let scalar = self.read_immediate(args[2])?;
|
||||
if vector[index].layout.size == scalar.layout.size {
|
||||
vector[index] = scalar;
|
||||
} else {
|
||||
throw_ub_format!(
|
||||
"Inserting `{:?}` with size `{}` to a vector element place of size `{}`",
|
||||
scalar, scalar.layout.size.bytes(), vector[index].layout.size.bytes()
|
||||
);
|
||||
}
|
||||
self.write_vector(vector, dest)?;
|
||||
}
|
||||
"simd_extract" => {
|
||||
let index = self.read_scalar(args[1])?.to_u32()? as _;
|
||||
let scalar = self.read_immediate(self.operand_field(args[0], index)?)?;
|
||||
self.write_immediate(*scalar, dest)?;
|
||||
}
|
||||
_ => return Ok(false),
|
||||
}
|
||||
|
||||
|
@ -335,6 +335,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Read vector from operand `op`
|
||||
pub fn read_vector(&self, op: OpTy<'tcx, M::PointerTag>)
|
||||
-> InterpResult<'tcx, Vec<ImmTy<'tcx, M::PointerTag>>> {
|
||||
if let layout::Abi::Vector { count, .. } = op.layout.abi {
|
||||
assert_ne!(count, 0);
|
||||
let mut scalars = Vec::new();
|
||||
for index in 0..count {
|
||||
scalars.push(self.read_immediate(self.operand_field(op, index as _)?)?);
|
||||
}
|
||||
Ok(scalars)
|
||||
} else {
|
||||
bug!("type is not a vector: {:?}, abi: {:?}", op.layout.ty, op.layout.abi);
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a scalar from a place
|
||||
pub fn read_scalar(
|
||||
&self,
|
||||
|
@ -696,6 +696,40 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Writes the `scalar` to the `index`-th element of the `vector`.
|
||||
pub fn write_scalar_to_vector(
|
||||
&mut self,
|
||||
scalar: ImmTy<'tcx, M::PointerTag>,
|
||||
vector: PlaceTy<'tcx, M::PointerTag>,
|
||||
index: usize,
|
||||
) -> InterpResult<'tcx> {
|
||||
let index = index as u64;
|
||||
let place = self.place_field(vector, index)?;
|
||||
self.write_immediate(*scalar, place)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Writes the `scalars` to the `vector`.
|
||||
pub fn write_vector(
|
||||
&mut self,
|
||||
scalars: Vec<ImmTy<'tcx, M::PointerTag>>,
|
||||
vector: PlaceTy<'tcx, M::PointerTag>,
|
||||
) -> InterpResult<'tcx> {
|
||||
assert_ne!(scalars.len(), 0);
|
||||
match vector.layout.ty.sty {
|
||||
ty::Adt(def, ..) if def.repr.simd() => {
|
||||
let tcx = &*self.tcx;
|
||||
let count = vector.layout.ty.simd_size(*tcx);
|
||||
assert_eq!(count, scalars.len());
|
||||
for index in 0..scalars.len() {
|
||||
self.write_scalar_to_vector(scalars[index], vector, index)?;
|
||||
}
|
||||
}
|
||||
_ => bug!("not a vector"),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write an `Immediate` to memory.
|
||||
#[inline(always)]
|
||||
pub fn write_immediate_to_mplace(
|
||||
|
@ -249,7 +249,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
match instance.def {
|
||||
ty::InstanceDef::Intrinsic(..) => {
|
||||
if caller_abi != Abi::RustIntrinsic {
|
||||
if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = caller_abi {
|
||||
// ok
|
||||
} else {
|
||||
throw_unsup!(FunctionAbiMismatch(caller_abi, Abi::RustIntrinsic))
|
||||
}
|
||||
// The intrinsic itself cannot diverge, so if we got here without a return
|
||||
|
24
src/test/ui/consts/const-eval/const_eval-simd.rs
Normal file
24
src/test/ui/consts/const-eval/const_eval-simd.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// run-pass
|
||||
// compile-flags: -Zunleash-the-miri-inside-of-you
|
||||
#![feature(repr_simd)]
|
||||
#![feature(platform_intrinsics)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
#[repr(simd)] struct i8x1(i8);
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
|
||||
fn simd_extract<T, U>(x: T, idx: u32) -> U;
|
||||
}
|
||||
|
||||
const fn foo(x: i8x1) -> i8 {
|
||||
unsafe { simd_insert(x, 0_u32, 42_i8) }.0
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const V: i8x1 = i8x1(13);
|
||||
const X: i8 = foo(V);
|
||||
const Y: i8 = unsafe { simd_extract(V, 0) };
|
||||
assert_eq!(X, 42);
|
||||
assert_eq!(Y, 13);
|
||||
}
|
48
src/test/ui/consts/const-eval/const_eval-simd.stderr
Normal file
48
src/test/ui/consts/const-eval/const_eval-simd.stderr
Normal file
@ -0,0 +1,48 @@
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_eval-simd.rs:22:5
|
||||
|
|
||||
LL | assert_eq!(X, 42);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_eval-simd.rs:22:5
|
||||
|
|
||||
LL | assert_eq!(X, 42);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_eval-simd.rs:22:5
|
||||
|
|
||||
LL | assert_eq!(X, 42);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_eval-simd.rs:23:5
|
||||
|
|
||||
LL | assert_eq!(Y, 13);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_eval-simd.rs:23:5
|
||||
|
|
||||
LL | assert_eq!(Y, 13);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_eval-simd.rs:23:5
|
||||
|
|
||||
LL | assert_eq!(Y, 13);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
Loading…
Reference in New Issue
Block a user