Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c37dd0d

Browse files
committed
Auto 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 f73bcd5 + f4888c2 commit c37dd0d

File tree

6 files changed

+97
-39
lines changed

6 files changed

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

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /