@@ -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.
0 commit comments