no more function pointers

This commit is contained in:
Oliver Schneider 2016-06-08 11:34:56 +02:00
parent 8b25bc8a9a
commit 3de30e33f5
No known key found for this signature in database
GPG Key ID: 56D6EEA0FC67AC46
2 changed files with 34 additions and 56 deletions

View File

@ -400,22 +400,18 @@ fn maybe_report<T>(&self, r: EvalResult<T>) -> EvalResult<T> {
fn run(&mut self) -> EvalResult<()> { fn run(&mut self) -> EvalResult<()> {
let mut stepper = stepper::Stepper::new(self); let mut stepper = stepper::Stepper::new(self);
'outer: loop { let mut done = false;
while !done {
use self::stepper::Event::*; use self::stepper::Event::*;
trace!("// {:?}", stepper.block()); stepper.step(|event| match event {
Block(b) => trace!("// {:?}", b),
loop { Assignment(a) => trace!("{:?}", a),
match stepper.step()? { Terminator(t) => trace!("{:?}", t.kind),
Constant => trace!("computing a constant"), Done => done = true,
Assignment => trace!("{:?}", stepper.stmt()), _ => {},
Terminator => { })?;
trace!("{:?}", stepper.term().kind);
continue 'outer;
},
Done => return Ok(()),
}
}
} }
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<'mir, 'tcx>, substs: &'tcx Substs<'tcx>,

View File

@ -14,16 +14,18 @@
use std::rc::Rc; use std::rc::Rc;
use memory::Pointer; use memory::Pointer;
pub enum Event { pub enum Event<'a, 'tcx: 'a> {
Block(mir::BasicBlock),
Return,
Call,
Constant, Constant,
Assignment, Assignment(&'a mir::Statement<'tcx>),
Terminator, Terminator(&'a mir::Terminator<'tcx>),
Done, Done,
} }
pub struct Stepper<'fncx, 'a: 'fncx, 'b: 'a + 'mir, 'mir: 'fncx, 'tcx: 'b>{ pub struct Stepper<'fncx, 'a: 'fncx, 'b: 'a + 'mir, 'mir: 'fncx, 'tcx: 'b>{
fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>, fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>,
process: fn (&mut Stepper<'fncx, 'a, 'b, 'mir, 'tcx>) -> EvalResult<()>,
// a cache of the constants to be computed before the next statement/terminator // 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 // this is an optimization, so we don't have to allocate a new vector for every statement
@ -34,17 +36,15 @@ 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 { pub(super) fn new(fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>) -> Self {
Stepper { Stepper {
fncx: fncx, fncx: fncx,
process: Self::dummy,
constants: Vec::new(), constants: Vec::new(),
} }
} }
fn dummy(&mut self) -> EvalResult<()> { Ok(()) } fn statement<F: for<'f> FnMut(Event<'f, 'tcx>)>(&mut self, mut f: F) -> EvalResult<()> {
fn statement(&mut self) -> EvalResult<()> {
let mir = self.fncx.mir(); let mir = self.fncx.mir();
let block_data = mir.basic_block_data(self.fncx.frame().next_block); let block_data = mir.basic_block_data(self.fncx.frame().next_block);
let stmt = &block_data.statements[self.fncx.frame().stmt]; let stmt = &block_data.statements[self.fncx.frame().stmt];
f(Event::Assignment(stmt));
let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind; let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind;
let result = self.fncx.eval_assignment(lvalue, rvalue); let result = self.fncx.eval_assignment(lvalue, rvalue);
self.fncx.maybe_report(result)?; self.fncx.maybe_report(result)?;
@ -52,33 +52,33 @@ fn statement(&mut self) -> EvalResult<()> {
Ok(()) Ok(())
} }
fn terminator(&mut self) -> EvalResult<()> { fn terminator<F: for<'f> FnMut(Event<'f, 'tcx>)>(&mut self, mut f: F) -> EvalResult<()> {
// after a terminator we go to a new block // after a terminator we go to a new block
self.fncx.frame_mut().stmt = 0; self.fncx.frame_mut().stmt = 0;
let term = { let term = {
let mir = self.fncx.mir(); let mir = self.fncx.mir();
let block_data = mir.basic_block_data(self.fncx.frame().next_block); let block_data = mir.basic_block_data(self.fncx.frame().next_block);
let terminator = block_data.terminator(); let terminator = block_data.terminator();
f(Event::Terminator(terminator));
let result = self.fncx.eval_terminator(terminator); let result = self.fncx.eval_terminator(terminator);
self.fncx.maybe_report(result)? self.fncx.maybe_report(result)?
}; };
match term { match term {
TerminatorTarget::Block => {}, TerminatorTarget::Block => f(Event::Block(self.fncx.frame().next_block)),
TerminatorTarget::Return => { TerminatorTarget::Return => {
f(Event::Return);
self.fncx.pop_stack_frame(); self.fncx.pop_stack_frame();
}, },
TerminatorTarget::Call => {}, TerminatorTarget::Call => f(Event::Call),
} }
Ok(()) Ok(())
} }
pub fn step(&mut self) -> EvalResult<Event> { // returns true as long as there are more things to do
(self.process)(self)?; pub fn step<F: for<'f> FnMut(Event<'f, 'tcx>)>(&mut self, mut f: F) -> EvalResult<()> {
if self.fncx.stack.is_empty() { if self.fncx.stack.is_empty() {
// fuse the iterator f(Event::Done);
self.process = Self::dummy; return Ok(());
return Ok(Event::Done);
} }
let block = self.fncx.frame().next_block; let block = self.fncx.frame().next_block;
@ -97,12 +97,9 @@ pub fn step(&mut self) -> EvalResult<Event> {
mir: &mir, mir: &mir,
}.visit_statement(block, stmt); }.visit_statement(block, stmt);
if self.constants.is_empty() { if self.constants.is_empty() {
self.process = Self::statement; return self.statement(f);
return Ok(Event::Assignment);
} else { } else {
self.process = Self::statement; return self.extract_constants(f);
self.extract_constants();
return Ok(Event::Constant);
} }
} }
@ -117,36 +114,21 @@ pub fn step(&mut self) -> EvalResult<Event> {
mir: &mir, mir: &mir,
}.visit_terminator(block, terminator); }.visit_terminator(block, terminator);
if self.constants.is_empty() { if self.constants.is_empty() {
self.process = Self::terminator; self.terminator(f)
Ok(Event::Terminator)
} else { } else {
self.process = Self::statement; self.extract_constants(f)
self.extract_constants();
Ok(Event::Constant)
} }
} }
fn extract_constants(&mut self) { fn extract_constants<F: for<'f> FnMut(Event<'f, 'tcx>)>(&mut self, mut f: F) -> EvalResult<()> {
assert!(!self.constants.is_empty()); assert!(!self.constants.is_empty());
for (cid, span, return_ptr, mir) in self.constants.drain(..) { for (cid, span, return_ptr, mir) in self.constants.drain(..) {
let def_id = cid.def_id(); let def_id = cid.def_id();
let substs = cid.substs(); let substs = cid.substs();
f(Event::Constant);
self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr)); self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr));
} }
} self.step(f)
/// returns the statement that will be processed next
pub fn stmt(&self) -> &mir::Statement {
&self.fncx.basic_block().statements[self.fncx.frame().stmt]
}
/// returns the terminator of the current block
pub fn term(&self) -> &mir::Terminator {
self.fncx.basic_block().terminator()
}
pub fn block(&self) -> mir::BasicBlock {
self.fncx.frame().next_block
} }
} }