Skip to content

Commit e792de2

Browse files
committed
linker: Simplify linking of compiler_builtins and profiler_builtins
This also fixes linking of native libraries bundled into these crates when `-Zpacked-bundled-libs` is enabled
1 parent cae3c93 commit e792de2

File tree

2 files changed

+46
-74
lines changed

2 files changed

+46
-74
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 33 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2425,10 +2425,6 @@ fn add_local_native_libraries(
24252425
);
24262426
}
24272427

2428-
/// # Linking Rust crates and their non-bundled static libraries
2429-
///
2430-
/// Rust crates are not considered at all when creating an rlib output. All dependencies will be
2431-
/// linked when producing the final output (instead of the intermediate rlib version).
24322428
fn add_upstream_rust_crates<'a>(
24332429
cmd: &mut dyn Linker,
24342430
sess: &'a Session,
@@ -2444,67 +2440,52 @@ fn add_upstream_rust_crates<'a>(
24442440
// Linking to a rlib involves just passing it to the linker (the linker
24452441
// will slurp up the object files inside), and linking to a dynamic library
24462442
// involves just passing the right -l flag.
2447-
24482443
let (_, data) = codegen_results
24492444
.crate_info
24502445
.dependency_formats
24512446
.iter()
24522447
.find(|(ty, _)| *ty == crate_type)
24532448
.expect("failed to find crate type in dependency format list");
24542449

2455-
// Invoke get_used_crates to ensure that we get a topological sorting of
2456-
// crates.
2457-
let deps = &codegen_results.crate_info.used_crates;
2458-
2459-
let mut compiler_builtins = None;
24602450
let search_paths = OnceCell::new();
2461-
2462-
for &cnum in deps.iter() {
2463-
// We may not pass all crates through to the linker. Some crates may
2464-
// appear statically in an existing dylib, meaning we'll pick up all the
2465-
// symbols from the dylib.
2451+
for &cnum in &codegen_results.crate_info.used_crates {
2452+
// We may not pass all crates through to the linker. Some crates may appear statically in
2453+
// an existing dylib, meaning we'll pick up all the symbols from the dylib.
2454+
// We must always link crates `compiler_builtins` and `profiler_builtins` statically.
2455+
// Even if they were already included into a dylib
2456+
// (e.g. `libstd` when `-C prefer-dynamic` is used).
24662457
let linkage = data[cnum.as_usize() - 1];
2467-
let bundled_libs =
2468-
if sess.opts.unstable_opts.packed_bundled_libs && linkage == Linkage::Static {
2469-
codegen_results.crate_info.native_libraries[&cnum]
2470-
.iter()
2471-
.filter_map(|lib| lib.filename)
2472-
.collect::<FxHashSet<_>>()
2473-
} else {
2474-
Default::default()
2475-
};
2458+
let link_static_crate = linkage == Linkage::Static
2459+
|| linkage == Linkage::IncludedFromDylib
2460+
&& (codegen_results.crate_info.compiler_builtins == Some(cnum)
2461+
|| codegen_results.crate_info.profiler_runtime == Some(cnum));
2462+
2463+
let mut bundled_libs = Default::default();
24762464
match linkage {
2477-
_ if codegen_results.crate_info.profiler_runtime == Some(cnum) => {
2478-
add_static_crate(
2479-
cmd,
2480-
sess,
2481-
archive_builder_builder,
2482-
codegen_results,
2483-
tmpdir,
2484-
cnum,
2485-
&Default::default(),
2486-
);
2487-
}
2488-
// compiler-builtins are always placed last to ensure that they're
2489-
// linked correctly.
2490-
_ if codegen_results.crate_info.compiler_builtins == Some(cnum) => {
2491-
assert!(compiler_builtins.is_none());
2492-
compiler_builtins = Some(cnum);
2465+
Linkage::Static | Linkage::IncludedFromDylib => {
2466+
if link_static_crate {
2467+
if sess.opts.unstable_opts.packed_bundled_libs {
2468+
bundled_libs = codegen_results.crate_info.native_libraries[&cnum]
2469+
.iter()
2470+
.filter_map(|lib| lib.filename)
2471+
.collect();
2472+
}
2473+
add_static_crate(
2474+
cmd,
2475+
sess,
2476+
archive_builder_builder,
2477+
codegen_results,
2478+
tmpdir,
2479+
cnum,
2480+
&bundled_libs,
2481+
);
2482+
}
24932483
}
2494-
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
2495-
Linkage::Static => add_static_crate(
2496-
cmd,
2497-
sess,
2498-
archive_builder_builder,
2499-
codegen_results,
2500-
tmpdir,
2501-
cnum,
2502-
&bundled_libs,
2503-
),
25042484
Linkage::Dynamic => {
25052485
let src = &codegen_results.crate_info.used_crate_source[&cnum];
25062486
add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0);
25072487
}
2488+
Linkage::NotLinked => {}
25082489
}
25092490

25102491
// Static libraries are linked for a subset of linked upstream crates.
@@ -2514,7 +2495,8 @@ fn add_upstream_rust_crates<'a>(
25142495
// the native library because it is already linked into the dylib, and even if
25152496
// inline/const/generic functions from the dylib can refer to symbols from the native
25162497
// library, those symbols should be exported and available from the dylib anyway.
2517-
let link_static = linkage == Linkage::Static;
2498+
// 3. Libraries bundled into `(compiler,profiler)_builtins` are special, see above.
2499+
let link_static = link_static_crate;
25182500
// Dynamic libraries are not linked here, see the FIXME in `add_upstream_native_libraries`.
25192501
let link_dynamic = false;
25202502
add_native_libs_from_crate(
@@ -2531,23 +2513,6 @@ fn add_upstream_rust_crates<'a>(
25312513
);
25322514
}
25332515

2534-
// compiler-builtins are always placed last to ensure that they're
2535-
// linked correctly.
2536-
// We must always link the `compiler_builtins` crate statically. Even if it
2537-
// was already "included" in a dylib (e.g., `libstd` when `-C prefer-dynamic`
2538-
// is used)
2539-
if let Some(cnum) = compiler_builtins {
2540-
add_static_crate(
2541-
cmd,
2542-
sess,
2543-
archive_builder_builder,
2544-
codegen_results,
2545-
tmpdir,
2546-
cnum,
2547-
&Default::default(),
2548-
);
2549-
}
2550-
25512516
// Converts a library file-stem into a cc -l argument
25522517
fn unlib<'a>(target: &Target, stem: &'a str) -> &'a str {
25532518
if stem.starts_with("lib") && !target.is_like_windows { &stem[3..] } else { stem }

compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -833,20 +833,30 @@ impl CrateInfo {
833833
//
834834
// In order to get this left-to-right dependency ordering, we use the reverse
835835
// postorder of all crates putting the leaves at the right-most positions.
836-
let used_crates = tcx
836+
let mut compiler_builtins = None;
837+
let mut used_crates: Vec<_> = tcx
837838
.postorder_cnums(())
838839
.iter()
839840
.rev()
840841
.copied()
841-
.filter(|&cnum| !tcx.dep_kind(cnum).macros_only())
842+
.filter(|&cnum| {
843+
let link = !tcx.dep_kind(cnum).macros_only();
844+
if link && tcx.is_compiler_builtins(cnum) {
845+
compiler_builtins = Some(cnum);
846+
return false;
847+
}
848+
link
849+
})
842850
.collect();
851+
// `compiler_builtins` are always placed last to ensure that they're linked correctly.
852+
used_crates.extend(compiler_builtins);
843853

844854
let mut info = CrateInfo {
845855
target_cpu,
846856
exported_symbols,
847857
linked_symbols,
848858
local_crate_name,
849-
compiler_builtins: None,
859+
compiler_builtins,
850860
profiler_runtime: None,
851861
is_no_builtins: Default::default(),
852862
native_libraries: Default::default(),
@@ -872,9 +882,6 @@ impl CrateInfo {
872882

873883
let used_crate_source = tcx.used_crate_source(cnum);
874884
info.used_crate_source.insert(cnum, used_crate_source.clone());
875-
if tcx.is_compiler_builtins(cnum) {
876-
info.compiler_builtins = Some(cnum);
877-
}
878885
if tcx.is_profiler_runtime(cnum) {
879886
info.profiler_runtime = Some(cnum);
880887
}

0 commit comments

Comments
 (0)