diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 9701e1157a4f..1b8be7bebd62 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -37,8 +37,8 @@ struct GlobalEvalContext<'a, 'tcx: 'a> { /// The virtual memory system. memory: Memory, - /// Precomputed statics and constants - statics: DefIdMap, + /// Precomputed statics, constants and promoteds + statics: HashMap, Pointer>, } struct FnEvalContext<'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> { @@ -92,9 +92,6 @@ struct Frame<'a, 'tcx: 'a> { /// The offset of the first temporary in `self.locals`. temp_offset: usize, - /// List of precomputed promoted constants - promoted: HashMap, - /// The index of the currently evaluated statment stmt: usize, @@ -136,10 +133,28 @@ enum TerminatorTarget { #[derive(Clone, Debug, Eq, PartialEq, Hash)] enum ConstantId<'tcx> { - Promoted { index: usize }, + Promoted { def_id: DefId, substs: &'tcx Substs<'tcx>, index: usize }, Static { def_id: DefId, substs: &'tcx Substs<'tcx> }, } +impl<'tcx> ConstantId<'tcx> { + fn substs(&self) -> &'tcx Substs<'tcx> { + use self::ConstantId::*; + match *self { + Promoted { substs, .. } | + Static { substs, .. } => substs + } + } + + fn def_id(&self) -> DefId { + use self::ConstantId::*; + match *self { + Promoted { def_id, .. } | + Static { def_id, .. } => def_id, + } + } +} + impl<'a, 'tcx> GlobalEvalContext<'a, 'tcx> { fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &'a MirMap<'tcx>) -> Self { @@ -152,7 +167,7 @@ impl<'a, 'tcx> GlobalEvalContext<'a, 'tcx> { .uint_type .bit_width() .expect("Session::target::uint_type was usize")/8), - statics: DefIdMap(), + statics: HashMap::new(), } } @@ -248,7 +263,6 @@ impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> { locals: Vec::new(), var_offset: num_args, temp_offset: num_args + num_vars, - promoted: HashMap::new(), span: span, def_id: def_id, substs: substs, @@ -1025,10 +1039,18 @@ impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> { if item_ty.ty.is_fn() { Err(EvalError::Unimplemented("unimplemented: mentions of function items".to_string())) } else { - Ok(*self.statics.get(&def_id).expect("static should have been cached (rvalue)")) + let cid = ConstantId::Static{ def_id: def_id, substs: substs }; + Ok(*self.statics.get(&cid).expect("static should have been cached (rvalue)")) } }, - Promoted { index } => Ok(*self.frame().promoted.get(&index).expect("a promoted constant hasn't been precomputed")), + Promoted { index } => { + let cid = ConstantId::Promoted { + def_id: self.frame().def_id, + substs: self.substs(), + index: index, + }; + Ok(*self.statics.get(&cid).expect("a promoted constant hasn't been precomputed")) + }, } } } @@ -1043,7 +1065,11 @@ impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> { Var(i) => self.frame().locals[self.frame().var_offset + i as usize], Temp(i) => self.frame().locals[self.frame().temp_offset + i as usize], - Static(def_id) => *self.gecx.statics.get(&def_id).expect("static should have been cached (lvalue)"), + Static(def_id) => { + let substs = self.tcx.mk_substs(subst::Substs::empty()); + let cid = ConstantId::Static{ def_id: def_id, substs: substs }; + *self.gecx.statics.get(&cid).expect("static should have been cached (lvalue)") + }, Projection(ref proj) => { let base = self.eval_lvalue(&proj.base)?; diff --git a/src/interpreter/stepper.rs b/src/interpreter/stepper.rs index 8abc7830f518..1a2fbe43408a 100644 --- a/src/interpreter/stepper.rs +++ b/src/interpreter/stepper.rs @@ -10,7 +10,6 @@ use rustc::ty::subst::{self, Subst}; use rustc::hir::def_id::DefId; use rustc::mir::visit::{Visitor, LvalueContext}; use syntax::codemap::Span; -use memory::Pointer; use std::rc::Rc; pub enum Event { @@ -73,23 +72,11 @@ impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx } fn constant(&mut self) -> EvalResult<()> { - match self.fncx.frame_mut().constants.pop() { - Some((ConstantId::Promoted { index }, span, return_ptr, mir)) => { - trace!("adding promoted constant {}, {:?}", index, span); - let substs = self.fncx.substs(); - // FIXME: somehow encode that this is a promoted constant's frame - let def_id = self.fncx.frame().def_id; - self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr)); - self.mir = self.fncx.mir(); - }, - Some((ConstantId::Static { def_id, substs }, span, return_ptr, mir)) => { - trace!("adding static {:?}, {:?}", def_id, span); - self.fncx.gecx.statics.insert(def_id, return_ptr); - self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr)); - self.mir = self.fncx.mir(); - }, - None => unreachable!(), - } + let (cid, span, return_ptr, mir) = self.fncx.frame_mut().constants.pop().expect("state machine broken"); + let def_id = cid.def_id(); + let substs = cid.substs(); + self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr)); + self.mir = self.fncx.mir(); Ok(()) } @@ -164,16 +151,17 @@ struct ConstantExtractor<'a: 'c, 'b: 'a + 'mir + 'c, 'c, 'mir: 'c, 'tcx: 'a + 'b } impl<'a, 'b, 'c, 'mir, 'tcx> ConstantExtractor<'a, 'b, 'c, 'mir, 'tcx> { - fn constant(&mut self, def_id: DefId, substs: &'tcx subst::Substs<'tcx>, span: Span) { - if self.fncx.gecx.statics.contains_key(&def_id) { - return; - } + fn static_item(&mut self, def_id: DefId, substs: &'tcx subst::Substs<'tcx>, span: Span) { let cid = ConstantId::Static { def_id: def_id, substs: substs, }; + if self.fncx.gecx.statics.contains_key(&cid) { + return; + } let mir = self.fncx.load_mir(def_id); let ptr = self.fncx.alloc_ret_ptr(mir.return_ty).expect("there's no such thing as an unreachable static"); + self.fncx.statics.insert(cid.clone(), ptr); self.fncx.frame_mut().constants.push((cid, span, ptr, mir)); } } @@ -189,19 +177,24 @@ impl<'a, 'b, 'c, 'mir, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'c, 'mi if item_ty.ty.is_fn() { // unimplemented } else { - self.constant(def_id, substs, constant.span); + self.static_item(def_id, substs, constant.span); } }, mir::Literal::Promoted { index } => { - if self.fncx.frame().promoted.contains_key(&index) { + let cid = ConstantId::Promoted { + def_id: self.fncx.frame().def_id, + substs: self.fncx.substs(), + index: index, + }; + if self.fncx.statics.contains_key(&cid) { return; } let mir = self.mir.promoted[index].clone(); let return_ty = mir.return_ty; let return_ptr = self.fncx.alloc_ret_ptr(return_ty).expect("there's no such thing as an unreachable static"); - self.fncx.frame_mut().promoted.insert(index, return_ptr); let mir = CachedMir::Owned(Rc::new(mir)); - self.fncx.frame_mut().constants.push((ConstantId::Promoted { index: index }, constant.span, return_ptr, mir)); + self.fncx.statics.insert(cid.clone(), return_ptr); + self.fncx.frame_mut().constants.push((cid, constant.span, return_ptr, mir)); } } } @@ -211,7 +204,7 @@ impl<'a, 'b, 'c, 'mir, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'c, 'mi if let mir::Lvalue::Static(def_id) = *lvalue { let substs = self.fncx.tcx.mk_substs(subst::Substs::empty()); let span = self.span; - self.constant(def_id, substs, span); + self.static_item(def_id, substs, span); } } }