@@ -270,14 +270,8 @@ pub fn each_linked_rlib(
270
270
271
271
for & cnum in crates {
272
272
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 ( _) => { }
281
275
None => return Err ( errors:: LinkRlibError :: MissingFormat ) ,
282
276
}
283
277
let crate_name = info. crate_name [ & cnum] ;
@@ -526,7 +520,8 @@ fn link_staticlib<'a>(
526
520
& codegen_results. crate_info ,
527
521
Some ( CrateType :: Staticlib ) ,
528
522
& 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) ;
530
525
531
526
let native_libs = codegen_results. crate_info . native_libraries [ & cnum] . iter ( ) ;
532
527
let relevant = native_libs. clone ( ) . filter ( |lib| relevant_lib ( sess, lib) ) ;
@@ -1277,6 +1272,24 @@ fn link_sanitizer_runtime(
1277
1272
}
1278
1273
}
1279
1274
1275
+ /// Returns a boolean indicating whether the specified crate should be ignored
1276
+ /// during LTO.
1277
+ ///
1278
+ /// Crates ignored during LTO are not lumped together in the "massive object
1279
+ /// file" that we create and are linked in their normal rlib states. See
1280
+ /// comments below for what crates do not participate in LTO.
1281
+ ///
1282
+ /// It's unusual for a crate to not participate in LTO. Typically only
1283
+ /// compiler-specific and unstable crates have a reason to not participate in
1284
+ /// LTO.
1285
+ pub fn ignored_for_lto ( sess : & Session , info : & CrateInfo , cnum : CrateNum ) -> bool {
1286
+ // If our target enables builtin function lowering in LLVM then the
1287
+ // crates providing these functions don't participate in LTO (e.g.
1288
+ // no_builtins or compiler builtins crates).
1289
+ !sess. target . no_builtins
1290
+ && ( info. compiler_builtins == Some ( cnum) || info. is_no_builtins . contains ( & cnum) )
1291
+ }
1292
+
1280
1293
/// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
1281
1294
pub fn linker_and_flavor ( sess : & Session ) -> ( PathBuf , LinkerFlavor ) {
1282
1295
fn infer_from (
@@ -2742,6 +2755,10 @@ fn rehome_sysroot_lib_dir<'a>(sess: &'a Session, lib_dir: &Path) -> PathBuf {
2742
2755
// symbols). We must continue to include the rest of the rlib, however, as
2743
2756
// it may contain static native libraries which must be linked in.
2744
2757
//
2758
+ // (*) Crates marked with `#![no_builtins]` don't participate in LTO and
2759
+ // their bytecode wasn't included. The object files in those libraries must
2760
+ // still be passed to the linker.
2761
+ //
2745
2762
// Note, however, that if we're not doing LTO we can just pass the rlib
2746
2763
// blindly to the linker (fast) because it's fine if it's not actually
2747
2764
// included as we're at the end of the dependency chain.
@@ -2767,7 +2784,9 @@ fn add_static_crate<'a>(
2767
2784
cmd. link_rlib ( & rlib_path) ;
2768
2785
} ;
2769
2786
2770
- if !are_upstream_rust_objects_already_included ( sess) {
2787
+ if !are_upstream_rust_objects_already_included ( sess)
2788
+ || ignored_for_lto ( sess, & codegen_results. crate_info , cnum)
2789
+ {
2771
2790
link_upstream ( cratepath) ;
2772
2791
return ;
2773
2792
}
@@ -2781,6 +2800,8 @@ fn add_static_crate<'a>(
2781
2800
let canonical_name = name. replace ( '-' , "_" ) ;
2782
2801
let upstream_rust_objects_already_included =
2783
2802
are_upstream_rust_objects_already_included ( sess) ;
2803
+ let is_builtins =
2804
+ sess. target . no_builtins || !codegen_results. crate_info . is_no_builtins . contains ( & cnum) ;
2784
2805
2785
2806
let mut archive = archive_builder_builder. new_archive_builder ( sess) ;
2786
2807
if let Err ( error) = archive. add_archive (
@@ -2797,8 +2818,9 @@ fn add_static_crate<'a>(
2797
2818
2798
2819
// If we're performing LTO and this is a rust-generated object
2799
2820
// file, then we don't need the object file as it's part of the
2800
- // LTO module.
2801
- if upstream_rust_objects_already_included && is_rust_object {
2821
+ // LTO module. Note that `#![no_builtins]` is excluded from LTO,
2822
+ // though, so we let that object file slide.
2823
+ if upstream_rust_objects_already_included && is_rust_object && is_builtins {
2802
2824
return true ;
2803
2825
}
2804
2826
0 commit comments