about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2021-08-07 17:04:32 +0200
committerNikita Popov <nikita.ppv@gmail.com>2021-08-16 18:28:18 +0200
commit7c015648dd78a329920060125378eb52762a728f (patch)
treee7ec3ef94f4f8b328fb4dc0f37b1be38cff10c22
parent154c8408e9f9d90d82aa3060ed13732c955f0c53 (diff)
downloadrust-7c015648dd78a329920060125378eb52762a728f.tar.gz
rust-7c015648dd78a329920060125378eb52762a728f.zip
Use llvm.compiler.used insetad of llvm.used
The #[used] attribute explicitly only requires symbols to be
retained in object files, but allows the linker to drop them
if dead. This corresponds to llvm.compiler.used semantics.

The motivation to change this *now* is that https://reviews.llvm.org/D97448
starts emitting #[used] symbols into unique sections with
SHF_GNU_RETAIN flag. This triggers a bug in some version of gold,
resulting in the ARGV_INIT_ARRAY symbol part of the .init_array
section to be incorrectly placed.
-rw-r--r--compiler/rustc_codegen_llvm/src/base.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs12
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt4
5 files changed, 16 insertions, 8 deletions
diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs
index cc3cbea4def..a9f43880ef6 100644
--- a/compiler/rustc_codegen_llvm/src/base.rs
+++ b/compiler/rustc_codegen_llvm/src/base.rs
@@ -157,12 +157,12 @@ pub fn compile_codegen_unit(
             }
 
             // Finalize code coverage by injecting the coverage map. Note, the coverage map will
-            // also be added to the `llvm.used` variable, created next.
+            // also be added to the `llvm.compiler.used` variable, created next.
             if cx.sess().instrument_coverage() {
                 cx.coverageinfo_finalize();
             }
 
-            // Create the llvm.used variable
+            // Create the llvm.compiler.used variable
             // This variable has type [N x i8*] and is stored in the llvm.metadata section
             if !cx.used_statics().borrow().is_empty() {
                 cx.create_used_variable()
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 3ca295f4a7e..7b14c179174 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -479,7 +479,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
         }
     }
 
-    /// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*.
+    /// Add a global value to a list to be stored in the `llvm.compiler.used` variable, an array of i8*.
     fn add_used_global(&self, global: &'ll Value) {
         let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) };
         self.used_statics.borrow_mut().push(cast);
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index a469a13bc72..9c0220d3448 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -71,8 +71,8 @@ pub struct CodegenCx<'ll, 'tcx> {
     /// to constants.)
     pub statics_to_rauw: RefCell<Vec<(&'ll Value, &'ll Value)>>,
 
-    /// Statics that will be placed in the llvm.used variable
-    /// See <https://llvm.org/docs/LangRef.html#the-llvm-used-global-variable> for details
+    /// Statics that will be placed in the llvm.compiler.used variable
+    /// See <https://llvm.org/docs/LangRef.html#the-llvm-compiler-used-global-variable> for details
     pub used_statics: RefCell<Vec<&'ll Value>>,
 
     /// Mapping of non-scalar types to llvm types and field remapping if needed.
@@ -447,7 +447,13 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     }
 
     fn create_used_variable(&self) {
-        let name = cstr!("llvm.used");
+        // 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.
+        // 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.
+        let name = cstr!("llvm.compiler.used");
         let section = cstr!("llvm.metadata");
         let array =
             self.const_array(&self.type_ptr_to(self.type_i8()), &*self.used_statics.borrow());
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 9ce5a149697..ddb11985cd8 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -178,7 +178,7 @@ declare_features! (
     /// Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`.
     /// This defines the behavior of panics.
     (accepted, panic_handler, "1.30.0", Some(44489), None),
-    /// Allows `#[used]` to preserve symbols (see llvm.used).
+    /// Allows `#[used]` to preserve symbols (see llvm.compiler.used).
     (accepted, used, "1.30.0", Some(40289), None),
     /// Allows `crate` in paths.
     (accepted, crate_in_paths, "1.30.0", Some(45477), None),
diff --git a/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt b/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt
index f54d49f7f96..9b1f810500b 100644
--- a/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt
+++ b/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt
@@ -28,9 +28,11 @@ CHECK-SAME:   section "[[INSTR_PROF_DATA]]"{{.*}}, align 8
 CHECK:        @__llvm_prf_nm = private constant
 CHECK-SAME:   section "[[INSTR_PROF_NAME]]", align 1
 
-CHECK:        @llvm.used = appending global
+CHECK:        @llvm.compiler.used = appending global
 CHECK-SAME:   i8* bitcast ({ {{.*}} }* @__llvm_coverage_mapping to i8*)
 WINDOWS-SAME: i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*)
+CHECK-SAME:   section "llvm.metadata"
+CHECK:        @llvm.used = appending global
 CHECK-SAME:   i8* getelementptr inbounds ({{.*}}* @__llvm_prf_nm, i32 0, i32 0)
 CHECK-SAME:   section "llvm.metadata"