Skip to content

Commit 0cb9379

Browse files
author
Keegan McAllister
committed
Allow plugins to register LLVM passes
1 parent 30e7e6e commit 0cb9379

File tree

6 files changed

+79
-1
lines changed

6 files changed

+79
-1
lines changed

src/librustc/plugin/registry.rs

+14
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use syntax::ptr::P;
2222
use syntax::ast;
2323

2424
use std::collections::HashMap;
25+
use std::borrow::ToOwned;
2526

2627
/// Structure used to register plugins.
2728
///
@@ -50,6 +51,9 @@ pub struct Registry<'a> {
5051

5152
#[doc(hidden)]
5253
pub lint_groups: HashMap<&'static str, Vec<LintId>>,
54+
55+
#[doc(hidden)]
56+
pub llvm_passes: Vec<String>,
5357
}
5458

5559
impl<'a> Registry<'a> {
@@ -62,6 +66,7 @@ impl<'a> Registry<'a> {
6266
syntax_exts: vec!(),
6367
lint_passes: vec!(),
6468
lint_groups: HashMap::new(),
69+
llvm_passes: vec!(),
6570
}
6671
}
6772

@@ -116,4 +121,13 @@ impl<'a> Registry<'a> {
116121
pub fn register_lint_group(&mut self, name: &'static str, to: Vec<&'static Lint>) {
117122
self.lint_groups.insert(name, to.into_iter().map(|x| LintId::of(x)).collect());
118123
}
124+
125+
/// Register an LLVM pass.
126+
///
127+
/// Registration with LLVM itself is handled through static C++ objects with
128+
/// constructors. This method simply adds a name to the list of passes to
129+
/// execute.
130+
pub fn register_llvm_pass(&mut self, name: &str) {
131+
self.llvm_passes.push(name.to_owned());
132+
}
119133
}

src/librustc/session/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub struct Session {
5252
pub working_dir: PathBuf,
5353
pub lint_store: RefCell<lint::LintStore>,
5454
pub lints: RefCell<NodeMap<Vec<(lint::LintId, codemap::Span, String)>>>,
55+
pub plugin_llvm_passes: RefCell<Vec<String>>,
5556
pub crate_types: RefCell<Vec<config::CrateType>>,
5657
pub crate_metadata: RefCell<Vec<String>>,
5758
pub features: RefCell<feature_gate::Features>,
@@ -391,6 +392,7 @@ pub fn build_session_(sopts: config::Options,
391392
working_dir: env::current_dir().unwrap(),
392393
lint_store: RefCell::new(lint::LintStore::new()),
393394
lints: RefCell::new(NodeMap()),
395+
plugin_llvm_passes: RefCell::new(Vec::new()),
394396
crate_types: RefCell::new(Vec::new()),
395397
crate_metadata: RefCell::new(Vec::new()),
396398
features: RefCell::new(feature_gate::Features::new()),

src/librustc_driver/driver.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
438438
}
439439
});
440440

441-
let Registry { syntax_exts, lint_passes, lint_groups, .. } = registry;
441+
let Registry { syntax_exts, lint_passes, lint_groups, llvm_passes, .. } = registry;
442442

443443
{
444444
let mut ls = sess.lint_store.borrow_mut();
@@ -449,6 +449,8 @@ pub fn phase_2_configure_and_expand(sess: &Session,
449449
for (name, to) in lint_groups {
450450
ls.register_group(Some(sess), true, name, to);
451451
}
452+
453+
*sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
452454
}
453455

454456
// Lint plugins are registered; now we can process command line flags.

src/librustc_trans/back/write.rs

+15
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,8 @@ struct CodegenContext<'a> {
319319
lto_ctxt: Option<(&'a Session, &'a [String])>,
320320
// Handler to use for diagnostics produced during codegen.
321321
handler: &'a Handler,
322+
// LLVM passes added by plugins.
323+
plugin_passes: Vec<String>,
322324
// LLVM optimizations for which we want to print remarks.
323325
remark: Passes,
324326
}
@@ -328,6 +330,7 @@ impl<'a> CodegenContext<'a> {
328330
CodegenContext {
329331
lto_ctxt: Some((sess, reachable)),
330332
handler: sess.diagnostic().handler(),
333+
plugin_passes: sess.plugin_llvm_passes.borrow().clone(),
331334
remark: sess.opts.cg.remark.clone(),
332335
}
333336
}
@@ -461,6 +464,16 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
461464
}
462465
}
463466

467+
for pass in &cgcx.plugin_passes {
468+
let pass = CString::new(pass.clone()).unwrap();
469+
if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
470+
cgcx.handler.err(&format!("a plugin asked for LLVM pass {:?} but LLVM \
471+
does not recognize it", pass));
472+
}
473+
}
474+
475+
cgcx.handler.abort_if_errors();
476+
464477
// Finally, run the actual optimization passes
465478
time(config.time_passes, "llvm function passes", (), |()|
466479
llvm::LLVMRustRunFunctionPassManager(fpm, llmod));
@@ -907,6 +920,7 @@ fn run_work_multithreaded(sess: &Session,
907920
for i in 0..num_workers {
908921
let work_items_arc = work_items_arc.clone();
909922
let diag_emitter = diag_emitter.clone();
923+
let plugin_passes = sess.plugin_llvm_passes.borrow().clone();
910924
let remark = sess.opts.cg.remark.clone();
911925

912926
let (tx, rx) = channel();
@@ -921,6 +935,7 @@ fn run_work_multithreaded(sess: &Session,
921935
let cgcx = CodegenContext {
922936
lto_ctxt: None,
923937
handler: &diag_handler,
938+
plugin_passes: plugin_passes,
924939
remark: remark,
925940
};
926941

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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)]
14+
#![feature(rustc_private)]
15+
16+
extern crate rustc;
17+
18+
use rustc::plugin::Registry;
19+
20+
#[plugin_registrar]
21+
pub fn plugin_registrar(reg: &mut Registry) {
22+
// This pass is built in to LLVM.
23+
//
24+
// Normally, we would name a pass that was registered through
25+
// C++ static object constructors in the same .so file as the
26+
// plugin registrar.
27+
reg.register_llvm_pass("inline");
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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:llvm_pass_plugin.rs
12+
// ignore-stage1
13+
14+
#![feature(plugin)]
15+
#![plugin(llvm_pass_plugin)]
16+
17+
pub fn main() { }

0 commit comments

Comments
 (0)