Skip to content

Commit 811b874

Browse files
committed
Add Pass manager for MIR
1 parent 5b5e521 commit 811b874

File tree

15 files changed

+177
-212
lines changed

15 files changed

+177
-212
lines changed

src/librustc/dep_graph/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub enum DepNode {
7070
IntrinsicCheck(DefId),
7171
MatchCheck(DefId),
7272
MirMapConstruction(DefId),
73+
MirPasses,
7374
BorrowCheck(DefId),
7475
RvalueCheck(DefId),
7576
Reachability,

src/librustc/mir/mir_map.rs

-22
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use dep_graph::DepNode;
1211
use util::nodemap::NodeMap;
1312
use mir::repr::Mir;
14-
use mir::transform::MirPass;
15-
use middle::ty::{self, TyCtxt};
16-
use middle::infer;
1713

1814
pub struct MirMap<'tcx> {
1915
pub map: NodeMap<Mir<'tcx>>,
2016
}
21-
22-
impl<'tcx> MirMap<'tcx> {
23-
pub fn run_passes(&mut self, passes: &mut [Box<MirPass>], tcx: &TyCtxt<'tcx>) {
24-
if passes.is_empty() { return; }
25-
26-
for (&id, mir) in &mut self.map {
27-
let did = tcx.map.local_def_id(id);
28-
let _task = tcx.dep_graph.in_task(DepNode::MirMapConstruction(did));
29-
30-
let param_env = ty::ParameterEnvironment::for_item(tcx, id);
31-
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env));
32-
33-
for pass in &mut *passes {
34-
pass.run_on_mir(mir, &infcx)
35-
}
36-
}
37-
}
38-
}

src/librustc/mir/repr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ impl Debug for BasicBlock {
207207
}
208208

209209
///////////////////////////////////////////////////////////////////////////
210-
// BasicBlock and Terminator
210+
// BasicBlockData and Terminator
211211

212212
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
213213
pub struct BasicBlockData<'tcx> {

src/librustc/mir/transform.rs

+60-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,66 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use mir::mir_map::MirMap;
1112
use mir::repr::Mir;
12-
use middle::infer::InferCtxt;
13+
use middle::ty::TyCtxt;
1314

14-
pub trait MirPass {
15-
fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>, infcx: &InferCtxt<'a, 'tcx>);
15+
/// Various information about pass.
16+
pub trait Pass {
17+
// fn name() for printouts of various sorts?
18+
// fn should_run(Session) to check if pass should run?
19+
}
20+
21+
/// A pass which inspects the whole MirMap.
22+
pub trait MirMapPass<'tcx>: Pass {
23+
fn run_pass(&mut self, cx: &TyCtxt<'tcx>, map: &mut MirMap<'tcx>);
24+
}
25+
26+
pub trait MirPass<'tcx>: Pass {
27+
fn run_pass(&mut self, cx: &TyCtxt<'tcx>, map: &mut Mir<'tcx>);
28+
}
29+
30+
impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T {
31+
fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, map: &mut MirMap<'tcx>) {
32+
for (_, mir) in &mut map.map {
33+
MirPass::run_pass(self, tcx, mir);
34+
}
35+
}
36+
}
37+
38+
/// A manager for MIR passes.
39+
pub struct Passes {
40+
passes: Vec<Box<for<'tcx> MirMapPass<'tcx>>>,
41+
plugin_passes: Vec<Box<for<'tcx> MirMapPass<'tcx>>>
42+
}
43+
44+
impl Passes {
45+
pub fn new() -> Passes {
46+
let passes = Passes {
47+
passes: Vec::new(),
48+
plugin_passes: Vec::new()
49+
};
50+
passes
51+
}
52+
53+
pub fn run_passes<'tcx>(&mut self, pcx: &TyCtxt<'tcx>, map: &mut MirMap<'tcx>) {
54+
for pass in &mut self.plugin_passes {
55+
pass.run_pass(pcx, map);
56+
}
57+
for pass in &mut self.passes {
58+
pass.run_pass(pcx, map);
59+
}
60+
}
61+
62+
/// Pushes a built-in pass.
63+
pub fn push_pass(&mut self, pass: Box<for<'a> MirMapPass<'a>>) {
64+
self.passes.push(pass);
65+
}
66+
}
67+
68+
/// Copies the plugin passes.
69+
impl ::std::iter::Extend<Box<for<'a> MirMapPass<'a>>> for Passes {
70+
fn extend<I: IntoIterator<Item=Box<for <'a> MirMapPass<'a>>>>(&mut self, it: I) {
71+
self.plugin_passes.extend(it);
72+
}
1673
}

src/librustc/session/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use middle::cstore::CrateStore;
1313
use middle::dependency_format;
1414
use session::search_paths::PathKind;
1515
use util::nodemap::{NodeMap, FnvHashMap};
16-
use mir::transform::MirPass;
16+
use mir::transform as mir_pass;
1717

1818
use syntax::ast::{NodeId, NodeIdAssigner, Name};
1919
use syntax::codemap::{Span, MultiSpan};
@@ -60,7 +60,7 @@ pub struct Session {
6060
pub lint_store: RefCell<lint::LintStore>,
6161
pub lints: RefCell<NodeMap<Vec<(lint::LintId, Span, String)>>>,
6262
pub plugin_llvm_passes: RefCell<Vec<String>>,
63-
pub plugin_mir_passes: RefCell<Vec<Box<MirPass>>>,
63+
pub mir_passes: RefCell<mir_pass::Passes>,
6464
pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>,
6565
pub crate_types: RefCell<Vec<config::CrateType>>,
6666
pub dependency_formats: RefCell<dependency_format::Dependencies>,
@@ -477,7 +477,7 @@ pub fn build_session_(sopts: config::Options,
477477
lint_store: RefCell::new(lint::LintStore::new()),
478478
lints: RefCell::new(NodeMap()),
479479
plugin_llvm_passes: RefCell::new(Vec::new()),
480-
plugin_mir_passes: RefCell::new(Vec::new()),
480+
mir_passes: RefCell::new(mir_pass::Passes::new()),
481481
plugin_attributes: RefCell::new(Vec::new()),
482482
crate_types: RefCell::new(Vec::new()),
483483
dependency_formats: RefCell::new(FnvHashMap()),

src/librustc_driver/driver.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use rustc::dep_graph::DepGraph;
11+
use rustc::dep_graph::{DepGraph, DepNode};
1212
use rustc::front;
1313
use rustc::front::map as hir_map;
1414
use rustc_mir as mir;
@@ -561,7 +561,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
561561
}
562562

563563
*sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
564-
*sess.plugin_mir_passes.borrow_mut() = mir_passes;
564+
sess.mir_passes.borrow_mut().extend(mir_passes);
565565
*sess.plugin_attributes.borrow_mut() = attributes.clone();
566566
}));
567567

@@ -861,9 +861,20 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
861861
"MIR dump",
862862
|| mir::mir_map::build_mir_for_crate(tcx));
863863

864-
time(time_passes,
865-
"MIR passes",
866-
|| mir_map.run_passes(&mut sess.plugin_mir_passes.borrow_mut(), tcx));
864+
time(time_passes, "MIR passes", || {
865+
let _task = tcx.dep_graph.in_task(DepNode::MirPasses);
866+
let mut passes = sess.mir_passes.borrow_mut();
867+
// Push all the built-in passes.
868+
passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks);
869+
passes.push_pass(box mir::transform::type_check::TypeckMir);
870+
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg);
871+
// Late passes
872+
passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
873+
passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks);
874+
passes.push_pass(box mir::transform::erase_regions::EraseRegions);
875+
// And run everything.
876+
passes.run_passes(tcx, &mut mir_map);
877+
});
867878

868879
time(time_passes,
869880
"borrow checking",
@@ -912,9 +923,8 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
912923
}
913924

914925
/// Run the translation phase to LLVM, after which the AST and analysis can
915-
/// be discarded.
916926
pub fn phase_4_translate_to_llvm<'tcx>(tcx: &TyCtxt<'tcx>,
917-
mut mir_map: MirMap<'tcx>,
927+
mir_map: MirMap<'tcx>,
918928
analysis: ty::CrateAnalysis)
919929
-> trans::CrateTranslation {
920930
let time_passes = tcx.sess.time_passes();
@@ -923,10 +933,6 @@ pub fn phase_4_translate_to_llvm<'tcx>(tcx: &TyCtxt<'tcx>,
923933
"resolving dependency formats",
924934
|| dependency_format::calculate(&tcx.sess));
925935

926-
time(time_passes,
927-
"erasing regions from MIR",
928-
|| mir::transform::erase_regions::erase_regions(tcx, &mut mir_map));
929-
930936
// Option dance to work around the lack of stack once closures.
931937
time(time_passes,
932938
"translation",

src/librustc_mir/mir_map.rs

+5-56
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,10 @@ extern crate syntax;
2020
extern crate rustc_front;
2121

2222
use build;
23-
use graphviz;
24-
use pretty;
25-
use transform::{clear_dead_blocks, simplify_cfg, type_check};
26-
use transform::{no_landing_pads};
2723
use rustc::dep_graph::DepNode;
2824
use rustc::mir::repr::Mir;
2925
use hair::cx::Cx;
30-
use std::fs::File;
3126

32-
use rustc::mir::transform::MirPass;
3327
use rustc::mir::mir_map::MirMap;
3428
use rustc::middle::infer;
3529
use rustc::middle::region::CodeExtentData;
@@ -136,61 +130,16 @@ impl<'a, 'm, 'tcx> Visitor<'tcx> for InnerDump<'a,'m,'tcx> {
136130
body: &'tcx hir::Block,
137131
span: Span,
138132
id: ast::NodeId) {
139-
let (prefix, implicit_arg_tys) = match fk {
140-
intravisit::FnKind::Closure =>
141-
(format!("{}-", id), vec![closure_self_ty(&self.tcx, id, body.id)]),
142-
_ =>
143-
(format!(""), vec![]),
133+
let implicit_arg_tys = if let intravisit::FnKind::Closure = fk {
134+
vec![closure_self_ty(&self.tcx, id, body.id)]
135+
} else {
136+
vec![]
144137
};
145138

146139
let param_env = ty::ParameterEnvironment::for_item(self.tcx, id);
147-
148140
let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env));
149-
150141
match build_mir(Cx::new(&infcx), implicit_arg_tys, id, span, decl, body) {
151-
Ok(mut mir) => {
152-
clear_dead_blocks::ClearDeadBlocks::new().run_on_mir(&mut mir, &infcx);
153-
type_check::TypeckMir::new().run_on_mir(&mut mir, &infcx);
154-
no_landing_pads::NoLandingPads.run_on_mir(&mut mir, &infcx);
155-
if self.tcx.sess.opts.mir_opt_level > 0 {
156-
simplify_cfg::SimplifyCfg::new().run_on_mir(&mut mir, &infcx);
157-
}
158-
let meta_item_list = self.attr
159-
.iter()
160-
.flat_map(|a| a.meta_item_list())
161-
.flat_map(|l| l.iter());
162-
for item in meta_item_list {
163-
if item.check_name("graphviz") || item.check_name("pretty") {
164-
match item.value_str() {
165-
Some(s) => {
166-
let filename = format!("{}{}", prefix, s);
167-
let result = File::create(&filename).and_then(|ref mut output| {
168-
if item.check_name("graphviz") {
169-
graphviz::write_mir_graphviz(&mir, output)
170-
} else {
171-
pretty::write_mir_pretty(&mir, output)
172-
}
173-
});
174-
175-
if let Err(e) = result {
176-
self.tcx.sess.span_fatal(
177-
item.span,
178-
&format!("Error writing MIR {} results to `{}`: {}",
179-
item.name(), filename, e));
180-
}
181-
}
182-
None => {
183-
self.tcx.sess.span_err(
184-
item.span,
185-
&format!("{} attribute requires a path", item.name()));
186-
}
187-
}
188-
}
189-
}
190-
191-
let previous = self.map.map.insert(id, mir);
192-
assert!(previous.is_none());
193-
}
142+
Ok(mir) => assert!(self.map.map.insert(id, mir).is_none()),
194143
Err(ErrorReported) => {}
195144
}
196145

src/librustc_mir/transform/erase_regions.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,7 @@
1515
use rustc::middle::ty::{self, TyCtxt};
1616
use rustc::mir::repr::*;
1717
use rustc::mir::visit::MutVisitor;
18-
use rustc::mir::mir_map::MirMap;
19-
20-
pub fn erase_regions<'tcx>(tcx: &TyCtxt<'tcx>, mir_map: &mut MirMap<'tcx>) {
21-
for (_, mir) in &mut mir_map.map {
22-
EraseRegionsVisitor::new(tcx).visit_mir(mir);
23-
}
24-
}
18+
use rustc::mir::transform::{MirPass, Pass};
2519

2620
struct EraseRegionsVisitor<'a, 'tcx: 'a> {
2721
tcx: &'a TyCtxt<'tcx>,
@@ -123,3 +117,13 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
123117
self.super_constant(constant);
124118
}
125119
}
120+
121+
pub struct EraseRegions;
122+
123+
impl Pass for EraseRegions {}
124+
125+
impl<'tcx> MirPass<'tcx> for EraseRegions {
126+
fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, mir: &mut Mir<'tcx>) {
127+
EraseRegionsVisitor::new(tcx).visit_mir(mir);
128+
}
129+
}

src/librustc_mir/transform/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
pub mod clear_dead_blocks;
11+
pub mod remove_dead_blocks;
1212
pub mod simplify_cfg;
1313
pub mod erase_regions;
1414
pub mod no_landing_pads;

src/librustc_mir/transform/no_landing_pads.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
//! This pass removes the unwind branch of all the terminators when the no-landing-pads option is
1212
//! specified.
1313
14-
use rustc::middle::infer;
14+
use rustc::middle::ty::TyCtxt;
1515
use rustc::mir::repr::*;
1616
use rustc::mir::visit::MutVisitor;
17-
use rustc::mir::transform::MirPass;
17+
use rustc::mir::transform::{Pass, MirPass};
1818

1919
pub struct NoLandingPads;
2020

@@ -40,11 +40,12 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
4040
}
4141
}
4242

43-
impl MirPass for NoLandingPads {
44-
fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>,
45-
infcx: &infer::InferCtxt<'a, 'tcx>) {
46-
if infcx.tcx.sess.no_landing_pads() {
43+
impl<'tcx> MirPass<'tcx> for NoLandingPads {
44+
fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, mir: &mut Mir<'tcx>) {
45+
if tcx.sess.no_landing_pads() {
4746
self.visit_mir(mir);
4847
}
4948
}
5049
}
50+
51+
impl Pass for NoLandingPads {}

0 commit comments

Comments
 (0)