#[used(linker)]
attribute (https://github.com/dtolnay/linkme/issues/41)
This commit is contained in:
parent
f624427f87
commit
03733ca65a
@ -144,7 +144,7 @@ fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
|
||||
// TODO(antoyo): set link section.
|
||||
}
|
||||
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::USED) || attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) {
|
||||
self.add_used_global(global.to_rvalue());
|
||||
}
|
||||
}
|
||||
|
@ -522,6 +522,9 @@ fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
|
||||
}
|
||||
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
|
||||
// `USED` and `USED_LINKER` can't be used together.
|
||||
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER));
|
||||
|
||||
// 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.
|
||||
@ -530,6 +533,12 @@ fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
|
||||
// in some versions of the gold linker.
|
||||
self.add_compiler_used_global(g);
|
||||
}
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) {
|
||||
// `USED` and `USED_LINKER` can't be used together.
|
||||
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED));
|
||||
|
||||
self.add_used_global(g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -533,6 +533,8 @@ pub fn set(&self, features: &mut Features, span: Span) {
|
||||
///
|
||||
/// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0.
|
||||
(active, untagged_unions, "1.13.0", Some(55149), None),
|
||||
/// Allows using the `#[used(retain)]` attribute.
|
||||
(active, used_with_arg, "1.60.0", None, None),
|
||||
/// Allows `extern "wasm" fn`
|
||||
(active, wasm_abi, "1.53.0", Some(83788), None),
|
||||
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
|
||||
|
@ -324,7 +324,7 @@ pub struct BuiltinAttribute {
|
||||
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
|
||||
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
|
||||
ungated!(no_mangle, Normal, template!(Word), WarnFollowing),
|
||||
ungated!(used, Normal, template!(Word), WarnFollowing),
|
||||
ungated!(used, Normal, template!(Word, List: "used"), WarnFollowing),
|
||||
|
||||
// Limits:
|
||||
ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
|
||||
|
@ -89,6 +89,8 @@ pub struct CodegenFnAttrFlags: u32 {
|
||||
/// the MIR `InstrumentCoverage` pass and not added to the coverage map
|
||||
/// during codegen.
|
||||
const NO_COVERAGE = 1 << 15;
|
||||
/// `#[used(linker)]`: indicates that LLVM nor the linker can eliminate this function.
|
||||
const USED_LINKER = 1 << 16;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,7 +466,10 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
|
||||
|
||||
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
|
||||
// forcefully, e.g., for placing it in a specific section.
|
||||
if cg_attrs.contains_extern_indicator() || cg_attrs.flags.contains(CodegenFnAttrFlags::USED) {
|
||||
if cg_attrs.contains_extern_indicator()
|
||||
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
|
||||
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -449,6 +449,7 @@
|
||||
compare_exchange_weak,
|
||||
compile_error,
|
||||
compile_error_macro,
|
||||
compiler,
|
||||
compiler_builtins,
|
||||
compiler_fence,
|
||||
concat,
|
||||
@ -815,6 +816,7 @@
|
||||
link_ordinal,
|
||||
link_section,
|
||||
linkage,
|
||||
linker,
|
||||
lint_reasons,
|
||||
literal,
|
||||
load,
|
||||
@ -1458,6 +1460,7 @@
|
||||
use_extern_macros,
|
||||
use_nested_groups,
|
||||
used,
|
||||
used_with_arg,
|
||||
usize,
|
||||
v1,
|
||||
va_arg,
|
||||
|
@ -2849,7 +2849,42 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
} else if attr.has_name(sym::rustc_std_internal_symbol) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
||||
} else if attr.has_name(sym::used) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
|
||||
let inner = attr.meta_item_list();
|
||||
match inner.as_deref() {
|
||||
Some([item]) if item.has_name(sym::linker) => {
|
||||
if !tcx.features().used_with_arg {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::used_with_arg,
|
||||
attr.span,
|
||||
"`#[used(linker)]` is currently unstable",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
|
||||
}
|
||||
Some([item]) if item.has_name(sym::compiler) => {
|
||||
if !tcx.features().used_with_arg {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::used_with_arg,
|
||||
attr.span,
|
||||
"`#[used(compiler)]` is currently unstable",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
|
||||
}
|
||||
Some(_) => {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
attr.span,
|
||||
"expected `used`, `used(compiler)` or `used(linker)`",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
None => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED,
|
||||
}
|
||||
} else if attr.has_name(sym::cmse_nonsecure_entry) {
|
||||
if !matches!(tcx.fn_sig(id).abi(), abi::Abi::C { .. }) {
|
||||
struct_span_err!(
|
||||
|
Loading…
Reference in New Issue
Block a user