about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2020-05-22 11:32:25 +0200
committerGitHub <noreply@github.com>2020-05-22 11:32:25 +0200
commit1119421e26da4e8cb530e14557b49c96c025f7ff (patch)
tree1eb1bf66c68d7c5d4314a9e1d481dfbc30ed023f
parent62d4e9eedd384c3a32c55dad71dc04c8891d550e (diff)
parentcc91041f26fa90920cc96c13c431610153a61586 (diff)
downloadrust-1119421e26da4e8cb530e14557b49c96c025f7ff.tar.gz
rust-1119421e26da4e8cb530e14557b49c96c025f7ff.zip
Rollup merge of #72325 - alexcrichton:ignore-linker-plugin-lto, r=nnethercote
Always generated object code for `#![no_builtins]`

This commit updates the code generation for `#![no_builtins]` to always
produce object files instead of conditionally respecting
`-Clinker-plugin-lto` and sometimes producing bitcode. This is intended
to address rust-lang/cargo#8239.

The issue at hand here is that Cargo has tried to get "smarter" about
codegen in whole crate graph scenarios. When LTO is enabled it attempts
to avoid codegen on as many crates as possible, opting to pass
`-Clinker-plugin-lto` where it can to only generate bitcode. When this
is combined with `-Zbuild-std`, however, it means that
`compiler-builtins` only generates LLVM bitcode instead of object files.
Rustc's own LTO passes then explicitly skip `compiler-builtins` (because
it wouldn't work anyway) which means that LLVM bitcode gets sent to the
linker, which chokes most of the time.

The fix in this PR is to not actually respect `-Clinker-plugin-lto` for
`#![no_builtins]` crates. These crates, even if slurped up by the linker
rather than rustc, will not work with LTO. They define symbols which are
only referenced as part of codegen, so LTO's aggressive internalization
would trivially remove the symbols only to have the linker realize later
that the symbol is undefined. Since pure-bitcode never makes sense for
these libraries, the `-Clinker-plugin-lto` flag is silently ignored.
-rw-r--r--src/librustc_codegen_ssa/back/write.rs16
1 files changed, 15 insertions, 1 deletions
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 53dfe7cb749..f9ee7d8c5de 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -142,8 +142,22 @@ impl ModuleConfig {
         let emit_obj = if !should_emit_obj {
             EmitObj::None
         } else if sess.target.target.options.obj_is_bitcode
-            || sess.opts.cg.linker_plugin_lto.enabled()
+            || (sess.opts.cg.linker_plugin_lto.enabled() && !no_builtins)
         {
+            // This case is selected if the target uses objects as bitcode, or
+            // if linker plugin LTO is enabled. In the linker plugin LTO case
+            // the assumption is that the final link-step will read the bitcode
+            // and convert it to object code. This may be done by either the
+            // native linker or rustc itself.
+            //
+            // Note, however, that the linker-plugin-lto requested here is
+            // explicitly ignored for `#![no_builtins]` crates. These crates are
+            // specifically ignored by rustc's LTO passes and wouldn't work if
+            // loaded into the linker. These crates define symbols that LLVM
+            // lowers intrinsics to, and these symbol dependencies aren't known
+            // until after codegen. As a result any crate marked
+            // `#![no_builtins]` is assumed to not participate in LTO and
+            // instead goes on to generate object code.
             EmitObj::Bitcode
         } else if need_bitcode_in_object(sess) {
             EmitObj::ObjectCode(BitcodeSection::Full)