Refactor
This commit is contained in:
parent
02b3234a77
commit
5976674a71
5 changed files with 76 additions and 58 deletions
|
@ -240,24 +240,55 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
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 index = self.read_scalar(args[1])?.to_u32()? as u64;
|
||||
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.layout.ty,
|
||||
scalar.layout.size.bytes(), vector[index].layout.size.bytes()
|
||||
);
|
||||
let input = args[0];
|
||||
let (len, e_ty) = self.read_vector_ty(input);
|
||||
assert!(
|
||||
index < len,
|
||||
"index `{}` must be in bounds of vector type `{}`: `[0, {})`",
|
||||
index, e_ty, len
|
||||
);
|
||||
assert_eq!(
|
||||
args[0].layout, dest.layout,
|
||||
"Return type `{}` must match vector type `{}`",
|
||||
dest.layout.ty, input.layout.ty
|
||||
);
|
||||
assert_eq!(
|
||||
scalar.layout.ty, e_ty,
|
||||
"Scalar type `{}` must match vector element type `{}`",
|
||||
scalar.layout.ty, e_ty
|
||||
);
|
||||
|
||||
for i in 0..len {
|
||||
let place = self.place_field(dest, index)?;
|
||||
if i == index {
|
||||
self.write_immediate(*scalar, place)?;
|
||||
} else {
|
||||
self.write_immediate(
|
||||
*self.read_immediate(self.operand_field(input, index)?)?,
|
||||
place
|
||||
)?;
|
||||
};
|
||||
}
|
||||
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)?;
|
||||
let (len, e_ty) = self.read_vector_ty(args[0]);
|
||||
assert!(
|
||||
index < len,
|
||||
"index `{}` must be in bounds of vector type `{}`: `[0, {})`",
|
||||
index, e_ty, len
|
||||
);
|
||||
assert_eq!(
|
||||
e_ty, dest.layout.ty,
|
||||
"Return type `{}` must match vector element type `{}`",
|
||||
dest.layout.ty, e_ty
|
||||
);
|
||||
self.write_immediate(
|
||||
*self.read_immediate(self.operand_field(args[0], index)?)?,
|
||||
dest
|
||||
)?;
|
||||
}
|
||||
_ => return Ok(false),
|
||||
}
|
||||
|
|
|
@ -335,18 +335,15 @@ 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)
|
||||
/// Read vector length and element type
|
||||
pub fn read_vector_ty(
|
||||
&self, op: OpTy<'tcx, M::PointerTag>
|
||||
)
|
||||
-> (u64, &rustc::ty::TyS<'tcx>) {
|
||||
if let layout::Abi::Vector { .. } = op.layout.abi {
|
||||
(op.layout.ty.simd_size(*self.tcx) as _, op.layout.ty.simd_type(*self.tcx))
|
||||
} else {
|
||||
bug!("type is not a vector: {:?}, abi: {:?}", op.layout.ty, op.layout.abi);
|
||||
bug!("Type `{}` is not a SIMD vector type", op.layout.ty)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -696,40 +696,6 @@ 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(
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
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 {
|
||||
|
@ -14,7 +15,13 @@ const fn foo(x: i8x1) -> i8 {
|
|||
unsafe { simd_insert(x, 0_u32, 42_i16) }.0 //~ ERROR
|
||||
}
|
||||
|
||||
const fn bar(x: i8x1) -> i16 {
|
||||
// the i8 is not a i16:
|
||||
unsafe { simd_extract(x, 0_u32) } //~ ERROR
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const V: i8x1 = i8x1(13);
|
||||
const X: i8 = foo(V);
|
||||
const Y: i16 = bar(V);
|
||||
}
|
||||
|
|
17
src/test/ui/consts/const-eval/simd/read_fail.rs
Normal file
17
src/test/ui/consts/const-eval/simd/read_fail.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
#![feature(const_fn)]
|
||||
#![feature(platform_intrinsics)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_extract<T, U>(x: T, idx: u32) -> U;
|
||||
}
|
||||
|
||||
const fn foo(x: i8) -> i8 {
|
||||
// i8 is not a vector type:
|
||||
unsafe { simd_extract(x, 0_u32) } //~ ERROR
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const V: i8 = 13;
|
||||
const X: i8 = foo(V);
|
||||
}
|
Loading…
Reference in a new issue