From 7c015648dd78a329920060125378eb52762a728f Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 7 Aug 2021 17:04:32 +0200 Subject: [PATCH] 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. --- compiler/rustc_codegen_llvm/src/base.rs | 4 ++-- compiler/rustc_codegen_llvm/src/consts.rs | 2 +- compiler/rustc_codegen_llvm/src/context.rs | 12 +++++++++--- compiler/rustc_feature/src/accepted.rs | 2 +- .../coverage-llvmir/filecheck.testprog.txt | 4 +++- 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>, - /// Statics that will be placed in the llvm.used variable - /// See for details + /// Statics that will be placed in the llvm.compiler.used variable + /// See for details pub used_statics: RefCell>, /// 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"