Skip to content

Commit db16909

Browse files
author
Jorge Aparicio
committed
exclude #![no_builtins] crates from LTO
this prevents intrinsics like `memcpy` from being mis-optimized to infinite recursive calls when LTO is used. fixes #31544 closes #35540
1 parent 8787a12 commit db16909

File tree

2 files changed

+28
-11
lines changed

2 files changed

+28
-11
lines changed

src/librustc_trans/back/link.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use std::process::Command;
4242
use std::str;
4343
use flate;
4444
use syntax::ast;
45-
use syntax::attr::AttrMetaMethods;
45+
use syntax::attr::{self, AttrMetaMethods};
4646
use syntax_pos::Span;
4747

4848
// RLIB LLVM-BYTECODE OBJECT LAYOUT
@@ -938,8 +938,10 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
938938
Linkage::NotLinked |
939939
Linkage::IncludedFromDylib => {}
940940
Linkage::Static => {
941+
let is_a_no_builtins_crate =
942+
attr::contains_name(&sess.cstore.crate_attrs(cnum), "no_builtins");
941943
add_static_crate(cmd, sess, tmpdir, crate_type,
942-
&src.rlib.unwrap().0)
944+
&src.rlib.unwrap().0, is_a_no_builtins_crate)
943945
}
944946
Linkage::Dynamic => {
945947
add_dynamic_crate(cmd, sess, &src.dylib.unwrap().0)
@@ -963,12 +965,16 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
963965
// * For LTO, we remove upstream object files.
964966
// * For dylibs we remove metadata and bytecode from upstream rlibs
965967
//
966-
// When performing LTO, all of the bytecode from the upstream libraries has
967-
// already been included in our object file output. As a result we need to
968-
// remove the object files in the upstream libraries so the linker doesn't
969-
// try to include them twice (or whine about duplicate symbols). We must
970-
// continue to include the rest of the rlib, however, as it may contain
971-
// static native libraries which must be linked in.
968+
// When performing LTO, almost(*) all of the bytecode from the upstream
969+
// libraries has already been included in our object file output. As a
970+
// result we need to remove the object files in the upstream libraries so
971+
// the linker doesn't try to include them twice (or whine about duplicate
972+
// symbols). We must continue to include the rest of the rlib, however, as
973+
// it may contain static native libraries which must be linked in.
974+
//
975+
// (*) Crates marked with `#![no_builtins]` don't participate in LTO and
976+
// their bytecode wasn't included. The object files in those libraries must
977+
// still be passed to the linker.
972978
//
973979
// When making a dynamic library, linkers by default don't include any
974980
// object files in an archive if they're not necessary to resolve the link.
@@ -988,7 +994,8 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
988994
sess: &Session,
989995
tmpdir: &Path,
990996
crate_type: config::CrateType,
991-
cratepath: &Path) {
997+
cratepath: &Path,
998+
is_a_no_builtins_crate: bool) {
992999
if !sess.lto() && crate_type != config::CrateTypeDylib {
9931000
cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath));
9941001
return
@@ -1012,7 +1019,8 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
10121019
}
10131020
let canonical = f.replace("-", "_");
10141021
let canonical_name = name.replace("-", "_");
1015-
if sess.lto() && canonical.starts_with(&canonical_name) &&
1022+
if sess.lto() && !is_a_no_builtins_crate &&
1023+
canonical.starts_with(&canonical_name) &&
10161024
canonical.ends_with(".o") {
10171025
let num = &f[name.len()..f.len() - 2];
10181026
if num.len() > 0 && num[1..].parse::<u32>().is_ok() {

src/librustc_trans/back/lto.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use llvm::{ModuleRef, TargetMachineRef, True, False};
1717
use rustc::util::common::time;
1818
use rustc::util::common::path2cstr;
1919
use back::write::{ModuleConfig, with_llvm_pmb};
20+
use syntax::attr;
2021

2122
use libc;
2223
use flate;
@@ -52,7 +53,15 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
5253
// For each of our upstream dependencies, find the corresponding rlib and
5354
// load the bitcode from the archive. Then merge it into the current LLVM
5455
// module that we've got.
55-
link::each_linked_rlib(sess, &mut |_, path| {
56+
link::each_linked_rlib(sess, &mut |cnum, path| {
57+
let is_a_no_builtins_crate =
58+
attr::contains_name(&sess.cstore.crate_attrs(cnum), "no_builtins");
59+
60+
// `#![no_builtins]` crates don't participate in LTO.
61+
if is_a_no_builtins_crate {
62+
return;
63+
}
64+
5665
let archive = ArchiveRO::open(&path).expect("wanted an rlib");
5766
let bytecodes = archive.iter().filter_map(|child| {
5867
child.ok().and_then(|c| c.name().map(|name| (name, c)))

0 commit comments

Comments
 (0)