rustc_codegen_llvm: use safe references for PassManager.

This commit is contained in:
Irina Popa 2018-07-17 14:17:47 +03:00
parent 0ab3444540
commit e22eebaf2b
2 changed files with 66 additions and 65 deletions

View File

@ -25,7 +25,7 @@ use rustc::session::config::{self, OutputFilenames, OutputType, Passes, SomePass
use rustc::session::Session; use rustc::session::Session;
use rustc::util::nodemap::FxHashMap; use rustc::util::nodemap::FxHashMap;
use time_graph::{self, TimeGraph, Timeline}; 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 {CodegenResults, ModuleSource, ModuleCodegen, CompiledModule, ModuleKind};
use CrateInfo; use CrateInfo;
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; 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( pub fn write_output_file(
handler: &errors::Handler, handler: &errors::Handler,
target: &llvm::TargetMachine, target: &'ll llvm::TargetMachine,
pm: llvm::PassManagerRef, pm: &llvm::PassManager<'ll>,
m: &llvm::Module, m: &'ll llvm::Module,
output: &Path, output: &Path,
file_type: llvm::FileType) -> Result<(), FatalError> { file_type: llvm::FileType) -> Result<(), FatalError> {
unsafe { unsafe {
@ -516,50 +516,52 @@ unsafe fn optimize(cgcx: &CodegenContext,
let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod); let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod);
let mpm = llvm::LLVMCreatePassManager(); let mpm = llvm::LLVMCreatePassManager();
// If we're verifying or linting, add them to the function pass {
// manager. // If we're verifying or linting, add them to the function pass
let addpass = |pass_name: &str| { // manager.
let pass_name = CString::new(pass_name).unwrap(); let addpass = |pass_name: &str| {
let pass = match llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()) { let pass_name = CString::new(pass_name).unwrap();
Some(pass) => pass, let pass = match llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()) {
None => return false, 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.verify_llvm_ir { assert!(addpass("verify")); }
if !config.no_prepopulate_passes { if !config.no_prepopulate_passes {
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod); llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod); llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None); let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal; 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| { with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| {
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm); llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm); llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
}) })
}
for pass in &config.passes {
if !addpass(pass) {
diag_handler.warn(&format!("unknown pass `{}`, ignoring",
pass));
} }
}
for pass in &cgcx.plugin_passes { for pass in &config.passes {
if !addpass(pass) { if !addpass(pass) {
diag_handler.err(&format!("a plugin asked for LLVM pass \ diag_handler.warn(&format!("unknown pass `{}`, ignoring",
`{}` but LLVM does not \ pass));
recognize it", 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 // pass manager passed to the closure should be ensured to not
// escape the closure itself, and the manager should only be // escape the closure itself, and the manager should only be
// used once. // used once.
unsafe fn with_codegen<F, R>(tm: &llvm::TargetMachine, unsafe fn with_codegen<'ll, F, R>(tm: &'ll llvm::TargetMachine,
llmod: &llvm::Module, llmod: &'ll llvm::Module,
no_builtins: bool, no_builtins: bool,
f: F) -> R f: F) -> R
where F: FnOnce(PassManagerRef) -> R, where F: FnOnce(&'ll mut PassManager<'ll>) -> R,
{ {
let cpm = llvm::LLVMCreatePassManager(); let cpm = llvm::LLVMCreatePassManager();
llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod); llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);

View File

@ -397,8 +397,7 @@ extern { pub type Metadata; }
extern { pub type BasicBlock; } extern { pub type BasicBlock; }
extern { pub type Builder; } extern { pub type Builder; }
extern { pub type MemoryBuffer; } extern { pub type MemoryBuffer; }
extern { pub type PassManager; } pub struct PassManager<'a>(InvariantOpaque<'a>);
pub type PassManagerRef = *mut PassManager;
extern { pub type PassManagerBuilder; } extern { pub type PassManagerBuilder; }
extern { pub type ObjectFile; } extern { pub type ObjectFile; }
extern { pub type SectionIterator; } extern { pub type SectionIterator; }
@ -1105,16 +1104,16 @@ extern "C" {
pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int; pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int;
/// Creates a pass manager. /// Creates a pass manager.
pub fn LLVMCreatePassManager() -> PassManagerRef; pub fn LLVMCreatePassManager() -> &'a mut PassManager<'a>;
/// Creates a function-by-function pass manager /// 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. /// Disposes a pass manager.
pub fn LLVMDisposePassManager(PM: PassManagerRef); pub fn LLVMDisposePassManager(PM: &'a mut PassManager<'a>);
/// Runs a pass manager on a module. /// 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(); pub fn LLVMInitializePasses();
@ -1125,17 +1124,17 @@ extern "C" {
pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(PMB: &PassManagerBuilder, pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(PMB: &PassManagerBuilder,
threshold: c_uint); threshold: c_uint);
pub fn LLVMPassManagerBuilderPopulateModulePassManager(PMB: &PassManagerBuilder, pub fn LLVMPassManagerBuilderPopulateModulePassManager(PMB: &PassManagerBuilder,
PM: PassManagerRef); PM: &PassManager);
pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(PMB: &PassManagerBuilder, pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(PMB: &PassManagerBuilder,
PM: PassManagerRef); PM: &PassManager);
pub fn LLVMPassManagerBuilderPopulateLTOPassManager(PMB: &PassManagerBuilder, pub fn LLVMPassManagerBuilderPopulateLTOPassManager(PMB: &PassManagerBuilder,
PM: PassManagerRef, PM: &PassManager,
Internalize: Bool, Internalize: Bool,
RunInliner: Bool); RunInliner: Bool);
pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager( pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
PMB: &PassManagerBuilder, PMB: &PassManagerBuilder,
PM: PassManagerRef) -> bool; PM: &PassManager) -> bool;
// Stuff that's in rustllvm/ because it's not upstream yet. // 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 LLVMRustPassKind(Pass: &Pass) -> PassKind;
pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>; 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; pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool;
@ -1437,7 +1436,7 @@ extern "C" {
Singlethread: bool) Singlethread: bool)
-> Option<&'static mut TargetMachine>; -> Option<&'static mut TargetMachine>;
pub fn LLVMRustDisposeTargetMachine(T: &'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, pub fn LLVMRustAddBuilderLibraryInfo(PMB: &'a PassManagerBuilder,
M: &'a Module, M: &'a Module,
DisableSimplifyLibCalls: bool); DisableSimplifyLibCalls: bool);
@ -1449,18 +1448,18 @@ extern "C" {
PrepareForThinLTO: bool, PrepareForThinLTO: bool,
PGOGenPath: *const c_char, PGOGenPath: *const c_char,
PGOUsePath: *const c_char); PGOUsePath: *const c_char);
pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, pub fn LLVMRustAddLibraryInfo(PM: &PassManager<'a>,
M: &Module, M: &'a Module,
DisableSimplifyLibCalls: bool); DisableSimplifyLibCalls: bool);
pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: &Module); pub fn LLVMRustRunFunctionPassManager(PM: &PassManager<'a>, M: &'a Module);
pub fn LLVMRustWriteOutputFile(T: &'a TargetMachine, pub fn LLVMRustWriteOutputFile(T: &'a TargetMachine,
PM: PassManagerRef, PM: &PassManager<'a>,
M: &'a Module, M: &'a Module,
Output: *const c_char, Output: *const c_char,
FileType: FileType) FileType: FileType)
-> LLVMRustResult; -> LLVMRustResult;
pub fn LLVMRustPrintModule(PM: PassManagerRef, pub fn LLVMRustPrintModule(PM: &PassManager<'a>,
M: &Module, M: &'a Module,
Output: *const c_char, Output: *const c_char,
Demangle: extern fn(*const c_char, Demangle: extern fn(*const c_char,
size_t, size_t,