Skip to content

Commit 2ee00e6

Browse files
arielb1Ariel Ben-Yehuda
authored and
Ariel Ben-Yehuda
committed
add hook infrastructure for automatically dumping MIR on every pass
1 parent 798be90 commit 2ee00e6

File tree

12 files changed

+152
-30
lines changed

12 files changed

+152
-30
lines changed

src/librustc/mir/transform.rs

+47-5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ use mir::repr::Mir;
1717
use ty::TyCtxt;
1818
use syntax::ast::NodeId;
1919

20+
use std::fmt;
21+
2022
/// Where a specific Mir comes from.
2123
#[derive(Debug, Copy, Clone)]
2224
pub enum MirSource {
@@ -70,16 +72,32 @@ impl<'a, 'tcx> MirSource {
7072

7173
/// Various information about pass.
7274
pub trait Pass {
73-
// fn name() for printouts of various sorts?
7475
// fn should_run(Session) to check if pass should run?
7576
fn dep_node(&self, def_id: DefId) -> DepNode<DefId> {
7677
DepNode::MirPass(def_id)
7778
}
79+
fn name(&self) -> &str;
80+
fn disambiguator<'a>(&'a self) -> Option<Box<fmt::Display+'a>> { None }
7881
}
7982

8083
/// A pass which inspects the whole MirMap.
8184
pub trait MirMapPass<'tcx>: Pass {
82-
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, map: &mut MirMap<'tcx>);
85+
fn run_pass<'a>(
86+
&mut self,
87+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
88+
map: &mut MirMap<'tcx>,
89+
hooks: &mut [Box<for<'s> MirPassHook<'s>>]);
90+
}
91+
92+
pub trait MirPassHook<'tcx>: Pass {
93+
fn on_mir_pass<'a>(
94+
&mut self,
95+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
96+
src: MirSource,
97+
mir: &Mir<'tcx>,
98+
pass: &Pass,
99+
is_after: bool
100+
);
83101
}
84102

85103
/// A pass which inspects Mir of functions in isolation.
@@ -94,16 +112,33 @@ pub trait MirPass<'tcx>: Pass {
94112
}
95113

96114
impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T {
97-
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, map: &mut MirMap<'tcx>) {
115+
fn run_pass<'a>(&mut self,
116+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
117+
map: &mut MirMap<'tcx>,
118+
hooks: &mut [Box<for<'s> MirPassHook<'s>>])
119+
{
98120
for (&id, mir) in &mut map.map {
99121
let def_id = tcx.map.local_def_id(id);
100122
let _task = tcx.dep_graph.in_task(self.dep_node(def_id));
101123

102124
let src = MirSource::from_node(tcx, id);
125+
126+
for hook in &mut *hooks {
127+
hook.on_mir_pass(tcx, src, mir, self, false);
128+
}
103129
MirPass::run_pass(self, tcx, src, mir);
130+
for hook in &mut *hooks {
131+
hook.on_mir_pass(tcx, src, mir, self, true);
132+
}
104133

105134
for (i, mir) in mir.promoted.iter_mut().enumerate() {
135+
for hook in &mut *hooks {
136+
hook.on_mir_pass(tcx, src, mir, self, false);
137+
}
106138
self.run_pass_on_promoted(tcx, id, i, mir);
139+
for hook in &mut *hooks {
140+
hook.on_mir_pass(tcx, src, mir, self, true);
141+
}
107142
}
108143
}
109144
}
@@ -112,31 +147,38 @@ impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T {
112147
/// A manager for MIR passes.
113148
pub struct Passes {
114149
passes: Vec<Box<for<'tcx> MirMapPass<'tcx>>>,
150+
pass_hooks: Vec<Box<for<'tcx> MirPassHook<'tcx>>>,
115151
plugin_passes: Vec<Box<for<'tcx> MirMapPass<'tcx>>>
116152
}
117153

118154
impl<'a, 'tcx> Passes {
119155
pub fn new() -> Passes {
120156
let passes = Passes {
121157
passes: Vec::new(),
158+
pass_hooks: Vec::new(),
122159
plugin_passes: Vec::new()
123160
};
124161
passes
125162
}
126163

127164
pub fn run_passes(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, map: &mut MirMap<'tcx>) {
128165
for pass in &mut self.plugin_passes {
129-
pass.run_pass(tcx, map);
166+
pass.run_pass(tcx, map, &mut self.pass_hooks);
130167
}
131168
for pass in &mut self.passes {
132-
pass.run_pass(tcx, map);
169+
pass.run_pass(tcx, map, &mut self.pass_hooks);
133170
}
134171
}
135172

136173
/// Pushes a built-in pass.
137174
pub fn push_pass(&mut self, pass: Box<for<'b> MirMapPass<'b>>) {
138175
self.passes.push(pass);
139176
}
177+
178+
/// Pushes a pass hook.
179+
pub fn push_hook(&mut self, hook: Box<for<'b> MirPassHook<'b>>) {
180+
self.pass_hooks.push(hook);
181+
}
140182
}
141183

142184
/// Copies the plugin passes.

src/librustc_borrowck/borrowck/mir/elaborate_drops.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use rustc::middle::const_val::ConstVal;
2323
use rustc::middle::lang_items;
2424
use rustc::util::nodemap::FnvHashMap;
2525
use rustc_data_structures::indexed_vec::Idx;
26-
use rustc_mir::pretty;
2726
use syntax::codemap::Span;
2827

2928
use std::fmt;
@@ -66,13 +65,13 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
6665
patch: MirPatch::new(mir),
6766
}.elaborate()
6867
};
69-
pretty::dump_mir(tcx, "elaborate_drops", &0, src, mir, None);
7068
elaborate_patch.apply(mir);
71-
pretty::dump_mir(tcx, "elaborate_drops", &1, src, mir, None);
7269
}
7370
}
7471

75-
impl Pass for ElaborateDrops {}
72+
impl Pass for ElaborateDrops {
73+
fn name(&self) -> &str { "elaborate-drops" }
74+
}
7675

7776
struct InitializationData {
7877
live: IdxSetBuf<MovePathIndex>,

src/librustc_driver/driver.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
976976
time(time_passes, "MIR passes", || {
977977
let mut passes = sess.mir_passes.borrow_mut();
978978
// Push all the built-in passes.
979+
passes.push_hook(box mir::transform::dump_mir::DumpMir);
979980
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("initial"));
980981
passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants);
981982
passes.push_pass(box mir::transform::type_check::TypeckMir);
@@ -1045,6 +1046,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10451046
// to LLVM code.
10461047
time(time_passes, "Prepare MIR codegen passes", || {
10471048
let mut passes = ::rustc::mir::transform::Passes::new();
1049+
passes.push_hook(box mir::transform::dump_mir::DumpMir);
10481050
passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
10491051
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("no-landing-pads"));
10501052

@@ -1056,7 +1058,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10561058
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("elaborate-drops"));
10571059

10581060
passes.push_pass(box mir::transform::add_call_guards::AddCallGuards);
1059-
passes.push_pass(box mir::transform::dump_mir::DumpMir("pre_trans"));
1061+
passes.push_pass(box mir::transform::dump_mir::Marker("pre-trans"));
10601062

10611063
passes.run_passes(tcx, &mut mir_map);
10621064
});

src/librustc_mir/transform/add_call_guards.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,6 @@ impl<'tcx> MirPass<'tcx> for AddCallGuards {
8282
}
8383
}
8484

85-
impl Pass for AddCallGuards {}
85+
impl Pass for AddCallGuards {
86+
fn name(&self) -> &str { "add-call-guards" }
87+
}

src/librustc_mir/transform/dump_mir.rs

+55-7
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,66 @@
1010

1111
//! This pass just dumps MIR at a specified point.
1212
13+
use std::fmt;
14+
1315
use rustc::ty::TyCtxt;
1416
use rustc::mir::repr::*;
15-
use rustc::mir::transform::{Pass, MirPass, MirSource};
17+
use rustc::mir::transform::{Pass, MirPass, MirPassHook, MirSource};
1618
use pretty;
1719

18-
pub struct DumpMir<'a>(pub &'a str);
20+
pub struct Marker<'a>(pub &'a str);
21+
22+
impl<'b, 'tcx> MirPass<'tcx> for Marker<'b> {
23+
fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>,
24+
_src: MirSource, _mir: &mut Mir<'tcx>)
25+
{}
26+
}
27+
28+
impl<'b> Pass for Marker<'b> {
29+
fn name(&self) -> &str { self.0 }
30+
}
31+
32+
pub struct Disambiguator<'a> {
33+
pass: &'a Pass,
34+
is_after: bool
35+
}
36+
37+
impl<'a> fmt::Display for Disambiguator<'a> {
38+
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
39+
let title = if self.is_after { "after" } else { "before" };
40+
if let Some(fmt) = self.pass.disambiguator() {
41+
write!(formatter, "{}-{}", fmt, title)
42+
} else {
43+
write!(formatter, "{}", title)
44+
}
45+
}
46+
}
47+
48+
pub struct DumpMir;
1949

20-
impl<'b, 'tcx> MirPass<'tcx> for DumpMir<'b> {
21-
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
22-
src: MirSource, mir: &mut Mir<'tcx>) {
23-
pretty::dump_mir(tcx, self.0, &0, src, mir, None);
50+
impl<'tcx> MirPassHook<'tcx> for DumpMir {
51+
fn on_mir_pass<'a>(
52+
&mut self,
53+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
54+
src: MirSource,
55+
mir: &Mir<'tcx>,
56+
pass: &Pass,
57+
is_after: bool)
58+
{
59+
pretty::dump_mir(
60+
tcx,
61+
pass.name(),
62+
&Disambiguator {
63+
pass: pass,
64+
is_after: is_after
65+
},
66+
src,
67+
mir,
68+
None
69+
);
2470
}
2571
}
2672

27-
impl<'b> Pass for DumpMir<'b> {}
73+
impl<'b> Pass for DumpMir {
74+
fn name(&self) -> &str { "dump-mir" }
75+
}

src/librustc_mir/transform/erase_regions.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
4343

4444
pub struct EraseRegions;
4545

46-
impl Pass for EraseRegions {}
46+
impl Pass for EraseRegions {
47+
fn name(&self) -> &str { "erase-regions" }
48+
}
4749

4850
impl<'tcx> MirPass<'tcx> for EraseRegions {
4951
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,

src/librustc_mir/transform/no_landing_pads.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,6 @@ impl<'tcx> MirPass<'tcx> for NoLandingPads {
5050
}
5151
}
5252

53-
impl Pass for NoLandingPads {}
53+
impl Pass for NoLandingPads {
54+
fn name(&self) -> &str { "no-landing-pads" }
55+
}

src/librustc_mir/transform/qualify_consts.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ use rustc::ty::{self, TyCtxt, Ty};
2525
use rustc::ty::cast::CastTy;
2626
use rustc::mir::repr::*;
2727
use rustc::mir::mir_map::MirMap;
28-
use rustc::mir::transform::{Pass, MirMapPass, MirSource};
2928
use rustc::mir::traversal::{self, ReversePostorder};
29+
use rustc::mir::transform::{Pass, MirMapPass, MirPassHook, MirSource};
3030
use rustc::mir::visit::{LvalueContext, Visitor};
3131
use rustc::util::nodemap::DefIdMap;
3232
use syntax::abi::Abi;
@@ -906,10 +906,15 @@ fn qualify_const_item_cached<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
906906

907907
pub struct QualifyAndPromoteConstants;
908908

909-
impl Pass for QualifyAndPromoteConstants {}
909+
impl Pass for QualifyAndPromoteConstants {
910+
fn name(&self) -> &str { "qualify-consts" }
911+
}
910912

911913
impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants {
912-
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, map: &mut MirMap<'tcx>) {
914+
fn run_pass<'a>(&mut self,
915+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
916+
map: &mut MirMap<'tcx>,
917+
hooks: &mut [Box<for<'s> MirPassHook<'s>>]) {
913918
let mut qualif_map = DefIdMap();
914919

915920
// First, visit `const` items, potentially recursing, to get
@@ -945,6 +950,10 @@ impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants {
945950
};
946951
let param_env = ty::ParameterEnvironment::for_item(tcx, id);
947952

953+
for hook in &mut *hooks {
954+
hook.on_mir_pass(tcx, src, mir, self, false);
955+
}
956+
948957
if mode == Mode::Fn || mode == Mode::ConstFn {
949958
// This is ugly because Qualifier holds onto mir,
950959
// which can't be mutated until its scope ends.
@@ -972,6 +981,10 @@ impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants {
972981
qualifier.qualify_const();
973982
}
974983

984+
for hook in &mut *hooks {
985+
hook.on_mir_pass(tcx, src, mir, self, true);
986+
}
987+
975988
// Statics must be Sync.
976989
if mode == Mode::Static {
977990
let ty = mir.return_ty.unwrap();

src/librustc_mir/transform/simplify_cfg.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ use rustc::ty::TyCtxt;
3939
use rustc::mir::repr::*;
4040
use rustc::mir::transform::{MirPass, MirSource, Pass};
4141
use rustc::mir::traversal;
42-
use pretty;
42+
43+
use std::fmt;
4344
use std::mem;
4445

4546
pub struct SimplifyCfg<'a> { label: &'a str }
@@ -51,20 +52,23 @@ impl<'a> SimplifyCfg<'a> {
5152
}
5253

5354
impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> {
54-
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) {
55-
pretty::dump_mir(tcx, "simplify_cfg", &format!("{}-before", self.label), src, mir, None);
55+
fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) {
5656
simplify_branches(mir);
5757
remove_dead_blocks(mir);
5858
merge_consecutive_blocks(mir);
5959
remove_dead_blocks(mir);
60-
pretty::dump_mir(tcx, "simplify_cfg", &format!("{}-after", self.label), src, mir, None);
6160

6261
// FIXME: Should probably be moved into some kind of pass manager
6362
mir.basic_blocks_mut().raw.shrink_to_fit();
6463
}
6564
}
6665

67-
impl<'l> Pass for SimplifyCfg<'l> {}
66+
impl<'l> Pass for SimplifyCfg<'l> {
67+
fn name(&self) -> &str { "simplify-cfg" }
68+
fn disambiguator<'a>(&'a self) -> Option<Box<fmt::Display+'a>> {
69+
Some(Box::new(self.label))
70+
}
71+
}
6872

6973
fn merge_consecutive_blocks(mir: &mut Mir) {
7074
let mut pred_count: IndexVec<_, _> =

src/librustc_mir/transform/type_check.rs

+2
Original file line numberDiff line numberDiff line change
@@ -717,4 +717,6 @@ impl Pass for TypeckMir {
717717
fn dep_node(&self, def_id: DefId) -> DepNode<DefId> {
718718
DepNode::MirTypeck(def_id)
719719
}
720+
721+
fn name(&self) -> &str { "typeck-mir" }
720722
}

src/librustc_trans/base.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1844,7 +1844,10 @@ pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
18441844
attributes::emit_uwtable(llfndecl, true);
18451845
}
18461846

1847-
debug!("trans_closure(..., {})", instance);
1847+
// this is an info! to allow collecting monomorphization statistics
1848+
// and to allow finding the last function before LLVM aborts from
1849+
// release builds.
1850+
info!("trans_closure(..., {})", instance);
18481851

18491852
let fn_ty = FnType::new(ccx, abi, sig, &[]);
18501853

src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ use rustc_plugin::Registry;
2828

2929
struct Pass;
3030

31-
impl transform::Pass for Pass {}
31+
impl transform::Pass for Pass {
32+
fn name(&self) -> &str { "dummy-mir-pass" }
33+
}
34+
3235
impl<'tcx> MirPass<'tcx> for Pass {
3336
fn run_pass<'a>(&mut self, _: TyCtxt<'a, 'tcx, 'tcx>,
3437
_: MirSource, mir: &mut Mir<'tcx>) {

0 commit comments

Comments
 (0)