Rollup merge of #91504 - cynecx:used_retain, r=nikic
`#[used(linker)]` attribute See https://github.com/dtolnay/linkme/issues/41#issuecomment-927255631.
This commit is contained in:
commit
3f4aaf4f2e
16 changed files with 182 additions and 4 deletions
|
@ -144,7 +144,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
|
||||||
// TODO(antoyo): set link section.
|
// 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());
|
self.add_used_global(global.to_rvalue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -522,6 +522,9 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
|
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
|
// 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
|
// 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.
|
// is dead. As such, use llvm.compiler.used instead of llvm.used.
|
||||||
|
@ -530,6 +533,12 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
|
||||||
// in some versions of the gold linker.
|
// in some versions of the gold linker.
|
||||||
self.add_compiler_used_global(g);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -531,6 +531,8 @@ declare_features! (
|
||||||
///
|
///
|
||||||
/// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0.
|
/// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0.
|
||||||
(active, untagged_unions, "1.13.0", Some(55149), None),
|
(active, untagged_unions, "1.13.0", Some(55149), None),
|
||||||
|
/// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
|
||||||
|
(active, used_with_arg, "1.60.0", Some(93798), None),
|
||||||
/// Allows `extern "wasm" fn`
|
/// Allows `extern "wasm" fn`
|
||||||
(active, wasm_abi, "1.53.0", Some(83788), None),
|
(active, wasm_abi, "1.53.0", Some(83788), None),
|
||||||
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
|
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
|
||||||
|
|
|
@ -324,7 +324,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
|
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
|
||||||
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
|
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
|
||||||
ungated!(no_mangle, Normal, template!(Word), WarnFollowing),
|
ungated!(no_mangle, Normal, template!(Word), WarnFollowing),
|
||||||
ungated!(used, Normal, template!(Word), WarnFollowing),
|
ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing),
|
||||||
|
|
||||||
// Limits:
|
// Limits:
|
||||||
ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
|
ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
|
||||||
|
|
|
@ -89,6 +89,8 @@ bitflags! {
|
||||||
/// the MIR `InstrumentCoverage` pass and not added to the coverage map
|
/// the MIR `InstrumentCoverage` pass and not added to the coverage map
|
||||||
/// during codegen.
|
/// during codegen.
|
||||||
const NO_COVERAGE = 1 << 15;
|
const NO_COVERAGE = 1 << 15;
|
||||||
|
/// `#[used(linker)]`: indicates that LLVM nor the linker can eliminate this function.
|
||||||
|
const USED_LINKER = 1 << 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1741,12 +1741,46 @@ impl CheckAttrVisitor<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_used(&self, attrs: &[Attribute], target: Target) {
|
fn check_used(&self, attrs: &[Attribute], target: Target) {
|
||||||
|
let mut used_linker_span = None;
|
||||||
|
let mut used_compiler_span = None;
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
if attr.has_name(sym::used) && target != Target::Static {
|
if attr.has_name(sym::used) && target != Target::Static {
|
||||||
self.tcx
|
self.tcx
|
||||||
.sess
|
.sess
|
||||||
.span_err(attr.span, "attribute must be applied to a `static` variable");
|
.span_err(attr.span, "attribute must be applied to a `static` variable");
|
||||||
}
|
}
|
||||||
|
let inner = attr.meta_item_list();
|
||||||
|
match inner.as_deref() {
|
||||||
|
Some([item]) if item.has_name(sym::linker) => {
|
||||||
|
if used_linker_span.is_none() {
|
||||||
|
used_linker_span = Some(attr.span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some([item]) if item.has_name(sym::compiler) => {
|
||||||
|
if used_compiler_span.is_none() {
|
||||||
|
used_compiler_span = Some(attr.span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(_) => {
|
||||||
|
// This error case is handled in rustc_typeck::collect.
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// Default case (compiler) when arg isn't defined.
|
||||||
|
if used_compiler_span.is_none() {
|
||||||
|
used_compiler_span = Some(attr.span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let (Some(linker_span), Some(compiler_span)) = (used_linker_span, used_compiler_span) {
|
||||||
|
let spans = vec![linker_span, compiler_span];
|
||||||
|
self.tcx
|
||||||
|
.sess
|
||||||
|
.struct_span_err(
|
||||||
|
spans,
|
||||||
|
"`used(compiler)` and `used(linker)` can't be used together",
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
|
||||||
// forcefully, e.g., for placing it in a specific section.
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -449,6 +449,7 @@ symbols! {
|
||||||
compare_exchange_weak,
|
compare_exchange_weak,
|
||||||
compile_error,
|
compile_error,
|
||||||
compile_error_macro,
|
compile_error_macro,
|
||||||
|
compiler,
|
||||||
compiler_builtins,
|
compiler_builtins,
|
||||||
compiler_fence,
|
compiler_fence,
|
||||||
concat,
|
concat,
|
||||||
|
@ -818,6 +819,7 @@ symbols! {
|
||||||
link_ordinal,
|
link_ordinal,
|
||||||
link_section,
|
link_section,
|
||||||
linkage,
|
linkage,
|
||||||
|
linker,
|
||||||
lint_reasons,
|
lint_reasons,
|
||||||
literal,
|
literal,
|
||||||
load,
|
load,
|
||||||
|
@ -1466,6 +1468,7 @@ symbols! {
|
||||||
use_extern_macros,
|
use_extern_macros,
|
||||||
use_nested_groups,
|
use_nested_groups,
|
||||||
used,
|
used,
|
||||||
|
used_with_arg,
|
||||||
usize,
|
usize,
|
||||||
v1,
|
v1,
|
||||||
va_arg,
|
va_arg,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// ignore-tidy-filelength
|
||||||
//! "Collection" is the process of determining the type and other external
|
//! "Collection" is the process of determining the type and other external
|
||||||
//! details of each item in Rust. Collection is specifically concerned
|
//! details of each item in Rust. Collection is specifically concerned
|
||||||
//! with *inter-procedural* things -- for example, for a function
|
//! with *inter-procedural* things -- for example, for a function
|
||||||
|
@ -2856,7 +2857,42 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||||
} else if attr.has_name(sym::rustc_std_internal_symbol) {
|
} else if attr.has_name(sym::rustc_std_internal_symbol) {
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
||||||
} else if attr.has_name(sym::used) {
|
} 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) {
|
} else if attr.has_name(sym::cmse_nonsecure_entry) {
|
||||||
if !matches!(tcx.fn_sig(id).abi(), abi::Abi::C { .. }) {
|
if !matches!(tcx.fn_sig(id).abi(), abi::Abi::C { .. }) {
|
||||||
struct_span_err!(
|
struct_span_err!(
|
||||||
|
|
10
src/test/codegen/used_with_arg.rs
Normal file
10
src/test/codegen/used_with_arg.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![feature(used_with_arg)]
|
||||||
|
|
||||||
|
// CHECK: @llvm.used = appending global [1 x i8*]{{.*}}USED_LINKER
|
||||||
|
#[used(linker)]
|
||||||
|
static mut USED_LINKER: [usize; 1] = [0];
|
||||||
|
|
||||||
|
// CHECK-NEXT: @llvm.compiler.used = appending global [1 x i8*]{{.*}}USED_COMPILER
|
||||||
|
#[used(compiler)]
|
||||||
|
static mut USED_COMPILER: [usize; 1] = [0];
|
19
src/test/ui/attributes/used_with_arg.rs
Normal file
19
src/test/ui/attributes/used_with_arg.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#![feature(used_with_arg)]
|
||||||
|
|
||||||
|
#[used(linker)]
|
||||||
|
static mut USED_LINKER: [usize; 1] = [0];
|
||||||
|
|
||||||
|
#[used(compiler)]
|
||||||
|
static mut USED_COMPILER: [usize; 1] = [0];
|
||||||
|
|
||||||
|
#[used(compiler)] //~ ERROR `used(compiler)` and `used(linker)` can't be used together
|
||||||
|
#[used(linker)]
|
||||||
|
static mut USED_COMPILER_LINKER2: [usize; 1] = [0];
|
||||||
|
|
||||||
|
#[used(compiler)] //~ ERROR `used(compiler)` and `used(linker)` can't be used together
|
||||||
|
#[used(linker)]
|
||||||
|
#[used(compiler)]
|
||||||
|
#[used(linker)]
|
||||||
|
static mut USED_COMPILER_LINKER3: [usize; 1] = [0];
|
||||||
|
|
||||||
|
fn main() {}
|
18
src/test/ui/attributes/used_with_arg.stderr
Normal file
18
src/test/ui/attributes/used_with_arg.stderr
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
error: `used(compiler)` and `used(linker)` can't be used together
|
||||||
|
--> $DIR/used_with_arg.rs:9:1
|
||||||
|
|
|
||||||
|
LL | #[used(compiler)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
LL | #[used(linker)]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `used(compiler)` and `used(linker)` can't be used together
|
||||||
|
--> $DIR/used_with_arg.rs:13:1
|
||||||
|
|
|
||||||
|
LL | #[used(compiler)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
LL | #[used(linker)]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
6
src/test/ui/attributes/used_with_multi_args.rs
Normal file
6
src/test/ui/attributes/used_with_multi_args.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#![feature(used_with_arg)]
|
||||||
|
|
||||||
|
#[used(compiler, linker)] //~ expected `used`, `used(compiler)` or `used(linker)`
|
||||||
|
static mut USED_COMPILER_LINKER: [usize; 1] = [0];
|
||||||
|
|
||||||
|
fn main() {}
|
8
src/test/ui/attributes/used_with_multi_args.stderr
Normal file
8
src/test/ui/attributes/used_with_multi_args.stderr
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
error: expected `used`, `used(compiler)` or `used(linker)`
|
||||||
|
--> $DIR/used_with_multi_args.rs:3:1
|
||||||
|
|
|
||||||
|
LL | #[used(compiler, linker)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
7
src/test/ui/feature-gates/feature-gate-used_with_arg.rs
Normal file
7
src/test/ui/feature-gates/feature-gate-used_with_arg.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#[used(linker)] //~ ERROR `#[used(linker)]` is currently unstable
|
||||||
|
static mut USED_LINKER: [usize; 1] = [0];
|
||||||
|
|
||||||
|
#[used(compiler)] //~ ERROR `#[used(compiler)]` is currently unstable
|
||||||
|
static mut USED_COMPILER: [usize; 1] = [0];
|
||||||
|
|
||||||
|
fn main() {}
|
21
src/test/ui/feature-gates/feature-gate-used_with_arg.stderr
Normal file
21
src/test/ui/feature-gates/feature-gate-used_with_arg.stderr
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
error[E0658]: `#[used(linker)]` is currently unstable
|
||||||
|
--> $DIR/feature-gate-used_with_arg.rs:1:1
|
||||||
|
|
|
||||||
|
LL | #[used(linker)]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #93798 <https://github.com/rust-lang/rust/issues/93798> for more information
|
||||||
|
= help: add `#![feature(used_with_arg)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0658]: `#[used(compiler)]` is currently unstable
|
||||||
|
--> $DIR/feature-gate-used_with_arg.rs:4:1
|
||||||
|
|
|
||||||
|
LL | #[used(compiler)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #93798 <https://github.com/rust-lang/rust/issues/93798> for more information
|
||||||
|
= help: add `#![feature(used_with_arg)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
Loading…
Add table
Add a link
Reference in a new issue