@@ -535,11 +535,41 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
535
535
536
536
// The semantics of #[used] in Rust only require the symbol to make it into the
537
537
// 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
+ //
539
541
// Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
540
542
// 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
+ }
543
573
}
544
574
if attrs. flags . contains ( CodegenFnAttrFlags :: USED_LINKER ) {
545
575
// `USED` and `USED_LINKER` can't be used together.
0 commit comments