diff options
| author | The Miri Conjob Bot <miri@cron.bot> | 2024-01-13 05:03:10 +0000 |
|---|---|---|
| committer | The Miri Conjob Bot <miri@cron.bot> | 2024-01-13 05:03:10 +0000 |
| commit | 9b46f3bb6499c263c9c81e7cea4815396bbbce14 (patch) | |
| tree | ab6ca2c31a68888b7c34f3b091e899054f3a56aa /compiler/rustc_codegen_ssa/src | |
| parent | 86190488cd05ffd48394d9d1c464d7f50ee19614 (diff) | |
| parent | f1f8687b06a5908dd096f51da32347b3313279db (diff) | |
| download | rust-9b46f3bb6499c263c9c81e7cea4815396bbbce14.tar.gz rust-9b46f3bb6499c263c9c81e7cea4815396bbbce14.zip | |
Merge from rustc
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/link.rs | 46 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/symbol_export.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/write.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/base.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/lib.rs | 3 |
5 files changed, 61 insertions, 34 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 70fda982b01..ace356ab153 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -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; } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 94841ab7b33..cae7c40c5ad 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -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(()) @@ -105,14 +105,8 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S } }) .map(|def_id| { - let codegen_attrs = tcx.codegen_fn_attrs(def_id.to_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) - && codegen_attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE); let used = name == "rust_eh_personality"; let export_level = if special_runtime_crate { @@ -120,6 +114,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S } else { symbol_export_level(tcx, def_id.to_def_id()) }; + let codegen_attrs = tcx.codegen_fn_attrs(def_id.to_def_id()); debug!( "EXPORTED SYMBOL (local): {} ({:?})", tcx.symbol_name(Instance::mono(tcx, def_id.to_def_id())), @@ -139,7 +134,6 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S used: codegen_attrs.flags.contains(CodegenFnAttrFlags::USED) || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) || used, - used_compiler: is_builtin_fn, }; (def_id.to_def_id(), info) }) @@ -152,7 +146,6 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S level: SymbolExportLevel::C, kind: SymbolExportKind::Data, used: false, - used_compiler: false, }, ); } @@ -201,7 +194,6 @@ fn exported_symbols_provider_local( level: info.level, kind: SymbolExportKind::Text, used: info.used, - used_compiler: false, }, ) }) @@ -218,7 +210,6 @@ fn exported_symbols_provider_local( level: SymbolExportLevel::C, kind: SymbolExportKind::Text, used: false, - used_compiler: false, }, )); } @@ -238,7 +229,6 @@ fn exported_symbols_provider_local( level: SymbolExportLevel::Rust, kind: SymbolExportKind::Text, used: false, - used_compiler: false, }, )); } @@ -251,7 +241,6 @@ fn exported_symbols_provider_local( level: SymbolExportLevel::Rust, kind: SymbolExportKind::Data, used: false, - used_compiler: false, }, )) } @@ -271,7 +260,6 @@ fn exported_symbols_provider_local( level: SymbolExportLevel::C, kind: SymbolExportKind::Data, used: false, - used_compiler: false, }, ) })); @@ -297,7 +285,6 @@ fn exported_symbols_provider_local( level: SymbolExportLevel::C, kind: SymbolExportKind::Data, used: false, - used_compiler: false, }, ) })); @@ -315,7 +302,6 @@ fn exported_symbols_provider_local( level: SymbolExportLevel::C, kind: SymbolExportKind::Data, used: true, - used_compiler: false, }, )); } @@ -356,7 +342,6 @@ fn exported_symbols_provider_local( level: SymbolExportLevel::Rust, kind: SymbolExportKind::Text, used: false, - used_compiler: false, }, )); } @@ -373,7 +358,6 @@ fn exported_symbols_provider_local( level: SymbolExportLevel::Rust, kind: SymbolExportKind::Text, used: false, - used_compiler: false, }, )); } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 8e835039970..af1c6594446 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -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())); })); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 9d1729c4b54..0ad4af968db 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -859,6 +859,7 @@ impl CrateInfo { local_crate_name, compiler_builtins, profiler_runtime: None, + is_no_builtins: Default::default(), native_libraries: Default::default(), used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(), crate_name: Default::default(), @@ -885,6 +886,9 @@ impl CrateInfo { if tcx.is_profiler_runtime(cnum) { info.profiler_runtime = Some(cnum); } + if tcx.is_no_builtins(cnum) { + info.is_no_builtins.insert(cnum); + } } // Handle circular dependencies in the standard library. @@ -892,7 +896,9 @@ impl CrateInfo { // If global LTO is enabled then almost everything (*) is glued into a single object file, // so this logic is not necessary and can cause issues on some targets (due to weak lang // item symbols being "privatized" to that object file), so we disable it. - // (*) Native libs are not glued, and we assume that they cannot define weak lang items. + // (*) Native libs, and `#[compiler_builtins]` and `#[no_builtins]` crates are not glued, + // and we assume that they cannot define weak lang items. This is not currently enforced + // by the compiler, but that's ok because all this stuff is unstable anyway. let target = &tcx.sess.target; if !are_upstream_rust_objects_already_included(tcx.sess) { let missing_weak_lang_items: FxHashSet<Symbol> = info diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 0d88df63280..99280fdba7c 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -25,7 +25,7 @@ extern crate tracing; extern crate rustc_middle; use rustc_ast as ast; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_hir::def_id::CrateNum; use rustc_middle::dep_graph::WorkProduct; @@ -158,6 +158,7 @@ pub struct CrateInfo { pub local_crate_name: Symbol, pub compiler_builtins: Option<CrateNum>, pub profiler_runtime: Option<CrateNum>, + pub is_no_builtins: FxHashSet<CrateNum>, pub native_libraries: FxHashMap<CrateNum, Vec<NativeLib>>, pub crate_name: FxHashMap<CrateNum, Symbol>, pub used_libraries: Vec<NativeLib>, |
