Rollup merge of #61104 - spastorino:eval-place-to-op-iterate, r=oli-obk

Make eval_place_to_op iterate instead of recurse

r? @oli-obk
This commit is contained in:
Mazdak Farrokhzad 2019-05-25 04:57:38 +02:00 committed by GitHub
commit 1cd3dddc94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 27 deletions

View File

@ -467,22 +467,34 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
mir_place: &mir::Place<'tcx>,
layout: Option<TyLayout<'tcx>>,
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
use rustc::mir::Place::*;
use rustc::mir::Place;
use rustc::mir::PlaceBase;
let op = match *mir_place {
Base(PlaceBase::Local(mir::RETURN_PLACE)) => return err!(ReadFromReturnPointer),
Base(PlaceBase::Local(local)) => self.access_local(self.frame(), local, layout)?,
Projection(ref proj) => {
let op = self.eval_place_to_op(&proj.base, None)?;
self.operand_projection(op, &proj.elem)?
}
_ => self.eval_place_to_mplace(mir_place)?.into(),
mir_place.iterate(|place_base, place_projection| {
let mut op = match place_base {
PlaceBase::Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
PlaceBase::Local(local) => {
// FIXME use place_projection.is_empty() when is available
let layout = if let Place::Base(_) = mir_place {
layout
} else {
None
};
self.access_local(self.frame(), *local, layout)?
}
PlaceBase::Static(place_static) => {
self.eval_static_to_mplace(place_static)?.into()
}
};
for proj in place_projection {
op = self.operand_projection(op, &proj.elem)?
}
trace!("eval_place_to_op: got {:?}", *op);
Ok(op)
})
}
/// Evaluate the operand, returning a place where you can then find the data.

View File

@ -562,15 +562,14 @@ where
/// Evaluate statics and promoteds to an `MPlace`. Used to share some code between
/// `eval_place` and `eval_place_to_op`.
pub(super) fn eval_place_to_mplace(
pub(super) fn eval_static_to_mplace(
&self,
mir_place: &mir::Place<'tcx>
place_static: &mir::Static<'tcx>
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
use rustc::mir::Place::*;
use rustc::mir::PlaceBase;
use rustc::mir::{Static, StaticKind};
Ok(match *mir_place {
Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted), .. })) => {
use rustc::mir::StaticKind;
Ok(match place_static.kind {
StaticKind::Promoted(promoted) => {
let instance = self.frame().instance;
self.const_eval_raw(GlobalId {
instance,
@ -578,7 +577,8 @@ where
})?
}
Base(PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), ty })) => {
StaticKind::Static(def_id) => {
let ty = place_static.ty;
assert!(!ty.needs_subst());
let layout = self.layout_of(ty)?;
let instance = ty::Instance::mono(*self.tcx, def_id);
@ -600,8 +600,6 @@ where
let alloc = self.tcx.alloc_map.lock().intern_static(cid.instance.def_id());
MPlaceTy::from_aligned_ptr(Pointer::from(alloc).with_default_tag(), layout)
}
_ => bug!("eval_place_to_mplace called on {:?}", mir_place),
})
}
@ -613,7 +611,7 @@ where
) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
use rustc::mir::Place::*;
use rustc::mir::PlaceBase;
let place = match *mir_place {
let place = match mir_place {
Base(PlaceBase::Local(mir::RETURN_PLACE)) => match self.frame().return_place {
Some(return_place) =>
// We use our layout to verify our assumption; caller will validate
@ -628,17 +626,19 @@ where
// This works even for dead/uninitialized locals; we check further when writing
place: Place::Local {
frame: self.cur_frame(),
local,
local: *local,
},
layout: self.layout_of_local(self.frame(), local, None)?,
layout: self.layout_of_local(self.frame(), *local, None)?,
},
Projection(ref proj) => {
Projection(proj) => {
let place = self.eval_place(&proj.base)?;
self.place_projection(place, &proj.elem)?
}
_ => self.eval_place_to_mplace(mir_place)?.into(),
Base(PlaceBase::Static(place_static)) => {
self.eval_static_to_mplace(place_static)?.into()
}
};
self.dump_place(place.place);