Skip to content

Commit e7a98a5

Browse files
committed
Fixes LTO + build-std + Oz failed to resolve undefined symbols for the compiler_builtins.
1 parent fa06a37 commit e7a98a5

File tree

3 files changed

+67
-2
lines changed

3 files changed

+67
-2
lines changed

compiler/rustc_codegen_llvm/src/back/lto.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,17 @@ fn prepare_lto(
5353
Lto::No => panic!("didn't request LTO but we're doing LTO"),
5454
};
5555

56+
let export_for_undefined_symbols =
57+
&|name: &str| match &cgcx.undefined_symbols_from_ignored_for_lto {
58+
Some(undefined_symbols) => undefined_symbols.contains(name),
59+
None => false,
60+
};
61+
5662
let symbol_filter = &|&(ref name, info): &(String, SymbolExportInfo)| {
57-
if info.level.is_below_threshold(export_threshold) || info.used {
63+
if info.level.is_below_threshold(export_threshold)
64+
|| info.used
65+
|| export_for_undefined_symbols(name)
66+
{
5867
Some(CString::new(name.as_str()).unwrap())
5968
} else {
6069
None

compiler/rustc_codegen_ssa/src/back/archive.rs

+30
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use object::{Object, ObjectSymbol};
12
use rustc_data_structures::fx::FxHashSet;
23
use rustc_data_structures::memmap::Mmap;
34
use rustc_session::cstore::DllImport;
@@ -308,3 +309,32 @@ impl<'a> ArArchiveBuilder<'a> {
308309
fn io_error_context(context: &str, err: io::Error) -> io::Error {
309310
io::Error::new(io::ErrorKind::Other, format!("{context}: {err}"))
310311
}
312+
313+
pub fn read_archive_file_undefined_symbols(archive_path: &Path) -> io::Result<Vec<String>> {
314+
let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
315+
let archive = ArchiveFile::parse(&*archive_map)
316+
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
317+
let mut undefined_symbols = Vec::new();
318+
for entry in archive.members() {
319+
let entry = entry.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
320+
if entry.name().ends_with(b".rmeta") {
321+
continue;
322+
}
323+
let data = entry
324+
.data(&*archive_map)
325+
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
326+
let file = object::File::parse(&*data)
327+
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
328+
for symbol in file.symbols() {
329+
if symbol.is_undefined() {
330+
undefined_symbols.push(
331+
symbol
332+
.name()
333+
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?
334+
.to_string(),
335+
);
336+
}
337+
}
338+
}
339+
Ok(undefined_symbols)
340+
}

compiler/rustc_codegen_ssa/src/back/write.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ use super::link::{self, ensure_removed};
22
use super::lto::{self, SerializedModule};
33
use super::symbol_export::symbol_name_for_instance_in_crate;
44

5+
use crate::back::archive::read_archive_file_undefined_symbols;
56
use crate::errors;
67
use crate::traits::*;
78
use crate::{
89
CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
910
};
1011
use jobserver::{Acquired, Client};
1112
use rustc_ast::attr;
12-
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
13+
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
1314
use rustc_data_structures::memmap::Mmap;
1415
use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
1516
use rustc_data_structures::sync::Lrc;
@@ -327,6 +328,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
327328
pub fewer_names: bool,
328329
pub time_trace: bool,
329330
pub exported_symbols: Option<Arc<ExportedSymbols>>,
331+
pub undefined_symbols_from_ignored_for_lto: Option<FxHashSet<String>>,
330332
pub opts: Arc<config::Options>,
331333
pub crate_types: Vec<CrateType>,
332334
pub each_linked_rlib_for_lto: Vec<(CrateNum, PathBuf)>,
@@ -989,13 +991,36 @@ fn start_executing_work<B: ExtraBackendMethods>(
989991
let sess = tcx.sess;
990992

991993
let mut each_linked_rlib_for_lto = Vec::new();
994+
let mut ignored_cnum_for_lto = Vec::new();
992995
drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| {
993996
if link::ignored_for_lto(sess, crate_info, cnum) {
997+
ignored_cnum_for_lto.push(cnum);
994998
return;
995999
}
9961000
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
9971001
}));
9981002

1003+
let undefined_symbols_from_ignored_for_lto = {
1004+
match sess.lto() {
1005+
Lto::Fat | Lto::Thin => {
1006+
let mut undefined_symbols_from_ignored_for_lto = FxHashSet::default();
1007+
if !sess.target.is_like_wasm {
1008+
// FIXME: Add an undefined symbol lookup for wasm. https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md
1009+
for cnum in ignored_cnum_for_lto {
1010+
let c_src = tcx.used_crate_source(cnum);
1011+
if let Some((path, _)) = &c_src.rlib {
1012+
let undefined_symbols = read_archive_file_undefined_symbols(path)
1013+
.expect("failed to read undefined symbols");
1014+
undefined_symbols_from_ignored_for_lto.extend(undefined_symbols);
1015+
}
1016+
}
1017+
}
1018+
Some(undefined_symbols_from_ignored_for_lto)
1019+
}
1020+
Lto::No | Lto::ThinLocal => None,
1021+
}
1022+
};
1023+
9991024
// Compute the set of symbols we need to retain when doing LTO (if we need to)
10001025
let exported_symbols = {
10011026
let mut exported_symbols = FxHashMap::default();
@@ -1049,6 +1074,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
10491074
backend: backend.clone(),
10501075
crate_types: sess.crate_types().to_vec(),
10511076
each_linked_rlib_for_lto,
1077+
undefined_symbols_from_ignored_for_lto,
10521078
lto: sess.lto(),
10531079
fewer_names: sess.fewer_names(),
10541080
save_temps: sess.opts.cg.save_temps,

0 commit comments

Comments
 (0)