diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index fc7fa299fb8..0f85c4528d2 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -461,6 +461,15 @@ pub enum ArchiveKind { K_COFF, } +/// Represents the different LLVM passes Rust supports +#[derive(Copy, Clone, PartialEq, Debug)] +#[repr(C)] +pub enum SupportedPassKind { + Function, + Module, + Unsupported, +} + // Opaque pointer types #[allow(missing_copy_implementations)] pub enum Module_opaque {} @@ -2008,7 +2017,10 @@ extern { pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef; pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef; - pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: *const c_char) -> bool; + pub fn LLVMRustPassKind(Pass: PassRef) -> SupportedPassKind; + pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef; + pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef); + pub fn LLVMRustCreateTargetMachine(Triple: *const c_char, CPU: *const c_char, Features: *const c_char, diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 85419a07250..06d32b8f601 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -145,7 +145,9 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, unsafe { let pm = llvm::LLVMCreatePassManager(); llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod); - llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _); + let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _); + assert!(!pass.is_null()); + llvm::LLVMRustAddPass(pm, pass); with_llvm_pmb(llmod, config, &mut |b| { llvm::LLVMPassManagerBuilderPopulateLTOPassManager(b, pm, @@ -153,7 +155,9 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, /* RunInliner = */ True); }); - llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _); + let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _); + assert!(!pass.is_null()); + llvm::LLVMRustAddPass(pm, pass); time(sess.time_passes(), "LTO passes", || llvm::LLVMRunPassManager(pm, llmod)); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 544df1798ea..bc007da7174 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -446,9 +446,22 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, // If we're verifying or linting, add them to the function pass // manager. - let addpass = |pass: &str| { - let pass = CString::new(pass).unwrap(); - llvm::LLVMRustAddPass(fpm, pass.as_ptr()) + let addpass = |pass_name: &str| { + let pass_name = CString::new(pass_name).unwrap(); + let pass = llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()); + if pass.is_null() { + return false; + } + let pass_manager = match llvm::LLVMRustPassKind(pass) { + llvm::SupportedPassKind::Function => fpm, + llvm::SupportedPassKind::Module => mpm, + llvm::SupportedPassKind::Unsupported => { + cgcx.handler.err("Encountered LLVM pass kind we can't handle"); + return true + }, + }; + llvm::LLVMRustAddPass(pass_manager, pass); + true }; if !config.no_verify { assert!(addpass("verify")); } diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 30096677aa4..d6985719acb 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -58,19 +58,43 @@ LLVMInitializePasses() { initializeTarget(Registry); } -extern "C" bool -LLVMRustAddPass(LLVMPassManagerRef PM, const char *PassName) { - PassManagerBase *pm = unwrap(PM); +enum class SupportedPassKind { + Function, + Module, + Unsupported +}; + +extern "C" Pass* +LLVMRustFindAndCreatePass(const char *PassName) { StringRef SR(PassName); PassRegistry *PR = PassRegistry::getPassRegistry(); const PassInfo *PI = PR->getPassInfo(SR); if (PI) { - pm->add(PI->createPass()); - return true; + return PI->createPass(); } - return false; + return NULL; +} + +extern "C" SupportedPassKind +LLVMRustPassKind(Pass *pass) { + assert(pass); + PassKind passKind = pass->getPassKind(); + if (passKind == PT_Module) { + return SupportedPassKind::Module; + } else if (passKind == PT_Function) { + return SupportedPassKind::Function; + } else { + return SupportedPassKind::Unsupported; + } +} + +extern "C" void +LLVMRustAddPass(LLVMPassManagerRef PM, Pass *pass) { + assert(pass); + PassManagerBase *pm = unwrap(PM); + pm->add(pass); } extern "C" LLVMTargetMachineRef