From 2ec959fc35a8b0bdab13c03fcce9c90a929e9bd7 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 22 Nov 2017 17:33:26 -0500 Subject: [PATCH] extend MIR dump with detailed, extra information --- src/librustc_mir/util/pretty.rs | 117 ++++++++++++++++++++++----- src/tools/compiletest/src/runtest.rs | 11 ++- 2 files changed, 104 insertions(+), 24 deletions(-) diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 8a3db0eb25b..98d746952a4 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -11,7 +11,8 @@ use rustc::hir; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::*; -use rustc::ty::TyCtxt; +use rustc::mir::visit::Visitor; +use rustc::ty::{self, TyCtxt}; use rustc::ty::item_path; use rustc_data_structures::fx::FxHashMap; 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<()>, { let _: io::Result<()> = do catch { - let mut file = create_dump_file( - tcx, - "mir", - pass_num, - pass_name, - disambiguator, - source, - )?; + let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?; writeln!(file, "// MIR for `{}`", node_path)?; writeln!(file, "// source = {:?}", source)?; 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 { - let _: io::Result<()> = do catch { - let mut file = create_dump_file( - tcx, - "dot", - pass_num, - pass_name, - disambiguator, - source, - )?; + let _: io::Result<()> = do catch { + let mut file = + create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, source)?; write_mir_fn_graphviz(tcx, source.def_id, mir, &mut file)?; Ok(()) }; @@ -297,10 +285,10 @@ pub fn write_mir_fn<'a, 'gcx, 'tcx, F>( } /// Write out a human-readable textual representation for the given basic block. -pub fn write_basic_block( - tcx: TyCtxt, +pub fn write_basic_block<'cx, 'gcx, 'tcx, F>( + tcx: TyCtxt<'cx, 'gcx, 'tcx>, block: BasicBlock, - mir: &Mir, + mir: &Mir<'tcx>, extra_data: &mut F, w: &mut Write, ) -> io::Result<()> @@ -330,6 +318,11 @@ pub fn write_basic_block( comment(tcx, statement.source_info), A = ALIGN, )?; + + write_extra(tcx, w, |visitor| { + visitor.visit_statement(current_location.block, statement, current_location); + })?; + extra_data(PassWhere::AfterLocation(current_location), w)?; current_location.statement_index += 1; @@ -346,11 +339,93 @@ pub fn write_basic_block( comment(tcx, data.terminator().source_info), A = ALIGN, )?; + + write_extra(tcx, w, |visitor| { + visitor.visit_terminator(current_location.block, data.terminator(), current_location); + })?; + extra_data(PassWhere::AfterLocation(current_location), w)?; 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, +} + +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 { format!( "scope {} at {}", diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 91d51d359ec..a18f4ec1aad 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2535,7 +2535,10 @@ fn compare_mir_test_output(&self, test_name: &str, expected_content: &[ExpectedL let mut dumped_file = fs::File::open(output_file.clone()).unwrap(); let mut dumped_string = String::new(); 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 .iter() .filter(|&l| { @@ -2573,7 +2576,7 @@ fn compare_mir_test_output(&self, test_name: &str, expected_content: &[ExpectedL .join("\n"); panic!( "Did not find expected line, error: {}\n\ - Actual Line: {:?}\n\ + Expected Line: {:?}\n\ Expected:\n{}\n\ Actual:\n{}", extra_msg, @@ -2599,7 +2602,9 @@ fn compare_mir_test_output(&self, test_name: &str, expected_content: &[ExpectedL error( expected_line, format!( - "Mismatch in lines\nCurrnt block: {}\nExpected Line: {:?}", + "Mismatch in lines\n\ + Current block: {}\n\ + Actual Line: {:?}", start_block_line.unwrap_or("None"), dumped_line ), -- GitLab