Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

various fixes and refactorings #20

Merged
merged 12 commits into from
Jun 10, 2016
87 changes: 84 additions & 3 deletions src/bin/miri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,21 @@ extern crate rustc;
extern crate rustc_driver;
extern crate env_logger;
extern crate log_settings;
extern crate log;
extern crate syntax;
#[macro_use] extern crate log;

use miri::interpreter;
use miri::{
EvalContext,
CachedMir,
step,
EvalError,
Frame,
};
use rustc::session::Session;
use rustc_driver::{driver, CompilerCalls};
use rustc::ty::{TyCtxt, subst};
use rustc::mir::mir_map::MirMap;
use rustc::hir::def_id::DefId;

struct MiriCompilerCalls;

Expand All @@ -25,13 +35,84 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {

control.after_analysis.callback = Box::new(|state| {
state.session.abort_if_errors();
interpreter::interpret_start_points(state.tcx.unwrap(), state.mir_map.unwrap());
interpret_start_points(state.tcx.unwrap(), state.mir_map.unwrap());
});

control
}
}



fn interpret_start_points<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir_map: &MirMap<'tcx>,
) {
let initial_indentation = ::log_settings::settings().indentation;
for (&id, mir) in &mir_map.map {
for attr in tcx.map.attrs(id) {
use syntax::attr::AttrMetaMethods;
if attr.check_name("miri_run") {
let item = tcx.map.expect_item(id);

::log_settings::settings().indentation = initial_indentation;

debug!("Interpreting: {}", item.name);

let mut ecx = EvalContext::new(tcx, mir_map);
let substs = tcx.mk_substs(subst::Substs::empty());
let return_ptr = ecx.alloc_ret_ptr(mir.return_ty, substs);

ecx.push_stack_frame(tcx.map.local_def_id(id), mir.span, CachedMir::Ref(mir), substs, return_ptr);

loop {
match (step(&mut ecx), return_ptr) {
(Ok(true), _) => {},
(Ok(false), Some(ptr)) => if log_enabled!(::log::LogLevel::Debug) {
ecx.memory().dump(ptr.alloc_id);
break;
},
(Ok(false), None) => {
warn!("diverging function returned");
break;
},
// FIXME: diverging functions can end up here in some future miri
(Err(e), _) => {
report(tcx, &ecx, e);
break;
},
}
}
}
}
}
}

fn report(tcx: TyCtxt, ecx: &EvalContext, e: EvalError) {
let frame = ecx.stack().last().expect("stackframe was empty");
let block = frame.mir.basic_block_data(frame.next_block);
let span = if frame.stmt < block.statements.len() {
block.statements[frame.stmt].span
} else {
block.terminator().span
};
let mut err = tcx.sess.struct_span_err(span, &e.to_string());
for &Frame { def_id, substs, span, .. } in ecx.stack().iter().rev() {
// FIXME(solson): Find a way to do this without this Display impl hack.
use rustc::util::ppaux;
use std::fmt;
struct Instance<'tcx>(DefId, &'tcx subst::Substs<'tcx>);
impl<'tcx> fmt::Display for Instance<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
ppaux::parameterized(f, self.1, self.0, ppaux::Ns::Value, &[],
|tcx| tcx.lookup_item_type(self.0).generics)
}
}
err.span_note(span, &format!("inside call to {}", Instance(def_id, substs)));
}
err.emit();
}

#[miri_run]
fn main() {
init_logger();
Expand Down
Loading