Allow LTO for dylibs
This commit is contained in:
parent
f7f17bf220
commit
32238ce1e2
3 changed files with 33 additions and 24 deletions
|
@ -32,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 {
|
pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
|
||||||
match crate_type {
|
match crate_type {
|
||||||
CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => true,
|
CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true,
|
||||||
CrateType::Dylib | CrateType::Rlib | CrateType::ProcMacro => false,
|
CrateType::Rlib | CrateType::ProcMacro => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,17 +73,6 @@ fn prepare_lto(
|
||||||
// with either fat or thin LTO
|
// with either fat or thin LTO
|
||||||
let mut upstream_modules = Vec::new();
|
let mut upstream_modules = Vec::new();
|
||||||
if cgcx.lto != Lto::ThinLocal {
|
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
|
// Make sure we actually can run LTO
|
||||||
for crate_type in cgcx.crate_types.iter() {
|
for crate_type in cgcx.crate_types.iter() {
|
||||||
if !crate_type_allows_lto(*crate_type) {
|
if !crate_type_allows_lto(*crate_type) {
|
||||||
|
@ -92,6 +81,8 @@ fn prepare_lto(
|
||||||
static library outputs",
|
static library outputs",
|
||||||
);
|
);
|
||||||
return Err(e);
|
return Err(e);
|
||||||
|
} else if *crate_type == CrateType::Dylib {
|
||||||
|
diag_handler.warn("LTO with dylibs may not be as effective");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use rustc_metadata::find_native_static_library;
|
||||||
use rustc_metadata::fs::{emit_metadata, METADATA_FILENAME};
|
use rustc_metadata::fs::{emit_metadata, METADATA_FILENAME};
|
||||||
use rustc_middle::middle::dependency_format::Linkage;
|
use rustc_middle::middle::dependency_format::Linkage;
|
||||||
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
||||||
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
|
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Lto, Strip};
|
||||||
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
|
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
|
||||||
use rustc_session::cstore::DllImport;
|
use rustc_session::cstore::DllImport;
|
||||||
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
||||||
|
@ -49,6 +49,7 @@ use std::ops::Deref;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{ExitStatus, Output, Stdio};
|
use std::process::{ExitStatus, Output, Stdio};
|
||||||
use std::{env, fmt, fs, io, mem, str};
|
use std::{env, fmt, fs, io, mem, str};
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
pub fn ensure_removed(diag_handler: &Handler, path: &Path) {
|
pub fn ensure_removed(diag_handler: &Handler, path: &Path) {
|
||||||
if let Err(e) = fs::remove_file(path) {
|
if let Err(e) = fs::remove_file(path) {
|
||||||
|
@ -208,11 +209,24 @@ pub fn link_binary<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn each_linked_rlib(
|
pub fn each_linked_rlib(
|
||||||
|
sess: &Session,
|
||||||
info: &CrateInfo,
|
info: &CrateInfo,
|
||||||
f: &mut dyn FnMut(CrateNum, &Path),
|
f: &mut dyn FnMut(CrateNum, &Path),
|
||||||
) -> Result<(), errors::LinkRlibError> {
|
) -> Result<(), errors::LinkRlibError> {
|
||||||
let crates = info.used_crates.iter();
|
let crates = info.used_crates.iter();
|
||||||
let mut fmts = None;
|
let mut fmts = None;
|
||||||
|
|
||||||
|
let lto_active = matches!(sess.lto(), Lto::Fat | Lto::Thin);
|
||||||
|
if lto_active {
|
||||||
|
for combination in info.dependency_formats.iter().combinations(2) {
|
||||||
|
let (ty1, list1) = combination[0];
|
||||||
|
let (ty2, list2) = combination[1];
|
||||||
|
if list1 != list2 {
|
||||||
|
return Err(format!("{ty1:?} and {ty2:?} do not have equivalent dependency formats (`{list1:?}` vs `{list2:?}`)"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (ty, list) in info.dependency_formats.iter() {
|
for (ty, list) in info.dependency_formats.iter() {
|
||||||
match ty {
|
match ty {
|
||||||
CrateType::Executable
|
CrateType::Executable
|
||||||
|
@ -222,6 +236,10 @@ pub fn each_linked_rlib(
|
||||||
fmts = Some(list);
|
fmts = Some(list);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
CrateType::Dylib if lto_active => {
|
||||||
|
fmts = Some(list);
|
||||||
|
break;
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -490,7 +508,7 @@ fn link_staticlib<'a>(
|
||||||
)?;
|
)?;
|
||||||
let mut all_native_libs = vec![];
|
let mut all_native_libs = vec![];
|
||||||
|
|
||||||
let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| {
|
let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| {
|
||||||
let name = codegen_results.crate_info.crate_name[&cnum];
|
let name = codegen_results.crate_info.crate_name[&cnum];
|
||||||
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
|
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
|
||||||
|
|
||||||
|
|
|
@ -999,6 +999,14 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||||
let coordinator_send = tx_to_llvm_workers;
|
let coordinator_send = tx_to_llvm_workers;
|
||||||
let sess = tcx.sess;
|
let sess = tcx.sess;
|
||||||
|
|
||||||
|
let mut each_linked_rlib_for_lto = Vec::new();
|
||||||
|
drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| {
|
||||||
|
if link::ignored_for_lto(sess, crate_info, cnum) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
|
||||||
|
}));
|
||||||
|
|
||||||
// Compute the set of symbols we need to retain when doing LTO (if we need to)
|
// Compute the set of symbols we need to retain when doing LTO (if we need to)
|
||||||
let exported_symbols = {
|
let exported_symbols = {
|
||||||
let mut exported_symbols = FxHashMap::default();
|
let mut exported_symbols = FxHashMap::default();
|
||||||
|
@ -1020,7 +1028,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||||
}
|
}
|
||||||
Lto::Fat | Lto::Thin => {
|
Lto::Fat | Lto::Thin => {
|
||||||
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
|
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
|
||||||
for &cnum in tcx.crates(()).iter() {
|
for &(cnum, ref _path) in &each_linked_rlib_for_lto {
|
||||||
exported_symbols.insert(cnum, copy_symbols(cnum));
|
exported_symbols.insert(cnum, copy_symbols(cnum));
|
||||||
}
|
}
|
||||||
Some(Arc::new(exported_symbols))
|
Some(Arc::new(exported_symbols))
|
||||||
|
@ -1040,14 +1048,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||||
})
|
})
|
||||||
.expect("failed to spawn helper thread");
|
.expect("failed to spawn helper thread");
|
||||||
|
|
||||||
let mut each_linked_rlib_for_lto = Vec::new();
|
|
||||||
drop(link::each_linked_rlib(crate_info, &mut |cnum, path| {
|
|
||||||
if link::ignored_for_lto(sess, crate_info, cnum) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
|
|
||||||
}));
|
|
||||||
|
|
||||||
let ol =
|
let ol =
|
||||||
if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
|
if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
|
||||||
// If we know that we won’t be doing codegen, create target machines without optimisation.
|
// If we know that we won’t be doing codegen, create target machines without optimisation.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue