diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 7df050e5e9e..b3ef98b26cb 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -25,7 +25,7 @@ use rustc::session::config::{self, OutputFilenames, OutputType, Passes, SomePass use rustc::session::Session; use rustc::util::nodemap::FxHashMap; use time_graph::{self, TimeGraph, Timeline}; -use llvm::{self, DiagnosticInfo, PassManagerRef, SMDiagnostic}; +use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic}; use {CodegenResults, ModuleSource, ModuleCodegen, CompiledModule, ModuleKind}; use CrateInfo; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -92,9 +92,9 @@ pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError { pub fn write_output_file( handler: &errors::Handler, - target: &llvm::TargetMachine, - pm: llvm::PassManagerRef, - m: &llvm::Module, + target: &'ll llvm::TargetMachine, + pm: &llvm::PassManager<'ll>, + m: &'ll llvm::Module, output: &Path, file_type: llvm::FileType) -> Result<(), FatalError> { unsafe { @@ -516,50 +516,52 @@ unsafe fn optimize(cgcx: &CodegenContext, let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod); let mpm = llvm::LLVMCreatePassManager(); - // If we're verifying or linting, add them to the function pass - // manager. - let addpass = |pass_name: &str| { - let pass_name = CString::new(pass_name).unwrap(); - let pass = match llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()) { - Some(pass) => pass, - None => return false, + { + // If we're verifying or linting, add them to the function pass + // manager. + let addpass = |pass_name: &str| { + let pass_name = CString::new(pass_name).unwrap(); + let pass = match llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()) { + Some(pass) => pass, + None => return false, + }; + let pass_manager = match llvm::LLVMRustPassKind(pass) { + llvm::PassKind::Function => &*fpm, + llvm::PassKind::Module => &*mpm, + llvm::PassKind::Other => { + diag_handler.err("Encountered LLVM pass kind we can't handle"); + return true + }, + }; + llvm::LLVMRustAddPass(pass_manager, pass); + true }; - let pass_manager = match llvm::LLVMRustPassKind(pass) { - llvm::PassKind::Function => fpm, - llvm::PassKind::Module => mpm, - llvm::PassKind::Other => { - diag_handler.err("Encountered LLVM pass kind we can't handle"); - return true - }, - }; - llvm::LLVMRustAddPass(pass_manager, pass); - true - }; - if config.verify_llvm_ir { assert!(addpass("verify")); } - if !config.no_prepopulate_passes { - llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod); - llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod); - let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None); - let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal; - with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| { - llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm); - llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm); - }) - } - - for pass in &config.passes { - if !addpass(pass) { - diag_handler.warn(&format!("unknown pass `{}`, ignoring", - pass)); + if config.verify_llvm_ir { assert!(addpass("verify")); } + if !config.no_prepopulate_passes { + llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod); + llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod); + let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None); + let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal; + with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| { + llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm); + llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm); + }) } - } - for pass in &cgcx.plugin_passes { - if !addpass(pass) { - diag_handler.err(&format!("a plugin asked for LLVM pass \ - `{}` but LLVM does not \ - recognize it", pass)); + for pass in &config.passes { + if !addpass(pass) { + diag_handler.warn(&format!("unknown pass `{}`, ignoring", + pass)); + } + } + + for pass in &cgcx.plugin_passes { + if !addpass(pass) { + diag_handler.err(&format!("a plugin asked for LLVM pass \ + `{}` but LLVM does not \ + recognize it", pass)); + } } } @@ -636,11 +638,11 @@ unsafe fn codegen(cgcx: &CodegenContext, // pass manager passed to the closure should be ensured to not // escape the closure itself, and the manager should only be // used once. - unsafe fn with_codegen(tm: &llvm::TargetMachine, - llmod: &llvm::Module, + unsafe fn with_codegen<'ll, F, R>(tm: &'ll llvm::TargetMachine, + llmod: &'ll llvm::Module, no_builtins: bool, f: F) -> R - where F: FnOnce(PassManagerRef) -> R, + where F: FnOnce(&'ll mut PassManager<'ll>) -> R, { let cpm = llvm::LLVMCreatePassManager(); llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod); diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 02a7bc045d6..7883315a5de 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -397,8 +397,7 @@ extern { pub type Metadata; } extern { pub type BasicBlock; } extern { pub type Builder; } extern { pub type MemoryBuffer; } -extern { pub type PassManager; } -pub type PassManagerRef = *mut PassManager; +pub struct PassManager<'a>(InvariantOpaque<'a>); extern { pub type PassManagerBuilder; } extern { pub type ObjectFile; } extern { pub type SectionIterator; } @@ -1105,16 +1104,16 @@ extern "C" { pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int; /// Creates a pass manager. - pub fn LLVMCreatePassManager() -> PassManagerRef; + pub fn LLVMCreatePassManager() -> &'a mut PassManager<'a>; /// Creates a function-by-function pass manager - pub fn LLVMCreateFunctionPassManagerForModule(M: &Module) -> PassManagerRef; + pub fn LLVMCreateFunctionPassManagerForModule(M: &'a Module) -> &'a mut PassManager<'a>; /// Disposes a pass manager. - pub fn LLVMDisposePassManager(PM: PassManagerRef); + pub fn LLVMDisposePassManager(PM: &'a mut PassManager<'a>); /// Runs a pass manager on a module. - pub fn LLVMRunPassManager(PM: PassManagerRef, M: &Module) -> Bool; + pub fn LLVMRunPassManager(PM: &PassManager<'a>, M: &'a Module) -> Bool; pub fn LLVMInitializePasses(); @@ -1125,17 +1124,17 @@ extern "C" { pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(PMB: &PassManagerBuilder, threshold: c_uint); pub fn LLVMPassManagerBuilderPopulateModulePassManager(PMB: &PassManagerBuilder, - PM: PassManagerRef); + PM: &PassManager); pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(PMB: &PassManagerBuilder, - PM: PassManagerRef); + PM: &PassManager); pub fn LLVMPassManagerBuilderPopulateLTOPassManager(PMB: &PassManagerBuilder, - PM: PassManagerRef, + PM: &PassManager, Internalize: Bool, RunInliner: Bool); pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager( PMB: &PassManagerBuilder, - PM: PassManagerRef) -> bool; + PM: &PassManager) -> bool; // Stuff that's in rustllvm/ because it's not upstream yet. @@ -1416,7 +1415,7 @@ extern "C" { pub fn LLVMRustPassKind(Pass: &Pass) -> PassKind; pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>; - pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: &'static mut Pass); + pub fn LLVMRustAddPass(PM: &PassManager, Pass: &'static mut Pass); pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; @@ -1437,7 +1436,7 @@ extern "C" { Singlethread: bool) -> Option<&'static mut TargetMachine>; pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine); - pub fn LLVMRustAddAnalysisPasses(T: &TargetMachine, PM: PassManagerRef, M: &Module); + pub fn LLVMRustAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>, M: &'a Module); pub fn LLVMRustAddBuilderLibraryInfo(PMB: &'a PassManagerBuilder, M: &'a Module, DisableSimplifyLibCalls: bool); @@ -1449,18 +1448,18 @@ extern "C" { PrepareForThinLTO: bool, PGOGenPath: *const c_char, PGOUsePath: *const c_char); - pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, - M: &Module, + pub fn LLVMRustAddLibraryInfo(PM: &PassManager<'a>, + M: &'a Module, DisableSimplifyLibCalls: bool); - pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: &Module); + pub fn LLVMRustRunFunctionPassManager(PM: &PassManager<'a>, M: &'a Module); pub fn LLVMRustWriteOutputFile(T: &'a TargetMachine, - PM: PassManagerRef, + PM: &PassManager<'a>, M: &'a Module, Output: *const c_char, FileType: FileType) -> LLVMRustResult; - pub fn LLVMRustPrintModule(PM: PassManagerRef, - M: &Module, + pub fn LLVMRustPrintModule(PM: &PassManager<'a>, + M: &'a Module, Output: *const c_char, Demangle: extern fn(*const c_char, size_t,