diff options
| author | bjorn3 <17426603+bjorn3@users.noreply.github.com> | 2025-07-04 14:59:53 +0000 |
|---|---|---|
| committer | bjorn3 <17426603+bjorn3@users.noreply.github.com> | 2025-07-21 07:58:44 +0000 |
| commit | 1c8dc6f4405124b092dc534d17d4b13f29a4adae (patch) | |
| tree | da9c7311c67c9651e63485ae293e0634d0eee666 /compiler/rustc_codegen_ssa/src | |
| parent | 2ad7930b40bd5cb0e103cb5c7145f4b335dd4520 (diff) | |
| download | rust-1c8dc6f4405124b092dc534d17d4b13f29a4adae.tar.gz rust-1c8dc6f4405124b092dc534d17d4b13f29a4adae.zip | |
Move LTO symbol export calculation from backends to cg_ssa
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/lto.rs | 83 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/errors.rs | 17 |
2 files changed, 100 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs index b49b6783bbd..474a5e08baf 100644 --- a/compiler/rustc_codegen_ssa/src/back/lto.rs +++ b/compiler/rustc_codegen_ssa/src/back/lto.rs @@ -2,7 +2,15 @@ use std::ffi::CString; use std::sync::Arc; use rustc_data_structures::memmap::Mmap; +use rustc_errors::{DiagCtxtHandle, FatalError}; +use rustc_hir::def_id::LOCAL_CRATE; +use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel}; +use rustc_session::config::{CrateType, Lto}; +use tracing::info; +use crate::back::symbol_export; +use crate::back::write::CodegenContext; +use crate::errors::{DynamicLinkingWithLTO, LtoDisallowed, LtoDylib, LtoProcMacro}; use crate::traits::*; pub struct ThinModule<B: WriteBackendMethods> { @@ -52,3 +60,78 @@ impl<M: ModuleBufferMethods> SerializedModule<M> { } } } + +fn crate_type_allows_lto(crate_type: CrateType) -> bool { + match crate_type { + CrateType::Executable + | CrateType::Dylib + | CrateType::Staticlib + | CrateType::Cdylib + | CrateType::ProcMacro + | CrateType::Sdylib => true, + CrateType::Rlib => false, + } +} + +pub fn exported_symbols_for_lto<'a, B: WriteBackendMethods>( + cgcx: &'a CodegenContext<B>, + dcx: DiagCtxtHandle<'_>, +) -> Result<Vec<&'a str>, FatalError> { + // FIXME move symbol filtering to cg_ssa + let export_threshold = match cgcx.lto { + // We're just doing LTO for our one crate + Lto::ThinLocal => SymbolExportLevel::Rust, + + // We're doing LTO for the entire crate graph + Lto::Fat | Lto::Thin => symbol_export::crates_export_threshold(&cgcx.crate_types), + + Lto::No => panic!("didn't request LTO but we're doing LTO"), + }; + + let symbol_filter = &|&(ref name, info): &'a (String, SymbolExportInfo)| { + if info.level.is_below_threshold(export_threshold) || info.used { + Some(name.as_str()) + } else { + None + } + }; + let exported_symbols = cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO"); + let mut symbols_below_threshold = { + let _timer = cgcx.prof.generic_activity("lto_generate_symbols_below_threshold"); + exported_symbols[&LOCAL_CRATE].iter().filter_map(symbol_filter).collect::<Vec<&str>>() + }; + info!("{} symbols to preserve in this crate", symbols_below_threshold.len()); + + // If we're performing LTO for the entire crate graph, then for each of our + // upstream dependencies, include their exported symbols. + if cgcx.lto != Lto::ThinLocal { + // Make sure we actually can run LTO + for crate_type in cgcx.crate_types.iter() { + if !crate_type_allows_lto(*crate_type) { + return Err(dcx.emit_almost_fatal(LtoDisallowed)); + } else if *crate_type == CrateType::Dylib { + if !cgcx.opts.unstable_opts.dylib_lto { + return Err(dcx.emit_almost_fatal(LtoDylib)); + } + } else if *crate_type == CrateType::ProcMacro && !cgcx.opts.unstable_opts.dylib_lto { + return Err(dcx.emit_almost_fatal(LtoProcMacro)); + } + } + + if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto { + return Err(dcx.emit_almost_fatal(DynamicLinkingWithLTO)); + } + + 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"); + { + let _timer = cgcx.prof.generic_activity("lto_generate_symbols_below_threshold"); + symbols_below_threshold + .extend(exported_symbols[&cnum].iter().filter_map(symbol_filter)); + } + } + } + + Ok(symbols_below_threshold) +} diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 9040915b6af..3d787d8bdbd 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -1294,3 +1294,20 @@ pub(crate) struct FeatureNotValid<'a> { #[help] pub plus_hint: bool, } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_lto_disallowed)] +pub(crate) struct LtoDisallowed; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_lto_dylib)] +pub(crate) struct LtoDylib; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_lto_proc_macro)] +pub(crate) struct LtoProcMacro; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_dynamic_linking_with_lto)] +#[note] +pub(crate) struct DynamicLinkingWithLTO; |
