Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 306259c

Browse files
committed
Always use llvm.used for coverage symbols
This follows what clang does in CoverageMappingGen. Using just llvm.compiler.used is insufficient at least for MSVC targets.
1 parent f3ae726 commit 306259c

File tree

6 files changed

+59
-35
lines changed

6 files changed

+59
-35
lines changed

compiler/rustc_codegen_llvm/src/base.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,13 @@ pub fn compile_codegen_unit(
162162
cx.coverageinfo_finalize();
163163
}
164164

165-
// Create the llvm.compiler.used variable
166-
// This variable has type [N x i8*] and is stored in the llvm.metadata section
165+
// Create the llvm.used and llvm.compiler.used variables.
167166
if !cx.used_statics().borrow().is_empty() {
168167
cx.create_used_variable()
169168
}
169+
if !cx.compiler_used_statics().borrow().is_empty() {
170+
cx.create_compiler_used_variable()
171+
}
170172

171173
// Finalize debuginfo
172174
if cx.sess().opts.debuginfo != DebugInfo::None {

compiler/rustc_codegen_llvm/src/consts.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,14 +474,27 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
474474
}
475475

476476
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
477-
self.add_used_global(g);
477+
// The semantics of #[used] in Rust only require the symbol to make it into the
478+
// object file. It is explicitly allowed for the linker to strip the symbol if it
479+
// is dead. As such, use llvm.compiler.used instead of llvm.used.
480+
// Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
481+
// sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs
482+
// in some versions of the gold linker.
483+
self.add_compiler_used_global(g);
478484
}
479485
}
480486
}
481487

482-
/// Add a global value to a list to be stored in the `llvm.compiler.used` variable, an array of i8*.
488+
/// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*.
483489
fn add_used_global(&self, global: &'ll Value) {
484490
let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) };
485491
self.used_statics.borrow_mut().push(cast);
486492
}
493+
494+
/// Add a global value to a list to be stored in the `llvm.compiler.used` variable,
495+
/// an array of i8*.
496+
fn add_compiler_used_global(&self, global: &'ll Value) {
497+
let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) };
498+
self.compiler_used_statics.borrow_mut().push(cast);
499+
}
487500
}

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,13 @@ pub struct CodegenCx<'ll, 'tcx> {
7171
/// to constants.)
7272
pub statics_to_rauw: RefCell<Vec<(&'ll Value, &'ll Value)>>,
7373

74+
/// Statics that will be placed in the llvm.used variable
75+
/// See <https://llvm.org/docs/LangRef.html#the-llvm-used-global-variable> for details
76+
pub used_statics: RefCell<Vec<&'ll Value>>,
77+
7478
/// Statics that will be placed in the llvm.compiler.used variable
7579
/// See <https://llvm.org/docs/LangRef.html#the-llvm-compiler-used-global-variable> for details
76-
pub used_statics: RefCell<Vec<&'ll Value>>,
80+
pub compiler_used_statics: RefCell<Vec<&'ll Value>>,
7781

7882
/// Mapping of non-scalar types to llvm types and field remapping if needed.
7983
pub type_lowering: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), TypeLowering<'ll>>>,
@@ -325,6 +329,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
325329
const_globals: Default::default(),
326330
statics_to_rauw: RefCell::new(Vec::new()),
327331
used_statics: RefCell::new(Vec::new()),
332+
compiler_used_statics: RefCell::new(Vec::new()),
328333
type_lowering: Default::default(),
329334
scalar_lltypes: Default::default(),
330335
pointee_infos: Default::default(),
@@ -347,6 +352,18 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
347352
pub fn coverage_context(&'a self) -> Option<&'a coverageinfo::CrateCoverageContext<'ll, 'tcx>> {
348353
self.coverage_cx.as_ref()
349354
}
355+
356+
fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) {
357+
let section = cstr!("llvm.metadata");
358+
let array = self.const_array(&self.type_ptr_to(self.type_i8()), values);
359+
360+
unsafe {
361+
let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
362+
llvm::LLVMSetInitializer(g, array);
363+
llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
364+
llvm::LLVMSetSection(g, section.as_ptr());
365+
}
366+
}
350367
}
351368

352369
impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
@@ -437,6 +454,10 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
437454
&self.used_statics
438455
}
439456

457+
fn compiler_used_statics(&self) -> &RefCell<Vec<&'ll Value>> {
458+
&self.compiler_used_statics
459+
}
460+
440461
fn set_frame_pointer_type(&self, llfn: &'ll Value) {
441462
attributes::set_frame_pointer_type(self, llfn)
442463
}
@@ -447,23 +468,14 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
447468
}
448469

449470
fn create_used_variable(&self) {
450-
// The semantics of #[used] in Rust only require the symbol to make it into the object
451-
// file. It is explicitly allowed for the linker to strip the symbol if it is dead.
452-
// As such, use llvm.compiler.used instead of llvm.used.
453-
// Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
454-
// sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs in
455-
// some versions of the gold linker.
456-
let name = cstr!("llvm.compiler.used");
457-
let section = cstr!("llvm.metadata");
458-
let array =
459-
self.const_array(&self.type_ptr_to(self.type_i8()), &*self.used_statics.borrow());
471+
self.create_used_variable_impl(cstr!("llvm.used"), &*self.used_statics.borrow());
472+
}
460473

461-
unsafe {
462-
let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
463-
llvm::LLVMSetInitializer(g, array);
464-
llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
465-
llvm::LLVMSetSection(g, section.as_ptr());
466-
}
474+
fn create_compiler_used_variable(&self) {
475+
self.create_used_variable_impl(
476+
cstr!("llvm.compiler.used"),
477+
&*self.compiler_used_statics.borrow(),
478+
);
467479
}
468480

469481
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {

compiler/rustc_codegen_ssa/src/traits/misc.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ pub trait MiscMethods<'tcx>: BackendTypes {
1616
fn sess(&self) -> &Session;
1717
fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx>;
1818
fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
19+
fn compiler_used_statics(&self) -> &RefCell<Vec<Self::Value>>;
1920
fn set_frame_pointer_type(&self, llfn: Self::Function);
2021
fn apply_target_cpu_attr(&self, llfn: Self::Function);
2122
fn create_used_variable(&self);
23+
fn create_compiler_used_variable(&self);
2224
/// Declares the extern "C" main function for the entry point. Returns None if the symbol already exists.
2325
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function>;
2426
}

compiler/rustc_codegen_ssa/src/traits/statics.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,15 @@ pub trait StaticMethods: BackendTypes {
66
fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value;
77
fn codegen_static(&self, def_id: DefId, is_mutable: bool);
88

9-
/// Mark the given global value as "used", to prevent a backend from potentially removing a
10-
/// static variable that may otherwise appear unused.
11-
///
12-
/// Static variables in Rust can be annotated with the `#[used]` attribute to direct the `rustc`
13-
/// compiler to mark the variable as a "used global".
14-
///
15-
/// ```no_run
16-
/// #[used]
17-
/// static FOO: u32 = 0;
18-
/// ```
9+
/// Mark the given global value as "used", to prevent the compiler and linker from potentially
10+
/// removing a static variable that may otherwise appear unused.
1911
fn add_used_global(&self, global: Self::Value);
12+
13+
/// Same as add_used_global(), but only prevent the compiler from potentially removing an
14+
/// otherwise unused symbol. The linker is still permitted to drop it.
15+
///
16+
/// This corresponds to the semantics of the `#[used]` attribute.
17+
fn add_compiler_used_global(&self, global: Self::Value);
2018
}
2119

2220
pub trait StaticBuilderMethods: BackendTypes {

src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,8 @@ CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8
2828
CHECK: @__llvm_prf_nm = private constant
2929
CHECK-SAME: section "[[INSTR_PROF_NAME]]", align 1
3030

31-
CHECK: @llvm.compiler.used = appending global
32-
CHECK-SAME: i8* bitcast ({ {{.*}} }* @__llvm_coverage_mapping to i8*)
33-
WINDOWS-SAME: i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*)
34-
CHECK-SAME: section "llvm.metadata"
3531
CHECK: @llvm.used = appending global
32+
CHECK-SAME: i8* bitcast ({ {{.*}} }* @__llvm_coverage_mapping to i8*)
3633
CHECK-SAME: i8* getelementptr inbounds ({{.*}}* @__llvm_prf_nm, i32 0, i32 0)
3734
CHECK-SAME: section "llvm.metadata"
3835

0 commit comments

Comments
 (0)