}
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
- self.add_used_global(g);
+ // 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.
+ self.add_compiler_used_global(g);
}
}
}
- /// Add a global value to a list to be stored in the `llvm.compiler.used` variable, an array of i8*.
+ /// Add a global value to a list to be stored in the `llvm.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);
}
+
+ /// Add a global value to a list to be stored in the `llvm.compiler.used` variable,
+ /// an array of i8*.
+ fn add_compiler_used_global(&self, global: &'ll Value) {
+ let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) };
+ self.compiler_used_statics.borrow_mut().push(cast);
+ }
}
/// 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
+ pub used_statics: RefCell<Vec<&'ll Value>>,
+
/// 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>>,
+ pub compiler_used_statics: RefCell<Vec<&'ll Value>>,
/// Mapping of non-scalar types to llvm types and field remapping if needed.
pub type_lowering: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), TypeLowering<'ll>>>,
const_globals: Default::default(),
statics_to_rauw: RefCell::new(Vec::new()),
used_statics: RefCell::new(Vec::new()),
+ compiler_used_statics: RefCell::new(Vec::new()),
type_lowering: Default::default(),
scalar_lltypes: Default::default(),
pointee_infos: Default::default(),
pub fn coverage_context(&'a self) -> Option<&'a coverageinfo::CrateCoverageContext<'ll, 'tcx>> {
self.coverage_cx.as_ref()
}
+
+ fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) {
+ let section = cstr!("llvm.metadata");
+ let array = self.const_array(&self.type_ptr_to(self.type_i8()), values);
+
+ unsafe {
+ let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
+ llvm::LLVMSetInitializer(g, array);
+ llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
+ llvm::LLVMSetSection(g, section.as_ptr());
+ }
+ }
}
impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
&self.used_statics
}
+ fn compiler_used_statics(&self) -> &RefCell<Vec<&'ll Value>> {
+ &self.compiler_used_statics
+ }
+
fn set_frame_pointer_type(&self, llfn: &'ll Value) {
attributes::set_frame_pointer_type(self, llfn)
}
}
fn create_used_variable(&self) {
- // 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());
+ self.create_used_variable_impl(cstr!("llvm.used"), &*self.used_statics.borrow());
+ }
- unsafe {
- let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
- llvm::LLVMSetInitializer(g, array);
- llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
- llvm::LLVMSetSection(g, section.as_ptr());
- }
+ fn create_compiler_used_variable(&self) {
+ self.create_used_variable_impl(
+ cstr!("llvm.compiler.used"),
+ &*self.compiler_used_statics.borrow(),
+ );
}
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value;
fn codegen_static(&self, def_id: DefId, is_mutable: bool);
- /// Mark the given global value as "used", to prevent a backend from potentially removing a
- /// static variable that may otherwise appear unused.
- ///
- /// Static variables in Rust can be annotated with the `#[used]` attribute to direct the `rustc`
- /// compiler to mark the variable as a "used global".
- ///
- /// ```no_run
- /// #[used]
- /// static FOO: u32 = 0;
- /// ```
+ /// Mark the given global value as "used", to prevent the compiler and linker from potentially
+ /// removing a static variable that may otherwise appear unused.
fn add_used_global(&self, global: Self::Value);
+
+ /// Same as add_used_global(), but only prevent the compiler from potentially removing an
+ /// otherwise unused symbol. The linker is still permitted to drop it.
+ ///
+ /// This corresponds to the semantics of the `#[used]` attribute.
+ fn add_compiler_used_global(&self, global: Self::Value);
}
pub trait StaticBuilderMethods: BackendTypes {