use syntax::ast;
use std::collections::HashMap;
+use std::borrow::ToOwned;
/// Structure used to register plugins.
///
#[doc(hidden)]
pub lint_groups: HashMap<&'static str, Vec<LintId>>,
+
+ #[doc(hidden)]
+ pub llvm_passes: Vec<String>,
}
impl<'a> Registry<'a> {
syntax_exts: vec!(),
lint_passes: vec!(),
lint_groups: HashMap::new(),
+ llvm_passes: vec!(),
}
}
pub fn register_lint_group(&mut self, name: &'static str, to: Vec<&'static Lint>) {
self.lint_groups.insert(name, to.into_iter().map(|x| LintId::of(x)).collect());
}
+
+ /// Register an LLVM pass.
+ ///
+ /// Registration with LLVM itself is handled through static C++ objects with
+ /// constructors. This method simply adds a name to the list of passes to
+ /// execute.
+ pub fn register_llvm_pass(&mut self, name: &str) {
+ self.llvm_passes.push(name.to_owned());
+ }
}
pub working_dir: PathBuf,
pub lint_store: RefCell<lint::LintStore>,
pub lints: RefCell<NodeMap<Vec<(lint::LintId, codemap::Span, String)>>>,
+ pub plugin_llvm_passes: RefCell<Vec<String>>,
pub crate_types: RefCell<Vec<config::CrateType>>,
pub crate_metadata: RefCell<Vec<String>>,
pub features: RefCell<feature_gate::Features>,
working_dir: env::current_dir().unwrap(),
lint_store: RefCell::new(lint::LintStore::new()),
lints: RefCell::new(NodeMap()),
+ plugin_llvm_passes: RefCell::new(Vec::new()),
crate_types: RefCell::new(Vec::new()),
crate_metadata: RefCell::new(Vec::new()),
features: RefCell::new(feature_gate::Features::new()),
}
});
- let Registry { syntax_exts, lint_passes, lint_groups, .. } = registry;
+ let Registry { syntax_exts, lint_passes, lint_groups, llvm_passes, .. } = registry;
{
let mut ls = sess.lint_store.borrow_mut();
for (name, to) in lint_groups {
ls.register_group(Some(sess), true, name, to);
}
+
+ *sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
}
// Lint plugins are registered; now we can process command line flags.
lto_ctxt: Option<(&'a Session, &'a [String])>,
// Handler to use for diagnostics produced during codegen.
handler: &'a Handler,
+ // LLVM passes added by plugins.
+ plugin_passes: Vec<String>,
// LLVM optimizations for which we want to print remarks.
remark: Passes,
}
CodegenContext {
lto_ctxt: Some((sess, reachable)),
handler: sess.diagnostic().handler(),
+ plugin_passes: sess.plugin_llvm_passes.borrow().clone(),
remark: sess.opts.cg.remark.clone(),
}
}
}
}
+ for pass in &cgcx.plugin_passes {
+ let pass = CString::new(pass.clone()).unwrap();
+ if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
+ cgcx.handler.err(&format!("a plugin asked for LLVM pass {:?} but LLVM \
+ does not recognize it", pass));
+ }
+ }
+
+ cgcx.handler.abort_if_errors();
+
// Finally, run the actual optimization passes
time(config.time_passes, "llvm function passes", (), |()|
llvm::LLVMRustRunFunctionPassManager(fpm, llmod));
for i in 0..num_workers {
let work_items_arc = work_items_arc.clone();
let diag_emitter = diag_emitter.clone();
+ let plugin_passes = sess.plugin_llvm_passes.borrow().clone();
let remark = sess.opts.cg.remark.clone();
let (tx, rx) = channel();
let cgcx = CodegenContext {
lto_ctxt: None,
handler: &diag_handler,
+ plugin_passes: plugin_passes,
remark: remark,
};
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// force-host
+
+#![feature(plugin_registrar)]
+#![feature(rustc_private)]
+
+extern crate rustc;
+
+use rustc::plugin::Registry;
+
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ // This pass is built in to LLVM.
+ //
+ // Normally, we would name a pass that was registered through
+ // C++ static object constructors in the same .so file as the
+ // plugin registrar.
+ reg.register_llvm_pass("inline");
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:llvm_pass_plugin.rs
+// ignore-stage1
+
+#![feature(plugin)]
+#![plugin(llvm_pass_plugin)]
+
+pub fn main() { }