Revert "Auto merge of #113923 - DianQK:restore-no-builtins-lto, r=pnkfelix"
This reverts commit8c2b577217, reversing changes made to9cf18e98f8.
This commit is contained in:
@@ -270,14 +270,8 @@ pub fn each_linked_rlib(
|
||||
|
||||
for &cnum in crates {
|
||||
match fmts.get(cnum.as_usize() - 1) {
|
||||
Some(&Linkage::NotLinked | &Linkage::Dynamic) => continue,
|
||||
Some(&Linkage::IncludedFromDylib) => {
|
||||
// We always link crate `compiler_builtins` statically. When enabling LTO, we include it as well.
|
||||
if info.compiler_builtins != Some(cnum) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Some(&Linkage::Static) => {}
|
||||
Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
|
||||
Some(_) => {}
|
||||
None => return Err(errors::LinkRlibError::MissingFormat),
|
||||
}
|
||||
let crate_name = info.crate_name[&cnum];
|
||||
@@ -526,7 +520,8 @@ fn link_staticlib<'a>(
|
||||
&codegen_results.crate_info,
|
||||
Some(CrateType::Staticlib),
|
||||
&mut |cnum, path| {
|
||||
let lto = are_upstream_rust_objects_already_included(sess);
|
||||
let lto = are_upstream_rust_objects_already_included(sess)
|
||||
&& !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
|
||||
|
||||
let native_libs = codegen_results.crate_info.native_libraries[&cnum].iter();
|
||||
let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, lib));
|
||||
@@ -1277,6 +1272,24 @@ fn link_sanitizer_runtime(
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a boolean indicating whether the specified crate should be ignored
|
||||
/// during LTO.
|
||||
///
|
||||
/// Crates ignored during LTO are not lumped together in the "massive object
|
||||
/// file" that we create and are linked in their normal rlib states. See
|
||||
/// comments below for what crates do not participate in LTO.
|
||||
///
|
||||
/// It's unusual for a crate to not participate in LTO. Typically only
|
||||
/// compiler-specific and unstable crates have a reason to not participate in
|
||||
/// LTO.
|
||||
pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool {
|
||||
// If our target enables builtin function lowering in LLVM then the
|
||||
// crates providing these functions don't participate in LTO (e.g.
|
||||
// no_builtins or compiler builtins crates).
|
||||
!sess.target.no_builtins
|
||||
&& (info.compiler_builtins == Some(cnum) || info.is_no_builtins.contains(&cnum))
|
||||
}
|
||||
|
||||
/// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
|
||||
pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
|
||||
fn infer_from(
|
||||
@@ -2742,6 +2755,10 @@ fn rehome_sysroot_lib_dir<'a>(sess: &'a Session, lib_dir: &Path) -> PathBuf {
|
||||
// symbols). We must continue to include the rest of the rlib, however, as
|
||||
// it may contain static native libraries which must be linked in.
|
||||
//
|
||||
// (*) Crates marked with `#![no_builtins]` don't participate in LTO and
|
||||
// their bytecode wasn't included. The object files in those libraries must
|
||||
// still be passed to the linker.
|
||||
//
|
||||
// Note, however, that if we're not doing LTO we can just pass the rlib
|
||||
// blindly to the linker (fast) because it's fine if it's not actually
|
||||
// included as we're at the end of the dependency chain.
|
||||
@@ -2767,7 +2784,9 @@ fn add_static_crate<'a>(
|
||||
cmd.link_rlib(&rlib_path);
|
||||
};
|
||||
|
||||
if !are_upstream_rust_objects_already_included(sess) {
|
||||
if !are_upstream_rust_objects_already_included(sess)
|
||||
|| ignored_for_lto(sess, &codegen_results.crate_info, cnum)
|
||||
{
|
||||
link_upstream(cratepath);
|
||||
return;
|
||||
}
|
||||
@@ -2781,6 +2800,8 @@ fn add_static_crate<'a>(
|
||||
let canonical_name = name.replace('-', "_");
|
||||
let upstream_rust_objects_already_included =
|
||||
are_upstream_rust_objects_already_included(sess);
|
||||
let is_builtins =
|
||||
sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum);
|
||||
|
||||
let mut archive = archive_builder_builder.new_archive_builder(sess);
|
||||
if let Err(error) = archive.add_archive(
|
||||
@@ -2797,8 +2818,9 @@ fn add_static_crate<'a>(
|
||||
|
||||
// If we're performing LTO and this is a rust-generated object
|
||||
// file, then we don't need the object file as it's part of the
|
||||
// LTO module.
|
||||
if upstream_rust_objects_already_included && is_rust_object {
|
||||
// LTO module. Note that `#![no_builtins]` is excluded from LTO,
|
||||
// though, so we let that object file slide.
|
||||
if upstream_rust_objects_already_included && is_rust_object && is_builtins {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,8 +54,8 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
|
||||
// export level, however, as they're just implementation details.
|
||||
// Down below we'll hardwire all of the symbols to the `Rust` export
|
||||
// level instead.
|
||||
let is_compiler_builtins = tcx.is_compiler_builtins(LOCAL_CRATE);
|
||||
let special_runtime_crate = tcx.is_panic_runtime(LOCAL_CRATE) || is_compiler_builtins;
|
||||
let special_runtime_crate =
|
||||
tcx.is_panic_runtime(LOCAL_CRATE) || tcx.is_compiler_builtins(LOCAL_CRATE);
|
||||
|
||||
let mut reachable_non_generics: DefIdMap<_> = tcx
|
||||
.reachable_set(())
|
||||
@@ -107,11 +107,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
|
||||
.map(|def_id| {
|
||||
// We won't link right if this symbol is stripped during LTO.
|
||||
let name = tcx.symbol_name(Instance::mono(tcx, def_id.to_def_id())).name;
|
||||
// We have to preserve the symbols of the built-in functions during LTO.
|
||||
let is_builtin_fn = is_compiler_builtins
|
||||
&& symbol_export_level(tcx, def_id.to_def_id())
|
||||
.is_below_threshold(SymbolExportLevel::C);
|
||||
let used = is_builtin_fn || name == "rust_eh_personality";
|
||||
let used = name == "rust_eh_personality";
|
||||
|
||||
let export_level = if special_runtime_crate {
|
||||
SymbolExportLevel::Rust
|
||||
|
||||
@@ -148,12 +148,23 @@ impl ModuleConfig {
|
||||
|
||||
let emit_obj = if !should_emit_obj {
|
||||
EmitObj::None
|
||||
} else if sess.target.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled() {
|
||||
} else if sess.target.obj_is_bitcode
|
||||
|| (sess.opts.cg.linker_plugin_lto.enabled() && !no_builtins)
|
||||
{
|
||||
// This case is selected if the target uses objects as bitcode, or
|
||||
// if linker plugin LTO is enabled. In the linker plugin LTO case
|
||||
// the assumption is that the final link-step will read the bitcode
|
||||
// and convert it to object code. This may be done by either the
|
||||
// native linker or rustc itself.
|
||||
//
|
||||
// Note, however, that the linker-plugin-lto requested here is
|
||||
// explicitly ignored for `#![no_builtins]` crates. These crates are
|
||||
// specifically ignored by rustc's LTO passes and wouldn't work if
|
||||
// loaded into the linker. These crates define symbols that LLVM
|
||||
// lowers intrinsics to, and these symbol dependencies aren't known
|
||||
// until after codegen. As a result any crate marked
|
||||
// `#![no_builtins]` is assumed to not participate in LTO and
|
||||
// instead goes on to generate object code.
|
||||
EmitObj::Bitcode
|
||||
} else if need_bitcode_in_object(tcx) {
|
||||
EmitObj::ObjectCode(BitcodeSection::Full)
|
||||
@@ -1023,6 +1034,9 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||
|
||||
let mut each_linked_rlib_for_lto = Vec::new();
|
||||
drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| {
|
||||
if link::ignored_for_lto(sess, crate_info, cnum) {
|
||||
return;
|
||||
}
|
||||
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
|
||||
}));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user