Skip to content

Commit 4f1bb1c

Browse files
committed
Ensure we emit an allocator shim when only some crate types need one
1 parent 43a2166 commit 4f1bb1c

File tree

3 files changed

+50
-9
lines changed

3 files changed

+50
-9
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

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

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

@@ -2280,7 +2289,7 @@ fn linker_with_args(
22802289
codegen_results,
22812290
metadata,
22822291
);
2283-
add_local_crate_allocator_objects(cmd, codegen_results);
2292+
add_local_crate_allocator_objects(cmd, codegen_results, crate_type);
22842293

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

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)