Skip to content

Commit

Permalink
Fixes LTO + build-std + Oz failed to resolve undefined symbols for th…
Browse files Browse the repository at this point in the history
…e compiler_builtins.
  • Loading branch information
DianQK committed Jun 22, 2023
1 parent fa06a37 commit e7a98a5
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 2 deletions.
11 changes: 10 additions & 1 deletion compiler/rustc_codegen_llvm/src/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,17 @@ fn prepare_lto(
Lto::No => panic!("didn't request LTO but we're doing LTO"),
};

let export_for_undefined_symbols =
&|name: &str| match &cgcx.undefined_symbols_from_ignored_for_lto {
Some(undefined_symbols) => undefined_symbols.contains(name),
None => false,
};

let symbol_filter = &|&(ref name, info): &(String, SymbolExportInfo)| {
if info.level.is_below_threshold(export_threshold) || info.used {
if info.level.is_below_threshold(export_threshold)
|| info.used
|| export_for_undefined_symbols(name)
{
Some(CString::new(name.as_str()).unwrap())
} else {
None
Expand Down
30 changes: 30 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/archive.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use object::{Object, ObjectSymbol};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::memmap::Mmap;
use rustc_session::cstore::DllImport;
Expand Down Expand Up @@ -308,3 +309,32 @@ impl<'a> ArArchiveBuilder<'a> {
fn io_error_context(context: &str, err: io::Error) -> io::Error {
io::Error::new(io::ErrorKind::Other, format!("{context}: {err}"))
}

pub fn read_archive_file_undefined_symbols(archive_path: &Path) -> io::Result<Vec<String>> {
let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
let archive = ArchiveFile::parse(&*archive_map)
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
let mut undefined_symbols = Vec::new();
for entry in archive.members() {
let entry = entry.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
if entry.name().ends_with(b".rmeta") {
continue;
}
let data = entry
.data(&*archive_map)
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
let file = object::File::parse(&*data)
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
for symbol in file.symbols() {
if symbol.is_undefined() {
undefined_symbols.push(
symbol
.name()
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?
.to_string(),
);
}
}
}
Ok(undefined_symbols)
}
28 changes: 27 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ use super::link::{self, ensure_removed};
use super::lto::{self, SerializedModule};
use super::symbol_export::symbol_name_for_instance_in_crate;

use crate::back::archive::read_archive_file_undefined_symbols;
use crate::errors;
use crate::traits::*;
use crate::{
CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
};
use jobserver::{Acquired, Client};
use rustc_ast::attr;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
use rustc_data_structures::sync::Lrc;
Expand Down Expand Up @@ -327,6 +328,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
pub fewer_names: bool,
pub time_trace: bool,
pub exported_symbols: Option<Arc<ExportedSymbols>>,
pub undefined_symbols_from_ignored_for_lto: Option<FxHashSet<String>>,
pub opts: Arc<config::Options>,
pub crate_types: Vec<CrateType>,
pub each_linked_rlib_for_lto: Vec<(CrateNum, PathBuf)>,
Expand Down Expand Up @@ -989,13 +991,36 @@ fn start_executing_work<B: ExtraBackendMethods>(
let sess = tcx.sess;

let mut each_linked_rlib_for_lto = Vec::new();
let mut ignored_cnum_for_lto = Vec::new();
drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| {
if link::ignored_for_lto(sess, crate_info, cnum) {
ignored_cnum_for_lto.push(cnum);
return;
}
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
}));

let undefined_symbols_from_ignored_for_lto = {
match sess.lto() {
Lto::Fat | Lto::Thin => {
let mut undefined_symbols_from_ignored_for_lto = FxHashSet::default();
if !sess.target.is_like_wasm {
// FIXME: Add an undefined symbol lookup for wasm. https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md
for cnum in ignored_cnum_for_lto {
let c_src = tcx.used_crate_source(cnum);
if let Some((path, _)) = &c_src.rlib {
let undefined_symbols = read_archive_file_undefined_symbols(path)
.expect("failed to read undefined symbols");
undefined_symbols_from_ignored_for_lto.extend(undefined_symbols);
}
}
}
Some(undefined_symbols_from_ignored_for_lto)
}
Lto::No | Lto::ThinLocal => None,
}
};

// Compute the set of symbols we need to retain when doing LTO (if we need to)
let exported_symbols = {
let mut exported_symbols = FxHashMap::default();
Expand Down Expand Up @@ -1049,6 +1074,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
backend: backend.clone(),
crate_types: sess.crate_types().to_vec(),
each_linked_rlib_for_lto,
undefined_symbols_from_ignored_for_lto,
lto: sess.lto(),
fewer_names: sess.fewer_names(),
save_temps: sess.opts.cg.save_temps,
Expand Down

0 comments on commit e7a98a5

Please sign in to comment.