Make step an EvalContext method and remove Stepper.

This commit is contained in:
Scott Olson
2016-06-23 00:02:47 -06:00
parent 3c19db95b8
commit 7bda9f24d6
3 changed files with 41 additions and 52 deletions

View File

@@ -25,10 +25,6 @@ use std::collections::HashMap;
mod stepper; mod stepper;
pub fn step<'ecx, 'a: 'ecx, 'tcx: 'a>(ecx: &'ecx mut EvalContext<'a, 'tcx>) -> EvalResult<'tcx, bool> {
stepper::Stepper::new(ecx).step()
}
pub struct EvalContext<'a, 'tcx: 'a> { pub struct EvalContext<'a, 'tcx: 'a> {
/// The results of the type checker, from rustc. /// The results of the type checker, from rustc.
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -1571,7 +1567,7 @@ pub fn eval_main<'a, 'tcx: 'a>(
} }
loop { loop {
match step(&mut ecx) { match ecx.step() {
Ok(true) => {} Ok(true) => {}
Ok(false) => break, Ok(false) => break,
// FIXME: diverging functions can end up here in some future miri // FIXME: diverging functions can end up here in some future miri

View File

@@ -1,3 +1,7 @@
//! This module contains the `EvalContext` methods for executing a single step of the interpreter.
//!
//! The main entry point is the `step` method.
use super::{ use super::{
CachedMir, CachedMir,
ConstantId, ConstantId,
@@ -12,57 +16,28 @@ use rustc::mir::visit::{Visitor, LvalueContext};
use syntax::codemap::Span; use syntax::codemap::Span;
use std::rc::Rc; use std::rc::Rc;
pub(super) struct Stepper<'ecx, 'a: 'ecx, 'tcx: 'a>{ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
ecx: &'ecx mut EvalContext<'a, 'tcx>, /// Returns true as long as there are more things to do.
} pub fn step(&mut self) -> EvalResult<'tcx, bool> {
if self.stack.is_empty() {
impl<'ecx, 'a, 'tcx> Stepper<'ecx, 'a, 'tcx> {
pub(super) fn new(ecx: &'ecx mut EvalContext<'a, 'tcx>) -> Self {
Stepper {
ecx: ecx,
}
}
fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx, ()> {
trace!("{:?}", stmt);
let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind;
self.ecx.eval_assignment(lvalue, rvalue)?;
self.ecx.frame_mut().stmt += 1;
Ok(())
}
fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<'tcx, ()> {
// after a terminator we go to a new block
self.ecx.frame_mut().stmt = 0;
trace!("{:?}", terminator.kind);
self.ecx.eval_terminator(terminator)?;
if !self.ecx.stack.is_empty() {
trace!("// {:?}", self.ecx.frame().block);
}
Ok(())
}
// returns true as long as there are more things to do
pub(super) fn step(&mut self) -> EvalResult<'tcx, bool> {
if self.ecx.stack.is_empty() {
return Ok(false); return Ok(false);
} }
let block = self.ecx.frame().block; let block = self.frame().block;
let stmt = self.ecx.frame().stmt; let stmt = self.frame().stmt;
let mir = self.ecx.mir(); let mir = self.mir();
let basic_block = &mir.basic_blocks()[block]; let basic_block = &mir.basic_blocks()[block];
if let Some(ref stmt) = basic_block.statements.get(stmt) { if let Some(ref stmt) = basic_block.statements.get(stmt) {
let current_stack = self.ecx.stack.len(); let current_stack = self.stack.len();
ConstantExtractor { ConstantExtractor {
span: stmt.source_info.span, span: stmt.source_info.span,
substs: self.ecx.substs(), substs: self.substs(),
def_id: self.ecx.frame().def_id, def_id: self.frame().def_id,
ecx: self.ecx, ecx: self,
mir: &mir, mir: &mir,
}.visit_statement(block, stmt); }.visit_statement(block, stmt);
if current_stack == self.ecx.stack.len() { if current_stack == self.stack.len() {
self.statement(stmt)?; self.statement(stmt)?;
} else { } else {
// ConstantExtractor added some new frames for statics/constants/promoteds // ConstantExtractor added some new frames for statics/constants/promoteds
@@ -73,15 +48,15 @@ impl<'ecx, 'a, 'tcx> Stepper<'ecx, 'a, 'tcx> {
} }
let terminator = basic_block.terminator(); let terminator = basic_block.terminator();
let current_stack = self.ecx.stack.len(); let current_stack = self.stack.len();
ConstantExtractor { ConstantExtractor {
span: terminator.source_info.span, span: terminator.source_info.span,
substs: self.ecx.substs(), substs: self.substs(),
def_id: self.ecx.frame().def_id, def_id: self.frame().def_id,
ecx: self.ecx, ecx: self,
mir: &mir, mir: &mir,
}.visit_terminator(block, terminator); }.visit_terminator(block, terminator);
if current_stack == self.ecx.stack.len() { if current_stack == self.stack.len() {
self.terminator(terminator)?; self.terminator(terminator)?;
} else { } else {
// ConstantExtractor added some new frames for statics/constants/promoteds // ConstantExtractor added some new frames for statics/constants/promoteds
@@ -90,6 +65,25 @@ impl<'ecx, 'a, 'tcx> Stepper<'ecx, 'a, 'tcx> {
} }
Ok(true) Ok(true)
} }
fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx, ()> {
trace!("{:?}", stmt);
let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind;
self.eval_assignment(lvalue, rvalue)?;
self.frame_mut().stmt += 1;
Ok(())
}
fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<'tcx, ()> {
// after a terminator we go to a new block
self.frame_mut().stmt = 0;
trace!("{:?}", terminator.kind);
self.eval_terminator(terminator)?;
if !self.stack.is_empty() {
trace!("// {:?}", self.frame().block);
}
Ok(())
}
} }
// WARNING: make sure that any methods implemented on this type don't ever access ecx.stack // WARNING: make sure that any methods implemented on this type don't ever access ecx.stack

View File

@@ -36,7 +36,6 @@ pub use interpreter::{
EvalContext, EvalContext,
Frame, Frame,
eval_main, eval_main,
step,
}; };
pub use memory::Memory; pub use memory::Memory;