Skip to content

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

+4-2
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

+15-2
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

+29-17
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

+2
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

+8-10
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

+1-4
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)