Skip to content

Commit 4ec2c5e

Browse files
committed
Ensuring proper codegen unit association for exported symbols.
1 parent b5d92a2 commit 4ec2c5e

File tree

8 files changed

+113
-82
lines changed

8 files changed

+113
-82
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::{env, fmt, fs, io, mem, str};
99

1010
use cc::windows_registry;
1111
use itertools::Itertools;
12-
use object::read::archive::{ArchiveFile, ArchiveOffset};
12+
use object::read::archive::ArchiveFile;
1313
use regex::Regex;
1414
use rustc_arena::TypedArena;
1515
use rustc_ast::CRATE_NODE_ID;
@@ -2953,21 +2953,24 @@ fn add_local_crate_linked_objects(
29532953
tempfiles_for_linked_objects: &mut Vec<PathBuf>,
29542954
outputs: &OutputFilenames,
29552955
) {
2956-
for (cnum, offsets) in &codegen_results.crate_info.linked_objects[&crate_type] {
2956+
for (cnum, objects) in &codegen_results.crate_info.linked_objects[&crate_type] {
29572957
let src = &codegen_results.crate_info.used_crate_source[cnum];
29582958
let cratepath = &src.rlib.as_ref().unwrap().0;
29592959
let archive_map = unsafe { Mmap::map(File::open(cratepath).unwrap()).unwrap() };
29602960
let archive = ArchiveFile::parse(&*archive_map)
29612961
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
29622962
.unwrap();
2963-
for &offset in offsets {
2964-
let member = archive.member(ArchiveOffset(offset)).unwrap();
2963+
for member in archive.members() {
2964+
let member = member.unwrap();
29652965
let name = std::str::from_utf8(member.name()).unwrap();
2966-
let data = member.data(&*archive_map).unwrap();
2967-
let obj = outputs.temp_path(OutputType::Object, Some(&format!("{name}.linked_object")));
2968-
fs::write(&obj, data).unwrap();
2969-
cmd.add_object(&obj);
2970-
tempfiles_for_linked_objects.push(obj);
2966+
if objects.contains(name) {
2967+
let data = member.data(&*archive_map).unwrap();
2968+
let obj =
2969+
outputs.temp_path(OutputType::Object, Some(&format!("{name}.linked_object")));
2970+
fs::write(&obj, data).unwrap();
2971+
cmd.add_object(&obj);
2972+
tempfiles_for_linked_objects.push(obj);
2973+
}
29712974
}
29722975
}
29732976
}

compiler/rustc_codegen_ssa/src/back/linker.rs

Lines changed: 37 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ use std::path::{Path, PathBuf};
55
use std::{env, io, iter, mem, str};
66

77
use cc::windows_registry;
8-
use object::read::archive::ArchiveFile;
9-
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
10-
use rustc_data_structures::memmap::Mmap;
8+
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
119
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
1210
use rustc_metadata::{
1311
find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library,
@@ -1813,33 +1811,11 @@ fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> {
18131811
vec![proc_macro_decls_name, metadata_symbol_name]
18141812
}
18151813

1816-
fn add_linked_objects(
1817-
archive_path: &Path,
1818-
linked_symbols: &mut FxHashSet<String>,
1819-
) -> Option<FxIndexSet<u64>> {
1820-
let archive_map = unsafe { Mmap::map(File::open(&archive_path).unwrap()).unwrap() };
1821-
let archive = ArchiveFile::parse(&*archive_map)
1822-
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
1823-
.unwrap();
1824-
let Some(archive_symbols) = archive.symbols().unwrap() else {
1825-
return None;
1826-
};
1827-
let mut offsets = FxIndexSet::default();
1828-
for symbol in archive_symbols {
1829-
let symbol = symbol.unwrap();
1830-
let name = std::str::from_utf8(symbol.name()).unwrap();
1831-
if linked_symbols.remove(name) {
1832-
offsets.insert(symbol.offset().0);
1833-
}
1834-
}
1835-
Some(offsets)
1836-
}
1837-
18381814
pub(crate) fn linked_objects(
18391815
tcx: TyCtxt<'_>,
18401816
crate_type: CrateType,
18411817
linked_symbols: &mut Vec<(String, SymbolExportKind)>,
1842-
) -> FxIndexMap<CrateNum, FxIndexSet<u64>> {
1818+
) -> FxIndexMap<CrateNum, FxHashSet<String>> {
18431819
match crate_type {
18441820
CrateType::Executable | CrateType::Cdylib | CrateType::Dylib => (),
18451821
CrateType::Staticlib | CrateType::ProcMacro | CrateType::Rlib => {
@@ -1852,14 +1828,21 @@ pub(crate) fn linked_objects(
18521828
are_upstream_rust_objects_already_included(tcx.sess);
18531829
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
18541830
for_each_exported_symbols_include_dep(tcx, crate_type, |exported_symbols, cnum| {
1831+
let exported_symbols = exported_symbols
1832+
.iter()
1833+
.filter(|(_, info)| info.level.is_below_threshold(export_threshold) || info.used);
18551834
if cnum == LOCAL_CRATE {
1856-
// We don't know here if the symbols are undefined, so we add them all.
1857-
// Since the local crate is always linked directly to object files, `#[used]` works as expected.
1835+
// Since the local crate is always linked directly to object files, `#[used]` works as expected,
1836+
// we only need add undefined symbols.
18581837
linked_symbols.extend(
18591838
exported_symbols
1860-
.iter()
1861-
.filter(|(_, info)| {
1862-
info.level.is_below_threshold(export_threshold) || info.used
1839+
.filter(|(symbol, _)| match symbol {
1840+
ExportedSymbol::NonGeneric { cgu, .. } => cgu.is_none(),
1841+
ExportedSymbol::Generic(..)
1842+
| ExportedSymbol::DropGlue(..)
1843+
| ExportedSymbol::AsyncDropGlueCtorShim(..) => false,
1844+
ExportedSymbol::ThreadLocalShim(_def_id) => false,
1845+
ExportedSymbol::NoDefId(..) => true,
18631846
})
18641847
.map(|&(symbol, info)| {
18651848
(
@@ -1872,35 +1855,33 @@ pub(crate) fn linked_objects(
18721855
);
18731856
return;
18741857
}
1875-
// TODO: let lto = upstream_rust_objects_already_included && !ignored_for_lto(tcx.sess, &codegen_results.crate_info, cnum);
1858+
// FIXME: should be `let lto = upstream_rust_objects_already_included && !ignored_for_lto(tcx.sess, &codegen_results.crate_info, cnum);`
18761859
let lto = upstream_rust_objects_already_included;
1877-
if lto {
1878-
return;
1860+
let mut cgus = FxHashSet::default();
1861+
for &(symbol, info) in exported_symbols {
1862+
match symbol {
1863+
ExportedSymbol::NonGeneric { cgu: Some(cgu), .. } => {
1864+
if !lto {
1865+
cgus.insert(cgu.as_str().to_string());
1866+
}
1867+
}
1868+
ExportedSymbol::NonGeneric { cgu: None, .. } | ExportedSymbol::NoDefId(..) => {
1869+
// Unresolved symbols may come from external libraries.
1870+
linked_symbols.push((
1871+
symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum),
1872+
info.kind,
1873+
));
1874+
}
1875+
ExportedSymbol::Generic(..)
1876+
| ExportedSymbol::DropGlue(..)
1877+
| ExportedSymbol::AsyncDropGlueCtorShim(..)
1878+
| ExportedSymbol::ThreadLocalShim(..) => {}
1879+
};
18791880
}
1880-
let symbols: Vec<_> = exported_symbols
1881-
.iter()
1882-
.filter(|(_, info)| info.level.is_below_threshold(export_threshold) || info.used)
1883-
.map(|&(symbol, info)| {
1884-
(
1885-
symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum),
1886-
info.kind,
1887-
)
1888-
})
1889-
.collect();
1890-
if symbols.is_empty() {
1881+
if cgus.is_empty() {
18911882
return;
18921883
}
1893-
let used_crate_source = tcx.used_crate_source(cnum);
1894-
let cratepath = &used_crate_source.rlib.as_ref().unwrap().0;
1895-
let mut crate_linked_symbols: FxHashSet<_> =
1896-
symbols.iter().map(|(symbol, _)| symbol.to_string()).collect();
1897-
if let Some(archive_offsets) = add_linked_objects(cratepath, &mut crate_linked_symbols) {
1898-
objects.insert(cnum, archive_offsets);
1899-
}
1900-
// Unresolved symbols may come from external libraries.
1901-
linked_symbols.extend(
1902-
symbols.into_iter().filter(|(symbol, _)| crate_linked_symbols.contains(symbol)),
1903-
);
1884+
objects.insert(cnum, cgus);
19041885
});
19051886

19061887
objects

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
99
use rustc_middle::middle::exported_symbols::{
1010
ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel, metadata_symbol_name,
1111
};
12+
use rustc_middle::mir::mono::{CodegenUnit, MonoItem};
1213
use rustc_middle::query::LocalCrate;
1314
use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, Ty, TyCtxt};
1415
use rustc_middle::util::Providers;
15-
use rustc_session::config::{CrateType, OomStrategy};
16+
use rustc_session::config::{CrateType, OomStrategy, OutputFilenames, OutputType};
17+
use rustc_span::Symbol;
1618
use rustc_target::callconv::Conv;
1719
use rustc_target::spec::{SanitizerSet, TlsModel};
1820
use tracing::debug;
@@ -168,6 +170,36 @@ fn is_reachable_non_generic_provider_extern(tcx: TyCtxt<'_>, def_id: DefId) -> b
168170
tcx.reachable_non_generics(def_id.krate).contains_key(&def_id)
169171
}
170172

173+
fn find_codegen_unit<'tcx>(
174+
tcx: TyCtxt<'tcx>,
175+
codegen_units: &'tcx [CodegenUnit<'tcx>],
176+
outputs: &'tcx OutputFilenames,
177+
def_id: DefId,
178+
) -> Option<Symbol> {
179+
if !tcx.is_codegened_item(def_id) {
180+
return None;
181+
}
182+
let item = if tcx.is_static(def_id) {
183+
MonoItem::Static(def_id)
184+
} else {
185+
MonoItem::Fn(Instance::mono(tcx, def_id))
186+
};
187+
codegen_units.iter().find_map(|cgu| {
188+
if cgu.contains_item(&item) {
189+
Some(Symbol::intern(
190+
outputs
191+
.temp_path(OutputType::Object, Some(cgu.name().as_str()))
192+
.file_name()
193+
.unwrap()
194+
.to_str()
195+
.unwrap(),
196+
))
197+
} else {
198+
None
199+
}
200+
})
201+
}
202+
171203
fn exported_symbols_provider_local(
172204
tcx: TyCtxt<'_>,
173205
_: LocalCrate,
@@ -182,8 +214,20 @@ fn exported_symbols_provider_local(
182214
tcx.reachable_non_generics(LOCAL_CRATE).to_sorted(&hcx, true)
183215
});
184216

185-
let mut symbols: Vec<_> =
186-
sorted.iter().map(|(&def_id, &info)| (ExportedSymbol::NonGeneric(def_id), info)).collect();
217+
let outputs = tcx.output_filenames(());
218+
let codegen_units = tcx.collect_and_partition_mono_items(()).codegen_units;
219+
let mut symbols: Vec<_> = sorted
220+
.iter()
221+
.map(|(&def_id, &info)| {
222+
(
223+
ExportedSymbol::NonGeneric {
224+
def_id,
225+
cgu: find_codegen_unit(tcx, codegen_units, outputs, def_id),
226+
},
227+
info,
228+
)
229+
})
230+
.collect();
187231

188232
// Export TLS shims
189233
if !tcx.sess.target.dll_tls_export {
@@ -433,7 +477,7 @@ fn upstream_monomorphizations_provider(
433477
continue;
434478
}
435479
}
436-
ExportedSymbol::NonGeneric(..)
480+
ExportedSymbol::NonGeneric { .. }
437481
| ExportedSymbol::ThreadLocalShim(..)
438482
| ExportedSymbol::NoDefId(..) => {
439483
// These are no monomorphizations
@@ -545,7 +589,7 @@ pub(crate) fn symbol_name_for_instance_in_crate<'tcx>(
545589
// This is something instantiated in an upstream crate, so we have to use
546590
// the slower (because uncached) version of computing the symbol name.
547591
match symbol {
548-
ExportedSymbol::NonGeneric(def_id) => {
592+
ExportedSymbol::NonGeneric { def_id, .. } => {
549593
rustc_symbol_mangling::symbol_name_for_instance_in_crate(
550594
tcx,
551595
Instance::mono(tcx, def_id),
@@ -590,12 +634,12 @@ fn calling_convention_for_symbol<'tcx>(
590634
symbol: ExportedSymbol<'tcx>,
591635
) -> (Conv, &'tcx [rustc_target::callconv::ArgAbi<'tcx, Ty<'tcx>>]) {
592636
let instance = match symbol {
593-
ExportedSymbol::NonGeneric(def_id) | ExportedSymbol::Generic(def_id, _)
637+
ExportedSymbol::NonGeneric { def_id, .. } | ExportedSymbol::Generic(def_id, _)
594638
if tcx.is_static(def_id) =>
595639
{
596640
None
597641
}
598-
ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)),
642+
ExportedSymbol::NonGeneric { def_id, .. } => Some(Instance::mono(tcx, def_id)),
599643
ExportedSymbol::Generic(def_id, args) => Some(Instance::new(def_id, args)),
600644
// DropGlue always use the Rust calling convention and thus follow the target's default
601645
// symbol decoration scheme.
@@ -711,7 +755,7 @@ fn maybe_emutls_symbol_name<'tcx>(
711755
undecorated: &str,
712756
) -> Option<String> {
713757
if matches!(tcx.sess.tls_model(), TlsModel::Emulated)
714-
&& let ExportedSymbol::NonGeneric(def_id) = symbol
758+
&& let ExportedSymbol::NonGeneric { def_id, .. } = symbol
715759
&& tcx.is_thread_local_static(def_id)
716760
{
717761
// When using emutls, LLVM will add the `__emutls_v.` prefix to thread local symbols,

compiler/rustc_codegen_ssa/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use std::path::{Path, PathBuf};
2727
use std::sync::Arc;
2828

2929
use rustc_ast as ast;
30-
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
30+
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
3131
use rustc_data_structures::unord::UnordMap;
3232
use rustc_hir::CRATE_HIR_ID;
3333
use rustc_hir::def_id::CrateNum;
@@ -194,7 +194,7 @@ pub struct CrateInfo {
194194
pub crate_types: Vec<CrateType>,
195195
pub exported_symbols: UnordMap<CrateType, Vec<String>>,
196196
pub linked_symbols: FxIndexMap<CrateType, Vec<(String, SymbolExportKind)>>,
197-
pub linked_objects: FxIndexMap<CrateType, FxIndexMap<CrateNum, FxIndexSet<u64>>>,
197+
pub linked_objects: FxIndexMap<CrateType, FxIndexMap<CrateNum, FxHashSet<String>>>,
198198
pub local_crate_name: Symbol,
199199
pub compiler_builtins: Option<CrateNum>,
200200
pub profiler_runtime: Option<CrateNum>,

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ provide! { tcx, def_id, other, cdata,
367367
.exported_symbols(cdata.cnum)
368368
.iter()
369369
.filter_map(|&(exported_symbol, export_info)| {
370-
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
370+
if let ExportedSymbol::NonGeneric { def_id, .. } = exported_symbol {
371371
Some((def_id, export_info))
372372
} else {
373373
None

compiler/rustc_middle/src/middle/exported_symbols.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
22
use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable};
3+
use rustc_span::Symbol;
34

45
use crate::ty::{self, GenericArgsRef, Ty, TyCtxt};
56

@@ -40,7 +41,7 @@ pub struct SymbolExportInfo {
4041

4142
#[derive(Eq, PartialEq, Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
4243
pub enum ExportedSymbol<'tcx> {
43-
NonGeneric(DefId),
44+
NonGeneric { def_id: DefId, cgu: Option<Symbol> },
4445
Generic(DefId, GenericArgsRef<'tcx>),
4546
DropGlue(Ty<'tcx>),
4647
AsyncDropGlueCtorShim(Ty<'tcx>),
@@ -53,7 +54,9 @@ impl<'tcx> ExportedSymbol<'tcx> {
5354
/// local crate.
5455
pub fn symbol_name_for_local_instance(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolName<'tcx> {
5556
match *self {
56-
ExportedSymbol::NonGeneric(def_id) => tcx.symbol_name(ty::Instance::mono(tcx, def_id)),
57+
ExportedSymbol::NonGeneric { def_id, .. } => {
58+
tcx.symbol_name(ty::Instance::mono(tcx, def_id))
59+
}
5760
ExportedSymbol::Generic(def_id, args) => {
5861
tcx.symbol_name(ty::Instance::new(def_id, args))
5962
}

src/tools/miri/src/bin/miri.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ use std::num::NonZero;
2929
use std::ops::Range;
3030
use std::path::PathBuf;
3131
use std::str::FromStr;
32-
use std::sync::{Arc, Once};
3332
use std::sync::atomic::{AtomicI32, AtomicU32, Ordering};
33+
use std::sync::{Arc, Once};
3434

3535
use miri::{
3636
BacktraceStyle, BorrowTrackerMethod, MiriConfig, MiriEntryFnType, ProvenanceMode, RetagFields,
@@ -81,7 +81,7 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) {
8181
let sym = tcx.exported_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| {
8282
if sym.symbol_name_for_local_instance(tcx).name == "miri_start" { Some(sym) } else { None }
8383
});
84-
if let Some(ExportedSymbol::NonGeneric(id)) = sym {
84+
if let Some(ExportedSymbol::NonGeneric { def_id: id, .. }) = sym {
8585
let start_def_id = id.expect_local();
8686
let start_span = tcx.def_span(start_def_id);
8787

@@ -265,7 +265,7 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
265265
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
266266
{
267267
Some((
268-
ExportedSymbol::NonGeneric(local_def_id.to_def_id()),
268+
ExportedSymbol::NonGeneric { def_id: local_def_id.to_def_id(), cgu: None },
269269
// Some dummy `SymbolExportInfo` here. We only use
270270
// `exported_symbols` in shims/foreign_items.rs and the export info
271271
// is ignored.

src/tools/miri/src/helpers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ pub fn iter_exported_symbols<'tcx>(
162162
// We can ignore `_export_info` here: we are a Rust crate, and everything is exported
163163
// from a Rust crate.
164164
for &(symbol, _export_info) in tcx.exported_symbols(cnum) {
165-
if let ExportedSymbol::NonGeneric(def_id) = symbol {
165+
if let ExportedSymbol::NonGeneric { def_id, .. } = symbol {
166166
f(cnum, def_id)?;
167167
}
168168
}

0 commit comments

Comments
 (0)