diff options
| author | b-naber <bn263@gmx.de> | 2022-04-21 19:35:06 +0200 | 
|---|---|---|
| committer | b-naber <bn263@gmx.de> | 2022-04-21 23:11:06 +0200 | 
| commit | bc698c73e90c253b0d37be8127b3fb542d9e95c2 (patch) | |
| tree | 14bc8c30dbcf7e6117798bd235a92f0caaaad399 /compiler/rustc_const_eval | |
| parent | 28af967bb9165999294250dc3f3a56c2193c35d9 (diff) | |
| download | rust-bc698c73e90c253b0d37be8127b3fb542d9e95c2.tar.gz rust-bc698c73e90c253b0d37be8127b3fb542d9e95c2.zip | |
deduplicate a lot of code
Diffstat (limited to 'compiler/rustc_const_eval')
| -rw-r--r-- | compiler/rustc_const_eval/src/const_eval/valtrees.rs | 339 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/mod.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/operand.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/place.rs | 16 | 
4 files changed, 121 insertions, 242 deletions
| diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index ded539fd340..39a3df79a28 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -2,16 +2,16 @@ use super::eval_queries::{mk_eval_cx, op_to_const}; use super::machine::CompileTimeEvalContext; use crate::interpret::{ intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemoryKind, PlaceTy, - Pointer, Scalar, ScalarMaybeUninit, + Scalar, ScalarMaybeUninit, }; -use rustc_middle::mir::interpret::{ConstAlloc, GlobalAlloc}; +use rustc_middle::mir::interpret::ConstAlloc; use rustc_middle::mir::{Field, ProjectionElem}; use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; use rustc_span::source_map::DUMMY_SP; use rustc_target::abi::VariantIdx; -use crate::interpret::visitor::Value; use crate::interpret::MPlaceTy; +use crate::interpret::Value; /// Convert an evaluated constant to a type level constant #[instrument(skip(tcx), level = "debug")] @@ -54,6 +54,7 @@ fn branches<'tcx>( Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?))) } +#[instrument(skip(ecx), level = "debug")] fn slice_branches<'tcx>( ecx: &CompileTimeEvalContext<'tcx, 'tcx>, place: &MPlaceTy<'tcx>, @@ -139,15 +140,44 @@ fn const_to_valtree_inner<'tcx>( #[instrument(skip(ecx), level = "debug")] fn create_mplace_from_layout<'tcx>( ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>, - param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + ty: Ty<'tcx>, ) -> MPlaceTy<'tcx> { let tcx = ecx.tcx; - let layout = tcx.layout_of(param_env_ty).unwrap(); + let param_env = ecx.param_env; + let layout = tcx.layout_of(param_env.and(ty)).unwrap(); debug!(?layout); ecx.allocate(layout, MemoryKind::Stack).unwrap() } +#[instrument(skip(ecx), level = "debug")] +fn create_pointee_place<'tcx>( + ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>, + ty: Ty<'tcx>, + valtree: ty::ValTree<'tcx>, +) -> MPlaceTy<'tcx> { + let tcx = ecx.tcx.tcx; + + match ty.kind() { + ty::Slice(_) | ty::Str => { + let slice_ty = match ty.kind() { + ty::Slice(slice_ty) => *slice_ty, + ty::Str => tcx.mk_ty(ty::Uint(ty::UintTy::U8)), + _ => bug!("expected ty::Slice | ty::Str"), + }; + + // Create a place for the underlying array + let len = valtree.unwrap_branch().len() as u64; + let arr_ty = tcx.mk_array(slice_ty, len as u64); + let place = create_mplace_from_layout(ecx, arr_ty); + debug!(?place); + + place + } + _ => create_mplace_from_layout(ecx, ty), + } +} + /// Converts a `ValTree` to a `ConstValue`, which is needed after mir /// construction has finished. #[instrument(skip(tcx), level = "debug")] @@ -174,96 +204,28 @@ pub fn valtree_to_const_value<'tcx>( ), }, ty::Ref(_, inner_ty, _) => { - match inner_ty.kind() { - ty::Slice(_) | ty::Str => { - let slice_ty = match inner_ty.kind() { - ty::Slice(slice_ty) => *slice_ty, - ty::Str => tcx.mk_ty(ty::Uint(ty::UintTy::U8)), - _ => bug!("expected ty::Slice | ty::Str"), - }; - debug!(?slice_ty); - - let valtrees = valtree.unwrap_branch(); - - // Create a place for the underlying array - let len = valtrees.len(); - let arr_ty = tcx.mk_array(slice_ty, len as u64); - let mut place = - create_mplace_from_layout(&mut ecx, ty::ParamEnv::empty().and(arr_ty)); - debug!(?place); - - // Insert elements of `arr_valtree` into `place` - fill_place_recursively(&mut ecx, &mut place, valtree, arr_ty); - dump_place(&ecx, place.into()); - - // The allocation behind `place` is local, we need to intern it - intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &place).unwrap(); - - // Now we need to get the Allocation - let alloc_id = place.mplace.ptr.provenance.unwrap(); - debug!(?alloc_id); - - let data = match tcx.get_global_alloc(alloc_id) { - Some(GlobalAlloc::Memory(const_alloc)) => const_alloc, - _ => bug!("expected memory allocation"), - }; - debug!(?data); - - return ConstValue::Slice { data, start: 0, end: len as usize }; - } - _ => { - match valtree { - ty::ValTree::Branch(_) => { - // create a place for the pointee - let mut place = create_mplace_from_layout( - &mut ecx, - ty::ParamEnv::empty().and(*inner_ty), - ); - debug!(?place); - - // insert elements of valtree into `place` - fill_place_recursively(&mut ecx, &mut place, valtree, *inner_ty); - dump_place(&ecx, place.into()); - intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &place) - .unwrap(); - - let ref_place = place.mplace.to_ref(&tcx); - let imm = ImmTy::from_immediate( - ref_place, - tcx.layout_of(param_env_ty).unwrap(), - ); - - let const_val = op_to_const(&ecx, &imm.into()); - debug!(?const_val); - - const_val - } - ty::ValTree::Leaf(_) => { - let mut place = create_mplace_from_layout( - &mut ecx, - ty::ParamEnv::empty().and(*inner_ty), - ); - - fill_place_recursively(&mut ecx, &mut place, valtree, *inner_ty); - dump_place(&ecx, place.into()); - - let ref_place = place.mplace.to_ref(&tcx); - let imm = ImmTy::from_immediate( - ref_place, - tcx.layout_of(param_env_ty).unwrap(), - ); - - op_to_const(&ecx, &imm.into()) - } - } - } - } + // create a place for the pointee + let mut pointee_place = create_pointee_place(&mut ecx, *inner_ty, valtree); + debug!(?pointee_place); + + // insert elements of valtree into `place` + fill_place_recursively(&mut ecx, &mut pointee_place, valtree); + dump_place(&ecx, pointee_place.into()); + intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &pointee_place).unwrap(); + + let ref_place = pointee_place.to_ref(&tcx); + let imm = ImmTy::from_immediate(ref_place, tcx.layout_of(param_env_ty).unwrap()); + + let const_val = op_to_const(&ecx, &imm.into()); + debug!(?const_val); + + const_val } ty::Tuple(_) | ty::Array(_, _) | ty::Adt(..) => { - let mut place = create_mplace_from_layout(&mut ecx, param_env_ty); + let mut place = create_mplace_from_layout(&mut ecx, ty); debug!(?place); - fill_place_recursively(&mut ecx, &mut place, valtree, ty); + fill_place_recursively(&mut ecx, &mut place, valtree); dump_place(&ecx, place.into()); intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &place).unwrap(); @@ -301,12 +263,12 @@ fn fill_place_recursively<'tcx>( ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>, place: &mut MPlaceTy<'tcx>, valtree: ty::ValTree<'tcx>, - ty: Ty<'tcx>, ) { // This will match on valtree and write the value(s) corresponding to the ValTree // inside the place recursively. let tcx = ecx.tcx.tcx; + let ty = place.layout.ty; match ty.kind() { ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => { @@ -319,161 +281,90 @@ fn fill_place_recursively<'tcx>( .unwrap(); } ty::Ref(_, inner_ty, _) => { - match inner_ty.kind() { + let mut pointee_place = create_pointee_place(ecx, *inner_ty, valtree); + debug!(?pointee_place); + + fill_place_recursively(ecx, &mut pointee_place, valtree); + dump_place(ecx, pointee_place.into()); + intern_const_alloc_recursive(ecx, InternKind::Constant, &pointee_place).unwrap(); + + let imm = match inner_ty.kind() { ty::Slice(_) | ty::Str => { - let slice_ty = match inner_ty.kind() { - ty::Slice(slice_ty) => *slice_ty, - ty::Str => tcx.mk_ty(ty::Uint(ty::UintTy::U8)), - _ => bug!("expected ty::Slice | ty::Str"), - }; - debug!(?slice_ty); - - let valtrees = valtree.unwrap_branch(); - debug!(?valtrees); - let len = valtrees.len(); - debug!(?len); - - // create a place for the underlying array - let arr_ty = tcx.mk_array(slice_ty, len as u64); - let mut arr_place = - create_mplace_from_layout(ecx, ty::ParamEnv::empty().and(arr_ty)); - debug!(?arr_place); - - // Insert elements of `arr_valtree` into `place` - fill_place_recursively(ecx, &mut arr_place, valtree, arr_ty); - dump_place(&ecx, arr_place.into()); - - // Now we need to create a `ScalarPair` from the filled `place` - // and write that into `place` - let (alloc_id, offset) = arr_place.mplace.ptr.into_parts(); - debug!(?alloc_id, ?offset); - let unwrapped_ptr = Pointer { offset, provenance: alloc_id.unwrap() }; + let len = valtree.unwrap_branch().len(); let len_scalar = ScalarMaybeUninit::Scalar(Scalar::from_u64(len as u64)); - let imm = Immediate::ScalarPair( - ScalarMaybeUninit::from_pointer(unwrapped_ptr, &tcx), + Immediate::ScalarPair( + ScalarMaybeUninit::from_maybe_pointer((*pointee_place).ptr, &tcx), len_scalar, - ); - debug!(?imm); - - // Now write the ScalarPair into the original place we wanted to fill - // in this call - let _ = ecx.write_immediate(imm, &(*place).into()).unwrap(); - - dump_place(&ecx, (*place).into()); + ) } - _ => { - let mut pointee_place = - create_mplace_from_layout(ecx, ty::ParamEnv::empty().and(*inner_ty)); - debug!(?pointee_place); - fill_place_recursively(ecx, &mut pointee_place, valtree, *inner_ty); + _ => pointee_place.to_ref(&tcx), + }; + debug!(?imm); - dump_place(ecx, pointee_place.into()); - intern_const_alloc_recursive(ecx, InternKind::Constant, &pointee_place) - .unwrap(); - - let imm = pointee_place.mplace.to_ref(&tcx); - debug!(?imm); - - ecx.write_immediate(imm, &(*place).into()).unwrap(); - } - } + ecx.write_immediate(imm, &(*place).into()).unwrap(); } - ty::Tuple(tuple_types) => { + ty::Adt(_, _) | ty::Tuple(_) | ty::Array(_, _) | ty::Str => { let branches = valtree.unwrap_branch(); - assert_eq!(tuple_types.len(), branches.len()); + // Need to downcast place for enums + let (place_adjusted, branches, variant_idx) = match ty.kind() { + ty::Adt(def, _) if def.is_enum() => { + // First element of valtree corresponds to variant + let scalar_int = branches[0].unwrap_leaf(); + let variant_idx = VariantIdx::from_u32(scalar_int.try_to_u32().unwrap()); + let variant = def.variant(variant_idx); + debug!(?variant); + + ( + place.project_downcast(ecx, variant_idx).unwrap(), + &branches[1..], + Some(variant_idx), + ) + } + _ => (*place, branches, None), + }; + debug!(?place_adjusted, ?branches); + + // Create the places for the fields and fill them recursively for (i, inner_valtree) in branches.iter().enumerate() { debug!(?i, ?inner_valtree); - let inner_ty = tuple_types.get(i).expect(&format!( - "expected to be able to index at position {} into {:?}", - i, tuple_types - )); - debug!(?inner_ty); - - // Create the mplace for the tuple element - let mut place_inner = ecx.mplace_field(place, i).unwrap(); + + let mut place_inner = match *ty.kind() { + ty::Adt(def, substs) if !def.is_enum() => { + let field = &def.variant(VariantIdx::from_usize(0)).fields[i]; + let field_ty = field.ty(tcx, substs); + let projection_elem = ProjectionElem::Field(Field::from_usize(i), field_ty); + + ecx.mplace_projection(&place_adjusted, projection_elem).unwrap() + } + ty::Adt(_, _) | ty::Tuple(_) => ecx.mplace_field(&place_adjusted, i).unwrap(), + ty::Array(_, _) | ty::Str => { + ecx.mplace_index(&place_adjusted, i as u64).unwrap() + } + _ => bug!(), + }; debug!(?place_inner); // insert valtree corresponding to tuple element into place - fill_place_recursively(ecx, &mut place_inner, *inner_valtree, *inner_ty); + fill_place_recursively(ecx, &mut place_inner, *inner_valtree); + dump_place(&ecx, place_inner.into()); } - } - ty::Array(inner_ty, _) => { - let inner_valtrees = valtree.unwrap_branch(); - for (i, inner_valtree) in inner_valtrees.iter().enumerate() { - debug!(?i, ?inner_valtree); - let mut place_inner = ecx.mplace_field(place, i).unwrap(); - debug!(?place_inner); + debug!("dump of place_adjusted:"); + dump_place(ecx, place_adjusted.into()); - fill_place_recursively(ecx, &mut place_inner, *inner_valtree, *inner_ty) - } - } - ty::Adt(def, substs) if def.is_enum() => { - debug!("enum, substs: {:?}", substs); - let inner_valtrees = valtree.unwrap_branch(); - - // First element of valtree corresponds to variant - let scalar_int = inner_valtrees[0].unwrap_leaf(); - let variant_idx = VariantIdx::from_u32(scalar_int.try_to_u32().unwrap()); - let variant = def.variant(variant_idx); - debug!(?variant); - - // Need to downcast place - let place_downcast = place.project_downcast(ecx, variant_idx).unwrap(); - debug!(?place_downcast); - - // fill `place_downcast` with the valtree elements corresponding to - // the fields of the enum - let fields = &variant.fields; - let inner_valtrees = &inner_valtrees[1..]; - for (i, field) in fields.iter().enumerate() { - debug!(?i, ?field); - - let field_ty = field.ty(tcx, substs); - debug!(?field_ty); - - let mut field_mplace = ecx.mplace_field(&place_downcast, i).unwrap(); - debug!(?field_mplace); - let inner_valtree = inner_valtrees[i]; - - fill_place_recursively(ecx, &mut field_mplace, inner_valtree, field_ty); - dump_place(&ecx, field_mplace.into()); + if let Some(variant_idx) = variant_idx { + // don't forget filling the place with the discriminant of the enum + ecx.write_discriminant(variant_idx, &(*place).into()).unwrap(); } - debug!("dump of place_downcast"); - dump_place(ecx, place_downcast.into()); - - // don't forget filling the place with the discriminant of the enum - ecx.write_discriminant(variant_idx, &(*place).into()).unwrap(); dump_place(ecx, (*place).into()); } - ty::Adt(def, substs) => { - debug!("Adt def: {:?} with substs: {:?}", def, substs); - let inner_valtrees = valtree.unwrap_branch(); - debug!(?inner_valtrees); - let (fields, inner_valtrees) = - (&def.variant(VariantIdx::from_usize(0)).fields[..], inner_valtrees); - - debug!("fields: {:?}", fields); - - for (i, field) in fields.iter().enumerate() { - let field_ty = field.ty(tcx, substs); - debug!(?field_ty); - let old_field_ty = tcx.type_of(field.did); - debug!(?old_field_ty); - let projection_elem = ProjectionElem::Field(Field::from_usize(i), field_ty); - let mut field_place = ecx.mplace_projection(place, projection_elem).unwrap(); - let inner_valtree = inner_valtrees[i]; - - fill_place_recursively(ecx, &mut field_place, inner_valtree, field_ty); - } - } - _ => {} + _ => bug!("shouldn't have created a ValTree for {:?}", ty), } } fn dump_place<'tcx>(ecx: &CompileTimeEvalContext<'tcx, 'tcx>, place: PlaceTy<'tcx>) { - trace!("{:?}", ecx.dump_place(place.place)); + trace!("{:?}", ecx.dump_place(*place)); } diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index dba746e72e2..69d6c8470a2 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -14,7 +14,7 @@ mod terminator; mod traits; mod util; mod validity; -pub(crate) mod visitor; +mod visitor; pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here @@ -27,7 +27,7 @@ pub use self::memory::{AllocCheck, AllocRef, AllocRefMut, FnVal, Memory, MemoryK pub use self::operand::{ImmTy, Immediate, OpTy, Operand}; pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy}; pub use self::validity::{CtfeValidationMode, RefTracking}; -pub use self::visitor::{MutValueVisitor, ValueVisitor}; +pub use self::visitor::{MutValueVisitor, Value, ValueVisitor}; crate use self::intrinsics::eval_nullary_intrinsic; use eval_context::{from_known_layout, mir_assign_valid_types}; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 170fbab2cce..f2d833b3202 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -98,7 +98,7 @@ impl<'tcx, Tag: Provenance> Immediate<Tag> { // as input for binary and cast operations. #[derive(Copy, Clone, Debug)] pub struct ImmTy<'tcx, Tag: Provenance = AllocId> { - pub imm: Immediate<Tag>, + imm: Immediate<Tag>, pub layout: TyAndLayout<'tcx>, } @@ -248,7 +248,7 @@ impl<'tcx, Tag: Provenance> ImmTy<'tcx, Tag> { impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`. /// Returns `None` if the layout does not permit loading this as a value. - pub(crate) fn try_read_immediate_from_mplace( + fn try_read_immediate_from_mplace( &self, mplace: &MPlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, Option<ImmTy<'tcx, M::PointerTag>>> { diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 8caf9eee2d9..3bc6494f008 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -82,7 +82,7 @@ rustc_data_structures::static_assert_size!(Place, 56); #[derive(Copy, Clone, Debug)] pub struct PlaceTy<'tcx, Tag: Provenance = AllocId> { - pub(crate) place: Place<Tag>, // Keep this private; it helps enforce invariants. + place: Place<Tag>, // Keep this private; it helps enforce invariants. pub layout: TyAndLayout<'tcx>, } @@ -100,7 +100,7 @@ impl<'tcx, Tag: Provenance> std::ops::Deref for PlaceTy<'tcx, Tag> { /// A MemPlace with its layout. Constructing it is only possible in this module. #[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)] pub struct MPlaceTy<'tcx, Tag: Provenance = AllocId> { - pub(crate) mplace: MemPlace<Tag>, + mplace: MemPlace<Tag>, pub layout: TyAndLayout<'tcx>, } @@ -589,7 +589,6 @@ where } /// Projects into a place. - #[instrument(skip(self), level = "debug")] pub fn place_projection( &mut self, base: &PlaceTy<'tcx, M::PointerTag>, @@ -626,18 +625,15 @@ where &mut self, place: mir::Place<'tcx>, ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { - debug!("projection: {:?}", place.projection); let mut place_ty = PlaceTy { // This works even for dead/uninitialized locals; we check further when writing place: Place::Local { frame: self.frame_idx(), local: place.local }, layout: self.layout_of_local(self.frame(), place.local, None)?, }; - debug!(?place_ty); for elem in place.projection.iter() { place_ty = self.place_projection(&place_ty, &elem)? } - debug!("place after projections: {:?}", place_ty); trace!("{:?}", self.dump_place(place_ty.place)); // Sanity-check the type we ended up with. @@ -693,7 +689,6 @@ where /// Write an immediate to a place. /// If you use this you are responsible for validating that things got copied at the /// right type. - #[instrument(skip(self), level = "debug")] fn write_immediate_no_validate( &mut self, src: Immediate<M::PointerTag>, @@ -746,7 +741,6 @@ where /// Write an immediate to memory. /// If you use this you are responsible for validating that things got copied at the /// right type. - #[instrument(skip(self), level = "debug")] fn write_immediate_to_mplace_no_validate( &mut self, value: Immediate<M::PointerTag>, @@ -769,7 +763,6 @@ where // cover all the bytes! match value { Immediate::Scalar(scalar) => { - debug!(?scalar); match dest.layout.abi { Abi::Scalar(_) => {} // fine _ => span_bug!( @@ -882,7 +875,6 @@ where // Let us see if the layout is simple so we take a shortcut, avoid force_allocation. let src = match self.try_read_immediate(src)? { Ok(src_val) => { - debug!("immediate from src is {:?}", src_val); assert!(!src.layout.is_unsized(), "cannot have unsized immediates"); // Yay, we got a value that we can write directly. // FIXME: Add a check to make sure that if `src` is indirect, @@ -978,7 +970,6 @@ where ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::PointerTag>, Option<Size>)> { let (mplace, size) = match place.place { Place::Local { frame, local } => { - debug!("LocalPlace"); match M::access_local_mut(self, frame, local)? { Ok(&mut local_val) => { // We need to make an allocation. @@ -992,12 +983,9 @@ where let (size, align) = self .size_and_align_of(&meta, &local_layout)? .expect("Cannot allocate for non-dyn-sized type"); - debug!(?size, ?align); let ptr = self.allocate_ptr(size, align, MemoryKind::Stack)?; - debug!("allocated ptr: {:?}", ptr); let mplace = MemPlace { ptr: ptr.into(), align, meta }; if let LocalValue::Live(Operand::Immediate(value)) = local_val { - debug!("LocalValue::Live: immediate value {:?}", value); // Preserve old value. // We don't have to validate as we can assume the local // was already valid for its type. | 
