Skip to content

Commit 62133d7

Browse files
committed
add hook infrastructure for automatically dumping MIR on every pass
1 parent b330fba commit 62133d7

File tree

12 files changed

+151
-30
lines changed

12 files changed

+151
-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
@@ -964,6 +964,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
964964
time(time_passes, "MIR passes", || {
965965
let mut passes = sess.mir_passes.borrow_mut();
966966
// Push all the built-in passes.
967+
passes.push_hook(box mir::transform::dump_mir::DumpMir);
967968
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("initial"));
968969
passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants);
969970
passes.push_pass(box mir::transform::type_check::TypeckMir);
@@ -1033,6 +1034,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10331034
// to LLVM code.
10341035
time(time_passes, "Prepare MIR codegen passes", || {
10351036
let mut passes = ::rustc::mir::transform::Passes::new();
1037+
passes.push_hook(box mir::transform::dump_mir::DumpMir);
10361038
passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
10371039
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("no-landing-pads"));
10381040

@@ -1044,7 +1046,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10441046
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("elaborate-drops"));
10451047

10461048
passes.push_pass(box mir::transform::add_call_guards::AddCallGuards);
1047-
passes.push_pass(box mir::transform::dump_mir::DumpMir("pre_trans"));
1049+
passes.push_pass(box mir::transform::dump_mir::Marker("pre-trans"));
10481050

10491051
passes.run_passes(tcx, &mut mir_map);
10501052
});

src/librustc_mir/transform/add_call_guards.rs

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

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

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,7 +25,7 @@ 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};
28+
use rustc::mir::transform::{Pass, MirMapPass, MirPassHook, MirSource};
2929
use rustc::mir::visit::{LvalueContext, Visitor};
3030
use rustc::util::nodemap::DefIdMap;
3131
use syntax::abi::Abi;
@@ -903,10 +903,15 @@ fn qualify_const_item_cached<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
903903

904904
pub struct QualifyAndPromoteConstants;
905905

906-
impl Pass for QualifyAndPromoteConstants {}
906+
impl Pass for QualifyAndPromoteConstants {
907+
fn name(&self) -> &str { "qualify-consts" }
908+
}
907909

908910
impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants {
909-
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, map: &mut MirMap<'tcx>) {
911+
fn run_pass<'a>(&mut self,
912+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
913+
map: &mut MirMap<'tcx>,
914+
hooks: &mut [Box<for<'s> MirPassHook<'s>>]) {
910915
let mut qualif_map = DefIdMap();
911916

912917
// First, visit `const` items, potentially recursing, to get
@@ -942,6 +947,10 @@ impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants {
942947
};
943948
let param_env = ty::ParameterEnvironment::for_item(tcx, id);
944949

950+
for hook in &mut *hooks {
951+
hook.on_mir_pass(tcx, src, mir, self, false);
952+
}
953+
945954
if mode == Mode::Fn || mode == Mode::ConstFn {
946955
// This is ugly because Qualifier holds onto mir,
947956
// which can't be mutated until its scope ends.
@@ -969,6 +978,10 @@ impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants {
969978
qualifier.qualify_const();
970979
}
971980

981+
for hook in &mut *hooks {
982+
hook.on_mir_pass(tcx, src, mir, self, true);
983+
}
984+
972985
// Statics must be Sync.
973986
if mode == Mode::Static {
974987
let ty = mir.return_ty.unwrap();

src/librustc_mir/transform/simplify_cfg.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use rustc::middle::const_val::ConstVal;
3838
use rustc::ty::TyCtxt;
3939
use rustc::mir::repr::*;
4040
use rustc::mir::transform::{MirPass, MirSource, Pass};
41-
use pretty;
41+
use std::fmt;
4242
use std::mem;
4343

4444
use traversal;
@@ -52,20 +52,23 @@ impl<'a> SimplifyCfg<'a> {
5252
}
5353

5454
impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> {
55-
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) {
56-
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>) {
5756
simplify_branches(mir);
5857
remove_dead_blocks(mir);
5958
merge_consecutive_blocks(mir);
6059
remove_dead_blocks(mir);
61-
pretty::dump_mir(tcx, "simplify_cfg", &format!("{}-after", self.label), src, mir, None);
6260

6361
// FIXME: Should probably be moved into some kind of pass manager
6462
mir.basic_blocks_mut().raw.shrink_to_fit();
6563
}
6664
}
6765

68-
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+
}
6972

7073
fn merge_consecutive_blocks(mir: &mut Mir) {
7174
let mut pred_count: IdxVec<_, _> =

src/librustc_mir/transform/type_check.rs

+2
Original file line numberDiff line numberDiff line change
@@ -697,4 +697,6 @@ impl Pass for TypeckMir {
697697
fn dep_node(&self, def_id: DefId) -> DepNode<DefId> {
698698
DepNode::MirTypeck(def_id)
699699
}
700+
701+
fn name(&self) -> &str { "typeck-mir" }
700702
}

src/librustc_trans/base.rs

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

1857-
debug!("trans_closure(..., {})", instance);
1857+
// this is an info! to allow collecting monomorphization statistics
1858+
// and to allow finding the last function before LLVM aborts from
1859+
// release builds.
1860+
info!("trans_closure(..., {})", instance);
18581861

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

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)