Rollup merge of #126184 - RalfJung:interpret-simd-nonpow2, r=oli-obk
interpret: do not ICE on padded non-pow2 SIMD vectors Fixes https://github.com/rust-lang/miri/issues/3458 r? ``@oli-obk``
This commit is contained in:
commit
07bb7ca9fa
3 changed files with 30 additions and 6 deletions
|
@ -499,13 +499,14 @@ where
|
||||||
&self,
|
&self,
|
||||||
mplace: &MPlaceTy<'tcx, M::Provenance>,
|
mplace: &MPlaceTy<'tcx, M::Provenance>,
|
||||||
) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, u64)> {
|
) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, u64)> {
|
||||||
// Basically we just transmute this place into an array following simd_size_and_type.
|
// Basically we want to transmute this place into an array following simd_size_and_type.
|
||||||
// (Transmuting is okay since this is an in-memory place. We also double-check the size
|
|
||||||
// stays the same.)
|
|
||||||
let (len, e_ty) = mplace.layout.ty.simd_size_and_type(*self.tcx);
|
let (len, e_ty) = mplace.layout.ty.simd_size_and_type(*self.tcx);
|
||||||
let array = Ty::new_array(self.tcx.tcx, e_ty, len);
|
// Some SIMD types have padding, so `len` many `e_ty` does not cover the entire place.
|
||||||
let layout = self.layout_of(array)?;
|
// Therefore we cannot transmute, and instead we project at offset 0, which side-steps
|
||||||
let mplace = mplace.transmute(layout, self)?;
|
// the size check.
|
||||||
|
let array_layout = self.layout_of(Ty::new_array(self.tcx.tcx, e_ty, len))?;
|
||||||
|
assert!(array_layout.size <= mplace.layout.size);
|
||||||
|
let mplace = mplace.offset(Size::ZERO, array_layout, self)?;
|
||||||
Ok((mplace, len))
|
Ok((mplace, len))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,8 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug {
|
||||||
ecx: &InterpCx<'tcx, M>,
|
ecx: &InterpCx<'tcx, M>,
|
||||||
) -> InterpResult<'tcx, Self> {
|
) -> InterpResult<'tcx, Self> {
|
||||||
assert!(layout.is_sized());
|
assert!(layout.is_sized());
|
||||||
|
// We sometimes do pointer arithmetic with this function, disregarding the source type.
|
||||||
|
// So we don't check the sizes here.
|
||||||
self.offset_with_meta(offset, OffsetMode::Inbounds, MemPlaceMeta::None, layout, ecx)
|
self.offset_with_meta(offset, OffsetMode::Inbounds, MemPlaceMeta::None, layout, ecx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -658,11 +658,32 @@ fn simd_masked_loadstore() {
|
||||||
assert_eq!(buf, [2, 3, 4]);
|
assert_eq!(buf, [2, 3, 4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn simd_ops_non_pow2() {
|
||||||
|
// Just a little smoke test for operations on non-power-of-two vectors.
|
||||||
|
#[repr(simd, packed)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct SimdPacked<T, const N: usize>([T; N]);
|
||||||
|
#[repr(simd)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct SimdPadded<T, const N: usize>([T; N]);
|
||||||
|
|
||||||
|
let x = SimdPacked([1u32; 3]);
|
||||||
|
let y = SimdPacked([2u32; 3]);
|
||||||
|
let z = unsafe { intrinsics::simd_add(x, y) };
|
||||||
|
assert_eq!({ z.0 }, [3u32; 3]);
|
||||||
|
|
||||||
|
let x = SimdPadded([1u32; 3]);
|
||||||
|
let y = SimdPadded([2u32; 3]);
|
||||||
|
let z = unsafe { intrinsics::simd_add(x, y) };
|
||||||
|
assert_eq!(z.0, [3u32; 3]);
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
simd_mask();
|
simd_mask();
|
||||||
simd_ops_f32();
|
simd_ops_f32();
|
||||||
simd_ops_f64();
|
simd_ops_f64();
|
||||||
simd_ops_i32();
|
simd_ops_i32();
|
||||||
|
simd_ops_non_pow2();
|
||||||
simd_cast();
|
simd_cast();
|
||||||
simd_swizzle();
|
simd_swizzle();
|
||||||
simd_gather_scatter();
|
simd_gather_scatter();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue