diff options
| author | Oliver Scherer <github35764891676564198441@oli-obk.de> | 2019-12-21 23:55:34 +0100 |
|---|---|---|
| committer | Oliver Scherer <github35764891676564198441@oli-obk.de> | 2020-01-07 15:41:47 +0100 |
| commit | cc0fbdffe7db21649f45b3407ff9766636727690 (patch) | |
| tree | 76b1abbd078f09311ad39194acac7d742d88a79b | |
| parent | ee84c30aee06a004b8d8f8d24000351e9d1cb4bf (diff) | |
| download | rust-cc0fbdffe7db21649f45b3407ff9766636727690.tar.gz rust-cc0fbdffe7db21649f45b3407ff9766636727690.zip | |
Automatically prefer integer addresses for zst MPlace
| -rw-r--r-- | src/librustc_mir/const_eval/eval_queries.rs | 4 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/operand.rs | 30 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/place.rs | 19 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/terminator.rs | 2 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/validity.rs | 11 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/visitor.rs | 10 | ||||
| -rw-r--r-- | src/librustc_mir/transform/const_prop.rs | 3 |
7 files changed, 26 insertions, 53 deletions
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index dbeb75b60c2..8c41f7d1e61 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -115,7 +115,7 @@ pub(super) fn op_to_const<'tcx>( // by-val is if we are in const_field, i.e., if this is (a field of) something that we // "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or // structs containing such. - op.try_as_mplace() + op.try_as_mplace(ecx) }; let val = match immediate { Ok(mplace) => { @@ -132,7 +132,7 @@ pub(super) fn op_to_const<'tcx>( // `Immediate` is when we are called from `const_field`, and that `Immediate` // comes from a constant so it can happen have `Undef`, because the indirect // memory that was read had undefined bytes. - let mplace = op.assert_mem_place(); + let mplace = op.assert_mem_place(ecx); let ptr = mplace.ptr.assert_ptr(); let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id); ConstValue::ByRef { alloc, offset: ptr.offset } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index def979b63b5..00aecf74c7d 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -267,7 +267,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, op: OpTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { - match op.try_as_mplace() { + match op.try_as_mplace(self) { Ok(mplace) => Ok(self.force_mplace_ptr(mplace)?.into()), Err(imm) => Ok(imm.into()), // Nothing to cast/force } @@ -335,7 +335,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, src: OpTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, Result<ImmTy<'tcx, M::PointerTag>, MPlaceTy<'tcx, M::PointerTag>>> { - Ok(match src.try_as_mplace() { + Ok(match src.try_as_mplace(self) { Ok(mplace) => { if let Some(val) = self.try_read_immediate_from_mplace(mplace)? { Ok(val) @@ -383,7 +383,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { op: OpTy<'tcx, M::PointerTag>, field: u64, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { - let base = match op.try_as_mplace() { + let base = match op.try_as_mplace(self) { Ok(mplace) => { // The easy case let field = self.mplace_field(mplace, field)?; @@ -420,7 +420,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { variant: VariantIdx, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { // Downcasts only change the layout - Ok(match op.try_as_mplace() { + Ok(match op.try_as_mplace(self) { Ok(mplace) => self.mplace_downcast(mplace, variant)?.into(), Err(..) => { let layout = op.layout.for_variant(self, variant); @@ -439,30 +439,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Field(field, _) => self.operand_field(base, field.index() as u64)?, Downcast(_, variant) => self.operand_downcast(base, variant)?, Deref => self.deref_operand(base)?.into(), - ConstantIndex { .. } | Index(_) if base.layout.is_zst() => { - OpTy { - op: Operand::Immediate(Scalar::zst().into()), - // the actual index doesn't matter, so we just pick a convenient one like 0 - layout: base.layout.field(self, 0)?, - } - } - Subslice { from, to, from_end } if base.layout.is_zst() => { - let elem_ty = if let ty::Array(elem_ty, _) = base.layout.ty.kind { - elem_ty - } else { - bug!("slices shouldn't be zero-sized"); - }; - assert!(!from_end, "arrays shouldn't be subsliced from the end"); - - OpTy { - op: Operand::Immediate(Scalar::zst().into()), - layout: self.layout_of(self.tcx.mk_array(elem_ty, (to - from) as u64))?, - } - } Subslice { .. } | ConstantIndex { .. } | Index(_) => { // The rest should only occur as mplace, we do not use Immediates for types // allowing such operations. This matches place_projection forcing an allocation. - let mplace = base.assert_mem_place(); + let mplace = base.assert_mem_place(self); self.mplace_projection(mplace, proj_elem)?.into() } }) diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index f4ac7de852a..7fbe691f183 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -200,16 +200,17 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> { // These are defined here because they produce a place. impl<'tcx, Tag: ::std::fmt::Debug + Copy> OpTy<'tcx, Tag> { #[inline(always)] - pub fn try_as_mplace(self) -> Result<MPlaceTy<'tcx, Tag>, ImmTy<'tcx, Tag>> { + pub fn try_as_mplace(self, cx: &impl HasDataLayout) -> Result<MPlaceTy<'tcx, Tag>, ImmTy<'tcx, Tag>> { match *self { Operand::Indirect(mplace) => Ok(MPlaceTy { mplace, layout: self.layout }), + Operand::Immediate(_) if self.layout.is_zst() => Ok(MPlaceTy::dangling(self.layout, cx)), Operand::Immediate(imm) => Err(ImmTy { imm, layout: self.layout }), } } #[inline(always)] - pub fn assert_mem_place(self) -> MPlaceTy<'tcx, Tag> { - self.try_as_mplace().unwrap() + pub fn assert_mem_place(self, cx: &impl HasDataLayout) -> MPlaceTy<'tcx, Tag> { + self.try_as_mplace(cx).unwrap() } } @@ -305,7 +306,7 @@ where /// On success, returns `None` for zero-sized accesses (where nothing else is /// left to do) and a `Pointer` to use for the actual access otherwise. #[inline] - pub fn check_mplace_access( + pub(super) fn check_mplace_access( &self, place: MPlaceTy<'tcx, M::PointerTag>, size: Option<Size>, @@ -338,7 +339,7 @@ where /// Force `place.ptr` to a `Pointer`. /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot. - pub fn force_mplace_ptr( + pub(super) fn force_mplace_ptr( &self, mut place: MPlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { @@ -415,7 +416,7 @@ where // Iterates over all fields of an array. Much more efficient than doing the // same by repeatedly calling `mplace_array`. - pub fn mplace_array_fields( + pub(super) fn mplace_array_fields( &self, base: MPlaceTy<'tcx, Tag>, ) -> InterpResult<'tcx, impl Iterator<Item = InterpResult<'tcx, MPlaceTy<'tcx, Tag>>> + 'tcx> @@ -430,7 +431,7 @@ where Ok((0..len).map(move |i| base.offset(i * stride, None, layout, dl))) } - pub fn mplace_subslice( + fn mplace_subslice( &self, base: MPlaceTy<'tcx, M::PointerTag>, from: u64, @@ -471,7 +472,7 @@ where base.offset(from_offset, meta, layout, self) } - pub fn mplace_downcast( + pub(super) fn mplace_downcast( &self, base: MPlaceTy<'tcx, M::PointerTag>, variant: VariantIdx, @@ -482,7 +483,7 @@ where } /// Project into an mplace - pub fn mplace_projection( + pub(super) fn mplace_projection( &self, base: MPlaceTy<'tcx, M::PointerTag>, proj_elem: &mir::PlaceElem<'tcx>, diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index a28bb539fd0..37dcab512b9 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -378,7 +378,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } None => { // Unsized self. - args[0].assert_mem_place() + args[0].assert_mem_place(self) } }; // Find and consult vtable diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 7b82bed2e7a..73f479ede76 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -571,12 +571,9 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> ) -> InterpResult<'tcx> { match op.layout.ty.kind { ty::Str => { - let mplace = op.assert_mem_place(); // strings are never immediate - try_validation!( - self.ecx.read_str(mplace), - "uninitialized or non-UTF-8 data in str", - self.path - ); + let mplace = op.assert_mem_place(self.ecx); // strings are never immediate + try_validation!(self.ecx.read_str(mplace), + "uninitialized or non-UTF-8 data in str", self.path); } ty::Array(tys, ..) | ty::Slice(tys) if { @@ -604,7 +601,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> return Ok(()); } // non-ZST array cannot be immediate, slices are never immediate - let mplace = op.assert_mem_place(); + let mplace = op.assert_mem_place(self.ecx); // This is the length of the array/slice. let len = mplace.len(self.ecx)?; // zero length slices have nothing to be checked diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs index 2cfcf0ff06d..d2594e87071 100644 --- a/src/librustc_mir/interpret/visitor.rs +++ b/src/librustc_mir/interpret/visitor.rs @@ -223,7 +223,7 @@ macro_rules! make_value_visitor { match v.layout().ty.kind { ty::Dynamic(..) => { // immediate trait objects are not a thing - let dest = v.to_op(self.ecx())?.assert_mem_place(); + let dest = v.to_op(self.ecx())?.assert_mem_place(self.ecx()); let inner = self.ecx().unpack_dyn_trait(dest)?.1; trace!("walk_value: dyn object layout: {:#?}", inner.layout); // recurse with the inner type @@ -292,13 +292,7 @@ macro_rules! make_value_visitor { }, layout::FieldPlacement::Array { .. } => { // Let's get an mplace first. - let mplace = if v.layout().is_zst() { - // it's a ZST, the memory content cannot matter - MPlaceTy::dangling(v.layout(), self.ecx()) - } else { - // non-ZST array/slice/str cannot be immediate - v.to_op(self.ecx())?.assert_mem_place() - }; + let mplace = v.to_op(self.ecx())?.assert_mem_place(self.ecx()); // Now we can go over all the fields. let iter = self.ecx().mplace_array_fields(mplace)? .map(|f| f.and_then(|f| { diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 6b0f7be8684..d5d56b36cf4 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -707,7 +707,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ScalarMaybeUndef::Scalar(r), )) => l.is_bits() && r.is_bits(), interpret::Operand::Indirect(_) if mir_opt_level >= 2 => { - intern_const_alloc_recursive(&mut self.ecx, None, op.assert_mem_place()) + let mplace = op.assert_mem_place(&self.ecx); + intern_const_alloc_recursive(&mut self.ecx, None, mplace) .expect("failed to intern alloc"); true } |
