Skip to content

Commit 5ce3797

Browse files
committed
Introduce MirDumper and MirWriter.
MIR dumping is a mess. There are lots of functions and entry points, e.g. `dump_mir`, `dump_mir_with_options`, `dump_polonius_mir`, `dump_mir_to_writer`. Also, it's crucial that `create_dump_file` is never called without `dump_enabled` first being checked, but there is no mechanism for ensuring this and it's hard to tell if it is satisfied on all paths. (`dump_enabled` is checked twice on some paths, however!) This commit introduces `MirWriter`, which controls the MIR writing, and encapsulates the `extra_data` closure and `options`. Two existing functions are now methods of this type. It sets reasonable defaults, allowing the removal of many `|_, _| Ok(())` closures. The commit also introduces `MirDumper`, which is layered on top of `MirWriter`, and which manages the creation of the dump files, encapsulating pass names, disambiguators, etc. Four existing functions are now methods of this type. - `MirDumper::new` will only succeed if dumps are enabled, and will return `None` otherwise, which makes it impossible to dump when you shouldn't. - It also sets reasonable defaults for various things like disambiguators, which means you no longer need to specify them in many cases. When they do need to be specified, it's now done via setter methods. - It avoids some repetition. E.g. `dump_nll_mir` previously specifed the pass name `"nll"` four times and the disambiguator `&0` three times; now it specifies them just once, to put them in the `MirDumper`. - For Polonius, the `extra_data` closure can now be specified earlier, which avoids having to pass some arguments through some functions.
1 parent 2d21c13 commit 5ce3797

File tree

14 files changed

+275
-276
lines changed

14 files changed

+275
-276
lines changed

compiler/rustc_borrowck/src/nll.rs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use std::str::FromStr;
88
use polonius_engine::{Algorithm, AllFacts, Output};
99
use rustc_data_structures::frozen::Frozen;
1010
use rustc_index::IndexSlice;
11-
use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options};
12-
use rustc_middle::mir::{Body, PassWhere, Promoted, create_dump_file, dump_enabled, dump_mir};
11+
use rustc_middle::mir::pretty::PrettyPrintMirOptions;
12+
use rustc_middle::mir::{Body, MirDumper, PassWhere, Promoted};
1313
use rustc_middle::ty::print::with_no_trimmed_paths;
1414
use rustc_middle::ty::{self, TyCtxt};
1515
use rustc_mir_dataflow::move_paths::MoveData;
@@ -68,7 +68,9 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
6868
// Replace all remaining regions with fresh inference variables.
6969
renumber::renumber_mir(infcx, body, promoted);
7070

71-
dump_mir(infcx.tcx, false, "renumber", &0, body, &|_, _| Ok(()));
71+
if let Some(dumper) = MirDumper::new(infcx.tcx, "renumber", body) {
72+
dumper.dump_mir(body);
73+
}
7274

7375
universal_regions
7476
}
@@ -175,9 +177,7 @@ pub(super) fn dump_nll_mir<'tcx>(
175177
borrow_set: &BorrowSet<'tcx>,
176178
) {
177179
let tcx = infcx.tcx;
178-
if !dump_enabled(tcx, "nll", body.source.def_id()) {
179-
return;
180-
}
180+
let Some(dumper) = MirDumper::new(tcx, "nll", body) else { return };
181181

182182
// We want the NLL extra comments printed by default in NLL MIR dumps (they were removed in
183183
// #112346). Specifying `-Z mir-include-spans` on the CLI still has priority: for example,
@@ -188,27 +188,24 @@ pub(super) fn dump_nll_mir<'tcx>(
188188
MirIncludeSpans::On | MirIncludeSpans::Nll
189189
),
190190
};
191-
dump_mir_with_options(
192-
tcx,
193-
false,
194-
"nll",
195-
&0,
196-
body,
197-
&|pass_where, out| {
198-
emit_nll_mir(tcx, regioncx, closure_region_requirements, borrow_set, pass_where, out)
199-
},
200-
options,
201-
);
191+
192+
let extra_data = &|pass_where, out: &mut dyn std::io::Write| {
193+
emit_nll_mir(tcx, regioncx, closure_region_requirements, borrow_set, pass_where, out)
194+
};
195+
196+
let dumper = dumper.set_extra_data(extra_data).set_options(options);
197+
198+
dumper.dump_mir(body);
202199

203200
// Also dump the region constraint graph as a graphviz file.
204201
let _: io::Result<()> = try {
205-
let mut file = create_dump_file(tcx, "regioncx.all.dot", false, "nll", &0, body)?;
202+
let mut file = dumper.create_dump_file("regioncx.all.dot", body)?;
206203
regioncx.dump_graphviz_raw_constraints(tcx, &mut file)?;
207204
};
208205

209206
// Also dump the region constraint SCC graph as a graphviz file.
210207
let _: io::Result<()> = try {
211-
let mut file = create_dump_file(tcx, "regioncx.scc.dot", false, "nll", &0, body)?;
208+
let mut file = dumper.create_dump_file("regioncx.scc.dot", body)?;
212209
regioncx.dump_graphviz_scc_constraints(tcx, &mut file)?;
213210
};
214211
}

compiler/rustc_borrowck/src/polonius/dump.rs

Lines changed: 32 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ use std::io;
22

33
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
44
use rustc_index::IndexVec;
5-
use rustc_middle::mir::pretty::{
6-
PassWhere, PrettyPrintMirOptions, create_dump_file, dump_enabled, dump_mir_to_writer,
7-
};
5+
use rustc_middle::mir::pretty::{MirDumper, PassWhere, PrettyPrintMirOptions};
86
use rustc_middle::mir::{Body, Location};
97
use rustc_middle::ty::{RegionVid, TyCtxt};
108
use rustc_mir_dataflow::points::PointIndex;
@@ -33,22 +31,41 @@ pub(crate) fn dump_polonius_mir<'tcx>(
3331
return;
3432
}
3533

36-
if !dump_enabled(tcx, "polonius", body.source.def_id()) {
37-
return;
38-
}
34+
let Some(dumper) = MirDumper::new(tcx, "polonius", body) else { return };
3935

4036
let polonius_diagnostics =
4137
polonius_diagnostics.expect("missing diagnostics context with `-Zpolonius=next`");
4238

39+
let extra_data = &|pass_where, out: &mut dyn io::Write| {
40+
emit_polonius_mir(
41+
tcx,
42+
regioncx,
43+
closure_region_requirements,
44+
borrow_set,
45+
&polonius_diagnostics.localized_outlives_constraints,
46+
pass_where,
47+
out,
48+
)
49+
};
50+
// We want the NLL extra comments printed by default in NLL MIR dumps. Specifying `-Z
51+
// mir-include-spans` on the CLI still has priority.
52+
let options = PrettyPrintMirOptions {
53+
include_extra_comments: matches!(
54+
tcx.sess.opts.unstable_opts.mir_include_spans,
55+
MirIncludeSpans::On | MirIncludeSpans::Nll
56+
),
57+
};
58+
59+
let dumper = dumper.set_extra_data(extra_data).set_options(options);
60+
4361
let _: io::Result<()> = try {
44-
let mut file = create_dump_file(tcx, "html", false, "polonius", &0, body)?;
62+
let mut file = dumper.create_dump_file("html", body)?;
4563
emit_polonius_dump(
46-
tcx,
64+
&dumper,
4765
body,
4866
regioncx,
4967
borrow_set,
5068
&polonius_diagnostics.localized_outlives_constraints,
51-
closure_region_requirements,
5269
&mut file,
5370
)?;
5471
};
@@ -61,12 +78,11 @@ pub(crate) fn dump_polonius_mir<'tcx>(
6178
/// - a mermaid graph of the NLL regions and the constraints between them
6279
/// - a mermaid graph of the NLL SCCs and the constraints between them
6380
fn emit_polonius_dump<'tcx>(
64-
tcx: TyCtxt<'tcx>,
81+
dumper: &MirDumper<'_, '_, 'tcx>,
6582
body: &Body<'tcx>,
6683
regioncx: &RegionInferenceContext<'tcx>,
6784
borrow_set: &BorrowSet<'tcx>,
6885
localized_outlives_constraints: &LocalizedOutlivesConstraintSet,
69-
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
7086
out: &mut dyn io::Write,
7187
) -> io::Result<()> {
7288
// Prepare the HTML dump file prologue.
@@ -79,15 +95,7 @@ fn emit_polonius_dump<'tcx>(
7995
writeln!(out, "<div>")?;
8096
writeln!(out, "Raw MIR dump")?;
8197
writeln!(out, "<pre><code>")?;
82-
emit_html_mir(
83-
tcx,
84-
body,
85-
regioncx,
86-
borrow_set,
87-
&localized_outlives_constraints,
88-
closure_region_requirements,
89-
out,
90-
)?;
98+
emit_html_mir(dumper, body, out)?;
9199
writeln!(out, "</code></pre>")?;
92100
writeln!(out, "</div>")?;
93101

@@ -116,15 +124,15 @@ fn emit_polonius_dump<'tcx>(
116124
writeln!(out, "<div>")?;
117125
writeln!(out, "NLL regions")?;
118126
writeln!(out, "<pre class='mermaid'>")?;
119-
emit_mermaid_nll_regions(tcx, regioncx, out)?;
127+
emit_mermaid_nll_regions(dumper.tcx(), regioncx, out)?;
120128
writeln!(out, "</pre>")?;
121129
writeln!(out, "</div>")?;
122130

123131
// Section 5: mermaid visualization of the NLL SCC graph.
124132
writeln!(out, "<div>")?;
125133
writeln!(out, "NLL SCCs")?;
126134
writeln!(out, "<pre class='mermaid'>")?;
127-
emit_mermaid_nll_sccs(tcx, regioncx, out)?;
135+
emit_mermaid_nll_sccs(dumper.tcx(), regioncx, out)?;
128136
writeln!(out, "</pre>")?;
129137
writeln!(out, "</div>")?;
130138

@@ -149,45 +157,14 @@ fn emit_polonius_dump<'tcx>(
149157

150158
/// Emits the polonius MIR, as escaped HTML.
151159
fn emit_html_mir<'tcx>(
152-
tcx: TyCtxt<'tcx>,
160+
dumper: &MirDumper<'_, '_, 'tcx>,
153161
body: &Body<'tcx>,
154-
regioncx: &RegionInferenceContext<'tcx>,
155-
borrow_set: &BorrowSet<'tcx>,
156-
localized_outlives_constraints: &LocalizedOutlivesConstraintSet,
157-
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
158162
out: &mut dyn io::Write,
159163
) -> io::Result<()> {
160164
// Buffer the regular MIR dump to be able to escape it.
161165
let mut buffer = Vec::new();
162166

163-
// We want the NLL extra comments printed by default in NLL MIR dumps. Specifying `-Z
164-
// mir-include-spans` on the CLI still has priority.
165-
let options = PrettyPrintMirOptions {
166-
include_extra_comments: matches!(
167-
tcx.sess.opts.unstable_opts.mir_include_spans,
168-
MirIncludeSpans::On | MirIncludeSpans::Nll
169-
),
170-
};
171-
172-
dump_mir_to_writer(
173-
tcx,
174-
"polonius",
175-
&0,
176-
body,
177-
&mut buffer,
178-
&|pass_where, out| {
179-
emit_polonius_mir(
180-
tcx,
181-
regioncx,
182-
closure_region_requirements,
183-
borrow_set,
184-
localized_outlives_constraints,
185-
pass_where,
186-
out,
187-
)
188-
},
189-
options,
190-
)?;
167+
dumper.dump_mir_to_writer(body, &mut buffer)?;
191168

192169
// Escape the handful of characters that need it. We don't need to be particularly efficient:
193170
// we're actually writing into a buffered writer already. Note that MIR dumps are valid UTF-8.

compiler/rustc_codegen_cranelift/src/base.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,8 @@ pub(crate) fn codegen_fn<'tcx>(
4444
let _mir_guard = crate::PrintOnPanic(|| {
4545
let mut buf = Vec::new();
4646
with_no_trimmed_paths!({
47-
use rustc_middle::mir::pretty;
48-
let options = pretty::PrettyPrintMirOptions::from_cli(tcx);
49-
pretty::write_mir_fn(tcx, mir, &|_, _| Ok(()), &mut buf, options).unwrap();
47+
let writer = pretty::MirWriter::new(tcx);
48+
writer.write_mir_fn(mir, &mut buf).unwrap();
5049
});
5150
String::from_utf8_lossy(&buf).into_owned()
5251
});

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,7 @@ pub use terminator::*;
6262

6363
pub use self::generic_graph::graphviz_safe_def_name;
6464
pub use self::graphviz::write_mir_graphviz;
65-
pub use self::pretty::{
66-
PassWhere, create_dump_file, display_allocation, dump_enabled, dump_mir, write_mir_pretty,
67-
};
65+
pub use self::pretty::{MirDumper, PassWhere, display_allocation, write_mir_pretty};
6866

6967
/// Types for locals
7068
pub type LocalDecls<'tcx> = IndexSlice<Local, LocalDecl<'tcx>>;

0 commit comments

Comments
 (0)