Skip to content

Commit a8d0812

Browse files
authored
Merge pull request rust-lang#20 from oli-obk/error_reporting
various fixes and refactorings
2 parents 1186a7d + cea2a8a commit a8d0812

File tree

4 files changed

+228
-292
lines changed

4 files changed

+228
-292
lines changed

src/bin/miri.rs

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,21 @@ extern crate rustc;
77
extern crate rustc_driver;
88
extern crate env_logger;
99
extern crate log_settings;
10-
extern crate log;
10+
extern crate syntax;
11+
#[macro_use] extern crate log;
1112

12-
use miri::interpreter;
13+
use miri::{
14+
EvalContext,
15+
CachedMir,
16+
step,
17+
EvalError,
18+
Frame,
19+
};
1320
use rustc::session::Session;
1421
use rustc_driver::{driver, CompilerCalls};
22+
use rustc::ty::{TyCtxt, subst};
23+
use rustc::mir::mir_map::MirMap;
24+
use rustc::hir::def_id::DefId;
1525

1626
struct MiriCompilerCalls;
1727

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

2636
control.after_analysis.callback = Box::new(|state| {
2737
state.session.abort_if_errors();
28-
interpreter::interpret_start_points(state.tcx.unwrap(), state.mir_map.unwrap());
38+
interpret_start_points(state.tcx.unwrap(), state.mir_map.unwrap());
2939
});
3040

3141
control
3242
}
3343
}
3444

45+
46+
47+
fn interpret_start_points<'a, 'tcx>(
48+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
49+
mir_map: &MirMap<'tcx>,
50+
) {
51+
let initial_indentation = ::log_settings::settings().indentation;
52+
for (&id, mir) in &mir_map.map {
53+
for attr in tcx.map.attrs(id) {
54+
use syntax::attr::AttrMetaMethods;
55+
if attr.check_name("miri_run") {
56+
let item = tcx.map.expect_item(id);
57+
58+
::log_settings::settings().indentation = initial_indentation;
59+
60+
debug!("Interpreting: {}", item.name);
61+
62+
let mut ecx = EvalContext::new(tcx, mir_map);
63+
let substs = tcx.mk_substs(subst::Substs::empty());
64+
let return_ptr = ecx.alloc_ret_ptr(mir.return_ty, substs);
65+
66+
ecx.push_stack_frame(tcx.map.local_def_id(id), mir.span, CachedMir::Ref(mir), substs, return_ptr);
67+
68+
loop {
69+
match (step(&mut ecx), return_ptr) {
70+
(Ok(true), _) => {},
71+
(Ok(false), Some(ptr)) => if log_enabled!(::log::LogLevel::Debug) {
72+
ecx.memory().dump(ptr.alloc_id);
73+
break;
74+
},
75+
(Ok(false), None) => {
76+
warn!("diverging function returned");
77+
break;
78+
},
79+
// FIXME: diverging functions can end up here in some future miri
80+
(Err(e), _) => {
81+
report(tcx, &ecx, e);
82+
break;
83+
},
84+
}
85+
}
86+
}
87+
}
88+
}
89+
}
90+
91+
fn report(tcx: TyCtxt, ecx: &EvalContext, e: EvalError) {
92+
let frame = ecx.stack().last().expect("stackframe was empty");
93+
let block = frame.mir.basic_block_data(frame.next_block);
94+
let span = if frame.stmt < block.statements.len() {
95+
block.statements[frame.stmt].span
96+
} else {
97+
block.terminator().span
98+
};
99+
let mut err = tcx.sess.struct_span_err(span, &e.to_string());
100+
for &Frame { def_id, substs, span, .. } in ecx.stack().iter().rev() {
101+
// FIXME(solson): Find a way to do this without this Display impl hack.
102+
use rustc::util::ppaux;
103+
use std::fmt;
104+
struct Instance<'tcx>(DefId, &'tcx subst::Substs<'tcx>);
105+
impl<'tcx> fmt::Display for Instance<'tcx> {
106+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
107+
ppaux::parameterized(f, self.1, self.0, ppaux::Ns::Value, &[],
108+
|tcx| tcx.lookup_item_type(self.0).generics)
109+
}
110+
}
111+
err.span_note(span, &format!("inside call to {}", Instance(def_id, substs)));
112+
}
113+
err.emit();
114+
}
115+
35116
#[miri_run]
36117
fn main() {
37118
init_logger();

0 commit comments

Comments
 (0)