Skip to content

Commit 4b06718

Browse files
committed
Allow registering MIR-passes through compiler plugins
1 parent 030b237 commit 4b06718

File tree

8 files changed

+110
-3
lines changed

8 files changed

+110
-3
lines changed

mk/crates.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ DEPS_rustc_passes := syntax rustc core rustc_front
106106
DEPS_rustc_mir := rustc rustc_front syntax
107107
DEPS_rustc_resolve := arena rustc rustc_front log syntax
108108
DEPS_rustc_platform_intrinsics := rustc rustc_llvm
109-
DEPS_rustc_plugin := rustc rustc_metadata syntax
109+
DEPS_rustc_plugin := rustc rustc_metadata syntax rustc_mir
110110
DEPS_rustc_privacy := rustc rustc_front log syntax
111111
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back rustc_mir \
112112
log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics

src/librustc/mir/mir_map.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,19 @@
1010

1111
use util::nodemap::NodeMap;
1212
use mir::repr::Mir;
13+
use mir::transform::MirPass;
14+
use middle::ty;
1315

1416
pub struct MirMap<'tcx> {
1517
pub map: NodeMap<Mir<'tcx>>,
1618
}
1719

20+
impl<'tcx> MirMap<'tcx> {
21+
pub fn run_passes(&mut self, passes: &mut [Box<MirPass>], tcx: &ty::ctxt<'tcx>) {
22+
for (_, ref mut mir) in &mut self.map {
23+
for pass in &mut *passes {
24+
pass.run_on_mir(mir, tcx)
25+
}
26+
}
27+
}
28+
}

src/librustc/session/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +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;
1617

1718
use syntax::ast::{NodeId, NodeIdAssigner, Name};
1819
use syntax::codemap::{Span, MultiSpan};
@@ -59,6 +60,7 @@ pub struct Session {
5960
pub lint_store: RefCell<lint::LintStore>,
6061
pub lints: RefCell<NodeMap<Vec<(lint::LintId, Span, String)>>>,
6162
pub plugin_llvm_passes: RefCell<Vec<String>>,
63+
pub plugin_mir_passes: RefCell<Vec<Box<MirPass>>>,
6264
pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>,
6365
pub crate_types: RefCell<Vec<config::CrateType>>,
6466
pub dependency_formats: RefCell<dependency_format::Dependencies>,
@@ -475,6 +477,7 @@ pub fn build_session_(sopts: config::Options,
475477
lint_store: RefCell::new(lint::LintStore::new()),
476478
lints: RefCell::new(NodeMap()),
477479
plugin_llvm_passes: RefCell::new(Vec::new()),
480+
plugin_mir_passes: RefCell::new(Vec::new()),
478481
plugin_attributes: RefCell::new(Vec::new()),
479482
crate_types: RefCell::new(Vec::new()),
480483
dependency_formats: RefCell::new(FnvHashMap()),

src/librustc_driver/driver.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
545545
});
546546

547547
let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups,
548-
llvm_passes, attributes, .. } = registry;
548+
llvm_passes, attributes, mir_passes, .. } = registry;
549549

550550
try!(sess.track_errors(|| {
551551
let mut ls = sess.lint_store.borrow_mut();
@@ -561,6 +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;
564565
*sess.plugin_attributes.borrow_mut() = attributes.clone();
565566
}));
566567

@@ -843,11 +844,15 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
843844
"match checking",
844845
|| middle::check_match::check_crate(tcx));
845846

846-
let mir_map =
847+
let mut mir_map =
847848
time(time_passes,
848849
"MIR dump",
849850
|| mir::mir_map::build_mir_for_crate(tcx));
850851

852+
time(time_passes,
853+
"MIR passes",
854+
|| mir_map.run_passes(&mut sess.plugin_mir_passes.borrow_mut(), tcx));
855+
851856
time(time_passes,
852857
"liveness checking",
853858
|| middle::liveness::check_crate(tcx));

src/librustc_plugin/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
extern crate rustc;
7272
extern crate rustc_front;
7373
extern crate rustc_metadata;
74+
extern crate rustc_mir;
7475

7576
pub use self::registry::Registry;
7677

src/librustc_plugin/registry.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint};
1414
use rustc::session::Session;
1515

16+
use rustc::mir::transform::MirPass;
17+
1618
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
1719
use syntax::ext::base::{IdentTT, MultiModifier, MultiDecorator};
1820
use syntax::ext::base::{MacroExpanderFn, MacroRulesTT};
@@ -53,6 +55,9 @@ pub struct Registry<'a> {
5355
#[doc(hidden)]
5456
pub late_lint_passes: Vec<LateLintPassObject>,
5557

58+
#[doc(hidden)]
59+
pub mir_passes: Vec<Box<MirPass>>,
60+
5661
#[doc(hidden)]
5762
pub lint_groups: HashMap<&'static str, Vec<LintId>>,
5863

@@ -76,6 +81,7 @@ impl<'a> Registry<'a> {
7681
lint_groups: HashMap::new(),
7782
llvm_passes: vec!(),
7883
attributes: vec!(),
84+
mir_passes: Vec::new(),
7985
}
8086
}
8187

@@ -134,6 +140,11 @@ impl<'a> Registry<'a> {
134140
self.lint_groups.insert(name, to.into_iter().map(|x| LintId::of(x)).collect());
135141
}
136142

143+
/// Register a MIR pass
144+
pub fn register_mir_pass(&mut self, pass: Box<MirPass>) {
145+
self.mir_passes.push(pass);
146+
}
147+
137148
/// Register an LLVM pass.
138149
///
139150
/// Registration with LLVM itself is handled through static C++ objects with

src/test/auxiliary/dummy_mir_pass.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// force-host
12+
13+
#![feature(plugin_registrar, rustc_private)]
14+
#![feature(box_syntax)]
15+
16+
#[macro_use] extern crate rustc;
17+
extern crate rustc_front;
18+
extern crate rustc_plugin;
19+
extern crate syntax;
20+
21+
use rustc::mir::transform::MirPass;
22+
use rustc::mir::repr::{Mir, Literal};
23+
use rustc::mir::visit::MutVisitor;
24+
use rustc::middle::ty;
25+
use rustc::middle::const_eval::ConstVal;
26+
use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray};
27+
use rustc_plugin::Registry;
28+
use rustc_front::hir;
29+
use syntax::attr;
30+
31+
struct Pass;
32+
33+
impl MirPass for Pass {
34+
fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, tcx: &ty::ctxt<'tcx>) {
35+
Visitor.visit_mir(mir)
36+
}
37+
}
38+
39+
struct Visitor;
40+
41+
impl<'tcx> MutVisitor<'tcx> for Visitor {
42+
fn visit_literal(&mut self, literal: &mut Literal<'tcx>) {
43+
if let Literal::Value { value: ConstVal::Int(ref mut i @ 11) } = *literal {
44+
*i = 42;
45+
}
46+
}
47+
}
48+
49+
#[plugin_registrar]
50+
pub fn plugin_registrar(reg: &mut Registry) {
51+
reg.register_mir_pass(box Pass);
52+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:dummy_mir_pass.rs
12+
// ignore-stage1
13+
14+
#![feature(plugin, rustc_attrs)]
15+
#![plugin(dummy_mir_pass)]
16+
17+
#[rustc_mir]
18+
fn math() -> i32 {
19+
11
20+
}
21+
22+
pub fn main() {
23+
assert_eq!(math(), 42);
24+
}

0 commit comments

Comments
 (0)