From: Oliver Schneider Date: Thu, 9 Jun 2016 14:01:53 +0000 (+0200) Subject: merge FnEvalContext into GlobalEvalContext X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=8fec1a7aa776ed0f1373a1531b8665f4e35919f5;p=rust.git merge FnEvalContext into GlobalEvalContext --- diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 6c0d58f1c47..33e7d49bc6d 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -9,7 +9,7 @@ use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::DefIdMap; use std::cell::RefCell; -use std::ops::{Deref, DerefMut}; +use std::ops::Deref; use std::rc::Rc; use std::{iter, mem}; use syntax::ast; @@ -39,26 +39,9 @@ struct GlobalEvalContext<'a, 'tcx: 'a> { /// Precomputed statics, constants and promoteds statics: HashMap, Pointer>, -} - -struct FnEvalContext<'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> { - gecx: &'a mut GlobalEvalContext<'b, 'tcx>, /// The virtual call stack. - stack: Vec>, -} - -impl<'a, 'b, 'mir, 'tcx> Deref for FnEvalContext<'a, 'b, 'mir, 'tcx> { - type Target = GlobalEvalContext<'b, 'tcx>; - fn deref(&self) -> &Self::Target { - self.gecx - } -} - -impl<'a, 'b, 'mir, 'tcx> DerefMut for FnEvalContext<'a, 'b, 'mir, 'tcx> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.gecx - } + stack: Vec>, } /// A stack frame. @@ -160,20 +143,19 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &'a MirMap<'tcx>) -> Self { .bit_width() .expect("Session::target::uint_type was usize")/8), statics: HashMap::new(), + stack: Vec::new(), } } - fn call(&mut self, mir: &mir::Mir<'tcx>, def_id: DefId) -> EvalResult> { + fn call(&mut self, mir: &'a mir::Mir<'tcx>, def_id: DefId) -> EvalResult> { let substs = self.tcx.mk_substs(subst::Substs::empty()); let return_ptr = self.alloc_ret_ptr(mir.return_ty, substs); - let mut nested_fecx = FnEvalContext::new(self); + self.push_stack_frame(def_id, mir.span, CachedMir::Ref(mir), substs, None); - nested_fecx.push_stack_frame(def_id, mir.span, CachedMir::Ref(mir), substs, None); + self.frame_mut().return_ptr = return_ptr; - nested_fecx.frame_mut().return_ptr = return_ptr; - - nested_fecx.run()?; + self.run()?; Ok(return_ptr) } @@ -349,15 +331,6 @@ fn type_layout(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> &'tcx Layout ty.layout(&infcx).unwrap() }) } -} - -impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> { - fn new(gecx: &'a mut GlobalEvalContext<'b, 'tcx>) -> Self { - FnEvalContext { - gecx: gecx, - stack: Vec::new(), - } - } #[inline(never)] #[cold] @@ -399,7 +372,7 @@ fn run(&mut self) -> EvalResult<()> { Ok(()) } - fn push_stack_frame(&mut self, def_id: DefId, span: codemap::Span, mir: CachedMir<'mir, 'tcx>, substs: &'tcx Substs<'tcx>, + fn push_stack_frame(&mut self, def_id: DefId, span: codemap::Span, mir: CachedMir<'a, 'tcx>, substs: &'tcx Substs<'tcx>, return_ptr: Option) { let arg_tys = mir.arg_decls.iter().map(|a| a.ty); @@ -425,7 +398,7 @@ fn push_stack_frame(&mut self, def_id: DefId, span: codemap::Span, mir: CachedMi }); let locals: Vec = arg_tys.chain(var_tys).chain(temp_tys).map(|ty| { - let size = self.type_size(ty); + let size = self.type_size(ty, self.substs()); self.memory.allocate(size) }).collect(); @@ -459,7 +432,7 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>) SwitchInt { ref discr, ref values, ref targets, .. } => { let discr_ptr = self.eval_lvalue(discr)?.to_ptr(); let discr_size = self - .type_layout(self.lvalue_ty(discr)) + .type_layout(self.lvalue_ty(discr), self.substs()) .size(&self.tcx.data_layout) .bytes() as usize; let discr_val = self.memory.read_uint(discr_ptr, discr_size)?; @@ -512,7 +485,7 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>) let name = self.tcx.item_name(def_id).as_str(); match fn_ty.sig.0.output { ty::FnConverging(ty) => { - let size = self.type_size(ty); + let size = self.type_size(ty, self.substs()); let ret = return_ptr.unwrap(); self.call_intrinsic(&name, substs, args, ret, size)? } @@ -523,7 +496,7 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>) Abi::C => { match fn_ty.sig.0.output { ty::FnConverging(ty) => { - let size = self.type_size(ty); + let size = self.type_size(ty, self.substs()); self.call_c_abi(def_id, args, return_ptr.unwrap(), size)? } ty::FnDiverging => unimplemented!(), @@ -553,7 +526,7 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>) let last_arg = args.last().unwrap(); let last = self.eval_operand(last_arg)?; let last_ty = self.operand_ty(last_arg); - let last_layout = self.type_layout(last_ty); + let last_layout = self.type_layout(last_ty, self.substs()); match (&last_ty.sty, last_layout) { (&ty::TyTuple(fields), &Layout::Univariant { ref variant, .. }) => { @@ -638,7 +611,7 @@ fn drop(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<()> { // Filling drop. // FIXME(solson): Trait objects (with no static size) probably get filled, too. - let size = self.type_size(ty); + let size = self.type_size(ty, self.substs()); self.memory.drop_fill(ptr, size)?; Ok(()) @@ -646,7 +619,7 @@ fn drop(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<()> { fn read_discriminant_value(&self, adt_ptr: Pointer, adt_ty: Ty<'tcx>) -> EvalResult { use rustc::ty::layout::Layout::*; - let adt_layout = self.type_layout(adt_ty); + let adt_layout = self.type_layout(adt_ty, self.substs()); let discr_val = match *adt_layout { General { discr, .. } | CEnum { discr, .. } => { @@ -699,7 +672,7 @@ fn call_intrinsic( // FIXME(solson): Handle different integer types correctly. "add_with_overflow" => { let ty = *substs.types.get(subst::FnSpace, 0); - let size = self.type_size(ty); + let size = self.type_size(ty, self.substs()); let left = self.memory.read_int(args[0], size)?; let right = self.memory.read_int(args[1], size)?; let (n, overflowed) = unsafe { @@ -713,7 +686,7 @@ fn call_intrinsic( "copy_nonoverlapping" => { let elem_ty = *substs.types.get(subst::FnSpace, 0); - let elem_size = self.type_size(elem_ty); + let elem_size = self.type_size(elem_ty, self.substs()); let src = self.memory.read_ptr(args[0])?; let dest = self.memory.read_ptr(args[1])?; let count = self.memory.read_isize(args[2])?; @@ -729,7 +702,7 @@ fn call_intrinsic( "forget" => { let arg_ty = *substs.types.get(subst::FnSpace, 0); - let arg_size = self.type_size(arg_ty); + let arg_size = self.type_size(arg_ty, self.substs()); self.memory.drop_fill(args[0], arg_size)?; } @@ -748,7 +721,7 @@ fn call_intrinsic( // FIXME(solson): Handle different integer types correctly. "mul_with_overflow" => { let ty = *substs.types.get(subst::FnSpace, 0); - let size = self.type_size(ty); + let size = self.type_size(ty, self.substs()); let left = self.memory.read_int(args[0], size)?; let right = self.memory.read_int(args[1], size)?; let (n, overflowed) = unsafe { @@ -760,7 +733,7 @@ fn call_intrinsic( "offset" => { let pointee_ty = *substs.types.get(subst::FnSpace, 0); - let pointee_size = self.type_size(pointee_ty) as isize; + let pointee_size = self.type_size(pointee_ty, self.substs()) as isize; let ptr_arg = args[0]; let offset = self.memory.read_isize(args[1])?; @@ -781,7 +754,7 @@ fn call_intrinsic( // FIXME(solson): Handle different integer types correctly. Use primvals? "overflowing_sub" => { let ty = *substs.types.get(subst::FnSpace, 0); - let size = self.type_size(ty); + let size = self.type_size(ty, self.substs()); let left = self.memory.read_int(args[0], size)?; let right = self.memory.read_int(args[1], size)?; let n = left.wrapping_sub(right); @@ -790,20 +763,20 @@ fn call_intrinsic( "size_of" => { let ty = *substs.types.get(subst::FnSpace, 0); - let size = self.type_size(ty) as u64; + let size = self.type_size(ty, self.substs()) as u64; self.memory.write_uint(dest, size, dest_size)?; } "size_of_val" => { let ty = *substs.types.get(subst::FnSpace, 0); if self.type_is_sized(ty) { - let size = self.type_size(ty) as u64; + let size = self.type_size(ty, self.substs()) as u64; self.memory.write_uint(dest, size, dest_size)?; } else { match ty.sty { ty::TySlice(_) | ty::TyStr => { let elem_ty = ty.sequence_element_type(self.tcx); - let elem_size = self.type_size(elem_ty) as u64; + let elem_size = self.type_size(elem_ty, self.substs()) as u64; let ptr_size = self.memory.pointer_size as isize; let n = self.memory.read_usize(args[0].offset(ptr_size))?; self.memory.write_uint(dest, n * elem_size, dest_size)?; @@ -911,7 +884,7 @@ fn eval_assignment(&mut self, lvalue: &mir::Lvalue<'tcx>, rvalue: &mir::Rvalue<' { let dest = self.eval_lvalue(lvalue)?.to_ptr(); let dest_ty = self.lvalue_ty(lvalue); - let dest_layout = self.type_layout(dest_ty); + let dest_layout = self.type_layout(dest_ty, self.substs()); use rustc::mir::repr::Rvalue::*; match *rvalue { @@ -951,7 +924,7 @@ fn eval_assignment(&mut self, lvalue: &mir::Lvalue<'tcx>, rvalue: &mir::Rvalue<' Array { .. } => { let elem_size = match dest_ty.sty { - ty::TyArray(elem_ty, _) => self.type_size(elem_ty) as u64, + ty::TyArray(elem_ty, _) => self.type_size(elem_ty, self.substs()) as u64, _ => panic!("tried to assign {:?} to non-array type {:?}", kind, dest_ty), }; @@ -1029,7 +1002,7 @@ fn eval_assignment(&mut self, lvalue: &mir::Lvalue<'tcx>, rvalue: &mir::Rvalue<' Repeat(ref operand, _) => { let (elem_size, length) = match dest_ty.sty { - ty::TyArray(elem_ty, n) => (self.type_size(elem_ty), n), + ty::TyArray(elem_ty, n) => (self.type_size(elem_ty, self.substs()), n), _ => panic!("tried to assign array-repeat to non-array type {:?}", dest_ty), }; @@ -1070,7 +1043,7 @@ fn eval_assignment(&mut self, lvalue: &mir::Lvalue<'tcx>, rvalue: &mir::Rvalue<' } Box(ty) => { - let size = self.type_size(ty); + let size = self.type_size(ty, self.substs()); let ptr = self.memory.allocate(size); self.memory.write_ptr(dest, ptr)?; } @@ -1164,7 +1137,7 @@ fn get_field_ty(&self, ty: Ty<'tcx>, field_index: usize) -> EvalResult> } fn get_field_offset(&self, ty: Ty<'tcx>, field_index: usize) -> EvalResult { - let layout = self.type_layout(ty); + let layout = self.type_layout(ty, self.substs()); use rustc::ty::layout::Layout::*; match *layout { @@ -1229,13 +1202,13 @@ fn eval_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>) -> EvalResult { substs: substs, kind: ConstantKind::Global, }; - *self.gecx.statics.get(&cid).expect("static should have been cached (lvalue)") + *self.statics.get(&cid).expect("static should have been cached (lvalue)") }, Projection(ref proj) => { let base = self.eval_lvalue(&proj.base)?; let base_ty = self.lvalue_ty(&proj.base); - let base_layout = self.type_layout(base_ty); + let base_layout = self.type_layout(base_ty, self.substs()); use rustc::mir::repr::ProjectionElem::*; match proj.elem { @@ -1296,7 +1269,7 @@ fn eval_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>) -> EvalResult { Index(ref operand) => { let elem_size = match base_ty.sty { ty::TyArray(elem_ty, _) | - ty::TySlice(elem_ty) => self.type_size(elem_ty), + ty::TySlice(elem_ty) => self.type_size(elem_ty, self.substs()), _ => panic!("indexing expected an array or slice, got {:?}", base_ty), }; let n_ptr = self.eval_operand(operand)?; @@ -1313,19 +1286,15 @@ fn eval_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>) -> EvalResult { } fn lvalue_ty(&self, lvalue: &mir::Lvalue<'tcx>) -> Ty<'tcx> { - self.monomorphize(self.mir().lvalue_ty(self.tcx, lvalue).to_ty(self.tcx)) + self.monomorphize(self.mir().lvalue_ty(self.tcx, lvalue).to_ty(self.tcx), self.substs()) } fn operand_ty(&self, operand: &mir::Operand<'tcx>) -> Ty<'tcx> { - self.monomorphize(self.mir().operand_ty(self.tcx, operand)) - } - - fn monomorphize(&self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.gecx.monomorphize(ty, self.substs()) + self.monomorphize(self.mir().operand_ty(self.tcx, operand), self.substs()) } fn move_(&mut self, src: Pointer, dest: Pointer, ty: Ty<'tcx>) -> EvalResult<()> { - let size = self.type_size(ty); + let size = self.type_size(ty, self.substs()); self.memory.copy(src, dest, size)?; if self.type_needs_drop(ty) { self.memory.drop_fill(src, size)?; @@ -1333,14 +1302,6 @@ fn move_(&mut self, src: Pointer, dest: Pointer, ty: Ty<'tcx>) -> EvalResult<()> Ok(()) } - fn type_size(&self, ty: Ty<'tcx>) -> usize { - self.gecx.type_size(ty, self.substs()) - } - - fn type_layout(&self, ty: Ty<'tcx>) -> &'tcx Layout { - self.gecx.type_layout(ty, self.substs()) - } - pub fn read_primval(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult { use syntax::ast::{IntTy, UintTy}; let val = match (self.memory.pointer_size, &ty.sty) { @@ -1380,7 +1341,7 @@ pub fn read_primval(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult &Frame<'mir, 'tcx> { + fn frame(&self) -> &Frame<'a, 'tcx> { self.stack.last().expect("no call frames exist") } @@ -1389,11 +1350,11 @@ fn basic_block(&self) -> &mir::BasicBlockData<'tcx> { frame.mir.basic_block_data(frame.next_block) } - fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx> { + fn frame_mut(&mut self) -> &mut Frame<'a, 'tcx> { self.stack.last_mut().expect("no call frames exist") } - fn mir(&self) -> CachedMir<'mir, 'tcx> { + fn mir(&self) -> CachedMir<'a, 'tcx> { self.frame().mir.clone() } diff --git a/src/interpreter/stepper.rs b/src/interpreter/stepper.rs index a113b8f98e8..836df7a8bf9 100644 --- a/src/interpreter/stepper.rs +++ b/src/interpreter/stepper.rs @@ -1,5 +1,4 @@ use super::{ - FnEvalContext, CachedMir, TerminatorTarget, ConstantId, @@ -15,18 +14,18 @@ use std::rc::Rc; use memory::Pointer; -pub struct Stepper<'fncx, 'a: 'fncx, 'b: 'a + 'mir, 'mir: 'fncx, 'tcx: 'b>{ - fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>, +pub struct Stepper<'fncx, 'a: 'fncx, 'tcx: 'a>{ + gecx: &'fncx mut GlobalEvalContext<'a, 'tcx>, // a cache of the constants to be computed before the next statement/terminator // this is an optimization, so we don't have to allocate a new vector for every statement - constants: Vec<(ConstantId<'tcx>, Span, Pointer, CachedMir<'mir, 'tcx>)>, + constants: Vec<(ConstantId<'tcx>, Span, Pointer, CachedMir<'a, 'tcx>)>, } -impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx> { - pub(super) fn new(fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>) -> Self { +impl<'fncx, 'a, 'tcx> Stepper<'fncx, 'a, 'tcx> { + pub(super) fn new(gecx: &'fncx mut GlobalEvalContext<'a, 'tcx>) -> Self { Stepper { - fncx: fncx, + gecx: gecx, constants: Vec::new(), } } @@ -34,48 +33,48 @@ pub(super) fn new(fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>) -> Self { fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<()> { trace!("{:?}", stmt); let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind; - let result = self.fncx.eval_assignment(lvalue, rvalue); - self.fncx.maybe_report(result)?; - self.fncx.frame_mut().stmt += 1; + let result = self.gecx.eval_assignment(lvalue, rvalue); + self.gecx.maybe_report(result)?; + self.gecx.frame_mut().stmt += 1; Ok(()) } fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<()> { // after a terminator we go to a new block - self.fncx.frame_mut().stmt = 0; + self.gecx.frame_mut().stmt = 0; let term = { trace!("{:?}", terminator.kind); - let result = self.fncx.eval_terminator(terminator); - self.fncx.maybe_report(result)? + let result = self.gecx.eval_terminator(terminator); + self.gecx.maybe_report(result)? }; match term { TerminatorTarget::Return => { - self.fncx.pop_stack_frame(); + self.gecx.pop_stack_frame(); }, TerminatorTarget::Block | - TerminatorTarget::Call => trace!("// {:?}", self.fncx.frame().next_block), + TerminatorTarget::Call => trace!("// {:?}", self.gecx.frame().next_block), } Ok(()) } // returns true as long as there are more things to do pub fn step(&mut self) -> EvalResult { - if self.fncx.stack.is_empty() { + if self.gecx.stack.is_empty() { return Ok(false); } - let block = self.fncx.frame().next_block; - let stmt = self.fncx.frame().stmt; - let mir = self.fncx.mir(); + let block = self.gecx.frame().next_block; + let stmt = self.gecx.frame().stmt; + let mir = self.gecx.mir(); let basic_block = mir.basic_block_data(block); if let Some(ref stmt) = basic_block.statements.get(stmt) { assert!(self.constants.is_empty()); ConstantExtractor { span: stmt.span, - substs: self.fncx.substs(), - def_id: self.fncx.frame().def_id, - gecx: self.fncx.gecx, + substs: self.gecx.substs(), + def_id: self.gecx.frame().def_id, + gecx: self.gecx, constants: &mut self.constants, mir: &mir, }.visit_statement(block, stmt); @@ -91,9 +90,9 @@ pub fn step(&mut self) -> EvalResult { assert!(self.constants.is_empty()); ConstantExtractor { span: terminator.span, - substs: self.fncx.substs(), - def_id: self.fncx.frame().def_id, - gecx: self.fncx.gecx, + substs: self.gecx.substs(), + def_id: self.gecx.frame().def_id, + gecx: self.gecx, constants: &mut self.constants, mir: &mir, }.visit_terminator(block, terminator); @@ -109,7 +108,7 @@ fn extract_constants(&mut self) -> EvalResult<()> { assert!(!self.constants.is_empty()); for (cid, span, return_ptr, mir) in self.constants.drain(..) { trace!("queuing a constant"); - self.fncx.push_stack_frame(cid.def_id, span, mir, cid.substs, Some(return_ptr)); + self.gecx.push_stack_frame(cid.def_id, span, mir, cid.substs, Some(return_ptr)); } // self.step() can't be "done", so it can't return false assert!(self.step()?);