Skip to content

Commit 91eb6fe

Browse files
committed
Auto merge of #45013 - chrisvittal:mir_pretty_printing_pr, r=nikomatsakis
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.
2 parents 64ee7d1 + 54d63a0 commit 91eb6fe

File tree

7 files changed

+107
-44
lines changed

7 files changed

+107
-44
lines changed

src/librustc_mir/build/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
149149
mem::transmute::<Mir, Mir<'tcx>>(mir)
150150
};
151151

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

154154
mir
155155
})
@@ -227,7 +227,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
227227
mem::transmute::<Mir, Mir<'tcx>>(mir)
228228
};
229229

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

232232
mir
233233
})

src/librustc_mir/transform/dump_mir.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,18 @@ impl PassHook for DumpMir {
6565
pass_name,
6666
&Disambiguator { is_after },
6767
source,
68-
mir);
68+
mir,
69+
|_, _| Ok(()) );
70+
for (index, promoted_mir) in mir.promoted.iter_enumerated() {
71+
let promoted_source = MirSource::Promoted(source.item_id(), index);
72+
mir_util::dump_mir(tcx,
73+
Some((suite, pass_num)),
74+
pass_name,
75+
&Disambiguator { is_after },
76+
promoted_source,
77+
promoted_mir,
78+
|_, _| Ok(()) );
79+
}
6980
}
7081
}
7182
}

src/librustc_mir/transform/generator.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
587587
// unrelated code from the resume part of the function
588588
simplify::remove_dead_blocks(&mut mir);
589589

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

592592
mir
593593
}
@@ -673,7 +673,7 @@ fn create_generator_resume_function<'a, 'tcx>(
673673
// unrelated code from the drop part of the function
674674
simplify::remove_dead_blocks(mir);
675675

676-
dump_mir(tcx, None, "generator_resume", &0, source, mir);
676+
dump_mir(tcx, None, "generator_resume", &0, source, mir, |_, _| Ok(()) );
677677
}
678678

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

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

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

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

828828
// Create a copy of our MIR and use it to create the drop shim for the generator
829829
let drop_shim = create_generator_drop_shim(tcx,

src/librustc_mir/transform/nll/mod.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ use rustc::util::nodemap::FxHashSet;
1919
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
2020
use syntax_pos::DUMMY_SP;
2121
use std::collections::HashMap;
22+
use std::fmt;
23+
24+
use util as mir_util;
25+
use self::mir_util::PassWhere;
2226

2327
#[allow(dead_code)]
2428
struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
@@ -134,7 +138,7 @@ pub struct NLL;
134138
impl MirPass for NLL {
135139
fn run_pass<'a, 'tcx>(&self,
136140
tcx: TyCtxt<'a, 'tcx, 'tcx>,
137-
_: MirSource,
141+
source: MirSource,
138142
mir: &mut Mir<'tcx>) {
139143
if !tcx.sess.opts.debugging_opts.nll {
140144
return;
@@ -145,14 +149,30 @@ impl MirPass for NLL {
145149
let mut renumbered_mir = mir.clone();
146150
let mut visitor = NLLVisitor::new(infcx);
147151
visitor.visit_mir(&mut renumbered_mir);
152+
mir_util::dump_mir(tcx, None, "nll", &0, source, mir, |pass_where, out| {
153+
if let PassWhere::BeforeCFG = pass_where {
154+
for (index, value) in visitor.regions.iter_enumerated() {
155+
writeln!(out, "// R{:03}: {:?}", index.0, value)?;
156+
}
157+
}
158+
Ok(())
159+
});
148160
let _results = visitor.into_results();
149161
})
150162
}
151163
}
152164

153-
#[derive(Clone, Debug, Default, PartialEq, Eq)]
165+
#[derive(Clone, Default, PartialEq, Eq)]
154166
struct Region {
155167
points: FxHashSet<Location>,
156168
}
157169

170+
impl fmt::Debug for Region {
171+
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
172+
write!(formatter, "{:?}", self.points)
173+
}
174+
}
175+
176+
177+
158178
newtype_index!(RegionIndex);

src/librustc_mir/util/liveness.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
232232
writeln!(w, "{} {{{}}}", prefix, live.join(", "))
233233
};
234234
print(w, " ", &result.ins)?;
235-
write_basic_block(tcx, block, mir, w)?;
235+
write_basic_block(tcx, block, mir, &mut |_, _| Ok(()), w)?;
236236
print(w, " ", &result.outs)?;
237237
if block.index() + 1 != mir.basic_blocks().len() {
238238
writeln!(w, "")?;

src/librustc_mir/util/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ mod graphviz;
1717
mod pretty;
1818
pub mod liveness;
1919

20-
pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty};
20+
pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere};
2121
pub use self::graphviz::{write_mir_graphviz};
2222
pub use self::graphviz::write_node_label as write_graphviz_node_label;

src/librustc_mir/util/pretty.rs

+65-33
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,22 @@ const INDENT: &'static str = " ";
2525
/// Alignment for lining up comments following MIR statements
2626
const ALIGN: usize = 40;
2727

28+
/// An indication of where we are in the control flow graph. Used for printing
29+
/// extra information in `dump_mir`
30+
pub enum PassWhere {
31+
/// We have not started dumping the control flow graph, but we are about to.
32+
BeforeCFG,
33+
34+
/// We just finished dumping the control flow graph. This is right before EOF
35+
AfterCFG,
36+
37+
/// We are about to start dumping the given basic block.
38+
BeforeBlock(BasicBlock),
39+
40+
/// We are just about to dumpt the given statement or terminator.
41+
InCFG(Location),
42+
}
43+
2844
/// If the session is properly configured, dumps a human-readable
2945
/// representation of the mir into:
3046
///
@@ -39,12 +55,16 @@ const ALIGN: usize = 40;
3955
/// - `substring1&substring2,...` -- `&`-separated list of substrings
4056
/// that can appear in the pass-name or the `item_path_str` for the given
4157
/// node-id. If any one of the substrings match, the data is dumped out.
42-
pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
43-
pass_num: Option<(MirSuite, MirPassIndex)>,
44-
pass_name: &str,
45-
disambiguator: &Display,
46-
source: MirSource,
47-
mir: &Mir<'tcx>) {
58+
pub fn dump_mir<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
59+
pass_num: Option<(MirSuite, MirPassIndex)>,
60+
pass_name: &str,
61+
disambiguator: &Display,
62+
source: MirSource,
63+
mir: &Mir<'tcx>,
64+
extra_data: F)
65+
where
66+
F: FnMut(PassWhere, &mut Write) -> io::Result<()>
67+
{
4868
if !dump_enabled(tcx, pass_name, source) {
4969
return;
5070
}
@@ -53,12 +73,7 @@ pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
5373
tcx.item_path_str(tcx.hir.local_def_id(source.item_id()))
5474
});
5575
dump_matched_mir_node(tcx, pass_num, pass_name, &node_path,
56-
disambiguator, source, mir);
57-
for (index, promoted_mir) in mir.promoted.iter_enumerated() {
58-
let promoted_source = MirSource::Promoted(source.item_id(), index);
59-
dump_matched_mir_node(tcx, pass_num, pass_name, &node_path, disambiguator,
60-
promoted_source, promoted_mir);
61-
}
76+
disambiguator, source, mir, extra_data);
6277
}
6378

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

88-
fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
89-
pass_num: Option<(MirSuite, MirPassIndex)>,
90-
pass_name: &str,
91-
node_path: &str,
92-
disambiguator: &Display,
93-
source: MirSource,
94-
mir: &Mir<'tcx>) {
103+
fn dump_matched_mir_node<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
104+
pass_num: Option<(MirSuite, MirPassIndex)>,
105+
pass_name: &str,
106+
node_path: &str,
107+
disambiguator: &Display,
108+
source: MirSource,
109+
mir: &Mir<'tcx>,
110+
mut extra_data: F)
111+
where
112+
F: FnMut(PassWhere, &mut Write) -> io::Result<()>
113+
{
95114
let promotion_id = match source {
96115
MirSource::Promoted(_, id) => format!("-{:?}", id),
97116
MirSource::GeneratorDrop(_) => format!("-drop"),
@@ -125,7 +144,9 @@ fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
125144
writeln!(file, "// generator_layout = {:?}", layout)?;
126145
}
127146
writeln!(file, "")?;
128-
write_mir_fn(tcx, source, mir, &mut file)?;
147+
extra_data(PassWhere::BeforeCFG, &mut file)?;
148+
write_mir_fn(tcx, source, mir, &mut extra_data, &mut file)?;
149+
extra_data(PassWhere::AfterCFG, &mut file)?;
129150
Ok(())
130151
});
131152
}
@@ -152,24 +173,29 @@ pub fn write_mir_pretty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
152173

153174
let id = tcx.hir.as_local_node_id(def_id).unwrap();
154175
let src = MirSource::from_node(tcx, id);
155-
write_mir_fn(tcx, src, mir, w)?;
176+
write_mir_fn(tcx, src, mir, &mut |_, _| Ok(()), w)?;
156177

157178
for (i, mir) in mir.promoted.iter_enumerated() {
158179
writeln!(w, "")?;
159-
write_mir_fn(tcx, MirSource::Promoted(id, i), mir, w)?;
180+
write_mir_fn(tcx, MirSource::Promoted(id, i), mir, &mut |_, _| Ok(()), w)?;
160181
}
161182
}
162183
Ok(())
163184
}
164185

165-
pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
166-
src: MirSource,
167-
mir: &Mir<'tcx>,
168-
w: &mut Write)
169-
-> io::Result<()> {
186+
pub fn write_mir_fn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
187+
src: MirSource,
188+
mir: &Mir<'tcx>,
189+
extra_data: &mut F,
190+
w: &mut Write)
191+
-> io::Result<()>
192+
where
193+
F: FnMut(PassWhere, &mut Write) -> io::Result<()>
194+
{
170195
write_mir_intro(tcx, src, mir, w)?;
171196
for block in mir.basic_blocks().indices() {
172-
write_basic_block(tcx, block, mir, w)?;
197+
extra_data(PassWhere::BeforeBlock(block), w)?;
198+
write_basic_block(tcx, block, mir, extra_data, w)?;
173199
if block.index() + 1 != mir.basic_blocks().len() {
174200
writeln!(w, "")?;
175201
}
@@ -180,11 +206,15 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
180206
}
181207

182208
/// Write out a human-readable textual representation for the given basic block.
183-
pub fn write_basic_block(tcx: TyCtxt,
184-
block: BasicBlock,
185-
mir: &Mir,
186-
w: &mut Write)
187-
-> io::Result<()> {
209+
pub fn write_basic_block<F>(tcx: TyCtxt,
210+
block: BasicBlock,
211+
mir: &Mir,
212+
extra_data: &mut F,
213+
w: &mut Write)
214+
-> io::Result<()>
215+
where
216+
F: FnMut(PassWhere, &mut Write) -> io::Result<()>
217+
{
188218
let data = &mir[block];
189219

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

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

0 commit comments

Comments
 (0)