diff options
| author | Ralf Jung <post@ralfj.de> | 2024-09-11 09:12:02 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2024-09-13 15:26:08 +0200 |
| commit | e2bc16c101e76532420e3af7e7805071f445b2f7 (patch) | |
| tree | 1c9666851ad2a66f8d379a3f72edb2236113d1ce /compiler/rustc_const_eval/src | |
| parent | a5efa01895e82fa705146507d15311b29c715450 (diff) | |
| download | rust-e2bc16c101e76532420e3af7e7805071f445b2f7.tar.gz rust-e2bc16c101e76532420e3af7e7805071f445b2f7.zip | |
interpret: simplify SIMD type handling
Diffstat (limited to 'compiler/rustc_const_eval/src')
5 files changed, 40 insertions, 52 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index bedc56de0da..8a07f90c951 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -384,8 +384,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { sym::simd_insert => { let index = u64::from(self.read_scalar(&args[1])?.to_u32()?); let elem = &args[2]; - let (input, input_len) = self.operand_to_simd(&args[0])?; - let (dest, dest_len) = self.mplace_to_simd(dest)?; + let (input, input_len) = self.project_to_simd(&args[0])?; + let (dest, dest_len) = self.project_to_simd(dest)?; assert_eq!(input_len, dest_len, "Return vector length must match input length"); // Bounds are not checked by typeck so we have to do it ourselves. if index >= input_len { @@ -406,7 +406,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } sym::simd_extract => { let index = u64::from(self.read_scalar(&args[1])?.to_u32()?); - let (input, input_len) = self.operand_to_simd(&args[0])?; + let (input, input_len) = self.project_to_simd(&args[0])?; // Bounds are not checked by typeck so we have to do it ourselves. if index >= input_len { throw_ub_format!( diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index bb7e58b83ac..2e02d1001c8 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -681,30 +681,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Ok(str) } - /// Converts a repr(simd) operand into an operand where `place_index` accesses the SIMD elements. - /// Also returns the number of elements. - /// - /// Can (but does not always) trigger UB if `op` is uninitialized. - pub fn operand_to_simd( - &self, - op: &OpTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, u64)> { - // Basically we just transmute this place into an array following simd_size_and_type. - // This only works in memory, but repr(simd) types should never be immediates anyway. - assert!(op.layout.ty.is_simd()); - match op.as_mplace_or_imm() { - Left(mplace) => self.mplace_to_simd(&mplace), - Right(imm) => match *imm { - Immediate::Uninit => { - throw_ub!(InvalidUninitBytes(None)) - } - Immediate::Scalar(..) | Immediate::ScalarPair(..) => { - bug!("arrays/slices can never have Scalar/ScalarPair layout") - } - }, - } - } - /// Read from a local of the current frame. /// Will not access memory, instead an indirect `Operand` is returned. /// diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 1eca92812df..9dd9ca80385 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -377,13 +377,15 @@ where Prov: Provenance, M: Machine<'tcx, Provenance = Prov>, { - pub fn ptr_with_meta_to_mplace( + fn ptr_with_meta_to_mplace( &self, ptr: Pointer<Option<M::Provenance>>, meta: MemPlaceMeta<M::Provenance>, layout: TyAndLayout<'tcx>, + unaligned: bool, ) -> MPlaceTy<'tcx, M::Provenance> { - let misaligned = self.is_ptr_misaligned(ptr, layout.align.abi); + let misaligned = + if unaligned { None } else { self.is_ptr_misaligned(ptr, layout.align.abi) }; MPlaceTy { mplace: MemPlace { ptr, meta, misaligned }, layout } } @@ -393,7 +395,16 @@ where layout: TyAndLayout<'tcx>, ) -> MPlaceTy<'tcx, M::Provenance> { assert!(layout.is_sized()); - self.ptr_with_meta_to_mplace(ptr, MemPlaceMeta::None, layout) + self.ptr_with_meta_to_mplace(ptr, MemPlaceMeta::None, layout, /*unaligned*/ false) + } + + pub fn ptr_to_mplace_unaligned( + &self, + ptr: Pointer<Option<M::Provenance>>, + layout: TyAndLayout<'tcx>, + ) -> MPlaceTy<'tcx, M::Provenance> { + assert!(layout.is_sized()); + self.ptr_with_meta_to_mplace(ptr, MemPlaceMeta::None, layout, /*unaligned*/ true) } /// Take a value, which represents a (thin or wide) reference, and make it a place. @@ -414,7 +425,7 @@ where // `ref_to_mplace` is called on raw pointers even if they don't actually get dereferenced; // we hence can't call `size_and_align_of` since that asserts more validity than we want. let ptr = ptr.to_pointer(self)?; - Ok(self.ptr_with_meta_to_mplace(ptr, meta, layout)) + Ok(self.ptr_with_meta_to_mplace(ptr, meta, layout, /*unaligned*/ false)) } /// Turn a mplace into a (thin or wide) mutable raw pointer, pointing to the same space. @@ -484,23 +495,6 @@ where Ok(a) } - /// Converts a repr(simd) place into a place where `place_index` accesses the SIMD elements. - /// Also returns the number of elements. - pub fn mplace_to_simd( - &self, - mplace: &MPlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, u64)> { - // 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); - // 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)) - } - /// Turn a local in the current frame into a place. pub fn local_to_place( &self, @@ -986,7 +980,7 @@ where span_bug!(self.cur_span(), "cannot allocate space for `extern` type, size is not known") }; let ptr = self.allocate_ptr(size, align, kind)?; - Ok(self.ptr_with_meta_to_mplace(ptr.into(), meta, layout)) + Ok(self.ptr_with_meta_to_mplace(ptr.into(), meta, layout, /*unaligned*/ false)) } pub fn allocate( @@ -1021,7 +1015,12 @@ where }; let meta = Scalar::from_target_usize(u64::try_from(str.len()).unwrap(), self); let layout = self.layout_of(self.tcx.types.str_).unwrap(); - Ok(self.ptr_with_meta_to_mplace(ptr.into(), MemPlaceMeta::Meta(meta), layout)) + Ok(self.ptr_with_meta_to_mplace( + ptr.into(), + MemPlaceMeta::Meta(meta), + layout, + /*unaligned*/ false, + )) } pub fn raw_const_to_mplace( diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index dd8dd21e0e8..641ed5bb7c0 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -244,6 +244,19 @@ where base.offset(offset, field_layout, self) } + /// Converts a repr(simd) value into an array of the right size, such that `project_index` + /// accesses the SIMD elements. Also returns the number of elements. + pub fn project_to_simd<P: Projectable<'tcx, M::Provenance>>( + &self, + base: &P, + ) -> InterpResult<'tcx, (P, u64)> { + assert!(base.layout().ty.ty_adt_def().unwrap().repr().simd()); + // SIMD types must be newtypes around arrays, so all we have to do is project to their only field. + let array = self.project_field(base, 0)?; + let len = array.len(self)?; + Ok((array, len)) + } + fn project_constant_index<P: Projectable<'tcx, M::Provenance>>( &self, base: &P, diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 6f5bcebbbb6..490355f416c 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::{ }; use tracing::debug; -use super::{throw_inval, InterpCx, MPlaceTy, MemPlaceMeta, MemoryKind}; +use super::{throw_inval, InterpCx, MPlaceTy, MemoryKind}; use crate::const_eval::{CompileTimeInterpCx, CompileTimeMachine, InterpretationResult}; /// Checks whether a type contains generic parameters which must be instantiated. @@ -103,5 +103,5 @@ pub(crate) fn create_static_alloc<'tcx>( assert_eq!(ecx.machine.static_root_ids, None); ecx.machine.static_root_ids = Some((alloc_id, static_def_id)); assert!(ecx.memory.alloc_map.insert(alloc_id, (MemoryKind::Stack, alloc)).is_none()); - Ok(ecx.ptr_with_meta_to_mplace(Pointer::from(alloc_id).into(), MemPlaceMeta::None, layout)) + Ok(ecx.ptr_to_mplace(Pointer::from(alloc_id).into(), layout)) } |
