Skip to content

Commit 097a84f

Browse files
committed
Merge exported_symbols computation into exported_symbols_for_lto
And move exported_symbols_for_lto call from backends to cg_ssa.
1 parent f462a74 commit 097a84f

File tree

4 files changed

+69
-90
lines changed

4 files changed

+69
-90
lines changed

compiler/rustc_codegen_gcc/src/back/lto.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ use std::sync::Arc;
2424

2525
use gccjit::{Context, OutputKind};
2626
use object::read::archive::ArchiveFile;
27-
use rustc_codegen_ssa::back::lto::{
28-
SerializedModule, ThinModule, ThinShared, exported_symbols_for_lto,
29-
};
27+
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared};
3028
use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput};
3129
use rustc_codegen_ssa::traits::*;
3230
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file};
@@ -54,7 +52,7 @@ fn prepare_lto(
5452
dcx: DiagCtxtHandle<'_>,
5553
) -> Result<LtoData, FatalError> {
5654
// FIXME(bjorn3): Limit LTO exports to these symbols
57-
let _symbols_below_threshold = exported_symbols_for_lto(cgcx, dcx)?;
55+
let _symbols_below_threshold = &cgcx.exported_symbols_for_lto;
5856

5957
let tmp_path = match tempdir() {
6058
Ok(tmp_path) => tmp_path,

compiler/rustc_codegen_llvm/src/back/lto.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ use std::sync::Arc;
77
use std::{io, iter, slice};
88

99
use object::read::archive::ArchiveFile;
10-
use rustc_codegen_ssa::back::lto::{
11-
SerializedModule, ThinModule, ThinShared, exported_symbols_for_lto,
12-
};
10+
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared};
1311
use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput};
1412
use rustc_codegen_ssa::traits::*;
1513
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file};
@@ -37,9 +35,10 @@ fn prepare_lto(
3735
cgcx: &CodegenContext<LlvmCodegenBackend>,
3836
dcx: DiagCtxtHandle<'_>,
3937
) -> Result<(Vec<CString>, Vec<(SerializedModule<ModuleBuffer>, CString)>), FatalError> {
40-
let mut symbols_below_threshold = exported_symbols_for_lto(cgcx, dcx)?
41-
.into_iter()
42-
.map(|symbol| CString::new(symbol).unwrap())
38+
let mut symbols_below_threshold = cgcx
39+
.exported_symbols_for_lto
40+
.iter()
41+
.map(|symbol| CString::new(symbol.to_owned()).unwrap())
4342
.collect::<Vec<CString>>();
4443

4544
// __llvm_profile_counter_bias is pulled in at link time by an undefined reference to

compiler/rustc_codegen_ssa/src/back/lto.rs

Lines changed: 53 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
use std::ffi::CString;
2+
use std::path::PathBuf;
23
use std::sync::Arc;
34

45
use rustc_data_structures::memmap::Mmap;
5-
use rustc_errors::{DiagCtxtHandle, FatalError};
6-
use rustc_hir::def_id::LOCAL_CRATE;
7-
use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
6+
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
7+
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportLevel};
8+
use rustc_middle::ty::TyCtxt;
89
use rustc_session::config::{CrateType, Lto};
910
use tracing::info;
1011

11-
use crate::back::symbol_export;
12+
use crate::back::symbol_export::{self, symbol_name_for_instance_in_crate};
1213
use crate::back::write::CodegenContext;
1314
use crate::errors::{DynamicLinkingWithLTO, LtoDisallowed, LtoDylib, LtoProcMacro};
1415
use crate::traits::*;
@@ -73,65 +74,73 @@ fn crate_type_allows_lto(crate_type: CrateType) -> bool {
7374
}
7475
}
7576

76-
pub fn exported_symbols_for_lto<'a, B: WriteBackendMethods>(
77-
cgcx: &'a CodegenContext<B>,
78-
dcx: DiagCtxtHandle<'_>,
79-
) -> Result<Vec<&'a str>, FatalError> {
80-
// FIXME move symbol filtering to cg_ssa
81-
let export_threshold = match cgcx.lto {
77+
pub(super) fn exported_symbols_for_lto(
78+
tcx: TyCtxt<'_>,
79+
each_linked_rlib_for_lto: &[(CrateNum, PathBuf)],
80+
) -> Vec<String> {
81+
let export_threshold = match tcx.sess.lto() {
8282
// We're just doing LTO for our one crate
8383
Lto::ThinLocal => SymbolExportLevel::Rust,
8484

8585
// We're doing LTO for the entire crate graph
86-
Lto::Fat | Lto::Thin => symbol_export::crates_export_threshold(&cgcx.crate_types),
86+
Lto::Fat | Lto::Thin => symbol_export::crates_export_threshold(&tcx.crate_types()),
8787

88-
Lto::No => panic!("didn't request LTO but we're doing LTO"),
88+
Lto::No => return vec![],
8989
};
9090

91-
let symbol_filter = &|&(ref name, info): &'a (String, SymbolExportInfo)| {
92-
if info.level.is_below_threshold(export_threshold) || info.used {
93-
Some(name.as_str())
94-
} else {
95-
None
96-
}
91+
let copy_symbols = |cnum| {
92+
tcx.exported_non_generic_symbols(cnum)
93+
.iter()
94+
.chain(tcx.exported_generic_symbols(cnum))
95+
.filter_map(|&(s, info): &(ExportedSymbol<'_>, SymbolExportInfo)| {
96+
if info.level.is_below_threshold(export_threshold) || info.used {
97+
Some(symbol_name_for_instance_in_crate(tcx, s, cnum))
98+
} else {
99+
None
100+
}
101+
})
102+
.collect::<Vec<_>>()
97103
};
98-
let exported_symbols = cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
99104
let mut symbols_below_threshold = {
100-
let _timer = cgcx.prof.generic_activity("lto_generate_symbols_below_threshold");
101-
exported_symbols[&LOCAL_CRATE].iter().filter_map(symbol_filter).collect::<Vec<&str>>()
105+
let _timer = tcx.prof.generic_activity("lto_generate_symbols_below_threshold");
106+
copy_symbols(LOCAL_CRATE)
102107
};
103108
info!("{} symbols to preserve in this crate", symbols_below_threshold.len());
104109

105110
// If we're performing LTO for the entire crate graph, then for each of our
106111
// upstream dependencies, include their exported symbols.
107-
if cgcx.lto != Lto::ThinLocal {
108-
// Make sure we actually can run LTO
109-
for crate_type in cgcx.crate_types.iter() {
110-
if !crate_type_allows_lto(*crate_type) {
111-
return Err(dcx.emit_almost_fatal(LtoDisallowed));
112-
} else if *crate_type == CrateType::Dylib {
113-
if !cgcx.opts.unstable_opts.dylib_lto {
114-
return Err(dcx.emit_almost_fatal(LtoDylib));
115-
}
116-
} else if *crate_type == CrateType::ProcMacro && !cgcx.opts.unstable_opts.dylib_lto {
117-
return Err(dcx.emit_almost_fatal(LtoProcMacro));
118-
}
112+
if tcx.sess.lto() != Lto::ThinLocal {
113+
for &(cnum, ref _path) in each_linked_rlib_for_lto {
114+
let _timer = tcx.prof.generic_activity("lto_generate_symbols_below_threshold");
115+
symbols_below_threshold.extend(copy_symbols(cnum));
119116
}
117+
}
120118

121-
if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto {
122-
return Err(dcx.emit_almost_fatal(DynamicLinkingWithLTO));
123-
}
119+
symbols_below_threshold
120+
}
121+
122+
pub(super) fn check_lto_allowed<B: WriteBackendMethods>(cgcx: &CodegenContext<B>) {
123+
if cgcx.lto == Lto::ThinLocal {
124+
// Crate local LTO is always allowed
125+
return;
126+
}
124127

125-
for &(cnum, ref _path) in cgcx.each_linked_rlib_for_lto.iter() {
126-
let exported_symbols =
127-
cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
128-
{
129-
let _timer = cgcx.prof.generic_activity("lto_generate_symbols_below_threshold");
130-
symbols_below_threshold
131-
.extend(exported_symbols[&cnum].iter().filter_map(symbol_filter));
128+
let dcx = cgcx.create_dcx();
129+
130+
// Make sure we actually can run LTO
131+
for crate_type in cgcx.crate_types.iter() {
132+
if !crate_type_allows_lto(*crate_type) {
133+
dcx.handle().emit_fatal(LtoDisallowed);
134+
} else if *crate_type == CrateType::Dylib {
135+
if !cgcx.opts.unstable_opts.dylib_lto {
136+
dcx.handle().emit_fatal(LtoDylib);
132137
}
138+
} else if *crate_type == CrateType::ProcMacro && !cgcx.opts.unstable_opts.dylib_lto {
139+
dcx.handle().emit_fatal(LtoProcMacro);
133140
}
134141
}
135142

136-
Ok(symbols_below_threshold)
143+
if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto {
144+
dcx.handle().emit_fatal(DynamicLinkingWithLTO);
145+
}
137146
}

compiler/rustc_codegen_ssa/src/back/write.rs

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::{fs, io, mem, str, thread};
99
use rustc_abi::Size;
1010
use rustc_ast::attr;
1111
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
12-
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
12+
use rustc_data_structures::fx::FxIndexMap;
1313
use rustc_data_structures::jobserver::{self, Acquired};
1414
use rustc_data_structures::memmap::Mmap;
1515
use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
@@ -20,14 +20,13 @@ use rustc_errors::{
2020
Suggestions,
2121
};
2222
use rustc_fs_util::link_or_copy;
23-
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
23+
use rustc_hir::def_id::CrateNum;
2424
use rustc_incremental::{
2525
copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess,
2626
};
2727
use rustc_metadata::fs::copy_to_stdout;
2828
use rustc_middle::bug;
2929
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
30-
use rustc_middle::middle::exported_symbols::SymbolExportInfo;
3130
use rustc_middle::ty::TyCtxt;
3231
use rustc_session::Session;
3332
use rustc_session::config::{
@@ -40,7 +39,7 @@ use tracing::debug;
4039

4140
use super::link::{self, ensure_removed};
4241
use super::lto::{self, SerializedModule};
43-
use super::symbol_export::symbol_name_for_instance_in_crate;
42+
use crate::back::lto::check_lto_allowed;
4443
use crate::errors::{AutodiffWithoutLto, ErrorCreatingRemarkDir};
4544
use crate::traits::*;
4645
use crate::{
@@ -330,8 +329,6 @@ pub type TargetMachineFactoryFn<B> = Arc<
330329
+ Sync,
331330
>;
332331

333-
type ExportedSymbols = FxHashMap<CrateNum, Arc<Vec<(String, SymbolExportInfo)>>>;
334-
335332
/// Additional resources used by optimize_and_codegen (not module specific)
336333
#[derive(Clone)]
337334
pub struct CodegenContext<B: WriteBackendMethods> {
@@ -341,10 +338,10 @@ pub struct CodegenContext<B: WriteBackendMethods> {
341338
pub save_temps: bool,
342339
pub fewer_names: bool,
343340
pub time_trace: bool,
344-
pub exported_symbols: Option<Arc<ExportedSymbols>>,
345341
pub opts: Arc<config::Options>,
346342
pub crate_types: Vec<CrateType>,
347343
pub each_linked_rlib_for_lto: Vec<(CrateNum, PathBuf)>,
344+
pub exported_symbols_for_lto: Arc<Vec<String>>,
348345
pub output_filenames: Arc<OutputFilenames>,
349346
pub invocation_temp: Option<String>,
350347
pub regular_module_config: Arc<ModuleConfig>,
@@ -1126,34 +1123,8 @@ fn start_executing_work<B: ExtraBackendMethods>(
11261123
}));
11271124

11281125
// Compute the set of symbols we need to retain when doing LTO (if we need to)
1129-
let exported_symbols = {
1130-
let mut exported_symbols = FxHashMap::default();
1131-
1132-
let copy_symbols = |cnum| {
1133-
let symbols = tcx
1134-
.exported_non_generic_symbols(cnum)
1135-
.iter()
1136-
.chain(tcx.exported_generic_symbols(cnum))
1137-
.map(|&(s, lvl)| (symbol_name_for_instance_in_crate(tcx, s, cnum), lvl))
1138-
.collect();
1139-
Arc::new(symbols)
1140-
};
1141-
1142-
match sess.lto() {
1143-
Lto::No => None,
1144-
Lto::ThinLocal => {
1145-
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
1146-
Some(Arc::new(exported_symbols))
1147-
}
1148-
Lto::Fat | Lto::Thin => {
1149-
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
1150-
for &(cnum, ref _path) in &each_linked_rlib_for_lto {
1151-
exported_symbols.insert(cnum, copy_symbols(cnum));
1152-
}
1153-
Some(Arc::new(exported_symbols))
1154-
}
1155-
}
1156-
};
1126+
let exported_symbols_for_lto =
1127+
Arc::new(lto::exported_symbols_for_lto(tcx, &each_linked_rlib_for_lto));
11571128

11581129
// First up, convert our jobserver into a helper thread so we can use normal
11591130
// mpsc channels to manage our messages and such.
@@ -1189,13 +1160,13 @@ fn start_executing_work<B: ExtraBackendMethods>(
11891160
let cgcx = CodegenContext::<B> {
11901161
crate_types: tcx.crate_types().to_vec(),
11911162
each_linked_rlib_for_lto,
1163+
exported_symbols_for_lto,
11921164
lto: sess.lto(),
11931165
fewer_names: sess.fewer_names(),
11941166
save_temps: sess.opts.cg.save_temps,
11951167
time_trace: sess.opts.unstable_opts.llvm_time_trace,
11961168
opts: Arc::new(sess.opts.clone()),
11971169
prof: sess.prof.clone(),
1198-
exported_symbols,
11991170
remark: sess.opts.cg.remark.clone(),
12001171
remark_dir,
12011172
incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()),
@@ -1463,6 +1434,8 @@ fn start_executing_work<B: ExtraBackendMethods>(
14631434
let needs_thin_lto = mem::take(&mut needs_thin_lto);
14641435
let import_only_modules = mem::take(&mut lto_import_only_modules);
14651436

1437+
check_lto_allowed(&cgcx);
1438+
14661439
if !needs_fat_lto.is_empty() {
14671440
assert!(needs_thin_lto.is_empty());
14681441

0 commit comments

Comments
 (0)