extend MIR dump with detailed, extra information

This commit is contained in:
Niko Matsakis 2017-11-22 17:33:26 -05:00
parent e5dc4ba280
commit 2ec959fc35
2 changed files with 104 additions and 24 deletions

View File

@ -11,7 +11,8 @@
use rustc::hir; use rustc::hir;
use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::mir::*; use rustc::mir::*;
use rustc::ty::TyCtxt; use rustc::mir::visit::Visitor;
use rustc::ty::{self, TyCtxt};
use rustc::ty::item_path; use rustc::ty::item_path;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::Idx;
@ -125,14 +126,7 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
F: FnMut(PassWhere, &mut Write) -> io::Result<()>, F: FnMut(PassWhere, &mut Write) -> io::Result<()>,
{ {
let _: io::Result<()> = do catch { let _: io::Result<()> = do catch {
let mut file = create_dump_file( let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?;
tcx,
"mir",
pass_num,
pass_name,
disambiguator,
source,
)?;
writeln!(file, "// MIR for `{}`", node_path)?; writeln!(file, "// MIR for `{}`", node_path)?;
writeln!(file, "// source = {:?}", source)?; writeln!(file, "// source = {:?}", source)?;
writeln!(file, "// pass_name = {}", pass_name)?; writeln!(file, "// pass_name = {}", pass_name)?;
@ -148,15 +142,9 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
}; };
if tcx.sess.opts.debugging_opts.dump_mir_graphviz { if tcx.sess.opts.debugging_opts.dump_mir_graphviz {
let _: io::Result<()> = do catch { let _: io::Result<()> = do catch {
let mut file = create_dump_file( let mut file =
tcx, create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, source)?;
"dot",
pass_num,
pass_name,
disambiguator,
source,
)?;
write_mir_fn_graphviz(tcx, source.def_id, mir, &mut file)?; write_mir_fn_graphviz(tcx, source.def_id, mir, &mut file)?;
Ok(()) Ok(())
}; };
@ -297,10 +285,10 @@ where
} }
/// Write out a human-readable textual representation for the given basic block. /// Write out a human-readable textual representation for the given basic block.
pub fn write_basic_block<F>( pub fn write_basic_block<'cx, 'gcx, 'tcx, F>(
tcx: TyCtxt, tcx: TyCtxt<'cx, 'gcx, 'tcx>,
block: BasicBlock, block: BasicBlock,
mir: &Mir, mir: &Mir<'tcx>,
extra_data: &mut F, extra_data: &mut F,
w: &mut Write, w: &mut Write,
) -> io::Result<()> ) -> io::Result<()>
@ -330,6 +318,11 @@ where
comment(tcx, statement.source_info), comment(tcx, statement.source_info),
A = ALIGN, A = ALIGN,
)?; )?;
write_extra(tcx, w, |visitor| {
visitor.visit_statement(current_location.block, statement, current_location);
})?;
extra_data(PassWhere::AfterLocation(current_location), w)?; extra_data(PassWhere::AfterLocation(current_location), w)?;
current_location.statement_index += 1; current_location.statement_index += 1;
@ -346,11 +339,93 @@ where
comment(tcx, data.terminator().source_info), comment(tcx, data.terminator().source_info),
A = ALIGN, A = ALIGN,
)?; )?;
write_extra(tcx, w, |visitor| {
visitor.visit_terminator(current_location.block, data.terminator(), current_location);
})?;
extra_data(PassWhere::AfterLocation(current_location), w)?; extra_data(PassWhere::AfterLocation(current_location), w)?;
writeln!(w, "{}}}", INDENT) writeln!(w, "{}}}", INDENT)
} }
/// After we print the main statement, we sometimes dump extra
/// information. There's often a lot of little things "nuzzled up" in
/// a statement.
fn write_extra<'cx, 'gcx, 'tcx, F>(
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
write: &mut Write,
mut visit_op: F,
) -> io::Result<()>
where F: FnMut(&mut ExtraComments<'cx, 'gcx, 'tcx>)
{
let mut extra_comments = ExtraComments {
_tcx: tcx,
comments: vec![],
};
visit_op(&mut extra_comments);
for comment in extra_comments.comments {
writeln!(write, "{:A$} // {}", "", comment, A = ALIGN)?;
}
Ok(())
}
struct ExtraComments<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
_tcx: TyCtxt<'cx, 'gcx, 'tcx>, // don't need it now, but bet we will soon
comments: Vec<String>,
}
impl<'cx, 'gcx, 'tcx> ExtraComments<'cx, 'gcx, 'tcx> {
fn push(&mut self, lines: &str) {
for line in lines.split("\n") {
self.comments.push(line.to_string());
}
}
}
impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ExtraComments<'cx, 'gcx, 'tcx> {
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
self.super_constant(constant, location);
let Constant { span, ty, literal } = constant;
self.push(&format!("mir::Constant"));
self.push(&format!("└ span: {:?}", span));
self.push(&format!("└ ty: {:?}", ty));
self.push(&format!("└ literal: {:?}", literal));
}
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
self.super_const(constant);
let ty::Const { ty, val } = constant;
self.push(&format!("ty::Const"));
self.push(&format!("└ ty: {:?}", ty));
self.push(&format!("└ val: {:?}", val));
}
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
self.super_rvalue(rvalue, location);
match rvalue {
Rvalue::Aggregate(kind, _) => match **kind {
AggregateKind::Closure(def_id, substs) => {
self.push(&format!("closure"));
self.push(&format!("└ def_id: {:?}", def_id));
self.push(&format!("└ substs: {:#?}", substs));
}
AggregateKind::Generator(def_id, substs, interior) => {
self.push(&format!("generator"));
self.push(&format!("└ def_id: {:?}", def_id));
self.push(&format!("└ substs: {:#?}", substs));
self.push(&format!("└ interior: {:?}", interior));
}
_ => {}
},
_ => {}
}
}
}
fn comment(tcx: TyCtxt, SourceInfo { span, scope }: SourceInfo) -> String { fn comment(tcx: TyCtxt, SourceInfo { span, scope }: SourceInfo) -> String {
format!( format!(
"scope {} at {}", "scope {} at {}",

View File

@ -2535,7 +2535,10 @@ impl<'test> TestCx<'test> {
let mut dumped_file = fs::File::open(output_file.clone()).unwrap(); let mut dumped_file = fs::File::open(output_file.clone()).unwrap();
let mut dumped_string = String::new(); let mut dumped_string = String::new();
dumped_file.read_to_string(&mut dumped_string).unwrap(); dumped_file.read_to_string(&mut dumped_string).unwrap();
let mut dumped_lines = dumped_string.lines().filter(|l| !l.is_empty()); let mut dumped_lines = dumped_string
.lines()
.map(|l| nocomment_mir_line(l))
.filter(|l| !l.is_empty());
let mut expected_lines = expected_content let mut expected_lines = expected_content
.iter() .iter()
.filter(|&l| { .filter(|&l| {
@ -2573,7 +2576,7 @@ impl<'test> TestCx<'test> {
.join("\n"); .join("\n");
panic!( panic!(
"Did not find expected line, error: {}\n\ "Did not find expected line, error: {}\n\
Actual Line: {:?}\n\ Expected Line: {:?}\n\
Expected:\n{}\n\ Expected:\n{}\n\
Actual:\n{}", Actual:\n{}",
extra_msg, extra_msg,
@ -2599,7 +2602,9 @@ impl<'test> TestCx<'test> {
error( error(
expected_line, expected_line,
format!( format!(
"Mismatch in lines\nCurrnt block: {}\nExpected Line: {:?}", "Mismatch in lines\n\
Current block: {}\n\
Actual Line: {:?}",
start_block_line.unwrap_or("None"), start_block_line.unwrap_or("None"),
dumped_line dumped_line
), ),