Skip to content

Commit f462a74

Browse files
committed
Move LTO symbol export calculation from backends to cg_ssa
1 parent 125c7c7 commit f462a74

File tree

9 files changed

+132
-191
lines changed

9 files changed

+132
-191
lines changed

compiler/rustc_codegen_gcc/messages.ftl

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,4 @@ codegen_gcc_unwinding_inline_asm =
33
44
codegen_gcc_copy_bitcode = failed to copy bitcode to object file: {$err}
55
6-
codegen_gcc_dynamic_linking_with_lto =
7-
cannot prefer dynamic linking when performing LTO
8-
.note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
9-
10-
codegen_gcc_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs
11-
12-
codegen_gcc_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto`
13-
146
codegen_gcc_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$gcc_err})

compiler/rustc_codegen_gcc/src/back/lto.rs

Lines changed: 8 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -24,36 +24,24 @@ use std::sync::Arc;
2424

2525
use gccjit::{Context, OutputKind};
2626
use object::read::archive::ArchiveFile;
27-
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared};
28-
use rustc_codegen_ssa::back::symbol_export;
27+
use rustc_codegen_ssa::back::lto::{
28+
SerializedModule, ThinModule, ThinShared, exported_symbols_for_lto,
29+
};
2930
use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput};
3031
use rustc_codegen_ssa::traits::*;
3132
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file};
3233
use rustc_data_structures::memmap::Mmap;
3334
use rustc_errors::{DiagCtxtHandle, FatalError};
34-
use rustc_hir::def_id::LOCAL_CRATE;
3535
use rustc_middle::bug;
3636
use rustc_middle::dep_graph::WorkProduct;
37-
use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
38-
use rustc_session::config::{CrateType, Lto};
37+
use rustc_session::config::Lto;
3938
use rustc_target::spec::RelocModel;
4039
use tempfile::{TempDir, tempdir};
4140

4241
use crate::back::write::save_temp_bitcode;
43-
use crate::errors::{DynamicLinkingWithLTO, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib};
42+
use crate::errors::LtoBitcodeFromRlib;
4443
use crate::{GccCodegenBackend, GccContext, SyncContext, to_gcc_opt_level};
4544

46-
pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
47-
match crate_type {
48-
CrateType::Executable
49-
| CrateType::Dylib
50-
| CrateType::Staticlib
51-
| CrateType::Cdylib
52-
| CrateType::Sdylib => true,
53-
CrateType::Rlib | CrateType::ProcMacro => false,
54-
}
55-
}
56-
5745
struct LtoData {
5846
// TODO(antoyo): use symbols_below_threshold.
5947
//symbols_below_threshold: Vec<String>,
@@ -65,15 +53,8 @@ fn prepare_lto(
6553
cgcx: &CodegenContext<GccCodegenBackend>,
6654
dcx: DiagCtxtHandle<'_>,
6755
) -> Result<LtoData, FatalError> {
68-
let export_threshold = match cgcx.lto {
69-
// We're just doing LTO for our one crate
70-
Lto::ThinLocal => SymbolExportLevel::Rust,
71-
72-
// We're doing LTO for the entire crate graph
73-
Lto::Fat | Lto::Thin => symbol_export::crates_export_threshold(&cgcx.crate_types),
74-
75-
Lto::No => panic!("didn't request LTO but we're doing LTO"),
76-
};
56+
// FIXME(bjorn3): Limit LTO exports to these symbols
57+
let _symbols_below_threshold = exported_symbols_for_lto(cgcx, dcx)?;
7758

7859
let tmp_path = match tempdir() {
7960
Ok(tmp_path) => tmp_path,
@@ -83,20 +64,6 @@ fn prepare_lto(
8364
}
8465
};
8566

86-
let symbol_filter = &|&(ref name, info): &(String, SymbolExportInfo)| {
87-
if info.level.is_below_threshold(export_threshold) || info.used {
88-
Some(name.clone())
89-
} else {
90-
None
91-
}
92-
};
93-
let exported_symbols = cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
94-
let mut symbols_below_threshold = {
95-
let _timer = cgcx.prof.generic_activity("GCC_lto_generate_symbols_below_threshold");
96-
exported_symbols[&LOCAL_CRATE].iter().filter_map(symbol_filter).collect::<Vec<String>>()
97-
};
98-
info!("{} symbols to preserve in this crate", symbols_below_threshold.len());
99-
10067
// If we're performing LTO for the entire crate graph, then for each of our
10168
// upstream dependencies, find the corresponding rlib and load the bitcode
10269
// from the archive.
@@ -105,32 +72,7 @@ fn prepare_lto(
10572
// with either fat or thin LTO
10673
let mut upstream_modules = Vec::new();
10774
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-
dcx.emit_err(LtoDisallowed);
112-
return Err(FatalError);
113-
}
114-
if *crate_type == CrateType::Dylib && !cgcx.opts.unstable_opts.dylib_lto {
115-
dcx.emit_err(LtoDylib);
116-
return Err(FatalError);
117-
}
118-
}
119-
120-
if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto {
121-
dcx.emit_err(DynamicLinkingWithLTO);
122-
return Err(FatalError);
123-
}
124-
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("GCC_lto_generate_symbols_below_threshold");
130-
symbols_below_threshold
131-
.extend(exported_symbols[&cnum].iter().filter_map(symbol_filter));
132-
}
133-
75+
for &(_cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() {
13476
let archive_data = unsafe {
13577
Mmap::map(File::open(path).expect("couldn't open rlib")).expect("couldn't map rlib")
13678
};

compiler/rustc_codegen_gcc/src/errors.rs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,6 @@ pub(crate) struct CopyBitcode {
1414
pub err: std::io::Error,
1515
}
1616

17-
#[derive(Diagnostic)]
18-
#[diag(codegen_gcc_dynamic_linking_with_lto)]
19-
#[note]
20-
pub(crate) struct DynamicLinkingWithLTO;
21-
22-
#[derive(Diagnostic)]
23-
#[diag(codegen_gcc_lto_disallowed)]
24-
pub(crate) struct LtoDisallowed;
25-
26-
#[derive(Diagnostic)]
27-
#[diag(codegen_gcc_lto_dylib)]
28-
pub(crate) struct LtoDylib;
29-
3017
#[derive(Diagnostic)]
3118
#[diag(codegen_gcc_lto_bitcode_from_rlib)]
3219
pub(crate) struct LtoBitcodeFromRlib {

compiler/rustc_codegen_llvm/messages.ftl

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@ codegen_llvm_autodiff_without_enable = using the autodiff feature requires -Z au
22
33
codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
44
5-
codegen_llvm_dynamic_linking_with_lto =
6-
cannot prefer dynamic linking when performing LTO
7-
.note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
8-
95
106
codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture
117
@@ -18,12 +14,6 @@ codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$na
1814
1915
codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$llvm_err})
2016
21-
codegen_llvm_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs
22-
23-
codegen_llvm_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto`
24-
25-
codegen_llvm_lto_proc_macro = lto cannot be used for `proc-macro` crate type without `-Zdylib-lto`
26-
2717
codegen_llvm_mismatch_data_layout =
2818
data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}`
2919

compiler/rustc_codegen_llvm/src/back/lto.rs

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

99
use object::read::archive::ArchiveFile;
10-
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared};
11-
use rustc_codegen_ssa::back::symbol_export;
10+
use rustc_codegen_ssa::back::lto::{
11+
SerializedModule, ThinModule, ThinShared, exported_symbols_for_lto,
12+
};
1213
use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput};
1314
use rustc_codegen_ssa::traits::*;
1415
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file};
1516
use rustc_data_structures::fx::FxHashMap;
1617
use rustc_data_structures::memmap::Mmap;
1718
use rustc_errors::{DiagCtxtHandle, FatalError};
18-
use rustc_hir::def_id::LOCAL_CRATE;
1919
use rustc_middle::bug;
2020
use rustc_middle::dep_graph::WorkProduct;
21-
use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
22-
use rustc_session::config::{self, CrateType, Lto};
21+
use rustc_session::config::{self, Lto};
2322
use tracing::{debug, info};
2423

2524
use crate::back::write::{
2625
self, CodegenDiagnosticsStage, DiagnosticHandlers, bitcode_section_name, save_temp_bitcode,
2726
};
28-
use crate::errors::{
29-
DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib, LtoProcMacro,
30-
};
27+
use crate::errors::{LlvmError, LtoBitcodeFromRlib};
3128
use crate::llvm::AttributePlace::Function;
3229
use crate::llvm::{self, build_string};
3330
use crate::{LlvmCodegenBackend, ModuleLlvm, SimpleCx, attributes};
@@ -36,45 +33,19 @@ use crate::{LlvmCodegenBackend, ModuleLlvm, SimpleCx, attributes};
3633
/// session to determine which CGUs we can reuse.
3734
const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin";
3835

39-
fn crate_type_allows_lto(crate_type: CrateType) -> bool {
40-
match crate_type {
41-
CrateType::Executable
42-
| CrateType::Dylib
43-
| CrateType::Staticlib
44-
| CrateType::Cdylib
45-
| CrateType::ProcMacro
46-
| CrateType::Sdylib => true,
47-
CrateType::Rlib => false,
48-
}
49-
}
50-
5136
fn prepare_lto(
5237
cgcx: &CodegenContext<LlvmCodegenBackend>,
5338
dcx: DiagCtxtHandle<'_>,
5439
) -> Result<(Vec<CString>, Vec<(SerializedModule<ModuleBuffer>, CString)>), FatalError> {
55-
let export_threshold = match cgcx.lto {
56-
// We're just doing LTO for our one crate
57-
Lto::ThinLocal => SymbolExportLevel::Rust,
58-
59-
// We're doing LTO for the entire crate graph
60-
Lto::Fat | Lto::Thin => symbol_export::crates_export_threshold(&cgcx.crate_types),
61-
62-
Lto::No => panic!("didn't request LTO but we're doing LTO"),
63-
};
40+
let mut symbols_below_threshold = exported_symbols_for_lto(cgcx, dcx)?
41+
.into_iter()
42+
.map(|symbol| CString::new(symbol).unwrap())
43+
.collect::<Vec<CString>>();
6444

65-
let symbol_filter = &|&(ref name, info): &(String, SymbolExportInfo)| {
66-
if info.level.is_below_threshold(export_threshold) || info.used {
67-
Some(CString::new(name.as_str()).unwrap())
68-
} else {
69-
None
70-
}
71-
};
72-
let exported_symbols = cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
73-
let mut symbols_below_threshold = {
74-
let _timer = cgcx.prof.generic_activity("LLVM_lto_generate_symbols_below_threshold");
75-
exported_symbols[&LOCAL_CRATE].iter().filter_map(symbol_filter).collect::<Vec<CString>>()
76-
};
77-
info!("{} symbols to preserve in this crate", symbols_below_threshold.len());
45+
// __llvm_profile_counter_bias is pulled in at link time by an undefined reference to
46+
// __llvm_profile_runtime, therefore we won't know until link time if this symbol
47+
// should have default visibility.
48+
symbols_below_threshold.push(c"__llvm_profile_counter_bias".to_owned());
7849

7950
// If we're performing LTO for the entire crate graph, then for each of our
8051
// upstream dependencies, find the corresponding rlib and load the bitcode
@@ -84,37 +55,7 @@ fn prepare_lto(
8455
// with either fat or thin LTO
8556
let mut upstream_modules = Vec::new();
8657
if cgcx.lto != Lto::ThinLocal {
87-
// Make sure we actually can run LTO
88-
for crate_type in cgcx.crate_types.iter() {
89-
if !crate_type_allows_lto(*crate_type) {
90-
dcx.emit_err(LtoDisallowed);
91-
return Err(FatalError);
92-
} else if *crate_type == CrateType::Dylib {
93-
if !cgcx.opts.unstable_opts.dylib_lto {
94-
dcx.emit_err(LtoDylib);
95-
return Err(FatalError);
96-
}
97-
} else if *crate_type == CrateType::ProcMacro && !cgcx.opts.unstable_opts.dylib_lto {
98-
dcx.emit_err(LtoProcMacro);
99-
return Err(FatalError);
100-
}
101-
}
102-
103-
if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto {
104-
dcx.emit_err(DynamicLinkingWithLTO);
105-
return Err(FatalError);
106-
}
107-
108-
for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() {
109-
let exported_symbols =
110-
cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
111-
{
112-
let _timer =
113-
cgcx.prof.generic_activity("LLVM_lto_generate_symbols_below_threshold");
114-
symbols_below_threshold
115-
.extend(exported_symbols[&cnum].iter().filter_map(symbol_filter));
116-
}
117-
58+
for &(_cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() {
11859
let archive_data = unsafe {
11960
Mmap::map(std::fs::File::open(&path).expect("couldn't open rlib"))
12061
.expect("couldn't map rlib")
@@ -147,10 +88,6 @@ fn prepare_lto(
14788
}
14889
}
14990

150-
// __llvm_profile_counter_bias is pulled in at link time by an undefined reference to
151-
// __llvm_profile_runtime, therefore we won't know until link time if this symbol
152-
// should have default visibility.
153-
symbols_below_threshold.push(c"__llvm_profile_counter_bias".to_owned());
15491
Ok((symbols_below_threshold, upstream_modules))
15592
}
15693

compiler/rustc_codegen_llvm/src/errors.rs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,6 @@ pub(crate) struct SymbolAlreadyDefined<'a> {
2020
#[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
2121
pub(crate) struct SanitizerMemtagRequiresMte;
2222

23-
#[derive(Diagnostic)]
24-
#[diag(codegen_llvm_dynamic_linking_with_lto)]
25-
#[note]
26-
pub(crate) struct DynamicLinkingWithLTO;
27-
2823
pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>);
2924

3025
impl<G: EmissionGuarantee> Diagnostic<'_, G> for ParseTargetMachineConfig<'_> {
@@ -41,18 +36,6 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for ParseTargetMachineConfig<'_> {
4136
#[diag(codegen_llvm_autodiff_without_enable)]
4237
pub(crate) struct AutoDiffWithoutEnable;
4338

44-
#[derive(Diagnostic)]
45-
#[diag(codegen_llvm_lto_disallowed)]
46-
pub(crate) struct LtoDisallowed;
47-
48-
#[derive(Diagnostic)]
49-
#[diag(codegen_llvm_lto_dylib)]
50-
pub(crate) struct LtoDylib;
51-
52-
#[derive(Diagnostic)]
53-
#[diag(codegen_llvm_lto_proc_macro)]
54-
pub(crate) struct LtoProcMacro;
55-
5639
#[derive(Diagnostic)]
5740
#[diag(codegen_llvm_lto_bitcode_from_rlib)]
5841
pub(crate) struct LtoBitcodeFromRlib {

compiler/rustc_codegen_ssa/messages.ftl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ codegen_ssa_dlltool_fail_import_library =
3535
{$stdout}
3636
{$stderr}
3737
38+
codegen_ssa_dynamic_linking_with_lto =
39+
cannot prefer dynamic linking when performing LTO
40+
.note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
41+
3842
codegen_ssa_error_calling_dlltool =
3943
Error calling dlltool '{$dlltool_path}': {$error}
4044
@@ -191,6 +195,12 @@ codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for
191195
192196
codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}
193197
198+
codegen_ssa_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs
199+
200+
codegen_ssa_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto`
201+
202+
codegen_ssa_lto_proc_macro = lto cannot be used for `proc-macro` crate type without `-Zdylib-lto`
203+
194204
codegen_ssa_malformed_cgu_name =
195205
found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case).
196206

0 commit comments

Comments
 (0)