This commit is contained in:
gnzlbg 2019-09-25 12:54:23 +02:00
parent 02b3234a77
commit 5976674a71
5 changed files with 76 additions and 58 deletions

View file

@ -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),
}

View file

@ -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)
}
}

View file

@ -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(

View file

@ -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);
}

View 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);
}