Skip to content

Commit

Permalink
Auto merge of #45013 - chrisvittal:mir_pretty_printing_pr, r=nikomats…
Browse files Browse the repository at this point in the history
…akis

Extend mir dump to dump each region

Building on #44878, implement the feature discussed in #44872.

Through discussions on the WG-nll-gitter, @nikomatsakis and I decided to implement this by extending `dump_mir` and all functions that it calls to take a callback of signature `FnMut(PassWhere, &mut Write) -> io::Result<()>` where `PassWhere` is an enum that represents possible locations that we may want to print out extra data in the process of dumping the MIR.

I'm not particularly wedded to the name `PassWhere`, but I felt that simply calling the enum `Where` wasn't the right thing to name it.

This work depends strongly on #44878, and should be rebased on the final version of that tree, whatever that may be.
  • Loading branch information
bors committed Oct 13, 2017
2 parents 64ee7d1 + 54d63a0 commit 91eb6fe
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 44 deletions.
4 changes: 2 additions & 2 deletions src/librustc_mir/build/mod.rs
Expand Up @@ -149,7 +149,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
mem::transmute::<Mir, Mir<'tcx>>(mir)
};

mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir);
mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir, |_, _| Ok(()) );

mir
})
Expand Down Expand Up @@ -227,7 +227,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
mem::transmute::<Mir, Mir<'tcx>>(mir)
};

mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir);
mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir, |_, _| Ok(()) );

mir
})
Expand Down
13 changes: 12 additions & 1 deletion src/librustc_mir/transform/dump_mir.rs
Expand Up @@ -65,7 +65,18 @@ impl PassHook for DumpMir {
pass_name,
&Disambiguator { is_after },
source,
mir);
mir,
|_, _| Ok(()) );
for (index, promoted_mir) in mir.promoted.iter_enumerated() {
let promoted_source = MirSource::Promoted(source.item_id(), index);
mir_util::dump_mir(tcx,
Some((suite, pass_num)),
pass_name,
&Disambiguator { is_after },
promoted_source,
promoted_mir,
|_, _| Ok(()) );
}
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_mir/transform/generator.rs
Expand Up @@ -587,7 +587,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
// unrelated code from the resume part of the function
simplify::remove_dead_blocks(&mut mir);

dump_mir(tcx, None, "generator_drop", &0, source, &mut mir);
dump_mir(tcx, None, "generator_drop", &0, source, &mut mir, |_, _| Ok(()) );

mir
}
Expand Down Expand Up @@ -673,7 +673,7 @@ fn create_generator_resume_function<'a, 'tcx>(
// unrelated code from the drop part of the function
simplify::remove_dead_blocks(mir);

dump_mir(tcx, None, "generator_resume", &0, source, mir);
dump_mir(tcx, None, "generator_resume", &0, source, mir, |_, _| Ok(()) );
}

fn source_info<'a, 'tcx>(mir: &Mir<'tcx>) -> SourceInfo {
Expand Down Expand Up @@ -816,14 +816,14 @@ impl MirPass for StateTransform {
// This is expanded to a drop ladder in `elaborate_generator_drops`.
let drop_clean = insert_clean_drop(mir);

dump_mir(tcx, None, "generator_pre-elab", &0, source, mir);
dump_mir(tcx, None, "generator_pre-elab", &0, source, mir, |_, _| Ok(()) );

// Expand `drop(generator_struct)` to a drop ladder which destroys upvars.
// If any upvars are moved out of, drop elaboration will handle upvar destruction.
// However we need to also elaborate the code generated by `insert_clean_drop`.
elaborate_generator_drops(tcx, def_id, mir);

dump_mir(tcx, None, "generator_post-transform", &0, source, mir);
dump_mir(tcx, None, "generator_post-transform", &0, source, mir, |_, _| Ok(()) );

// Create a copy of our MIR and use it to create the drop shim for the generator
let drop_shim = create_generator_drop_shim(tcx,
Expand Down
24 changes: 22 additions & 2 deletions src/librustc_mir/transform/nll/mod.rs
Expand Up @@ -19,6 +19,10 @@ use rustc::util::nodemap::FxHashSet;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use syntax_pos::DUMMY_SP;
use std::collections::HashMap;
use std::fmt;

use util as mir_util;
use self::mir_util::PassWhere;

#[allow(dead_code)]
struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
Expand Down Expand Up @@ -134,7 +138,7 @@ pub struct NLL;
impl MirPass for NLL {
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_: MirSource,
source: MirSource,
mir: &mut Mir<'tcx>) {
if !tcx.sess.opts.debugging_opts.nll {
return;
Expand All @@ -145,14 +149,30 @@ impl MirPass for NLL {
let mut renumbered_mir = mir.clone();
let mut visitor = NLLVisitor::new(infcx);
visitor.visit_mir(&mut renumbered_mir);
mir_util::dump_mir(tcx, None, "nll", &0, source, mir, |pass_where, out| {
if let PassWhere::BeforeCFG = pass_where {
for (index, value) in visitor.regions.iter_enumerated() {
writeln!(out, "// R{:03}: {:?}", index.0, value)?;
}
}
Ok(())
});
let _results = visitor.into_results();
})
}
}

#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[derive(Clone, Default, PartialEq, Eq)]
struct Region {
points: FxHashSet<Location>,
}

impl fmt::Debug for Region {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(formatter, "{:?}", self.points)
}
}



newtype_index!(RegionIndex);
2 changes: 1 addition & 1 deletion src/librustc_mir/util/liveness.rs
Expand Up @@ -232,7 +232,7 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
writeln!(w, "{} {{{}}}", prefix, live.join(", "))
};
print(w, " ", &result.ins)?;
write_basic_block(tcx, block, mir, w)?;
write_basic_block(tcx, block, mir, &mut |_, _| Ok(()), w)?;
print(w, " ", &result.outs)?;
if block.index() + 1 != mir.basic_blocks().len() {
writeln!(w, "")?;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/util/mod.rs
Expand Up @@ -17,6 +17,6 @@ mod graphviz;
mod pretty;
pub mod liveness;

pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty};
pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere};
pub use self::graphviz::{write_mir_graphviz};
pub use self::graphviz::write_node_label as write_graphviz_node_label;
98 changes: 65 additions & 33 deletions src/librustc_mir/util/pretty.rs
Expand Up @@ -25,6 +25,22 @@ const INDENT: &'static str = " ";
/// Alignment for lining up comments following MIR statements
const ALIGN: usize = 40;

/// An indication of where we are in the control flow graph. Used for printing
/// extra information in `dump_mir`
pub enum PassWhere {
/// We have not started dumping the control flow graph, but we are about to.
BeforeCFG,

/// We just finished dumping the control flow graph. This is right before EOF
AfterCFG,

/// We are about to start dumping the given basic block.
BeforeBlock(BasicBlock),

/// We are just about to dumpt the given statement or terminator.
InCFG(Location),
}

/// If the session is properly configured, dumps a human-readable
/// representation of the mir into:
///
Expand All @@ -39,12 +55,16 @@ const ALIGN: usize = 40;
/// - `substring1&substring2,...` -- `&`-separated list of substrings
/// that can appear in the pass-name or the `item_path_str` for the given
/// node-id. If any one of the substrings match, the data is dumped out.
pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
pass_num: Option<(MirSuite, MirPassIndex)>,
pass_name: &str,
disambiguator: &Display,
source: MirSource,
mir: &Mir<'tcx>) {
pub fn dump_mir<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
pass_num: Option<(MirSuite, MirPassIndex)>,
pass_name: &str,
disambiguator: &Display,
source: MirSource,
mir: &Mir<'tcx>,
extra_data: F)
where
F: FnMut(PassWhere, &mut Write) -> io::Result<()>
{
if !dump_enabled(tcx, pass_name, source) {
return;
}
Expand All @@ -53,12 +73,7 @@ pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
tcx.item_path_str(tcx.hir.local_def_id(source.item_id()))
});
dump_matched_mir_node(tcx, pass_num, pass_name, &node_path,
disambiguator, source, mir);
for (index, promoted_mir) in mir.promoted.iter_enumerated() {
let promoted_source = MirSource::Promoted(source.item_id(), index);
dump_matched_mir_node(tcx, pass_num, pass_name, &node_path, disambiguator,
promoted_source, promoted_mir);
}
disambiguator, source, mir, extra_data);
}

pub fn dump_enabled<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Expand All @@ -85,13 +100,17 @@ pub fn dump_enabled<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// `item_path_str()` would otherwise trigger `type_of`, and this can
// run while we are already attempting to evaluate `type_of`.

fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
pass_num: Option<(MirSuite, MirPassIndex)>,
pass_name: &str,
node_path: &str,
disambiguator: &Display,
source: MirSource,
mir: &Mir<'tcx>) {
fn dump_matched_mir_node<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
pass_num: Option<(MirSuite, MirPassIndex)>,
pass_name: &str,
node_path: &str,
disambiguator: &Display,
source: MirSource,
mir: &Mir<'tcx>,
mut extra_data: F)
where
F: FnMut(PassWhere, &mut Write) -> io::Result<()>
{
let promotion_id = match source {
MirSource::Promoted(_, id) => format!("-{:?}", id),
MirSource::GeneratorDrop(_) => format!("-drop"),
Expand Down Expand Up @@ -125,7 +144,9 @@ fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
writeln!(file, "// generator_layout = {:?}", layout)?;
}
writeln!(file, "")?;
write_mir_fn(tcx, source, mir, &mut file)?;
extra_data(PassWhere::BeforeCFG, &mut file)?;
write_mir_fn(tcx, source, mir, &mut extra_data, &mut file)?;
extra_data(PassWhere::AfterCFG, &mut file)?;
Ok(())
});
}
Expand All @@ -152,24 +173,29 @@ pub fn write_mir_pretty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,

let id = tcx.hir.as_local_node_id(def_id).unwrap();
let src = MirSource::from_node(tcx, id);
write_mir_fn(tcx, src, mir, w)?;
write_mir_fn(tcx, src, mir, &mut |_, _| Ok(()), w)?;

for (i, mir) in mir.promoted.iter_enumerated() {
writeln!(w, "")?;
write_mir_fn(tcx, MirSource::Promoted(id, i), mir, w)?;
write_mir_fn(tcx, MirSource::Promoted(id, i), mir, &mut |_, _| Ok(()), w)?;
}
}
Ok(())
}

pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource,
mir: &Mir<'tcx>,
w: &mut Write)
-> io::Result<()> {
pub fn write_mir_fn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource,
mir: &Mir<'tcx>,
extra_data: &mut F,
w: &mut Write)
-> io::Result<()>
where
F: FnMut(PassWhere, &mut Write) -> io::Result<()>
{
write_mir_intro(tcx, src, mir, w)?;
for block in mir.basic_blocks().indices() {
write_basic_block(tcx, block, mir, w)?;
extra_data(PassWhere::BeforeBlock(block), w)?;
write_basic_block(tcx, block, mir, extra_data, w)?;
if block.index() + 1 != mir.basic_blocks().len() {
writeln!(w, "")?;
}
Expand All @@ -180,11 +206,15 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}

/// Write out a human-readable textual representation for the given basic block.
pub fn write_basic_block(tcx: TyCtxt,
block: BasicBlock,
mir: &Mir,
w: &mut Write)
-> io::Result<()> {
pub fn write_basic_block<F>(tcx: TyCtxt,
block: BasicBlock,
mir: &Mir,
extra_data: &mut F,
w: &mut Write)
-> io::Result<()>
where
F: FnMut(PassWhere, &mut Write) -> io::Result<()>
{
let data = &mir[block];

// Basic block label at the top.
Expand All @@ -195,6 +225,7 @@ pub fn write_basic_block(tcx: TyCtxt,
// List of statements in the middle.
let mut current_location = Location { block: block, statement_index: 0 };
for statement in &data.statements {
extra_data(PassWhere::InCFG(current_location), w)?;
let indented_mir = format!("{0}{0}{1:?};", INDENT, statement);
writeln!(w, "{0:1$} // {2}",
indented_mir,
Expand All @@ -205,6 +236,7 @@ pub fn write_basic_block(tcx: TyCtxt,
}

// Terminator at the bottom.
extra_data(PassWhere::InCFG(current_location), w)?;
let indented_terminator = format!("{0}{0}{1:?};", INDENT, data.terminator().kind);
writeln!(w, "{0:1$} // {2}",
indented_terminator,
Expand Down

0 comments on commit 91eb6fe

Please sign in to comment.