diff options
| author | Irina Popa <irinagpopa@gmail.com> | 2018-06-27 17:57:25 +0300 |
|---|---|---|
| committer | Irina Popa <irinagpopa@gmail.com> | 2018-07-30 18:27:52 +0300 |
| commit | 249d5acaec0b10ee15b21b888977b5445baba42e (patch) | |
| tree | 966ea8d75c9e97d2b6e70d0bcd30ceef689d4b8a /src/librustc_codegen_llvm | |
| parent | af04e9426c71ac1050b9007c93b03864e45a81df (diff) | |
| download | rust-249d5acaec0b10ee15b21b888977b5445baba42e.tar.gz rust-249d5acaec0b10ee15b21b888977b5445baba42e.zip | |
rustc_codegen_llvm: use safe references for Context and Module.
Diffstat (limited to 'src/librustc_codegen_llvm')
| -rw-r--r-- | src/librustc_codegen_llvm/allocator.rs | 4 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/back/lto.rs | 326 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/back/write.rs | 357 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/base.rs | 72 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/common.rs | 6 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/context.rs | 110 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/debuginfo/metadata.rs | 2 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/debuginfo/mod.rs | 12 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/debuginfo/utils.rs | 2 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/lib.rs | 36 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/llvm/ffi.rs | 168 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/llvm/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/type_.rs | 8 |
13 files changed, 549 insertions, 556 deletions
diff --git a/src/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs index 49cdbf34fa9..2d401da958b 100644 --- a/src/librustc_codegen_llvm/allocator.rs +++ b/src/librustc_codegen_llvm/allocator.rs @@ -20,8 +20,8 @@ use ModuleLlvm; use llvm::{self, False, True}; pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) { - let llcx = mods.llcx; - let llmod = mods.llmod; + let llcx = &*mods.llcx; + let llmod = mods.llmod(); let usize = match &tcx.sess.target.target.target_pointer_width[..] { "16" => llvm::LLVMInt16TypeInContext(llcx), "32" => llvm::LLVMInt32TypeInContext(llcx), diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 93cb9eb9767..fce34710b81 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -14,7 +14,7 @@ use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext}; use back::write; use errors::{FatalError, Handler}; use llvm::archive_ro::ArchiveRO; -use llvm::{ModuleRef, TargetMachineRef, True, False}; +use llvm::{TargetMachineRef, True, False}; use llvm; use rustc::hir::def_id::LOCAL_CRATE; use rustc::middle::exported_symbols::SymbolExportLevel; @@ -73,11 +73,13 @@ impl LtoModuleCodegen { match *self { LtoModuleCodegen::Fat { ref mut module, .. } => { let module = module.take().unwrap(); - let config = cgcx.config(module.kind); - let llmod = module.llvm().unwrap().llmod; - let tm = module.llvm().unwrap().tm; - run_pass_manager(cgcx, tm, llmod, config, false); - timeline.record("fat-done"); + { + let config = cgcx.config(module.kind); + let llmod = module.llvm().unwrap().llmod(); + let tm = &*module.llvm().unwrap().tm; + run_pass_manager(cgcx, tm, llmod, config, false); + timeline.record("fat-done"); + } Ok(module) } LtoModuleCodegen::Thin(ref mut thin) => thin.optimize(cgcx, timeline), @@ -223,66 +225,68 @@ fn fat_lto(cgcx: &CodegenContext, .filter(|&(_, module)| module.kind == ModuleKind::Regular) .map(|(i, module)| { let cost = unsafe { - llvm::LLVMRustModuleCost(module.llvm().unwrap().llmod) + llvm::LLVMRustModuleCost(module.llvm().unwrap().llmod()) }; (cost, i) }) .max() .expect("must be codegen'ing at least one module"); let module = modules.remove(costliest_module); - let llmod = module.llvm().expect("can't lto pre-codegened modules").llmod; - info!("using {:?} as a base module", module.llmod_id); - - // For all other modules we codegened we'll need to link them into our own - // bitcode. All modules were codegened in their own LLVM context, however, - // and we want to move everything to the same LLVM context. Currently the - // way we know of to do that is to serialize them to a string and them parse - // them later. Not great but hey, that's why it's "fat" LTO, right? - for module in modules { - let llvm = module.llvm().expect("can't lto pre-codegened modules"); - let buffer = ModuleBuffer::new(llvm.llmod); - let llmod_id = CString::new(&module.llmod_id[..]).unwrap(); - serialized_modules.push((SerializedModule::Local(buffer), llmod_id)); - } - - // For all serialized bitcode files we parse them and link them in as we did - // above, this is all mostly handled in C++. Like above, though, we don't - // know much about the memory management here so we err on the side of being - // save and persist everything with the original module. let mut serialized_bitcode = Vec::new(); - let mut linker = Linker::new(llmod); - for (bc_decoded, name) in serialized_modules { - info!("linking {:?}", name); - time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || { - let data = bc_decoded.data(); - linker.add(&data).map_err(|()| { - let msg = format!("failed to load bc of {:?}", name); - write::llvm_err(&diag_handler, msg) - }) - })?; - timeline.record(&format!("link {:?}", name)); - serialized_bitcode.push(bc_decoded); - } - drop(linker); - cgcx.save_temp_bitcode(&module, "lto.input"); + { + let llmod = module.llvm().expect("can't lto pre-codegened modules").llmod(); + info!("using {:?} as a base module", module.llmod_id); + + // For all other modules we codegened we'll need to link them into our own + // bitcode. All modules were codegened in their own LLVM context, however, + // and we want to move everything to the same LLVM context. Currently the + // way we know of to do that is to serialize them to a string and them parse + // them later. Not great but hey, that's why it's "fat" LTO, right? + for module in modules { + let llvm = module.llvm().expect("can't lto pre-codegened modules"); + let buffer = ModuleBuffer::new(llvm.llmod()); + let llmod_id = CString::new(&module.llmod_id[..]).unwrap(); + serialized_modules.push((SerializedModule::Local(buffer), llmod_id)); + } - // Internalize everything that *isn't* in our whitelist to help strip out - // more modules and such - unsafe { - let ptr = symbol_white_list.as_ptr(); - llvm::LLVMRustRunRestrictionPass(llmod, - ptr as *const *const libc::c_char, - symbol_white_list.len() as libc::size_t); - cgcx.save_temp_bitcode(&module, "lto.after-restriction"); - } + // For all serialized bitcode files we parse them and link them in as we did + // above, this is all mostly handled in C++. Like above, though, we don't + // know much about the memory management here so we err on the side of being + // save and persist everything with the original module. + let mut linker = Linker::new(llmod); + for (bc_decoded, name) in serialized_modules { + info!("linking {:?}", name); + time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || { + let data = bc_decoded.data(); + linker.add(&data).map_err(|()| { + let msg = format!("failed to load bc of {:?}", name); + write::llvm_err(&diag_handler, msg) + }) + })?; + timeline.record(&format!("link {:?}", name)); + serialized_bitcode.push(bc_decoded); + } + drop(linker); + cgcx.save_temp_bitcode(&module, "lto.input"); - if cgcx.no_landing_pads { + // Internalize everything that *isn't* in our whitelist to help strip out + // more modules and such unsafe { - llvm::LLVMRustMarkAllFunctionsNounwind(llmod); + let ptr = symbol_white_list.as_ptr(); + llvm::LLVMRustRunRestrictionPass(llmod, + ptr as *const *const libc::c_char, + symbol_white_list.len() as libc::size_t); + cgcx.save_temp_bitcode(&module, "lto.after-restriction"); } - cgcx.save_temp_bitcode(&module, "lto.after-nounwind"); + + if cgcx.no_landing_pads { + unsafe { + llvm::LLVMRustMarkAllFunctionsNounwind(llmod); + } + cgcx.save_temp_bitcode(&module, "lto.after-nounwind"); + } + timeline.record("passes"); } - timeline.record("passes"); Ok(vec![LtoModuleCodegen::Fat { module: Some(module), @@ -293,7 +297,7 @@ fn fat_lto(cgcx: &CodegenContext, struct Linker(llvm::LinkerRef); impl Linker { - fn new(llmod: ModuleRef) -> Linker { + fn new(llmod: &llvm::Module) -> Linker { unsafe { Linker(llvm::LLVMRustLinkerNew(llmod)) } } @@ -371,7 +375,7 @@ fn thin_lto(diag_handler: &Handler, info!("local module: {} - {}", i, module.llmod_id); let llvm = module.llvm().expect("can't lto precodegened module"); let name = CString::new(module.llmod_id.clone()).unwrap(); - let buffer = ThinBuffer::new(llvm.llmod); + let buffer = ThinBuffer::new(llvm.llmod()); thin_modules.push(llvm::ThinLTOModule { identifier: name.as_ptr(), data: buffer.data().as_ptr(), @@ -449,7 +453,7 @@ fn thin_lto(diag_handler: &Handler, fn run_pass_manager(cgcx: &CodegenContext, tm: TargetMachineRef, - llmod: ModuleRef, + llmod: &llvm::Module, config: &ModuleConfig, thin: bool) { // Now we have one massive module inside of llmod. Time to run the @@ -531,7 +535,7 @@ unsafe impl Send for ModuleBuffer {} unsafe impl Sync for ModuleBuffer {} impl ModuleBuffer { - pub fn new(m: ModuleRef) -> ModuleBuffer { + pub fn new(m: &llvm::Module) -> ModuleBuffer { ModuleBuffer(unsafe { llvm::LLVMRustModuleBufferCreate(m) }) @@ -583,7 +587,7 @@ unsafe impl Send for ThinBuffer {} unsafe impl Sync for ThinBuffer {} impl ThinBuffer { - pub fn new(m: ModuleRef) -> ThinBuffer { + pub fn new(m: &llvm::Module) -> ThinBuffer { unsafe { let buffer = llvm::LLVMRustThinLTOBufferCreate(m); ThinBuffer(buffer) @@ -640,19 +644,18 @@ impl ThinModule { // crates but for locally codegened modules we may be able to reuse // that LLVM Context and Module. let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names); - let llmod = llvm::LLVMRustParseBitcodeForThinLTO( + let llmod_raw = llvm::LLVMRustParseBitcodeForThinLTO( llcx, self.data().as_ptr(), self.data().len(), self.shared.module_names[self.idx].as_ptr(), - ); - if llmod.is_null() { + ).ok_or_else(|| { let msg = "failed to parse bitcode for thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)); - } + write::llvm_err(&diag_handler, msg) + })? as *const _; let module = ModuleCodegen { source: ModuleSource::Codegened(ModuleLlvm { - llmod, + llmod_raw, llcx, tm, }), @@ -660,104 +663,107 @@ impl ThinModule { name: self.name().to_string(), kind: ModuleKind::Regular, }; - cgcx.save_temp_bitcode(&module, "thin-lto-input"); - - // Before we do much else find the "main" `DICompileUnit` that we'll be - // using below. If we find more than one though then rustc has changed - // in a way we're not ready for, so generate an ICE by returning - // an error. - let mut cu1 = ptr::null_mut(); - let mut cu2 = ptr::null_mut(); - llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); - if !cu2.is_null() { - let msg = "multiple source DICompileUnits found".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) - } + { + let llmod = module.llvm().unwrap().llmod(); + cgcx.save_temp_bitcode(&module, "thin-lto-input"); + + // Before we do much else find the "main" `DICompileUnit` that we'll be + // using below. If we find more than one though then rustc has changed + // in a way we're not ready for, so generate an ICE by returning + // an error. + let mut cu1 = ptr::null_mut(); + let mut cu2 = ptr::null_mut(); + llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); + if !cu2.is_null() { + let msg = "multiple source DICompileUnits found".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } - // Like with "fat" LTO, get some better optimizations if landing pads - // are disabled by removing all landing pads. - if cgcx.no_landing_pads { - llvm::LLVMRustMarkAllFunctionsNounwind(llmod); - cgcx.save_temp_bitcode(&module, "thin-lto-after-nounwind"); - timeline.record("nounwind"); - } + // Like with "fat" LTO, get some better optimizations if landing pads + // are disabled by removing all landing pads. + if cgcx.no_landing_pads { + llvm::LLVMRustMarkAllFunctionsNounwind(llmod); + cgcx.save_temp_bitcode(&module, "thin-lto-after-nounwind"); + timeline.record("nounwind"); + } - // Up next comes the per-module local analyses that we do for Thin LTO. - // Each of these functions is basically copied from the LLVM - // implementation and then tailored to suit this implementation. Ideally - // each of these would be supported by upstream LLVM but that's perhaps - // a patch for another day! - // - // You can find some more comments about these functions in the LLVM - // bindings we've got (currently `PassWrapper.cpp`) - if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) - } - cgcx.save_temp_bitcode(&module, "thin-lto-after-rename"); - timeline.record("rename"); - if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) - } - cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve"); - timeline.record("resolve"); - if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) - } - cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize"); - timeline.record("internalize"); - if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) + // Up next comes the per-module local analyses that we do for Thin LTO. + // Each of these functions is basically copied from the LLVM + // implementation and then tailored to suit this implementation. Ideally + // each of these would be supported by upstream LLVM but that's perhaps + // a patch for another day! + // + // You can find some more comments about these functions in the LLVM + // bindings we've got (currently `PassWrapper.cpp`) + if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&module, "thin-lto-after-rename"); + timeline.record("rename"); + if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve"); + timeline.record("resolve"); + if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize"); + timeline.record("internalize"); + if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&module, "thin-lto-after-import"); + timeline.record("import"); + + // Ok now this is a bit unfortunate. This is also something you won't + // find upstream in LLVM's ThinLTO passes! This is a hack for now to + // work around bugs in LLVM. + // + // First discovered in #45511 it was found that as part of ThinLTO + // importing passes LLVM will import `DICompileUnit` metadata + // information across modules. This means that we'll be working with one + // LLVM module that has multiple `DICompileUnit` instances in it (a + // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of + // bugs in LLVM's backend which generates invalid DWARF in a situation + // like this: + // + // https://bugs.llvm.org/show_bug.cgi?id=35212 + // https://bugs.llvm.org/show_bug.cgi?id=35562 + // + // While the first bug there is fixed the second ended up causing #46346 + // which was basically a resurgence of #45511 after LLVM's bug 35212 was + // fixed. + // + // This function below is a huge hack around this problem. The function + // below is defined in `PassWrapper.cpp` and will basically "merge" + // all `DICompileUnit` instances in a module. Basically it'll take all + // the objects, rewrite all pointers of `DISubprogram` to point to the + // first `DICompileUnit`, and then delete all the other units. + // + // This is probably mangling to the debug info slightly (but hopefully + // not too much) but for now at least gets LLVM to emit valid DWARF (or + // so it appears). Hopefully we can remove this once upstream bugs are + // fixed in LLVM. + llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1); + cgcx.save_temp_bitcode(&module, "thin-lto-after-patch"); + timeline.record("patch"); + + // Alright now that we've done everything related to the ThinLTO + // analysis it's time to run some optimizations! Here we use the same + // `run_pass_manager` as the "fat" LTO above except that we tell it to + // populate a thin-specific pass manager, which presumably LLVM treats a + // little differently. + info!("running thin lto passes over {}", module.name); + let config = cgcx.config(module.kind); + run_pass_manager(cgcx, module.llvm().unwrap().tm, llmod, config, true); + cgcx.save_temp_bitcode(&module, "thin-lto-after-pm"); + timeline.record("thin-done"); } - cgcx.save_temp_bitcode(&module, "thin-lto-after-import"); - timeline.record("import"); - - // Ok now this is a bit unfortunate. This is also something you won't - // find upstream in LLVM's ThinLTO passes! This is a hack for now to - // work around bugs in LLVM. - // - // First discovered in #45511 it was found that as part of ThinLTO - // importing passes LLVM will import `DICompileUnit` metadata - // information across modules. This means that we'll be working with one - // LLVM module that has multiple `DICompileUnit` instances in it (a - // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of - // bugs in LLVM's backend which generates invalid DWARF in a situation - // like this: - // - // https://bugs.llvm.org/show_bug.cgi?id=35212 - // https://bugs.llvm.org/show_bug.cgi?id=35562 - // - // While the first bug there is fixed the second ended up causing #46346 - // which was basically a resurgence of #45511 after LLVM's bug 35212 was - // fixed. - // - // This function below is a huge hack around this problem. The function - // below is defined in `PassWrapper.cpp` and will basically "merge" - // all `DICompileUnit` instances in a module. Basically it'll take all - // the objects, rewrite all pointers of `DISubprogram` to point to the - // first `DICompileUnit`, and then delete all the other units. - // - // This is probably mangling to the debug info slightly (but hopefully - // not too much) but for now at least gets LLVM to emit valid DWARF (or - // so it appears). Hopefully we can remove this once upstream bugs are - // fixed in LLVM. - llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1); - cgcx.save_temp_bitcode(&module, "thin-lto-after-patch"); - timeline.record("patch"); - - // Alright now that we've done everything related to the ThinLTO - // analysis it's time to run some optimizations! Here we use the same - // `run_pass_manager` as the "fat" LTO above except that we tell it to - // populate a thin-specific pass manager, which presumably LLVM treats a - // little differently. - info!("running thin lto passes over {}", module.name); - let config = cgcx.config(module.kind); - run_pass_manager(cgcx, tm, llmod, config, true); - cgcx.save_temp_bitcode(&module, "thin-lto-after-pm"); - timeline.record("thin-done"); Ok(module) } diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index d36142af56c..f5c2ca22ec8 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -26,8 +26,8 @@ use rustc::session::Session; use rustc::util::nodemap::FxHashMap; use time_graph::{self, TimeGraph, Timeline}; use llvm; -use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef}; -use llvm::{SMDiagnosticRef, ContextRef}; +use llvm::{TargetMachineRef, PassManagerRef, DiagnosticInfoRef}; +use llvm::SMDiagnosticRef; use {CodegenResults, ModuleSource, ModuleCodegen, CompiledModule, ModuleKind}; use CrateInfo; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -96,7 +96,7 @@ pub fn write_output_file( handler: &errors::Handler, target: llvm::TargetMachineRef, pm: llvm::PassManagerRef, - m: ModuleRef, + m: &llvm::Module, output: &Path, file_type: llvm::FileType) -> Result<(), FatalError> { unsafe { @@ -130,7 +130,7 @@ fn get_llvm_opt_size(optimize: config::OptLevel) -> llvm::CodeGenOptSize { } } -pub fn create_target_machine(sess: &Session, find_features: bool) -> TargetMachineRef { +pub fn create_target_machine(sess: &Session, find_features: bool) -> &'static mut llvm::TargetMachine { target_machine_factory(sess, find_features)().unwrap_or_else(|err| { llvm_err(sess.diagnostic(), err).raise() }) @@ -140,7 +140,7 @@ pub fn create_target_machine(sess: &Session, find_features: bool) -> TargetMachi // that `is_pie_binary` is false. When we discover LLVM target features // `sess.crate_types` is uninitialized so we cannot access it. pub fn target_machine_factory(sess: &Session, find_features: bool) - -> Arc<dyn Fn() -> Result<TargetMachineRef, String> + Send + Sync> + -> Arc<dyn Fn() -> Result<&'static mut llvm::TargetMachine, String> + Send + Sync> { let reloc_model = get_reloc_model(sess); @@ -199,12 +199,10 @@ pub fn target_machine_factory(sess: &Session, find_features: bool) ) }; - if tm.is_null() { - Err(format!("Could not create LLVM TargetMachine for triple: {}", - triple.to_str().unwrap())) - } else { - Ok(tm) - } + tm.ok_or_else(|| { + format!("Could not create LLVM TargetMachine for triple: {}", + triple.to_str().unwrap()) + }) }) } @@ -343,7 +341,7 @@ pub struct CodegenContext { regular_module_config: Arc<ModuleConfig>, metadata_module_config: Arc<ModuleConfig>, allocator_module_config: Arc<ModuleConfig>, - pub tm_factory: Arc<dyn Fn() -> Result<TargetMachineRef, String> + Send + Sync>, + pub tm_factory: Arc<dyn Fn() -> Result<&'static mut llvm::TargetMachine, String> + Send + Sync>, pub msvc_imps_needed: bool, pub target_pointer_width: String, debuginfo: config::DebugInfoLevel, @@ -392,7 +390,7 @@ impl CodegenContext { let cgu = Some(&module.name[..]); let path = self.output_filenames.temp_path_ext(&ext, cgu); let cstr = path2cstr(&path); - let llmod = module.llvm().unwrap().llmod; + let llmod = module.llvm().unwrap().llmod(); llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr()); } } @@ -400,13 +398,13 @@ impl CodegenContext { struct DiagnosticHandlers<'a> { data: *mut (&'a CodegenContext, &'a Handler), - llcx: ContextRef, + llcx: &'a llvm::Context, } impl<'a> DiagnosticHandlers<'a> { fn new(cgcx: &'a CodegenContext, handler: &'a Handler, - llcx: ContextRef) -> DiagnosticHandlers<'a> { + llcx: &'a llvm::Context) -> Self { let data = Box::into_raw(Box::new((cgcx, handler))); unsafe { llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data as *mut _); @@ -495,7 +493,7 @@ unsafe fn optimize(cgcx: &CodegenContext, -> Result<(), FatalError> { let (llmod, llcx, tm) = match module.source { - ModuleSource::Codegened(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm), + ModuleSource::Codegened(ref llvm) => (llvm.llmod(), &*llvm.llcx, &*llvm.tm), ModuleSource::Preexisting(_) => { bug!("optimize_and_codegen: called with ModuleSource::Preexisting") } @@ -617,192 +615,191 @@ unsafe fn codegen(cgcx: &CodegenContext, -> Result<CompiledModule, FatalError> { timeline.record("codegen"); - let (llmod, llcx, tm) = match module.source { - ModuleSource::Codegened(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm), - ModuleSource::Preexisting(_) => { - bug!("codegen: called with ModuleSource::Preexisting") - } - }; - let module_name = module.name.clone(); - let module_name = Some(&module_name[..]); - let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx); - - if cgcx.msvc_imps_needed { - create_msvc_imps(cgcx, llcx, llmod); - } - - // A codegen-specific pass manager is used to generate object - // files for an LLVM module. - // - // Apparently each of these pass managers is a one-shot kind of - // thing, so we create a new one for each type of output. The - // 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<F, R>(tm: TargetMachineRef, - llmod: ModuleRef, - no_builtins: bool, - f: F) -> R - where F: FnOnce(PassManagerRef) -> R, { - let cpm = llvm::LLVMCreatePassManager(); - llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod); - llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); - f(cpm) - } - - // If we don't have the integrated assembler, then we need to emit asm - // from LLVM and use `gcc` to create the object file. - let asm_to_obj = config.emit_obj && config.no_integrated_as; - - // Change what we write and cleanup based on whether obj files are - // just llvm bitcode. In that case write bitcode, and possibly - // delete the bitcode if it wasn't requested. Don't generate the - // machine code, instead copy the .o file from the .bc - let write_bc = config.emit_bc || config.obj_is_bitcode; - let rm_bc = !config.emit_bc && config.obj_is_bitcode; - let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj; - let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode; - - let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); - let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); - - - if write_bc || config.emit_bc_compressed || config.embed_bitcode { - let thin; - let old; - let data = if llvm::LLVMRustThinLTOAvailable() { - thin = ThinBuffer::new(llmod); - thin.data() - } else { - old = ModuleBuffer::new(llmod); - old.data() + let (llmod, llcx, tm) = match module.source { + ModuleSource::Codegened(ref llvm) => (llvm.llmod(), &*llvm.llcx, &*llvm.tm), + ModuleSource::Preexisting(_) => { + bug!("codegen: called with ModuleSource::Preexisting") + } }; - timeline.record("make-bc"); + let module_name = module.name.clone(); + let module_name = Some(&module_name[..]); + let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx); - if write_bc { - if let Err(e) = fs::write(&bc_out, data) { - diag_handler.err(&format!("failed to write bytecode: {}", e)); - } - timeline.record("write-bc"); + if cgcx.msvc_imps_needed { + create_msvc_imps(cgcx, llcx, llmod); } - if config.embed_bitcode { - embed_bitcode(cgcx, llcx, llmod, Some(data)); - timeline.record("embed-bc"); - } + // A codegen-specific pass manager is used to generate object + // files for an LLVM module. + // + // Apparently each of these pass managers is a one-shot kind of + // thing, so we create a new one for each type of output. The + // 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<F, R>(tm: TargetMachineRef, + llmod: &llvm::Module, + no_builtins: bool, + f: F) -> R + where F: FnOnce(PassManagerRef) -> R, + { + let cpm = llvm::LLVMCreatePassManager(); + llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod); + llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); + f(cpm) + } + + // If we don't have the integrated assembler, then we need to emit asm + // from LLVM and use `gcc` to create the object file. + let asm_to_obj = config.emit_obj && config.no_integrated_as; + + // Change what we write and cleanup based on whether obj files are + // just llvm bitcode. In that case write bitcode, and possibly + // delete the bitcode if it wasn't requested. Don't generate the + // machine code, instead copy the .o file from the .bc + let write_bc = config.emit_bc || config.obj_is_bitcode; + let rm_bc = !config.emit_bc && config.obj_is_bitcode; + let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj; + let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode; + + let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); + let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); + + + if write_bc || config.emit_bc_compressed || config.embed_bitcode { + let thin; + let old; + let data = if llvm::LLVMRustThinLTOAvailable() { + thin = ThinBuffer::new(llmod); + thin.data() + } else { + old = ModuleBuffer::new(llmod); + old.data() + }; + timeline.record("make-bc"); - if config.emit_bc_compressed { - let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION); - let data = bytecode::encode(&module.llmod_id, data); - if let Err(e) = fs::write(&dst, data) { - diag_handler.err(&format!("failed to write bytecode: {}", e)); + if write_bc { + if let Err(e) = fs::write(&bc_out, data) { + diag_handler.err(&format!("failed to write bytecode: {}", e)); + } + timeline.record("write-bc"); } - timeline.record("compress-bc"); - } - } else if config.embed_bitcode_marker { - embed_bitcode(cgcx, llcx, llmod, None); - } - time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()), - || -> Result<(), FatalError> { - if config.emit_ir { - let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); - let out = path2cstr(&out); - - extern "C" fn demangle_callback(input_ptr: *const c_char, - input_len: size_t, - output_ptr: *mut c_char, - output_len: size_t) -> size_t { - let input = unsafe { - slice::from_raw_parts(input_ptr as *const u8, input_len as usize) - }; + if config.embed_bitcode { + embed_bitcode(cgcx, llcx, llmod, Some(data)); + timeline.record("embed-bc"); + } - let input = match str::from_utf8(input) { - Ok(s) => s, - Err(_) => return 0, - }; + if config.emit_bc_compressed { + let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION); + let data = bytecode::encode(&module.llmod_id, data); + if let Err(e) = fs::write(&dst, data) { + diag_handler.err(&format!("failed to write bytecode: {}", e)); + } + timeline.record("compress-bc"); + } + } else if config.embed_bitcode_marker { + embed_bitcode(cgcx, llcx, llmod, None); + } + + time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()), + || -> Result<(), FatalError> { + if config.emit_ir { + let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); + let out = path2cstr(&out); + + extern "C" fn demangle_callback(input_ptr: *const c_char, + input_len: size_t, + output_ptr: *mut c_char, + output_len: size_t) -> size_t { + let input = unsafe { + slice::from_raw_parts(input_ptr as *const u8, input_len as usize) + }; - let output = unsafe { - slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize) - }; - let mut cursor = io::Cursor::new(output); + let input = match str::from_utf8(input) { + Ok(s) => s, + Err(_) => return 0, + }; - let demangled = match rustc_demangle::try_demangle(input) { - Ok(d) => d, - Err(_) => return 0, - }; + let output = unsafe { + slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize) + }; + let mut cursor = io::Cursor::new(output); + + let demangled = match rustc_demangle::try_demangle(input) { + Ok(d) => d, + Err(_) => return 0, + }; - if let Err(_) = write!(cursor, "{:#}", demangled) { - // Possible only if provided buffer is not big enough - return 0; + if let Err(_) = write!(cursor, "{:#}", demangled) { + // Possible only if provided buffer is not big enough + return 0; + } + + cursor.position() as size_t } - cursor.position() as size_t + with_codegen(tm, llmod, config.no_builtins, |cpm| { + llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback); + llvm::LLVMDisposePassManager(cpm); + }); + timeline.record("ir"); } - with_codegen(tm, llmod, config.no_builtins, |cpm| { - llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback); - llvm::LLVMDisposePassManager(cpm); - }); - timeline.record("ir"); - } + if config.emit_asm || asm_to_obj { + let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); - if config.emit_asm || asm_to_obj { - let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); - - // We can't use the same module for asm and binary output, because that triggers - // various errors like invalid IR or broken binaries, so we might have to clone the - // module to produce the asm output - let llmod = if config.emit_obj { - llvm::LLVMCloneModule(llmod) - } else { - llmod - }; - with_codegen(tm, llmod, config.no_builtins, |cpm| { - write_output_file(diag_handler, tm, cpm, llmod, &path, - llvm::FileType::AssemblyFile) - })?; - if config.emit_obj { - llvm::LLVMDisposeModule(llmod); + // We can't use the same module for asm and binary output, because that triggers + // various errors like invalid IR or broken binaries, so we might have to clone the + // module to produce the asm output + let llmod = if config.emit_obj { + llvm::LLVMCloneModule(llmod) + } else { + llmod + }; + with_codegen(tm, llmod, config.no_builtins, |cpm| { + write_output_file(diag_handler, tm, cpm, llmod, &path, + llvm::FileType::AssemblyFile) + })?; + timeline.record("asm"); } - timeline.record("asm"); - } - if write_obj { - with_codegen(tm, llmod, config.no_builtins, |cpm| { - write_output_file(diag_handler, tm, cpm, llmod, &obj_out, - llvm::FileType::ObjectFile) - })?; - timeline.record("obj"); - } else if asm_to_obj { - let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); - run_assembler(cgcx, diag_handler, &assembly, &obj_out); - timeline.record("asm_to_obj"); - - if !config.emit_asm && !cgcx.save_temps { - drop(fs::remove_file(&assembly)); + if write_obj { + with_codegen(tm, llmod, config.no_builtins, |cpm| { + write_output_file(diag_handler, tm, cpm, llmod, &obj_out, + llvm::FileType::ObjectFile) + })?; + timeline.record("obj"); + } else if asm_to_obj { + let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + run_assembler(cgcx, diag_handler, &assembly, &obj_out); + timeline.record("asm_to_obj"); + + if !config.emit_asm && !cgcx.save_temps { + drop(fs::remove_file(&assembly)); + } } - } - Ok(()) - })?; + Ok(()) + })?; - if copy_bc_to_obj { - debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out); - if let Err(e) = link_or_copy(&bc_out, &obj_out) { - diag_handler.err(&format!("failed to copy bitcode to object file: {}", e)); + if copy_bc_to_obj { + debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out); + if let Err(e) = link_or_copy(&bc_out, &obj_out) { + diag_handler.err(&format!("failed to copy bitcode to object file: {}", e)); + } } - } - if rm_bc { - debug!("removing_bitcode {:?}", bc_out); - if let Err(e) = fs::remove_file(&bc_out) { - diag_handler.err(&format!("failed to remove bitcode: {}", e)); + if rm_bc { + debug!("removing_bitcode {:?}", bc_out); + if let Err(e) = fs::remove_file(&bc_out) { + diag_handler.err(&format!("failed to remove bitcode: {}", e)); + } } - } - drop(handlers); + drop(handlers); + } Ok(module.into_compiled_module(config.emit_obj, config.emit_bc, config.emit_bc_compressed, @@ -828,8 +825,8 @@ unsafe fn codegen(cgcx: &CodegenContext, /// Basically all of this is us attempting to follow in the footsteps of clang /// on iOS. See #35968 for lots more info. unsafe fn embed_bitcode(cgcx: &CodegenContext, - llcx: ContextRef, - llmod: ModuleRef, + llcx: &llvm::Context, + llmod: &llvm::Module, bitcode: Option<&[u8]>) { let llconst = C_bytes_in_context(llcx, bitcode.unwrap_or(&[])); let llglobal = llvm::LLVMAddGlobal( @@ -2050,7 +2047,7 @@ pub fn run_assembler(cgcx: &CodegenContext, handler: &Handler, assembly: &Path, } } -pub unsafe fn with_llvm_pmb(llmod: ModuleRef, +pub unsafe fn with_llvm_pmb(llmod: &llvm::Module, config: &ModuleConfig, opt_level: llvm::CodeGenOptLevel, prepare_for_thin_lto: bool, @@ -2353,7 +2350,7 @@ fn msvc_imps_needed(tcx: TyCtxt) -> bool { // when using MSVC linker. We do this only for data, as linker can fix up // code references on its own. // See #26591, #27438 -fn create_msvc_imps(cgcx: &CodegenContext, llcx: ContextRef, llmod: ModuleRef) { +fn create_msvc_imps(cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::Module) { if !cgcx.msvc_imps_needed { return } diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 223c04f420f..c4fb251c5f4 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -30,8 +30,8 @@ use super::ModuleKind; use abi; use back::link; -use back::write::{self, OngoingCodegen, create_target_machine}; -use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param}; +use back::write::{self, OngoingCodegen}; +use llvm::{ValueRef, Vector, get_param}; use llvm; use metadata; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; @@ -59,7 +59,7 @@ use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode}; use rustc_mir::monomorphize::item::DefPathBasedNames; use common::{self, C_struct_in_context, C_array, val_ty}; use consts; -use context::{self, CodegenCx}; +use context::CodegenCx; use debuginfo; use declare; use meth; @@ -77,7 +77,6 @@ use rustc_data_structures::sync::Lrc; use std::any::Any; use std::ffi::CString; -use std::str; use std::sync::Arc; use std::time::{Instant, Duration}; use std::i32; @@ -609,16 +608,14 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) { } fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, - llmod_id: &str, + llvm_module: &ModuleLlvm, link_meta: &LinkMeta) - -> (ContextRef, ModuleRef, EncodedMetadata) { + -> EncodedMetadata { use std::io::Write; use flate2::Compression; use flate2::write::DeflateEncoder; - let (metadata_llcx, metadata_llmod) = unsafe { - context::create_context_and_module(tcx.sess, llmod_id) - }; + let (metadata_llcx, metadata_llmod) = (&*llvm_module.llcx, llvm_module.llmod()); #[derive(PartialEq, Eq, PartialOrd, Ord)] enum MetadataKind { @@ -641,14 +638,12 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, }).max().unwrap_or(MetadataKind::None); if kind == MetadataKind::None { - return (metadata_llcx, - metadata_llmod, - EncodedMetadata::new()); + return EncodedMetadata::new(); } let metadata = tcx.encode_metadata(link_meta); if kind == MetadataKind::Uncompressed { - return (metadata_llcx, metadata_llmod, metadata); + return metadata; } assert!(kind == MetadataKind::Compressed); @@ -676,7 +671,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, let directive = CString::new(directive).unwrap(); llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr()) } - return (metadata_llcx, metadata_llmod, metadata); + return metadata; } pub struct ValueIter { @@ -698,7 +693,7 @@ impl Iterator for ValueIter { } } -pub fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter { +pub fn iter_globals(llmod: &llvm::Module) -> ValueIter { unsafe { ValueIter { cur: llvm::LLVMGetFirstGlobal(llmod), @@ -731,19 +726,15 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Codegen the metadata. let llmod_id = "metadata"; - let (metadata_llcx, metadata_llmod, metadata) = - time(tcx.sess, "write metadata", || { - write_metadata(tcx, llmod_id, &link_meta) - }); + let metadata_llvm_module = ModuleLlvm::new(tcx.sess, llmod_id); + let metadata = time(tcx.sess, "write metadata", || { + write_metadata(tcx, &metadata_llvm_module, &link_meta) + }); let metadata_module = ModuleCodegen { name: link::METADATA_MODULE_NAME.to_string(), llmod_id: llmod_id.to_string(), - source: ModuleSource::Codegened(ModuleLlvm { - llcx: metadata_llcx, - llmod: metadata_llmod, - tm: create_target_machine(tcx.sess, false), - }), + source: ModuleSource::Codegened(metadata_llvm_module), kind: ModuleKind::Metadata, }; @@ -803,13 +794,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let allocator_module = if let Some(kind) = *tcx.sess.allocator_kind.get() { unsafe { let llmod_id = "allocator"; - let (llcx, llmod) = - context::create_context_and_module(tcx.sess, llmod_id); - let modules = ModuleLlvm { - llmod, - llcx, - tm: create_target_machine(tcx.sess, false), - }; + let modules = ModuleLlvm::new(tcx.sess, llmod_id); time(tcx.sess, "write allocator module", || { allocator::codegen(tcx, &modules, kind) }); @@ -1200,8 +1185,9 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .to_fingerprint().to_hex()); // Instantiate monomorphizations without filling out definitions yet... - let cx = CodegenCx::new(tcx, cgu, &llmod_id); - let module = { + let llvm_module = ModuleLlvm::new(tcx.sess, &llmod_id); + let stats = { + let cx = CodegenCx::new(tcx, cgu, &llvm_module); let mono_items = cx.codegen_unit .items_in_deterministic_order(cx.tcx); for &(mono_item, (linkage, visibility)) in &mono_items { @@ -1248,21 +1234,15 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debuginfo::finalize(&cx); } - let llvm_module = ModuleLlvm { - llcx: cx.llcx, - llmod: cx.llmod, - tm: create_target_machine(cx.sess(), false), - }; - - ModuleCodegen { - name: cgu_name, - source: ModuleSource::Codegened(llvm_module), - kind: ModuleKind::Regular, - llmod_id, - } + cx.stats.into_inner() }; - (cx.into_stats(), module) + (stats, ModuleCodegen { + name: cgu_name, + source: ModuleSource::Codegened(llvm_module), + kind: ModuleKind::Regular, + llmod_id, + }) } } diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index 60bba635a78..be948442707 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -13,7 +13,7 @@ //! Code that is useful in various codegen modules. use llvm; -use llvm::{ValueRef, ContextRef, TypeKind}; +use llvm::{ValueRef, TypeKind}; use llvm::{True, False, Bool, OperandBundleDef}; use rustc::hir::def_id::DefId; use rustc::middle::lang_items::LangItem; @@ -225,7 +225,7 @@ pub fn C_struct(cx: &CodegenCx, elts: &[ValueRef], packed: bool) -> ValueRef { C_struct_in_context(cx.llcx, elts, packed) } -pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) -> ValueRef { +pub fn C_struct_in_context(llcx: &llvm::Context, elts: &[ValueRef], packed: bool) -> ValueRef { unsafe { llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), elts.len() as c_uint, @@ -249,7 +249,7 @@ pub fn C_bytes(cx: &CodegenCx, bytes: &[u8]) -> ValueRef { C_bytes_in_context(cx.llcx, bytes) } -pub fn C_bytes_in_context(llcx: ContextRef, bytes: &[u8]) -> ValueRef { +pub fn C_bytes_in_context(llcx: &llvm::Context, bytes: &[u8]) -> ValueRef { unsafe { let ptr = bytes.as_ptr() as *const c_char; return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True); diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 130e14c976d..f91173226c4 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -10,7 +10,7 @@ use common; use llvm; -use llvm::{ContextRef, ModuleRef, ValueRef}; +use llvm::ValueRef; use rustc::dep_graph::DepGraphSafe; use rustc::hir; use rustc::hir::def_id::DefId; @@ -42,16 +42,16 @@ use syntax::symbol::LocalInternedString; use abi::Abi; /// There is one `CodegenCx` per compilation unit. Each one has its own LLVM -/// `ContextRef` so that several compilation units may be optimized in parallel. -/// All other LLVM data structures in the `CodegenCx` are tied to that `ContextRef`. +/// `llvm::Context` so that several compilation units may be optimized in parallel. +/// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`. pub struct CodegenCx<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, pub check_overflow: bool, pub use_dll_storage_attrs: bool, pub tls_model: llvm::ThreadLocalMode, - pub llmod: ModuleRef, - pub llcx: ContextRef, + pub llmod: &'a llvm::Module, + pub llcx: &'a llvm::Context, pub stats: RefCell<Stats>, pub codegen_unit: Arc<CodegenUnit<'tcx>>, @@ -94,7 +94,7 @@ pub struct CodegenCx<'a, 'tcx: 'a> { pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>, pub isize_ty: Type, - pub dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>, + pub dbg_cx: Option<debuginfo::CrateDebugContext<'a, 'tcx>>, eh_personality: Cell<Option<ValueRef>>, eh_unwind_resume: Cell<Option<ValueRef>>, @@ -155,8 +155,7 @@ pub fn is_pie_binary(sess: &Session) -> bool { !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC } -pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) { - let llcx = llvm::LLVMRustContextCreate(sess.fewer_names()); +pub unsafe fn create_module(sess: &Session, llcx: &'ll llvm::Context, mod_name: &str) -> &'ll llvm::Module { let mod_name = CString::new(mod_name).unwrap(); let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); @@ -208,13 +207,13 @@ pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (Cont llvm::LLVMRustSetModulePIELevel(llmod); } - (llcx, llmod) + llmod } impl<'a, 'tcx> CodegenCx<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + crate fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, codegen_unit: Arc<CodegenUnit<'tcx>>, - llmod_id: &str) + llvm_module: &'a ::ModuleLlvm) -> CodegenCx<'a, 'tcx> { // An interesting part of Windows which MSVC forces our hand on (and // apparently MinGW didn't) is the usage of `dllimport` and `dllexport` @@ -265,55 +264,48 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> { let tls_model = get_tls_model(&tcx.sess); - unsafe { - let (llcx, llmod) = create_context_and_module(&tcx.sess, - &llmod_id[..]); - - let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo { - let dctx = debuginfo::CrateDebugContext::new(llmod); - debuginfo::metadata::compile_unit_metadata(tcx, - &codegen_unit.name().as_str(), - &dctx); - Some(dctx) - } else { - None - }; - - let isize_ty = Type::ix_llcx(llcx, tcx.data_layout.pointer_size.bits()); - - CodegenCx { - tcx, - check_overflow, - use_dll_storage_attrs, - tls_model, - llmod, - llcx, - stats: RefCell::new(Stats::default()), - codegen_unit, - instances: RefCell::new(FxHashMap()), - vtables: RefCell::new(FxHashMap()), - const_cstr_cache: RefCell::new(FxHashMap()), - const_unsized: RefCell::new(FxHashMap()), - const_globals: RefCell::new(FxHashMap()), - statics: RefCell::new(FxHashMap()), - statics_to_rauw: RefCell::new(Vec::new()), - used_statics: RefCell::new(Vec::new()), - lltypes: RefCell::new(FxHashMap()), - scalar_lltypes: RefCell::new(FxHashMap()), - pointee_infos: RefCell::new(FxHashMap()), - isize_ty, - dbg_cx, - eh_personality: Cell::new(None), - eh_unwind_resume: Cell::new(None), - rust_try_fn: Cell::new(None), - intrinsics: RefCell::new(FxHashMap()), - local_gen_sym_counter: Cell::new(0), - } - } - } + let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod()); - pub fn into_stats(self) -> Stats { - self.stats.into_inner() + let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo { + let dctx = debuginfo::CrateDebugContext::new(llmod); + debuginfo::metadata::compile_unit_metadata(tcx, + &codegen_unit.name().as_str(), + &dctx); + Some(dctx) + } else { + None + }; + + let isize_ty = Type::ix_llcx(llcx, tcx.data_layout.pointer_size.bits()); + + CodegenCx { + tcx, + check_overflow, + use_dll_storage_attrs, + tls_model, + llmod, + llcx, + stats: RefCell::new(Stats::default()), + codegen_unit, + instances: RefCell::new(FxHashMap()), + vtables: RefCell::new(FxHashMap()), + const_cstr_cache: RefCell::new(FxHashMap()), + const_unsized: RefCell::new(FxHashMap()), + const_globals: RefCell::new(FxHashMap()), + statics: RefCell::new(FxHashMap()), + statics_to_rauw: RefCell::new(Vec::new()), + used_statics: RefCell::new(Vec::new()), + lltypes: RefCell::new(FxHashMap()), + scalar_lltypes: RefCell::new(FxHashMap()), + pointee_infos: RefCell::new(FxHashMap()), + isize_ty, + dbg_cx, + eh_personality: Cell::new(None), + eh_unwind_resume: Cell::new(None), + rust_try_fn: Cell::new(None), + intrinsics: RefCell::new(FxHashMap()), + local_gen_sym_counter: Cell::new(0), + } } } diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 59c14a6910b..e7a6dc45222 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -862,7 +862,7 @@ pub fn compile_unit_metadata(tcx: TyCtxt, return unit_metadata; }; - fn path_to_mdstring(llcx: llvm::ContextRef, path: &Path) -> llvm::ValueRef { + fn path_to_mdstring(llcx: &llvm::Context, path: &Path) -> llvm::ValueRef { let path_str = path2cstr(path); unsafe { llvm::LLVMMDStringInContext(llcx, diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index fcabd273326..d4b51106033 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -21,7 +21,7 @@ use self::metadata::{type_metadata, file_metadata, TypeMap}; use self::source_loc::InternalDebugLocation::{self, UnknownLocation}; use llvm; -use llvm::{ModuleRef, ContextRef, ValueRef}; +use llvm::ValueRef; use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags}; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::{DefId, CrateNum}; @@ -67,9 +67,9 @@ const DW_TAG_auto_variable: c_uint = 0x100; const DW_TAG_arg_variable: c_uint = 0x101; /// A context object for maintaining all state needed by the debuginfo module. -pub struct CrateDebugContext<'tcx> { - llcontext: ContextRef, - llmod: ModuleRef, +pub struct CrateDebugContext<'a, 'tcx> { + llcontext: &'a llvm::Context, + llmod: &'a llvm::Module, builder: DIBuilderRef, created_files: RefCell<FxHashMap<(Symbol, Symbol), DIFile>>, created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Primitive), DIType>>, @@ -82,8 +82,8 @@ pub struct CrateDebugContext<'tcx> { composite_types_completed: RefCell<FxHashSet<DIType>>, } -impl<'tcx> CrateDebugContext<'tcx> { - pub fn new(llmod: ModuleRef) -> CrateDebugContext<'tcx> { +impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> { + pub fn new(llmod: &'a llvm::Module) -> Self { debug!("CrateDebugContext::new"); let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) }; // DIBuilder inherits context from the module, so we'd better use the same one diff --git a/src/librustc_codegen_llvm/debuginfo/utils.rs b/src/librustc_codegen_llvm/debuginfo/utils.rs index 87da3316628..85cddb0a580 100644 --- a/src/librustc_codegen_llvm/debuginfo/utils.rs +++ b/src/librustc_codegen_llvm/debuginfo/utils.rs @@ -50,7 +50,7 @@ pub fn span_start(cx: &CodegenCx, span: Span) -> syntax_pos::Loc { #[inline] pub fn debug_context<'a, 'tcx>(cx: &'a CodegenCx<'a, 'tcx>) - -> &'a CrateDebugContext<'tcx> { + -> &'a CrateDebugContext<'a, 'tcx> { cx.dbg_cx.as_ref().unwrap() } diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 0b5524990e8..724a2e3e65f 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -20,9 +20,11 @@ #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(crate_visibility_modifier)] #![feature(custom_attribute)] #![feature(extern_types)] #![feature(fs_read_write)] +#![feature(in_band_lifetimes)] #![allow(unused_attributes)] #![feature(libc)] #![feature(quote)] @@ -34,6 +36,7 @@ #![feature(link_args)] #![feature(static_nobundle)] +use back::write::create_target_machine; use rustc::dep_graph::WorkProduct; use syntax_pos::symbol::Symbol; @@ -340,22 +343,41 @@ enum ModuleSource { Codegened(ModuleLlvm), } -#[derive(Debug)] struct ModuleLlvm { - llcx: llvm::ContextRef, - llmod: llvm::ModuleRef, - tm: llvm::TargetMachineRef, + llcx: &'static mut llvm::Context, + llmod_raw: *const llvm::Module, + tm: &'static mut llvm::TargetMachine, } unsafe impl Send for ModuleLlvm { } unsafe impl Sync for ModuleLlvm { } +impl ModuleLlvm { + fn new(sess: &Session, mod_name: &str) -> Self { + unsafe { + let llcx = llvm::LLVMRustContextCreate(sess.fewer_names()); + let llmod_raw = context::create_module(sess, llcx, mod_name) as *const _; + + ModuleLlvm { + llmod_raw, + llcx, + tm: create_target_machine(sess, false), + } + } + } + + fn llmod(&self) -> &llvm::Module { + unsafe { + &*self.llmod_raw + } + } +} + impl Drop for ModuleLlvm { fn drop(&mut self) { unsafe { - llvm::LLVMDisposeModule(self.llmod); - llvm::LLVMContextDispose(self.llcx); - llvm::LLVMRustDisposeTargetMachine(self.tm); + llvm::LLVMContextDispose(&mut *(self.llcx as *mut _)); + llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _)); } } } diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 6e61b327f1d..9d94869dab0 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -375,10 +375,8 @@ pub enum ThreadLocalMode { } // Opaque pointer types -extern { pub type Module_opaque; } -pub type ModuleRef = *mut Module_opaque; -extern { pub type Context_opaque; } -pub type ContextRef = *mut Context_opaque; +extern { pub type Module; } +extern { pub type Context; } extern { pub type Type_opaque; } pub type TypeRef = *mut Type_opaque; extern { pub type Value_opaque; } @@ -407,8 +405,8 @@ extern { pub type SectionIterator_opaque; } pub type SectionIteratorRef = *mut SectionIterator_opaque; extern { pub type Pass_opaque; } pub type PassRef = *mut Pass_opaque; -extern { pub type TargetMachine_opaque; } -pub type TargetMachineRef = *mut TargetMachine_opaque; +extern { pub type TargetMachine; } +pub type TargetMachineRef = *const TargetMachine; extern { pub type Archive_opaque; } pub type ArchiveRef = *mut Archive_opaque; extern { pub type ArchiveIterator_opaque; } @@ -498,43 +496,42 @@ extern { pub type ModuleBuffer; } #[allow(improper_ctypes)] // TODO remove this (use for NonNull) extern "C" { // Create and destroy contexts. - pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> ContextRef; - pub fn LLVMContextDispose(C: ContextRef); - pub fn LLVMGetMDKindIDInContext(C: ContextRef, Name: *const c_char, SLen: c_uint) -> c_uint; + pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> &'static mut Context; + pub fn LLVMContextDispose(C: &'static mut Context); + pub fn LLVMGetMDKindIDInContext(C: &Context, Name: *const c_char, SLen: c_uint) -> c_uint; - // Create and destroy modules. - pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char, C: ContextRef) -> ModuleRef; - pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef; - pub fn LLVMCloneModule(M: ModuleRef) -> ModuleRef; - pub fn LLVMDisposeModule(M: ModuleRef); + // Create modules. + pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char, C: &Context) -> &Module; + pub fn LLVMGetModuleContext(M: &Module) -> &Context; + pub fn LLVMCloneModule(M: &Module) -> &Module; /// Data layout. See Module::getDataLayout. - pub fn LLVMGetDataLayout(M: ModuleRef) -> *const c_char; - pub fn LLVMSetDataLayout(M: ModuleRef, Triple: *const c_char); + pub fn LLVMGetDataLayout(M: &Module) -> *const c_char; + pub fn LLVMSetDataLayout(M: &Module, Triple: *const c_char); /// See Module::dump. - pub fn LLVMDumpModule(M: ModuleRef); + pub fn LLVMDumpModule(M: &Module); /// See Module::setModuleInlineAsm. - pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char); - pub fn LLVMRustAppendModuleInlineAsm(M: ModuleRef, Asm: *const c_char); + pub fn LLVMSetModuleInlineAsm(M: &Module, Asm: *const c_char); + pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char); /// See llvm::LLVMTypeKind::getTypeID. pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind; // Operations on integer types - pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint) -> TypeRef; + pub fn LLVMInt1TypeInContext(C: &Context) -> TypeRef; + pub fn LLVMInt8TypeInContext(C: &Context) -> TypeRef; + pub fn LLVMInt16TypeInContext(C: &Context) -> TypeRef; + pub fn LLVMInt32TypeInContext(C: &Context) -> TypeRef; + pub fn LLVMInt64TypeInContext(C: &Context) -> TypeRef; + pub fn LLVMIntTypeInContext(C: &Context, NumBits: c_uint) -> TypeRef; pub fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint; // Operations on real types - pub fn LLVMFloatTypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMDoubleTypeInContext(C: ContextRef) -> TypeRef; + pub fn LLVMFloatTypeInContext(C: &Context) -> TypeRef; + pub fn LLVMDoubleTypeInContext(C: &Context) -> TypeRef; // Operations on function types pub fn LLVMFunctionType(ReturnType: TypeRef, @@ -547,7 +544,7 @@ extern "C" { pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *mut TypeRef); // Operations on struct types - pub fn LLVMStructTypeInContext(C: ContextRef, + pub fn LLVMStructTypeInContext(C: &Context, ElementTypes: *const TypeRef, ElementCount: c_uint, Packed: Bool) @@ -563,9 +560,9 @@ extern "C" { pub fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint; // Operations on other types - pub fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMX86MMXTypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMRustMetadataTypeInContext(C: ContextRef) -> TypeRef; + pub fn LLVMVoidTypeInContext(C: &Context) -> TypeRef; + pub fn LLVMX86MMXTypeInContext(C: &Context) -> TypeRef; + pub fn LLVMRustMetadataTypeInContext(C: &Context) -> TypeRef; // Operations on all values pub fn LLVMTypeOf(Val: ValueRef) -> TypeRef; @@ -589,9 +586,9 @@ extern "C" { pub fn LLVMGetUndef(Ty: TypeRef) -> ValueRef; // Operations on metadata - pub fn LLVMMDStringInContext(C: ContextRef, Str: *const c_char, SLen: c_uint) -> ValueRef; - pub fn LLVMMDNodeInContext(C: ContextRef, Vals: *const ValueRef, Count: c_uint) -> ValueRef; - pub fn LLVMAddNamedMetadataOperand(M: ModuleRef, Name: *const c_char, Val: ValueRef); + pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> ValueRef; + pub fn LLVMMDNodeInContext(C: &Context, Vals: *const ValueRef, Count: c_uint) -> ValueRef; + pub fn LLVMAddNamedMetadataOperand(M: &Module, Name: *const c_char, Val: ValueRef); // Operations on scalar constants pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) -> ValueRef; @@ -604,12 +601,12 @@ extern "C" { // Operations on composite constants - pub fn LLVMConstStringInContext(C: ContextRef, + pub fn LLVMConstStringInContext(C: &Context, Str: *const c_char, Length: c_uint, DontNullTerminate: Bool) -> ValueRef; - pub fn LLVMConstStructInContext(C: ContextRef, + pub fn LLVMConstStructInContext(C: &Context, ConstantVals: *const ValueRef, Count: c_uint, Packed: Bool) @@ -679,7 +676,6 @@ extern "C" { // Operations on global variables, functions, and aliases (globals) - pub fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef; pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool; pub fn LLVMRustGetLinkage(Global: ValueRef) -> Linkage; pub fn LLVMRustSetLinkage(Global: ValueRef, RustLinkage: Linkage); @@ -694,10 +690,10 @@ extern "C" { // Operations on global variables pub fn LLVMIsAGlobalVariable(GlobalVar: ValueRef) -> ValueRef; - pub fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *const c_char) -> ValueRef; - pub fn LLVMGetNamedGlobal(M: ModuleRef, Name: *const c_char) -> ValueRef; - pub fn LLVMRustGetOrInsertGlobal(M: ModuleRef, Name: *const c_char, T: TypeRef) -> ValueRef; - pub fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef; + pub fn LLVMAddGlobal(M: &Module, Ty: TypeRef, Name: *const c_char) -> ValueRef; + pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> ValueRef; + pub fn LLVMRustGetOrInsertGlobal(M: &Module, Name: *const c_char, T: TypeRef) -> ValueRef; + pub fn LLVMGetFirstGlobal(M: &Module) -> ValueRef; pub fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef; pub fn LLVMDeleteGlobal(GlobalVar: ValueRef); pub fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef; @@ -706,15 +702,15 @@ extern "C" { pub fn LLVMSetThreadLocalMode(GlobalVar: ValueRef, Mode: ThreadLocalMode); pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool; pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool); - pub fn LLVMRustGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef; + pub fn LLVMRustGetNamedValue(M: &Module, Name: *const c_char) -> ValueRef; pub fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool); // Operations on functions - pub fn LLVMAddFunction(M: ModuleRef, Name: *const c_char, FunctionTy: TypeRef) -> ValueRef; - pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *const c_char) -> ValueRef; - pub fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef; + pub fn LLVMAddFunction(M: &Module, Name: *const c_char, FunctionTy: TypeRef) -> ValueRef; + pub fn LLVMGetNamedFunction(M: &Module, Name: *const c_char) -> ValueRef; + pub fn LLVMGetFirstFunction(M: &Module) -> ValueRef; pub fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef; - pub fn LLVMRustGetOrInsertFunction(M: ModuleRef, + pub fn LLVMRustGetOrInsertFunction(M: &Module, Name: *const c_char, FunctionTy: TypeRef) -> ValueRef; @@ -736,7 +732,7 @@ extern "C" { // Operations on basic blocks pub fn LLVMBasicBlockAsValue(BB: BasicBlockRef) -> ValueRef; pub fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef; - pub fn LLVMAppendBasicBlockInContext(C: ContextRef, + pub fn LLVMAppendBasicBlockInContext(C: &Context, Fn: ValueRef, Name: *const c_char) -> BasicBlockRef; @@ -767,7 +763,7 @@ extern "C" { Count: c_uint); // Instruction builders - pub fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef; + pub fn LLVMCreateBuilderInContext(C: &Context) -> BuilderRef; pub fn LLVMPositionBuilder(Builder: BuilderRef, Block: BasicBlockRef, Instr: ValueRef); pub fn LLVMPositionBuilderBefore(Builder: BuilderRef, Instr: ValueRef); pub fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef); @@ -1277,7 +1273,7 @@ extern "C" { pub fn LLVMIsAStoreInst(Inst: ValueRef) -> ValueRef; /// Writes a module to the specified path. Returns 0 on success. - pub fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *const c_char) -> c_int; + pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int; /// Creates target data from a target layout string. pub fn LLVMCreateTargetData(StringRep: *const c_char) -> TargetDataRef; @@ -1289,13 +1285,13 @@ extern "C" { pub fn LLVMCreatePassManager() -> PassManagerRef; /// Creates a function-by-function pass manager - pub fn LLVMCreateFunctionPassManagerForModule(M: ModuleRef) -> PassManagerRef; + pub fn LLVMCreateFunctionPassManagerForModule(M: &Module) -> PassManagerRef; /// Disposes a pass manager. pub fn LLVMDisposePassManager(PM: PassManagerRef); /// Runs a pass manager on a module. - pub fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool; + pub fn LLVMRunPassManager(PM: PassManagerRef, M: &Module) -> Bool; pub fn LLVMInitializePasses(); @@ -1351,7 +1347,7 @@ extern "C" { /// Print the pass timings since static dtors aren't picking them up. pub fn LLVMRustPrintPassTimings(); - pub fn LLVMStructCreateNamed(C: ContextRef, Name: *const c_char) -> TypeRef; + pub fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> TypeRef; pub fn LLVMStructSetBody(StructTy: TypeRef, ElementTypes: *const TypeRef, @@ -1371,11 +1367,11 @@ extern "C" { pub fn LLVMRustVersionMajor() -> u32; pub fn LLVMRustVersionMinor() -> u32; - pub fn LLVMRustAddModuleFlag(M: ModuleRef, name: *const c_char, value: u32); + pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32); - pub fn LLVMRustMetadataAsValue(C: ContextRef, MD: MetadataRef) -> ValueRef; + pub fn LLVMRustMetadataAsValue(C: &Context, MD: MetadataRef) -> ValueRef; - pub fn LLVMRustDIBuilderCreate(M: ModuleRef) -> DIBuilderRef; + pub fn LLVMRustDIBuilderCreate(M: &Module) -> DIBuilderRef; pub fn LLVMRustDIBuilderDispose(Builder: DIBuilderRef); @@ -1582,7 +1578,7 @@ extern "C" { TypeArray: DIArray); - pub fn LLVMRustDIBuilderCreateDebugLocation(Context: ContextRef, + pub fn LLVMRustDIBuilderCreateDebugLocation(Context: &Context, Line: c_uint, Column: c_uint, Scope: DIScope, @@ -1618,11 +1614,11 @@ extern "C" { DataSections: bool, TrapUnreachable: bool, Singlethread: bool) - -> TargetMachineRef; - pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef); - pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef, PM: PassManagerRef, M: ModuleRef); + -> Option<&'static mut TargetMachine>; + pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine); + pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef, PM: PassManagerRef, M: &Module); pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef, - M: ModuleRef, + M: &Module, DisableSimplifyLibCalls: bool); pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef, OptLevel: CodeGenOptLevel, @@ -1633,17 +1629,17 @@ extern "C" { PGOGenPath: *const c_char, PGOUsePath: *const c_char); pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, - M: ModuleRef, + M: &Module, DisableSimplifyLibCalls: bool); - pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef); + pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: &Module); pub fn LLVMRustWriteOutputFile(T: TargetMachineRef, PM: PassManagerRef, - M: ModuleRef, + M: &Module, Output: *const c_char, FileType: FileType) -> LLVMRustResult; pub fn LLVMRustPrintModule(PM: PassManagerRef, - M: ModuleRef, + M: &Module, Output: *const c_char, Demangle: extern fn(*const c_char, size_t, @@ -1651,10 +1647,10 @@ extern "C" { size_t) -> size_t); pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char); pub fn LLVMRustPrintPasses(); - pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char); + pub fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char); pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef, AddLifetimes: bool); - pub fn LLVMRustRunRestrictionPass(M: ModuleRef, syms: *const *const c_char, len: size_t); - pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef); + pub fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t); + pub fn LLVMRustMarkAllFunctionsNounwind(M: &Module); pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef; pub fn LLVMRustArchiveIteratorNew(AR: ArchiveRef) -> ArchiveIteratorRef; @@ -1669,7 +1665,7 @@ extern "C" { pub fn LLVMRustWriteTwineToString(T: TwineRef, s: RustStringRef); - pub fn LLVMContextSetDiagnosticHandler(C: ContextRef, + pub fn LLVMContextSetDiagnosticHandler(C: &Context, Handler: DiagnosticHandler, DiagnosticContext: *mut c_void); @@ -1688,7 +1684,7 @@ extern "C" { pub fn LLVMRustWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef); pub fn LLVMRustGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind; - pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: ContextRef, + pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: &Context, H: InlineAsmDiagHandler, CX: *mut c_void); @@ -1706,7 +1702,7 @@ extern "C" { -> RustArchiveMemberRef; pub fn LLVMRustArchiveMemberFree(Member: RustArchiveMemberRef); - pub fn LLVMRustSetDataLayoutFromTargetMachine(M: ModuleRef, TM: TargetMachineRef); + pub fn LLVMRustSetDataLayoutFromTargetMachine(M: &Module, TM: TargetMachineRef); pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char, Inputs: *const ValueRef, @@ -1716,21 +1712,21 @@ extern "C" { pub fn LLVMRustPositionBuilderAtStart(B: BuilderRef, BB: BasicBlockRef); - pub fn LLVMRustSetComdat(M: ModuleRef, V: ValueRef, Name: *const c_char); + pub fn LLVMRustSetComdat(M: &Module, V: ValueRef, Name: *const c_char); pub fn LLVMRustUnsetComdat(V: ValueRef); - pub fn LLVMRustSetModulePIELevel(M: ModuleRef); - pub fn LLVMRustModuleBufferCreate(M: ModuleRef) -> *mut ModuleBuffer; + pub fn LLVMRustSetModulePIELevel(M: &Module); + pub fn LLVMRustModuleBufferCreate(M: &Module) -> *mut ModuleBuffer; pub fn LLVMRustModuleBufferPtr(p: *const ModuleBuffer) -> *const u8; pub fn LLVMRustModuleBufferLen(p: *const ModuleBuffer) -> usize; pub fn LLVMRustModuleBufferFree(p: *mut ModuleBuffer); - pub fn LLVMRustModuleCost(M: ModuleRef) -> u64; + pub fn LLVMRustModuleCost(M: &Module) -> u64; pub fn LLVMRustThinLTOAvailable() -> bool; pub fn LLVMRustPGOAvailable() -> bool; pub fn LLVMRustWriteThinBitcodeToFile(PMR: PassManagerRef, - M: ModuleRef, + M: &Module, BC: *const c_char) -> bool; - pub fn LLVMRustThinLTOBufferCreate(M: ModuleRef) -> *mut ThinLTOBuffer; + pub fn LLVMRustThinLTOBufferCreate(M: &Module) -> *mut ThinLTOBuffer; pub fn LLVMRustThinLTOBufferFree(M: *mut ThinLTOBuffer); pub fn LLVMRustThinLTOBufferPtr(M: *const ThinLTOBuffer) -> *const c_char; pub fn LLVMRustThinLTOBufferLen(M: *const ThinLTOBuffer) -> size_t; @@ -1742,34 +1738,34 @@ extern "C" { ) -> *mut ThinLTOData; pub fn LLVMRustPrepareThinLTORename( Data: *const ThinLTOData, - Module: ModuleRef, + Module: &Module, ) -> bool; pub fn LLVMRustPrepareThinLTOResolveWeak( Data: *const ThinLTOData, - Module: ModuleRef, + Module: &Module, ) -> bool; pub fn LLVMRustPrepareThinLTOInternalize( Data: *const ThinLTOData, - Module: ModuleRef, + Module: &Module, ) -> bool; pub fn LLVMRustPrepareThinLTOImport( Data: *const ThinLTOData, - Module: ModuleRef, + Module: &Module, ) -> bool; pub fn LLVMRustFreeThinLTOData(Data: *mut ThinLTOData); pub fn LLVMRustParseBitcodeForThinLTO( - Context: ContextRef, + Context: &Context, Data: *const u8, len: usize, Identifier: *const c_char, - ) -> ModuleRef; - pub fn LLVMGetModuleIdentifier(M: ModuleRef, size: *mut usize) -> *const c_char; - pub fn LLVMRustThinLTOGetDICompileUnit(M: ModuleRef, + ) -> Option<&Module>; + pub fn LLVMGetModuleIdentifier(M: &Module, size: *mut usize) -> *const c_char; + pub fn LLVMRustThinLTOGetDICompileUnit(M: &Module, CU1: *mut *mut c_void, CU2: *mut *mut c_void); - pub fn LLVMRustThinLTOPatchDICompileUnit(M: ModuleRef, CU: *mut c_void); + pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void); - pub fn LLVMRustLinkerNew(M: ModuleRef) -> LinkerRef; + pub fn LLVMRustLinkerNew(M: &Module) -> LinkerRef; pub fn LLVMRustLinkerAdd(linker: LinkerRef, bytecode: *const c_char, bytecode_len: usize) -> bool; diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs index b6ff9b17bd9..75f13e88858 100644 --- a/src/librustc_codegen_llvm/llvm/mod.rs +++ b/src/librustc_codegen_llvm/llvm/mod.rs @@ -127,7 +127,7 @@ pub fn SetFunctionCallConv(fn_: ValueRef, cc: CallConv) { // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the // function. // For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52 -pub fn SetUniqueComdat(llmod: ModuleRef, val: ValueRef) { +pub fn SetUniqueComdat(llmod: &Module, val: ValueRef) { unsafe { LLVMRustSetComdat(llmod, val, LLVMGetValueName(val)); } diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs index 37157635b2d..cb77ce00397 100644 --- a/src/librustc_codegen_llvm/type_.rs +++ b/src/librustc_codegen_llvm/type_.rs @@ -11,7 +11,7 @@ #![allow(non_upper_case_globals)] use llvm; -use llvm::{ContextRef, TypeRef, Bool, False, True, TypeKind}; +use llvm::{TypeRef, Bool, False, True, TypeKind}; use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128}; use context::CodegenCx; @@ -77,7 +77,7 @@ impl Type { ty!(llvm::LLVMInt8TypeInContext(cx.llcx)) } - pub fn i8_llcx(llcx: ContextRef) -> Type { + pub fn i8_llcx(llcx: &llvm::Context) -> Type { ty!(llvm::LLVMInt8TypeInContext(llcx)) } @@ -103,7 +103,7 @@ impl Type { } // Creates an integer type with the given number of bits, e.g. i24 - pub fn ix_llcx(llcx: ContextRef, num_bits: u64) -> Type { + pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> Type { ty!(llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint)) } @@ -127,7 +127,7 @@ impl Type { Type::i8(cx).ptr_to() } - pub fn i8p_llcx(llcx: ContextRef) -> Type { + pub fn i8p_llcx(llcx: &llvm::Context) -> Type { Type::i8_llcx(llcx).ptr_to() } |
