store the current block in the frame

This commit is contained in:
Oliver Schneider 2016-06-03 16:51:51 +02:00
parent cc1ca73f57
commit f995db9ffb
No known key found for this signature in database
GPG key ID: 56D6EEA0FC67AC46
2 changed files with 34 additions and 30 deletions

View file

@ -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")
}

View file

@ -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<usize>,
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
}
}