Skip to content

Commit 54133cf

Browse files
committed
Only compile #[used] as llvm.compiler.used for ELF targets
1 parent ecd4495 commit 54133cf

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

compiler/rustc_codegen_llvm/src/consts.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -535,11 +535,41 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
535535

536536
// The semantics of #[used] in Rust only require the symbol to make it into the
537537
// object file. It is explicitly allowed for the linker to strip the symbol if it
538-
// is dead. As such, use llvm.compiler.used instead of llvm.used.
538+
// is dead, which means we are allowed use `llvm.compiler.used` instead of
539+
// `llvm.used` here.
540+
//
539541
// Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
540542
// sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs
541-
// in some versions of the gold linker.
542-
self.add_compiler_used_global(g);
543+
// in the handling of `.init_array` (the static constructor list) in versions of
544+
// the gold linker (prior to the one released with binutils 2.36).
545+
//
546+
// However, unconditional use of `llvm.compiler.used` caused a nontrivial amount of
547+
// ecosystem breakage, especially on Mach-O targets. To resolve this, we compile it
548+
// as llvm.used on ELF targets and llvm.compiler.used elsewhere, which and should be
549+
// equivalent to how we compiled `#[used]` before LLVM 13, as `llvm.used` and
550+
// `llvm.compiler.used` were treated the same on ELF targets prior in earlier LLVM
551+
// versions (additionally, it seems to be how Clang handles `__attribute__((used))`,
552+
// perhaps for similar compatibility-motivated reasons).
553+
//
554+
// See https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146 and
555+
// following comments for some discussion of this.
556+
//
557+
// The final wrinkle is it's not really clear how to tell if we're going to output
558+
// ELF, so it's been approximated as "not like wasm, osx, or windows", which is
559+
// not exactly correct, but is pretty close and hopefully handles all the platforms
560+
// platforms where old versions of `ld.gold` are likely to show up.
561+
//
562+
// All this is subject to change in the future. Which is a good thing, because this
563+
// probably should be firmed up somehow!
564+
let seems_like_elf = !(self.tcx.sess.target.is_like_osx
565+
|| self.tcx.sess.target.is_like_windows
566+
|| self.tcx.sess.target.is_like_wasm);
567+
568+
if seems_like_elf {
569+
self.add_compiler_used_global(g);
570+
} else {
571+
self.add_used_global(g);
572+
}
543573
}
544574
if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) {
545575
// `USED` and `USED_LINKER` can't be used together.

compiler/rustc_codegen_ssa/src/traits/statics.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ pub trait StaticMethods: BackendTypes {
1313
/// Same as add_used_global(), but only prevent the compiler from potentially removing an
1414
/// otherwise unused symbol. The linker is still permitted to drop it.
1515
///
16-
/// This corresponds to the semantics of the `#[used]` attribute.
16+
/// This corresponds to the documented semantics of the `#[used]` attribute, although
17+
/// on some targets (non-ELF), we may use `add_used_global` for `#[used]` statics
18+
/// instead.
1719
fn add_compiler_used_global(&self, global: Self::Value);
1820
}
1921

0 commit comments

Comments
 (0)