about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThom Chiovoloni <chiovolonit@gmail.com>2022-02-06 13:51:11 -0800
committerThom Chiovoloni <chiovolonit@gmail.com>2022-05-11 01:29:56 -0700
commit54133cfcf49c68886a7cd8046007ea14e3d3944d (patch)
tree09f22cb6e789c937d4edccc8f8450b0328d31efe
parentecd44958e0a21110d09862ee080d95a4ca6c52f8 (diff)
downloadrust-54133cfcf49c68886a7cd8046007ea14e3d3944d.tar.gz
rust-54133cfcf49c68886a7cd8046007ea14e3d3944d.zip
Only compile #[used] as llvm.compiler.used for ELF targets
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs36
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/statics.rs4
2 files changed, 36 insertions, 4 deletions
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 4d3f3f318b8..98b412f9397 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -535,11 +535,41 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
 
                 // The semantics of #[used] in Rust only require the symbol to make it into the
                 // object file. It is explicitly allowed for the linker to strip the symbol if it
-                // is dead. As such, use llvm.compiler.used instead of llvm.used.
+                // is dead, which means we are allowed use `llvm.compiler.used` instead of
+                // `llvm.used` here.
+                //
                 // Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
                 // sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs
-                // in some versions of the gold linker.
-                self.add_compiler_used_global(g);
+                // in the handling of `.init_array` (the static constructor list) in versions of
+                // the gold linker (prior to the one released with binutils 2.36).
+                //
+                // However, unconditional use of `llvm.compiler.used` caused a nontrivial amount of
+                // ecosystem breakage, especially on Mach-O targets. To resolve this, we compile it
+                // as llvm.used on ELF targets and llvm.compiler.used elsewhere, which and should be
+                // equivalent to how we compiled `#[used]` before LLVM 13, as `llvm.used` and
+                // `llvm.compiler.used` were treated the same on ELF targets prior in earlier LLVM
+                // versions (additionally, it seems to be how Clang handles `__attribute__((used))`,
+                // perhaps for similar compatibility-motivated reasons).
+                //
+                // See https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146 and
+                // following comments for some discussion of this.
+                //
+                // The final wrinkle is it's not really clear how to tell if we're going to output
+                // ELF, so it's been approximated as "not like wasm, osx, or windows", which is
+                // not exactly correct, but is pretty close and hopefully handles all the platforms
+                // platforms where old versions of `ld.gold` are likely to show up.
+                //
+                // All this is subject to change in the future. Which is a good thing, because this
+                // probably should be firmed up somehow!
+                let seems_like_elf = !(self.tcx.sess.target.is_like_osx
+                    || self.tcx.sess.target.is_like_windows
+                    || self.tcx.sess.target.is_like_wasm);
+
+                if seems_like_elf {
+                    self.add_compiler_used_global(g);
+                } else {
+                    self.add_used_global(g);
+                }
             }
             if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) {
                 // `USED` and `USED_LINKER` can't be used together.
diff --git a/compiler/rustc_codegen_ssa/src/traits/statics.rs b/compiler/rustc_codegen_ssa/src/traits/statics.rs
index a2a3cb56c78..413d31bb942 100644
--- a/compiler/rustc_codegen_ssa/src/traits/statics.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/statics.rs
@@ -13,7 +13,9 @@ pub trait StaticMethods: BackendTypes {
     /// Same as add_used_global(), but only prevent the compiler from potentially removing an
     /// otherwise unused symbol. The linker is still permitted to drop it.
     ///
-    /// This corresponds to the semantics of the `#[used]` attribute.
+    /// This corresponds to the documented semantics of the `#[used]` attribute, although
+    /// on some targets (non-ELF), we may use `add_used_global` for `#[used]` statics
+    /// instead.
     fn add_compiler_used_global(&self, global: Self::Value);
 }