diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-06-10 21:12:25 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-10 21:12:25 +0200 |
| commit | 07bb7ca9fabdc2f6483703bc43514fd6af386893 (patch) | |
| tree | 01988183844e1563a1f115067bcc053fbea9ea79 | |
| parent | 2d7f7ffba5697a1393c275d669bb1489951dd90e (diff) | |
| parent | d5fb8257e7533edd1f2699f9b92f80848477c800 (diff) | |
| download | rust-07bb7ca9fabdc2f6483703bc43514fd6af386893.tar.gz rust-07bb7ca9fabdc2f6483703bc43514fd6af386893.zip | |
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``
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/place.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/projection.rs | 2 | ||||
| -rw-r--r-- | src/tools/miri/tests/pass/intrinsics/portable-simd.rs | 21 |
3 files changed, 30 insertions, 6 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 4a86ec3f57a..046ff34e3d0 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -499,13 +499,14 @@ where &self, mplace: &MPlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, u64)> { - // Basically we just 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.) + // Basically we want to transmute this place into an array following simd_size_and_type. let (len, e_ty) = mplace.layout.ty.simd_size_and_type(*self.tcx); - let array = Ty::new_array(self.tcx.tcx, e_ty, len); - let layout = self.layout_of(array)?; - let mplace = mplace.transmute(layout, self)?; + // Some SIMD types have padding, so `len` many `e_ty` does not cover the entire place. + // Therefore we cannot transmute, and instead we project at offset 0, which side-steps + // 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)) } diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 0e594914c3a..09e1a59dfa1 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -81,6 +81,8 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug { ecx: &InterpCx<'tcx, M>, ) -> InterpResult<'tcx, Self> { 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) } diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs index c4ec45e4bbe..03d9fc0a76f 100644 --- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs +++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs @@ -658,11 +658,32 @@ fn simd_masked_loadstore() { 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() { simd_mask(); simd_ops_f32(); simd_ops_f64(); simd_ops_i32(); + simd_ops_non_pow2(); simd_cast(); simd_swizzle(); simd_gather_scatter(); |
