Skip to content

Commit 96b178b

Browse files
Some simple improvements to MIR pretty printing
In short, this PR changes the MIR printer so that it: * places an empty line between the MIR for each item * does *not* write an empty line before the first BB when there are no var decls * aligns the "// Scope" comments 50 chars in (makes the output more readable) * prints the scope comments as "// scope N at ..." instead of "// Scope(N) at ..." * prints a prettier scope tree: * no more unbalanced delimiters! * no more "Parent" entry (these convey no useful information) * drop the "Scope()" and just print scope IDs * no braces when the scope is empty
1 parent e88defe commit 96b178b

File tree

1 file changed

+55
-22
lines changed

1 file changed

+55
-22
lines changed

src/librustc_mir/pretty.rs

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ use syntax::ast::NodeId;
2121
use syntax::codemap::Span;
2222

2323
const INDENT: &'static str = " ";
24+
/// Alignment for lining up comments following MIR statements
25+
const ALIGN: usize = 50;
2426

2527
/// If the session is properly configured, dumps a human-readable
2628
/// representation of the mir into:
@@ -79,11 +81,20 @@ pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
7981
-> io::Result<()>
8082
where I: Iterator<Item=(&'a NodeId, &'a Mir<'tcx>)>, 'tcx: 'a
8183
{
84+
let mut first = true;
8285
for (&id, mir) in iter {
86+
if first {
87+
first = false;
88+
} else {
89+
// Put empty lines between all items
90+
writeln!(w, "")?;
91+
}
92+
8393
let src = MirSource::from_node(tcx, id);
8494
write_mir_fn(tcx, src, mir, w, None)?;
8595

8696
for (i, mir) in mir.promoted.iter().enumerate() {
97+
writeln!(w, "")?;
8798
write_mir_fn(tcx, MirSource::Promoted(id, i), mir, w, None)?;
8899
}
89100
}
@@ -131,6 +142,8 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
131142
.or_insert(vec![])
132143
.push(ScopeId::new(index));
133144
}
145+
146+
writeln!(w, "{}scope tree:", INDENT)?;
134147
write_scope_tree(tcx, mir, auxiliary, &scope_tree, w, None, 1)?;
135148

136149
writeln!(w, "}}")?;
@@ -147,7 +160,7 @@ fn write_basic_block(tcx: TyCtxt,
147160
let data = mir.basic_block_data(block);
148161

149162
// Basic block label at the top.
150-
writeln!(w, "\n{}{:?}: {{", INDENT, block)?;
163+
writeln!(w, "{}{:?}: {{", INDENT, block)?;
151164

152165
// List of statements in the middle.
153166
let mut current_location = Location { block: block, statement_index: 0 };
@@ -165,25 +178,27 @@ fn write_basic_block(tcx: TyCtxt,
165178
}
166179
}
167180

168-
writeln!(w, "{0}{0}{1:?}; // {2}",
169-
INDENT,
170-
statement,
181+
let indented_mir = format!("{0}{0}{1:?};", INDENT, statement);
182+
writeln!(w, "{0:1$} // {2}",
183+
indented_mir,
184+
ALIGN,
171185
comment(tcx, statement.scope, statement.span))?;
172186

173187
current_location.statement_index += 1;
174188
}
175189

176190
// Terminator at the bottom.
177-
writeln!(w, "{0}{0}{1:?}; // {2}",
178-
INDENT,
179-
data.terminator().kind,
191+
let indented_terminator = format!("{0}{0}{1:?};", INDENT, data.terminator().kind);
192+
writeln!(w, "{0:1$} // {2}",
193+
indented_terminator,
194+
ALIGN,
180195
comment(tcx, data.terminator().scope, data.terminator().span))?;
181196

182-
writeln!(w, "{}}}", INDENT)
197+
writeln!(w, "{}}}\n", INDENT)
183198
}
184199

185200
fn comment(tcx: TyCtxt, scope: ScopeId, span: Span) -> String {
186-
format!("Scope({}) at {}", scope.index(), tcx.sess.codemap().span_to_string(span))
201+
format!("scope {} at {}", scope.index(), tcx.sess.codemap().span_to_string(span))
187202
}
188203

189204
fn write_scope_tree(tcx: TyCtxt,
@@ -198,22 +213,28 @@ fn write_scope_tree(tcx: TyCtxt,
198213
let indent = depth * INDENT.len();
199214
let data = &mir.scopes[child];
200215
assert_eq!(data.parent_scope, parent);
201-
writeln!(w, "{0:1$}Scope({2}) {{", "", indent, child.index())?;
216+
write!(w, "{0:1$}{2}", "", indent, child.index())?;
202217

203218
let indent = indent + INDENT.len();
204-
if let Some(parent) = parent {
205-
writeln!(w, "{0:1$}Parent: Scope({2})", "", indent, parent.index())?;
206-
}
207219

208220
if let Some(auxiliary) = auxiliary {
209221
let extent = auxiliary[child].extent;
210222
let data = tcx.region_maps.code_extent_data(extent);
211223
writeln!(w, "{0:1$}Extent: {2:?}", "", indent, data)?;
212224
}
213225

214-
write_scope_tree(tcx, mir, auxiliary, scope_tree, w,
215-
Some(child), depth + 1)?;
226+
if scope_tree.get(&Some(child)).map(Vec::is_empty).unwrap_or(true) {
227+
// No child scopes, skip the braces
228+
writeln!(w, "")?;
229+
} else {
230+
writeln!(w, " {{")?;
231+
write_scope_tree(tcx, mir, auxiliary, scope_tree, w,
232+
Some(child), depth + 1)?;
233+
234+
writeln!(w, "{0:1$}}}", "", indent - INDENT.len())?;
235+
}
216236
}
237+
217238
Ok(())
218239
}
219240

@@ -261,13 +282,20 @@ fn write_mir_intro<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
261282

262283
// User variable types (including the user's name in a comment).
263284
for (i, var) in mir.var_decls.iter().enumerate() {
264-
write!(w, "{}let ", INDENT)?;
265-
if var.mutability == Mutability::Mut {
266-
write!(w, "mut ")?;
267-
}
268-
writeln!(w, "{:?}: {}; // {} in {}",
269-
Lvalue::Var(i as u32),
270-
var.ty,
285+
let mut_str = if var.mutability == Mutability::Mut {
286+
"mut "
287+
} else {
288+
""
289+
};
290+
291+
let indented_var = format!("{}let {}{:?}: {};",
292+
INDENT,
293+
mut_str,
294+
Lvalue::Var(i as u32),
295+
var.ty);
296+
writeln!(w, "{0:1$} // \"{2}\" in {3}",
297+
indented_var,
298+
ALIGN,
271299
var.name,
272300
comment(tcx, var.scope, var.span))?;
273301
}
@@ -277,5 +305,10 @@ fn write_mir_intro<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
277305
writeln!(w, "{}let mut {:?}: {};", INDENT, Lvalue::Temp(i as u32), temp.ty)?;
278306
}
279307

308+
// Wrote any declaration? Add an empty line before the first block is printed.
309+
if !mir.var_decls.is_empty() || !mir.temp_decls.is_empty() {
310+
writeln!(w, "")?;
311+
}
312+
280313
Ok(())
281314
}

0 commit comments

Comments
 (0)