@@ -270,14 +270,8 @@ pub fn each_linked_rlib(
270270
271271 for & cnum in crates {
272272 match fmts. get ( cnum. as_usize ( ) - 1 ) {
273- Some ( & Linkage :: NotLinked | & Linkage :: Dynamic ) => continue ,
274- Some ( & Linkage :: IncludedFromDylib ) => {
275- // We always link crate `compiler_builtins` statically. When enabling LTO, we include it as well.
276- if info. compiler_builtins != Some ( cnum) {
277- continue ;
278- }
279- }
280- Some ( & Linkage :: Static ) => { }
273+ Some ( & Linkage :: NotLinked | & Linkage :: Dynamic | & Linkage :: IncludedFromDylib ) => continue ,
274+ Some ( _) => { }
281275 None => return Err ( errors:: LinkRlibError :: MissingFormat ) ,
282276 }
283277 let crate_name = info. crate_name [ & cnum] ;
@@ -526,7 +520,8 @@ fn link_staticlib<'a>(
526520 & codegen_results. crate_info ,
527521 Some ( CrateType :: Staticlib ) ,
528522 & mut |cnum, path| {
529- let lto = are_upstream_rust_objects_already_included ( sess) ;
523+ let lto = are_upstream_rust_objects_already_included ( sess)
524+ && !ignored_for_lto ( sess, & codegen_results. crate_info , cnum) ;
530525
531526 let native_libs = codegen_results. crate_info . native_libraries [ & cnum] . iter ( ) ;
532527 let relevant = native_libs. clone ( ) . filter ( |lib| relevant_lib ( sess, lib) ) ;
@@ -1261,6 +1256,24 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
12611256 }
12621257}
12631258
1259+ /// Returns a boolean indicating whether the specified crate should be ignored
1260+ /// during LTO.
1261+ ///
1262+ /// Crates ignored during LTO are not lumped together in the "massive object
1263+ /// file" that we create and are linked in their normal rlib states. See
1264+ /// comments below for what crates do not participate in LTO.
1265+ ///
1266+ /// It's unusual for a crate to not participate in LTO. Typically only
1267+ /// compiler-specific and unstable crates have a reason to not participate in
1268+ /// LTO.
1269+ pub fn ignored_for_lto ( sess : & Session , info : & CrateInfo , cnum : CrateNum ) -> bool {
1270+ // If our target enables builtin function lowering in LLVM then the
1271+ // crates providing these functions don't participate in LTO (e.g.
1272+ // no_builtins or compiler builtins crates).
1273+ !sess. target . no_builtins
1274+ && ( info. compiler_builtins == Some ( cnum) || info. is_no_builtins . contains ( & cnum) )
1275+ }
1276+
12641277/// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
12651278pub fn linker_and_flavor ( sess : & Session ) -> ( PathBuf , LinkerFlavor ) {
12661279 fn infer_from (
@@ -2726,6 +2739,10 @@ fn rehome_sysroot_lib_dir<'a>(sess: &'a Session, lib_dir: &Path) -> PathBuf {
27262739// symbols). We must continue to include the rest of the rlib, however, as
27272740// it may contain static native libraries which must be linked in.
27282741//
2742+ // (*) Crates marked with `#![no_builtins]` don't participate in LTO and
2743+ // their bytecode wasn't included. The object files in those libraries must
2744+ // still be passed to the linker.
2745+ //
27292746// Note, however, that if we're not doing LTO we can just pass the rlib
27302747// blindly to the linker (fast) because it's fine if it's not actually
27312748// included as we're at the end of the dependency chain.
@@ -2751,7 +2768,9 @@ fn add_static_crate<'a>(
27512768 cmd. link_rlib ( & rlib_path) ;
27522769 } ;
27532770
2754- if !are_upstream_rust_objects_already_included ( sess) {
2771+ if !are_upstream_rust_objects_already_included ( sess)
2772+ || ignored_for_lto ( sess, & codegen_results. crate_info , cnum)
2773+ {
27552774 link_upstream ( cratepath) ;
27562775 return ;
27572776 }
@@ -2765,6 +2784,8 @@ fn add_static_crate<'a>(
27652784 let canonical_name = name. replace ( '-' , "_" ) ;
27662785 let upstream_rust_objects_already_included =
27672786 are_upstream_rust_objects_already_included ( sess) ;
2787+ let is_builtins =
2788+ sess. target . no_builtins || !codegen_results. crate_info . is_no_builtins . contains ( & cnum) ;
27682789
27692790 let mut archive = archive_builder_builder. new_archive_builder ( sess) ;
27702791 if let Err ( error) = archive. add_archive (
@@ -2781,8 +2802,9 @@ fn add_static_crate<'a>(
27812802
27822803 // If we're performing LTO and this is a rust-generated object
27832804 // file, then we don't need the object file as it's part of the
2784- // LTO module.
2785- if upstream_rust_objects_already_included && is_rust_object {
2805+ // LTO module. Note that `#![no_builtins]` is excluded from LTO,
2806+ // though, so we let that object file slide.
2807+ if upstream_rust_objects_already_included && is_rust_object && is_builtins {
27862808 return true ;
27872809 }
27882810
0 commit comments