Skip to content

Commit 4ecbd4f

Browse files
authored
Unrolled build for #145962
Rollup merge of #145962 - bjorn3:linkage_fixes, r=WaffleLapkin Ensure we emit an allocator shim when only some crate types need one Found this while trying to write a test for #145955.
2 parents 9385c64 + 0711bba commit 4ecbd4f

File tree

6 files changed

+98
-39
lines changed

6 files changed

+98
-39
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ use super::linker::{self, Linker};
5858
use super::metadata::{MetadataPosition, create_wrapper_file};
5959
use super::rpath::{self, RPathConfig};
6060
use super::{apple, versioned_llvm_target};
61+
use crate::base::needs_allocator_shim_for_linking;
6162
use crate::{
6263
CodegenResults, CompiledModule, CrateInfo, NativeLib, errors, looks_like_rust_object_file,
6364
};
@@ -2080,9 +2081,17 @@ fn add_local_crate_regular_objects(cmd: &mut dyn Linker, codegen_results: &Codeg
20802081
}
20812082

20822083
/// Add object files for allocator code linked once for the whole crate tree.
2083-
fn add_local_crate_allocator_objects(cmd: &mut dyn Linker, codegen_results: &CodegenResults) {
2084-
if let Some(obj) = codegen_results.allocator_module.as_ref().and_then(|m| m.object.as_ref()) {
2085-
cmd.add_object(obj);
2084+
fn add_local_crate_allocator_objects(
2085+
cmd: &mut dyn Linker,
2086+
codegen_results: &CodegenResults,
2087+
crate_type: CrateType,
2088+
) {
2089+
if needs_allocator_shim_for_linking(&codegen_results.crate_info.dependency_formats, crate_type)
2090+
{
2091+
if let Some(obj) = codegen_results.allocator_module.as_ref().and_then(|m| m.object.as_ref())
2092+
{
2093+
cmd.add_object(obj);
2094+
}
20862095
}
20872096
}
20882097

@@ -2281,7 +2290,7 @@ fn linker_with_args(
22812290
codegen_results,
22822291
metadata,
22832292
);
2284-
add_local_crate_allocator_objects(cmd, codegen_results);
2293+
add_local_crate_allocator_objects(cmd, codegen_results, crate_type);
22852294

22862295
// Avoid linking to dynamic libraries unless they satisfy some undefined symbols
22872296
// at the point at which they are specified on the command line.

compiler/rustc_codegen_ssa/src/back/linker.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ use rustc_metadata::{
1111
};
1212
use rustc_middle::bug;
1313
use rustc_middle::middle::dependency_format::Linkage;
14-
use rustc_middle::middle::exported_symbols;
15-
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportKind};
14+
use rustc_middle::middle::exported_symbols::{
15+
self, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
16+
};
1617
use rustc_middle::ty::TyCtxt;
1718
use rustc_session::Session;
1819
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
@@ -22,6 +23,8 @@ use tracing::{debug, warn};
2223

2324
use super::command::Command;
2425
use super::symbol_export;
26+
use crate::back::symbol_export::allocator_shim_symbols;
27+
use crate::base::needs_allocator_shim_for_linking;
2528
use crate::errors;
2629

2730
#[cfg(test)]
@@ -1827,7 +1830,7 @@ fn exported_symbols_for_non_proc_macro(
18271830
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
18281831
for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
18291832
// Do not export mangled symbols from cdylibs and don't attempt to export compiler-builtins
1830-
// from any cdylib. The latter doesn't work anyway as we use hidden visibility for
1833+
// from any dylib. The latter doesn't work anyway as we use hidden visibility for
18311834
// compiler-builtins. Most linkers silently ignore it, but ld64 gives a warning.
18321835
if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum) {
18331836
symbols.push((
@@ -1838,6 +1841,14 @@ fn exported_symbols_for_non_proc_macro(
18381841
}
18391842
});
18401843

1844+
// Mark allocator shim symbols as exported only if they were generated.
1845+
if export_threshold == SymbolExportLevel::Rust
1846+
&& needs_allocator_shim_for_linking(tcx.dependency_formats(()), crate_type)
1847+
&& tcx.allocator_kind(()).is_some()
1848+
{
1849+
symbols.extend(allocator_shim_symbols(tcx));
1850+
}
1851+
18411852
symbols
18421853
}
18431854

compiler/rustc_codegen_ssa/src/back/lto.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ use rustc_middle::ty::TyCtxt;
88
use rustc_session::config::{CrateType, Lto};
99
use tracing::info;
1010

11-
use crate::back::symbol_export::{self, symbol_name_for_instance_in_crate};
11+
use crate::back::symbol_export::{self, allocator_shim_symbols, symbol_name_for_instance_in_crate};
1212
use crate::back::write::CodegenContext;
13+
use crate::base::allocator_kind_for_codegen;
1314
use crate::errors::{DynamicLinkingWithLTO, LtoDisallowed, LtoDylib, LtoProcMacro};
1415
use crate::traits::*;
1516

@@ -115,6 +116,11 @@ pub(super) fn exported_symbols_for_lto(
115116
}
116117
}
117118

119+
// Mark allocator shim symbols as exported only if they were generated.
120+
if export_threshold == SymbolExportLevel::Rust && allocator_kind_for_codegen(tcx).is_some() {
121+
symbols_below_threshold.extend(allocator_shim_symbols(tcx).map(|(name, _kind)| name));
122+
}
123+
118124
symbols_below_threshold
119125
}
120126

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_symbol_mangling::mangle_internal_symbol;
1818
use rustc_target::spec::TlsModel;
1919
use tracing::debug;
2020

21-
use crate::base::allocator_kind_for_codegen;
21+
use crate::back::symbol_export;
2222

2323
fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
2424
crates_export_threshold(tcx.crate_types())
@@ -217,31 +217,6 @@ fn exported_non_generic_symbols_provider_local<'tcx>(
217217
));
218218
}
219219

220-
// Mark allocator shim symbols as exported only if they were generated.
221-
if allocator_kind_for_codegen(tcx).is_some() {
222-
for symbol_name in ALLOCATOR_METHODS
223-
.iter()
224-
.map(|method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str()))
225-
.chain([
226-
mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
227-
mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
228-
mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE),
229-
])
230-
{
231-
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));
232-
233-
symbols.push((
234-
exported_symbol,
235-
SymbolExportInfo {
236-
level: SymbolExportLevel::Rust,
237-
kind: SymbolExportKind::Text,
238-
used: false,
239-
rustc_std_internal_symbol: true,
240-
},
241-
));
242-
}
243-
}
244-
245220
// Sort so we get a stable incr. comp. hash.
246221
symbols.sort_by_cached_key(|s| s.0.symbol_name_for_local_instance(tcx));
247222

@@ -516,6 +491,31 @@ pub(crate) fn provide(providers: &mut Providers) {
516491
upstream_monomorphizations_for_provider;
517492
}
518493

494+
pub(crate) fn allocator_shim_symbols(
495+
tcx: TyCtxt<'_>,
496+
) -> impl Iterator<Item = (String, SymbolExportKind)> {
497+
ALLOCATOR_METHODS
498+
.iter()
499+
.map(move |method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str()))
500+
.chain([
501+
mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
502+
mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
503+
mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE),
504+
])
505+
.map(move |symbol_name| {
506+
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));
507+
508+
(
509+
symbol_export::exporting_symbol_name_for_instance_in_crate(
510+
tcx,
511+
exported_symbol,
512+
LOCAL_CRATE,
513+
),
514+
SymbolExportKind::Text,
515+
)
516+
})
517+
}
518+
519519
fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel {
520520
// We export anything that's not mangled at the "C" layer as it probably has
521521
// to do with ABI concerns. We do not, however, apply such treatment to

compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc_hir::lang_items::LangItem;
1717
use rustc_hir::{ItemId, Target};
1818
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
1919
use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
20+
use rustc_middle::middle::dependency_format::Dependencies;
2021
use rustc_middle::middle::exported_symbols::{self, SymbolExportKind};
2122
use rustc_middle::middle::lang_items;
2223
use rustc_middle::mir::BinOp;
@@ -630,14 +631,30 @@ pub fn allocator_kind_for_codegen(tcx: TyCtxt<'_>) -> Option<AllocatorKind> {
630631
// If the crate doesn't have an `allocator_kind` set then there's definitely
631632
// no shim to generate. Otherwise we also check our dependency graph for all
632633
// our output crate types. If anything there looks like its a `Dynamic`
633-
// linkage, then it's already got an allocator shim and we'll be using that
634-
// one instead. If nothing exists then it's our job to generate the
635-
// allocator!
636-
let any_dynamic_crate = tcx.dependency_formats(()).iter().any(|(_, list)| {
634+
// linkage for all crate types we may link as, then it's already got an
635+
// allocator shim and we'll be using that one instead. If nothing exists
636+
// then it's our job to generate the allocator! If crate types disagree
637+
// about whether an allocator shim is necessary or not, we generate one
638+
// and let needs_allocator_shim_for_linking decide at link time whether or
639+
// not to use it for any particular linker invocation.
640+
let all_crate_types_any_dynamic_crate = tcx.dependency_formats(()).iter().all(|(_, list)| {
637641
use rustc_middle::middle::dependency_format::Linkage;
638642
list.iter().any(|&linkage| linkage == Linkage::Dynamic)
639643
});
640-
if any_dynamic_crate { None } else { tcx.allocator_kind(()) }
644+
if all_crate_types_any_dynamic_crate { None } else { tcx.allocator_kind(()) }
645+
}
646+
647+
/// Decide if this particular crate type needs an allocator shim linked in.
648+
/// This may return true even when allocator_kind_for_codegen returns false. In
649+
/// this case no allocator shim shall be linked.
650+
pub(crate) fn needs_allocator_shim_for_linking(
651+
dependency_formats: &Dependencies,
652+
crate_type: CrateType,
653+
) -> bool {
654+
use rustc_middle::middle::dependency_format::Linkage;
655+
let any_dynamic_crate =
656+
dependency_formats[&crate_type].iter().any(|&linkage| linkage == Linkage::Dynamic);
657+
!any_dynamic_crate
641658
}
642659

643660
pub fn codegen_crate<B: ExtraBackendMethods>(
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ build-pass
2+
//@ compile-flags: --crate-type staticlib,dylib -Zstaticlib-prefer-dynamic
3+
//@ no-prefer-dynamic
4+
//@ needs-crate-type: dylib
5+
6+
// Test that compiling for multiple crate types in a single compilation with
7+
// mismatching allocator shim requirements doesn't result in the allocator shim
8+
// missing entirely.
9+
// In this particular test the dylib crate type will statically link libstd and
10+
// thus need an allocator shim, while the staticlib crate type will dynamically
11+
// link libstd and thus not need an allocator shim.
12+
// The -Zstaticlib-prefer-dynamic flag could be avoided by doing it the other
13+
// way around, but testing that the staticlib correctly has the allocator shim
14+
// in that case would require a run-make test instead.
15+
16+
pub fn foo() {}

0 commit comments

Comments
 (0)