summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_codegen_llvm/src/back/lto.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs121
1 files changed, 41 insertions, 80 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 3731c6bcf..a49cc7f8d 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -1,15 +1,14 @@
-use crate::back::write::{
- self, save_temp_bitcode, to_llvm_opt_settings, with_llvm_pmb, DiagnosticHandlers,
-};
-use crate::llvm::archive_ro::ArchiveRO;
-use crate::llvm::{self, build_string, False, True};
-use crate::{llvm_util, LlvmCodegenBackend, ModuleLlvm};
+use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers};
+use crate::llvm::{self, build_string};
+use crate::{LlvmCodegenBackend, ModuleLlvm};
+use object::read::archive::ArchiveFile;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
use rustc_codegen_ssa::back::symbol_export;
use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, TargetMachineFactoryConfig};
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{looks_like_rust_object_file, ModuleCodegen, ModuleKind};
use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::memmap::Mmap;
use rustc_errors::{FatalError, Handler};
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::bug;
@@ -17,7 +16,6 @@ use rustc_middle::dep_graph::WorkProduct;
use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
use rustc_session::cgu_reuse_tracker::CguReuse;
use rustc_session::config::{self, CrateType, Lto};
-use tracing::{debug, info};
use std::ffi::{CStr, CString};
use std::fs::File;
@@ -34,8 +32,8 @@ pub const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin";
pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
match crate_type {
- CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => true,
- CrateType::Dylib | CrateType::Rlib | CrateType::ProcMacro => false,
+ CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true,
+ CrateType::Rlib | CrateType::ProcMacro => false,
}
}
@@ -75,17 +73,6 @@ fn prepare_lto(
// with either fat or thin LTO
let mut upstream_modules = Vec::new();
if cgcx.lto != Lto::ThinLocal {
- if cgcx.opts.cg.prefer_dynamic {
- diag_handler
- .struct_err("cannot prefer dynamic linking when performing LTO")
- .note(
- "only 'staticlib', 'bin', and 'cdylib' outputs are \
- supported with LTO",
- )
- .emit();
- return Err(FatalError);
- }
-
// Make sure we actually can run LTO
for crate_type in cgcx.crate_types.iter() {
if !crate_type_allows_lto(*crate_type) {
@@ -94,9 +81,25 @@ fn prepare_lto(
static library outputs",
);
return Err(e);
+ } else if *crate_type == CrateType::Dylib {
+ if !cgcx.opts.unstable_opts.dylib_lto {
+ return Err(diag_handler
+ .fatal("lto cannot be used for `dylib` crate type without `-Zdylib-lto`"));
+ }
}
}
+ if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto {
+ diag_handler
+ .struct_err("cannot prefer dynamic linking when performing LTO")
+ .note(
+ "only 'staticlib', 'bin', and 'cdylib' outputs are \
+ supported with LTO",
+ )
+ .emit();
+ return Err(FatalError);
+ }
+
for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() {
let exported_symbols =
cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
@@ -107,14 +110,24 @@ fn prepare_lto(
.extend(exported_symbols[&cnum].iter().filter_map(symbol_filter));
}
- let archive = ArchiveRO::open(path).expect("wanted an rlib");
+ let archive_data = unsafe {
+ Mmap::map(std::fs::File::open(&path).expect("couldn't open rlib"))
+ .expect("couldn't map rlib")
+ };
+ let archive = ArchiveFile::parse(&*archive_data).expect("wanted an rlib");
let obj_files = archive
- .iter()
- .filter_map(|child| child.ok().and_then(|c| c.name().map(|name| (name, c))))
+ .members()
+ .filter_map(|child| {
+ child.ok().and_then(|c| {
+ std::str::from_utf8(c.name()).ok().map(|name| (name.trim(), c))
+ })
+ })
.filter(|&(name, _)| looks_like_rust_object_file(name));
for (name, child) in obj_files {
info!("adding bitcode from {}", name);
- match get_bitcode_slice_from_object_data(child.data()) {
+ match get_bitcode_slice_from_object_data(
+ child.data(&*archive_data).expect("corrupt rlib"),
+ ) {
Ok(data) => {
let module = SerializedModule::FromRlib(data.to_vec());
upstream_modules.push((module, CString::new(name).unwrap()));
@@ -565,7 +578,7 @@ pub(crate) fn run_pass_manager(
module: &mut ModuleCodegen<ModuleLlvm>,
thin: bool,
) -> Result<(), FatalError> {
- let _timer = cgcx.prof.extra_verbose_generic_activity("LLVM_lto_optimize", &*module.name);
+ let _timer = cgcx.prof.verbose_generic_activity_with_arg("LLVM_lto_optimize", &*module.name);
let config = cgcx.config(module.kind);
// Now we have one massive module inside of llmod. Time to run the
@@ -587,61 +600,9 @@ pub(crate) fn run_pass_manager(
1,
);
}
- if llvm_util::should_use_new_llvm_pass_manager(
- &config.new_llvm_pass_manager,
- &cgcx.target_arch,
- ) {
- let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO };
- let opt_level = config.opt_level.unwrap_or(config::OptLevel::No);
- write::optimize_with_new_llvm_pass_manager(
- cgcx,
- diag_handler,
- module,
- config,
- opt_level,
- opt_stage,
- )?;
- debug!("lto done");
- return Ok(());
- }
-
- let pm = llvm::LLVMCreatePassManager();
- llvm::LLVMAddAnalysisPasses(module.module_llvm.tm, pm);
-
- if config.verify_llvm_ir {
- let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast());
- llvm::LLVMRustAddPass(pm, pass.unwrap());
- }
-
- let opt_level = config
- .opt_level
- .map(|x| to_llvm_opt_settings(x).0)
- .unwrap_or(llvm::CodeGenOptLevel::None);
- with_llvm_pmb(module.module_llvm.llmod(), config, opt_level, false, &mut |b| {
- if thin {
- llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm);
- } else {
- llvm::LLVMRustPassManagerBuilderPopulateLTOPassManager(
- b, pm, /* Internalize = */ False, /* RunInliner = */ True,
- );
- }
- });
-
- // We always generate bitcode through ThinLTOBuffers,
- // which do not support anonymous globals
- if config.bitcode_needed() {
- let pass = llvm::LLVMRustFindAndCreatePass("name-anon-globals\0".as_ptr().cast());
- llvm::LLVMRustAddPass(pm, pass.unwrap());
- }
-
- if config.verify_llvm_ir {
- let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast());
- llvm::LLVMRustAddPass(pm, pass.unwrap());
- }
-
- llvm::LLVMRunPassManager(pm, module.module_llvm.llmod());
-
- llvm::LLVMDisposePassManager(pm);
+ let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO };
+ let opt_level = config.opt_level.unwrap_or(config::OptLevel::No);
+ write::llvm_optimize(cgcx, diag_handler, module, config, opt_level, opt_stage)?;
}
debug!("lto done");
Ok(())