/// 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,
})?
}
- 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);
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),
})
}
/// place; for reading, a more efficient alternative is `eval_place_for_read`.
pub fn eval_place(
&mut self,
- mir_place: &mir::Place<'tcx>
+ mir_place: &mir::Place<'tcx>,
) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
- use rustc::mir::Place::*;
use rustc::mir::PlaceBase;
- 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
- // their layout on return.
- PlaceTy {
- place: *return_place,
- layout: self.layout_of(self.monomorphize(self.frame().mir.return_ty())?)?,
+
+ mir_place.iterate(|place_base, place_projection| {
+ let mut place = match 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
+ // their layout on return.
+ PlaceTy {
+ place: *return_place,
+ layout: self
+ .layout_of(self.monomorphize(self.frame().mir.return_ty())?)?,
+ }
+ }
+ None => return err!(InvalidNullPointerUsage),
+ },
+ PlaceBase::Local(local) => PlaceTy {
+ // This works even for dead/uninitialized locals; we check further when writing
+ place: Place::Local {
+ frame: self.cur_frame(),
+ local: *local,
},
- None => return err!(InvalidNullPointerUsage),
- },
- Base(PlaceBase::Local(local)) => PlaceTy {
- // This works even for dead/uninitialized locals; we check further when writing
- place: Place::Local {
- frame: self.cur_frame(),
- local,
+ layout: self.layout_of_local(self.frame(), *local, None)?,
},
- layout: self.layout_of_local(self.frame(), local, None)?,
- },
+ PlaceBase::Static(place_static) => self.eval_static_to_mplace(place_static)?.into(),
+ };
- Projection(ref proj) => {
- let place = self.eval_place(&proj.base)?;
- self.place_projection(place, &proj.elem)?
+ for proj in place_projection {
+ place = self.place_projection(place, &proj.elem)?
}
- _ => self.eval_place_to_mplace(mir_place)?.into(),
- };
-
- self.dump_place(place.place);
- Ok(place)
+ self.dump_place(place.place);
+ Ok(place)
+ })
}
/// Write a scalar to a place
Immediate::Scalar(ScalarMaybeUndef::Scalar(Scalar::Ptr(_))) =>
assert_eq!(self.pointer_size(), dest.layout.size,
"Size mismatch when writing pointer"),
- Immediate::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits { size, .. })) =>
+ Immediate::Scalar(ScalarMaybeUndef::Scalar(Scalar::Raw { size, .. })) =>
assert_eq!(Size::from_bytes(size.into()), dest.layout.size,
"Size mismatch when writing bits"),
Immediate::Scalar(ScalarMaybeUndef::Undef) => {}, // undef can have any size