From f995db9ffba925590e4c78917362998be02fcbc1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 3 Jun 2016 16:51:51 +0200 Subject: [PATCH] store the current block in the frame --- src/interpreter/mod.rs | 28 +++++++++++++++++++++------- src/interpreter/stepper.rs | 36 +++++++++++++----------------------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 7e59b2674e87..f20a958cd0e7 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -118,8 +118,8 @@ enum CachedMir<'mir, 'tcx: 'mir> { /// Represents the action to be taken in the main loop as a result of executing a terminator. enum TerminatorTarget { - /// Make a local jump to the given block. - Block(mir::BasicBlock), + /// Make a local jump to the next block + Block, /// Start executing from the new current frame. (For function calls.) Call, @@ -268,12 +268,16 @@ impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> { let target = match terminator.kind { Return => TerminatorTarget::Return, - Goto { target } => TerminatorTarget::Block(target), + Goto { target } => { + self.frame_mut().next_block = target; + TerminatorTarget::Block + }, If { ref cond, targets: (then_target, else_target) } => { let cond_ptr = self.eval_operand(cond)?; let cond_val = self.memory.read_bool(cond_ptr)?; - TerminatorTarget::Block(if cond_val { then_target } else { else_target }) + self.frame_mut().next_block = if cond_val { then_target } else { else_target }; + TerminatorTarget::Block } SwitchInt { ref discr, ref values, ref targets, .. } => { @@ -296,7 +300,8 @@ impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> { } } - TerminatorTarget::Block(target_block) + self.frame_mut().next_block = target_block; + TerminatorTarget::Block } Switch { ref discr, ref targets, adt_def } => { @@ -307,7 +312,10 @@ impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> { .position(|v| discr_val == v.disr_val.to_u64_unchecked()); match matching { - Some(i) => TerminatorTarget::Block(targets[i]), + Some(i) => { + self.frame_mut().next_block = targets[i]; + TerminatorTarget::Block + }, None => return Err(EvalError::InvalidDiscriminant), } } @@ -408,7 +416,8 @@ impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> { let ptr = self.eval_lvalue(value)?.to_ptr(); let ty = self.lvalue_ty(value); self.drop(ptr, ty)?; - TerminatorTarget::Block(target) + self.frame_mut().next_block = target; + TerminatorTarget::Block } Resume => unimplemented!(), @@ -1238,6 +1247,11 @@ impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> { self.stack.last().expect("no call frames exist") } + fn basic_block(&self) -> &mir::BasicBlockData<'tcx> { + let frame = self.frame(); + frame.mir.basic_block_data(frame.next_block) + } + fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx> { self.stack.last_mut().expect("no call frames exist") } diff --git a/src/interpreter/stepper.rs b/src/interpreter/stepper.rs index b84680f73378..4a0dedf8a0f9 100644 --- a/src/interpreter/stepper.rs +++ b/src/interpreter/stepper.rs @@ -22,7 +22,6 @@ pub enum Event { pub struct Stepper<'fncx, 'a: 'fncx, 'b: 'a + 'mir, 'mir: 'fncx, 'tcx: 'b>{ fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>, - block: mir::BasicBlock, // a stack of statement positions stmt: Vec, mir: CachedMir<'mir, 'tcx>, @@ -34,7 +33,6 @@ pub struct Stepper<'fncx, 'a: 'fncx, 'b: 'a + 'mir, 'mir: 'fncx, 'tcx: 'b>{ 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 { Stepper { - block: fncx.frame().next_block, mir: fncx.mir(), fncx: fncx, stmt: vec![0], @@ -46,7 +44,7 @@ impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx fn dummy(&mut self) -> EvalResult<()> { Ok(()) } fn statement(&mut self) -> EvalResult<()> { - let block_data = self.mir.basic_block_data(self.block); + let block_data = self.mir.basic_block_data(self.fncx.frame().next_block); let stmt = &block_data.statements[*self.stmt.last().unwrap()]; let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind; let result = self.fncx.eval_assignment(lvalue, rvalue); @@ -58,27 +56,23 @@ impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx fn terminator(&mut self) -> EvalResult<()> { *self.stmt.last_mut().unwrap() = 0; let term = { - let block_data = self.mir.basic_block_data(self.block); + let block_data = self.mir.basic_block_data(self.fncx.frame().next_block); let terminator = block_data.terminator(); let result = self.fncx.eval_terminator(terminator); self.fncx.maybe_report(terminator.span, result)? }; match term { - TerminatorTarget::Block(block) => { - self.block = block; - }, + TerminatorTarget::Block => {}, TerminatorTarget::Return => { self.fncx.pop_stack_frame(); self.stmt.pop(); assert!(self.constants.last().unwrap().is_empty()); self.constants.pop(); if !self.fncx.stack.is_empty() { - self.block = self.fncx.frame().next_block; self.mir = self.fncx.mir(); } }, TerminatorTarget::Call => { - self.block = self.fncx.frame().next_block; self.mir = self.fncx.mir(); self.stmt.push(0); self.constants.push(Vec::new()); @@ -97,7 +91,6 @@ impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr)); self.stmt.push(0); self.constants.push(Vec::new()); - self.block = self.fncx.frame().next_block; self.mir = self.fncx.mir(); }, Some((ConstantId::Static { def_id, substs }, span, return_ptr, mir)) => { @@ -106,7 +99,6 @@ impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr)); self.stmt.push(0); self.constants.push(Vec::new()); - self.block = self.fncx.frame().next_block; self.mir = self.fncx.mir(); }, None => unreachable!(), @@ -128,7 +120,8 @@ impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx return Ok(Event::Constant); } - let basic_block = self.mir.basic_block_data(self.block); + let block = self.fncx.frame().next_block; + let basic_block = self.mir.basic_block_data(block); if let Some(ref stmt) = basic_block.statements.get(*self.stmt.last().unwrap()) { assert!(self.constants.last().unwrap().is_empty()); @@ -137,7 +130,7 @@ impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx span: stmt.span, fncx: self.fncx, mir: &self.mir, - }.visit_statement(self.block, stmt); + }.visit_statement(block, stmt); if self.constants.last().unwrap().is_empty() { self.process = Self::statement; return Ok(Event::Assignment); @@ -153,7 +146,7 @@ impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx span: terminator.span, fncx: self.fncx, mir: &self.mir, - }.visit_terminator(self.block, terminator); + }.visit_terminator(block, terminator); if self.constants.last().unwrap().is_empty() { self.process = Self::terminator; Ok(Event::Terminator) @@ -163,21 +156,18 @@ impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx } } - /// returns the basic block index of the currently processed block - pub fn block(&self) -> mir::BasicBlock { - self.block - } - /// returns the statement that will be processed next pub fn stmt(&self) -> &mir::Statement { - let block_data = self.mir.basic_block_data(self.block); - &block_data.statements[*self.stmt.last().unwrap()] + &self.fncx.basic_block().statements[*self.stmt.last().unwrap()] } /// returns the terminator of the current block pub fn term(&self) -> &mir::Terminator { - let block_data = self.mir.basic_block_data(self.block); - block_data.terminator() + self.fncx.basic_block().terminator() + } + + pub fn block(&self) -> mir::BasicBlock { + self.fncx.frame().next_block } }