about summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa/src
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2022-10-20 18:57:47 +0400
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2022-11-12 23:02:33 +0300
commite792de28c8f753b43d2af5fce662eddef1517aa4 (patch)
treec979d8442f183d4b10739e11cd65f0ca5c205188 /compiler/rustc_codegen_ssa/src
parentcae3c936eb963cedc6523baeeaa9a58d13fa4c2e (diff)
downloadrust-e792de28c8f753b43d2af5fce662eddef1517aa4.tar.gz
rust-e792de28c8f753b43d2af5fce662eddef1517aa4.zip
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
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs101
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs19
2 files changed, 46 insertions, 74 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 2ba8d701189..e7a67bc64e3 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2425,10 +2425,6 @@ fn add_local_native_libraries(
     );
 }
 
-/// # Linking Rust crates and their non-bundled static libraries
-///
-/// Rust crates are not considered at all when creating an rlib output. All dependencies will be
-/// linked when producing the final output (instead of the intermediate rlib version).
 fn add_upstream_rust_crates<'a>(
     cmd: &mut dyn Linker,
     sess: &'a Session,
@@ -2444,7 +2440,6 @@ fn add_upstream_rust_crates<'a>(
     // Linking to a rlib involves just passing it to the linker (the linker
     // will slurp up the object files inside), and linking to a dynamic library
     // involves just passing the right -l flag.
-
     let (_, data) = codegen_results
         .crate_info
         .dependency_formats
@@ -2452,59 +2447,45 @@ fn add_upstream_rust_crates<'a>(
         .find(|(ty, _)| *ty == crate_type)
         .expect("failed to find crate type in dependency format list");
 
-    // Invoke get_used_crates to ensure that we get a topological sorting of
-    // crates.
-    let deps = &codegen_results.crate_info.used_crates;
-
-    let mut compiler_builtins = None;
     let search_paths = OnceCell::new();
-
-    for &cnum in deps.iter() {
-        // We may not pass all crates through to the linker. Some crates may
-        // appear statically in an existing dylib, meaning we'll pick up all the
-        // symbols from the dylib.
+    for &cnum in &codegen_results.crate_info.used_crates {
+        // We may not pass all crates through to the linker. Some crates may appear statically in
+        // an existing dylib, meaning we'll pick up all the symbols from the dylib.
+        // We must always link crates `compiler_builtins` and `profiler_builtins` statically.
+        // Even if they were already included into a dylib
+        // (e.g. `libstd` when `-C prefer-dynamic` is used).
         let linkage = data[cnum.as_usize() - 1];
-        let bundled_libs =
-            if sess.opts.unstable_opts.packed_bundled_libs && linkage == Linkage::Static {
-                codegen_results.crate_info.native_libraries[&cnum]
-                    .iter()
-                    .filter_map(|lib| lib.filename)
-                    .collect::<FxHashSet<_>>()
-            } else {
-                Default::default()
-            };
+        let link_static_crate = linkage == Linkage::Static
+            || linkage == Linkage::IncludedFromDylib
+                && (codegen_results.crate_info.compiler_builtins == Some(cnum)
+                    || codegen_results.crate_info.profiler_runtime == Some(cnum));
+
+        let mut bundled_libs = Default::default();
         match linkage {
-            _ if codegen_results.crate_info.profiler_runtime == Some(cnum) => {
-                add_static_crate(
-                    cmd,
-                    sess,
-                    archive_builder_builder,
-                    codegen_results,
-                    tmpdir,
-                    cnum,
-                    &Default::default(),
-                );
-            }
-            // compiler-builtins are always placed last to ensure that they're
-            // linked correctly.
-            _ if codegen_results.crate_info.compiler_builtins == Some(cnum) => {
-                assert!(compiler_builtins.is_none());
-                compiler_builtins = Some(cnum);
+            Linkage::Static | Linkage::IncludedFromDylib => {
+                if link_static_crate {
+                    if sess.opts.unstable_opts.packed_bundled_libs {
+                        bundled_libs = codegen_results.crate_info.native_libraries[&cnum]
+                            .iter()
+                            .filter_map(|lib| lib.filename)
+                            .collect();
+                    }
+                    add_static_crate(
+                        cmd,
+                        sess,
+                        archive_builder_builder,
+                        codegen_results,
+                        tmpdir,
+                        cnum,
+                        &bundled_libs,
+                    );
+                }
             }
-            Linkage::NotLinked | Linkage::IncludedFromDylib => {}
-            Linkage::Static => add_static_crate(
-                cmd,
-                sess,
-                archive_builder_builder,
-                codegen_results,
-                tmpdir,
-                cnum,
-                &bundled_libs,
-            ),
             Linkage::Dynamic => {
                 let src = &codegen_results.crate_info.used_crate_source[&cnum];
                 add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0);
             }
+            Linkage::NotLinked => {}
         }
 
         // Static libraries are linked for a subset of linked upstream crates.
@@ -2514,7 +2495,8 @@ fn add_upstream_rust_crates<'a>(
         // the native library because it is already linked into the dylib, and even if
         // inline/const/generic functions from the dylib can refer to symbols from the native
         // library, those symbols should be exported and available from the dylib anyway.
-        let link_static = linkage == Linkage::Static;
+        // 3. Libraries bundled into `(compiler,profiler)_builtins` are special, see above.
+        let link_static = link_static_crate;
         // Dynamic libraries are not linked here, see the FIXME in `add_upstream_native_libraries`.
         let link_dynamic = false;
         add_native_libs_from_crate(
@@ -2531,23 +2513,6 @@ fn add_upstream_rust_crates<'a>(
         );
     }
 
-    // compiler-builtins are always placed last to ensure that they're
-    // linked correctly.
-    // We must always link the `compiler_builtins` crate statically. Even if it
-    // was already "included" in a dylib (e.g., `libstd` when `-C prefer-dynamic`
-    // is used)
-    if let Some(cnum) = compiler_builtins {
-        add_static_crate(
-            cmd,
-            sess,
-            archive_builder_builder,
-            codegen_results,
-            tmpdir,
-            cnum,
-            &Default::default(),
-        );
-    }
-
     // Converts a library file-stem into a cc -l argument
     fn unlib<'a>(target: &Target, stem: &'a str) -> &'a str {
         if stem.starts_with("lib") && !target.is_like_windows { &stem[3..] } else { stem }
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index c1411690f82..4f396e970ad 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -833,20 +833,30 @@ impl CrateInfo {
         //
         // In order to get this left-to-right dependency ordering, we use the reverse
         // postorder of all crates putting the leaves at the right-most positions.
-        let used_crates = tcx
+        let mut compiler_builtins = None;
+        let mut used_crates: Vec<_> = tcx
             .postorder_cnums(())
             .iter()
             .rev()
             .copied()
-            .filter(|&cnum| !tcx.dep_kind(cnum).macros_only())
+            .filter(|&cnum| {
+                let link = !tcx.dep_kind(cnum).macros_only();
+                if link && tcx.is_compiler_builtins(cnum) {
+                    compiler_builtins = Some(cnum);
+                    return false;
+                }
+                link
+            })
             .collect();
+        // `compiler_builtins` are always placed last to ensure that they're linked correctly.
+        used_crates.extend(compiler_builtins);
 
         let mut info = CrateInfo {
             target_cpu,
             exported_symbols,
             linked_symbols,
             local_crate_name,
-            compiler_builtins: None,
+            compiler_builtins,
             profiler_runtime: None,
             is_no_builtins: Default::default(),
             native_libraries: Default::default(),
@@ -872,9 +882,6 @@ impl CrateInfo {
 
             let used_crate_source = tcx.used_crate_source(cnum);
             info.used_crate_source.insert(cnum, used_crate_source.clone());
-            if tcx.is_compiler_builtins(cnum) {
-                info.compiler_builtins = Some(cnum);
-            }
             if tcx.is_profiler_runtime(cnum) {
                 info.profiler_runtime = Some(cnum);
             }