Skip to content

Commit 3f4aaf4

Browse files
authored
Rollup merge of #91504 - cynecx:used_retain, r=nikic
`#[used(linker)]` attribute See dtolnay/linkme#41 (comment).
2 parents 9634559 + 1705933 commit 3f4aaf4

File tree

16 files changed

+182
-4
lines changed

16 files changed

+182
-4
lines changed

compiler/rustc_codegen_gcc/src/consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
144144
// TODO(antoyo): set link section.
145145
}
146146

147-
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
147+
if attrs.flags.contains(CodegenFnAttrFlags::USED) || attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) {
148148
self.add_used_global(global.to_rvalue());
149149
}
150150
}

compiler/rustc_codegen_llvm/src/consts.rs

+9
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,9 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
522522
}
523523

524524
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
525+
// `USED` and `USED_LINKER` can't be used together.
526+
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER));
527+
525528
// The semantics of #[used] in Rust only require the symbol to make it into the
526529
// object file. It is explicitly allowed for the linker to strip the symbol if it
527530
// is dead. As such, use llvm.compiler.used instead of llvm.used.
@@ -530,6 +533,12 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
530533
// in some versions of the gold linker.
531534
self.add_compiler_used_global(g);
532535
}
536+
if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) {
537+
// `USED` and `USED_LINKER` can't be used together.
538+
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED));
539+
540+
self.add_used_global(g);
541+
}
533542
}
534543
}
535544

compiler/rustc_feature/src/active.rs

+2
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,8 @@ declare_features! (
531531
///
532532
/// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0.
533533
(active, untagged_unions, "1.13.0", Some(55149), None),
534+
/// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
535+
(active, used_with_arg, "1.60.0", Some(93798), None),
534536
/// Allows `extern "wasm" fn`
535537
(active, wasm_abi, "1.53.0", Some(83788), None),
536538
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!

compiler/rustc_feature/src/builtin_attrs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
324324
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
325325
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
326326
ungated!(no_mangle, Normal, template!(Word), WarnFollowing),
327-
ungated!(used, Normal, template!(Word), WarnFollowing),
327+
ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing),
328328

329329
// Limits:
330330
ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

+2
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ bitflags! {
8989
/// the MIR `InstrumentCoverage` pass and not added to the coverage map
9090
/// during codegen.
9191
const NO_COVERAGE = 1 << 15;
92+
/// `#[used(linker)]`: indicates that LLVM nor the linker can eliminate this function.
93+
const USED_LINKER = 1 << 16;
9294
}
9395
}
9496

compiler/rustc_passes/src/check_attr.rs

+34
Original file line numberDiff line numberDiff line change
@@ -1741,12 +1741,46 @@ impl CheckAttrVisitor<'_> {
17411741
}
17421742

17431743
fn check_used(&self, attrs: &[Attribute], target: Target) {
1744+
let mut used_linker_span = None;
1745+
let mut used_compiler_span = None;
17441746
for attr in attrs {
17451747
if attr.has_name(sym::used) && target != Target::Static {
17461748
self.tcx
17471749
.sess
17481750
.span_err(attr.span, "attribute must be applied to a `static` variable");
17491751
}
1752+
let inner = attr.meta_item_list();
1753+
match inner.as_deref() {
1754+
Some([item]) if item.has_name(sym::linker) => {
1755+
if used_linker_span.is_none() {
1756+
used_linker_span = Some(attr.span);
1757+
}
1758+
}
1759+
Some([item]) if item.has_name(sym::compiler) => {
1760+
if used_compiler_span.is_none() {
1761+
used_compiler_span = Some(attr.span);
1762+
}
1763+
}
1764+
Some(_) => {
1765+
// This error case is handled in rustc_typeck::collect.
1766+
}
1767+
None => {
1768+
// Default case (compiler) when arg isn't defined.
1769+
if used_compiler_span.is_none() {
1770+
used_compiler_span = Some(attr.span);
1771+
}
1772+
}
1773+
}
1774+
}
1775+
if let (Some(linker_span), Some(compiler_span)) = (used_linker_span, used_compiler_span) {
1776+
let spans = vec![linker_span, compiler_span];
1777+
self.tcx
1778+
.sess
1779+
.struct_span_err(
1780+
spans,
1781+
"`used(compiler)` and `used(linker)` can't be used together",
1782+
)
1783+
.emit();
17501784
}
17511785
}
17521786

compiler/rustc_passes/src/dead.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,10 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
466466

467467
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
468468
// forcefully, e.g., for placing it in a specific section.
469-
if cg_attrs.contains_extern_indicator() || cg_attrs.flags.contains(CodegenFnAttrFlags::USED) {
469+
if cg_attrs.contains_extern_indicator()
470+
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
471+
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
472+
{
470473
return true;
471474
}
472475

compiler/rustc_span/src/symbol.rs

+3
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ symbols! {
449449
compare_exchange_weak,
450450
compile_error,
451451
compile_error_macro,
452+
compiler,
452453
compiler_builtins,
453454
compiler_fence,
454455
concat,
@@ -818,6 +819,7 @@ symbols! {
818819
link_ordinal,
819820
link_section,
820821
linkage,
822+
linker,
821823
lint_reasons,
822824
literal,
823825
load,
@@ -1466,6 +1468,7 @@ symbols! {
14661468
use_extern_macros,
14671469
use_nested_groups,
14681470
used,
1471+
used_with_arg,
14691472
usize,
14701473
v1,
14711474
va_arg,

compiler/rustc_typeck/src/collect.rs

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// ignore-tidy-filelength
12
//! "Collection" is the process of determining the type and other external
23
//! details of each item in Rust. Collection is specifically concerned
34
//! with *inter-procedural* things -- for example, for a function
@@ -2856,7 +2857,42 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
28562857
} else if attr.has_name(sym::rustc_std_internal_symbol) {
28572858
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
28582859
} else if attr.has_name(sym::used) {
2859-
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
2860+
let inner = attr.meta_item_list();
2861+
match inner.as_deref() {
2862+
Some([item]) if item.has_name(sym::linker) => {
2863+
if !tcx.features().used_with_arg {
2864+
feature_err(
2865+
&tcx.sess.parse_sess,
2866+
sym::used_with_arg,
2867+
attr.span,
2868+
"`#[used(linker)]` is currently unstable",
2869+
)
2870+
.emit();
2871+
}
2872+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
2873+
}
2874+
Some([item]) if item.has_name(sym::compiler) => {
2875+
if !tcx.features().used_with_arg {
2876+
feature_err(
2877+
&tcx.sess.parse_sess,
2878+
sym::used_with_arg,
2879+
attr.span,
2880+
"`#[used(compiler)]` is currently unstable",
2881+
)
2882+
.emit();
2883+
}
2884+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
2885+
}
2886+
Some(_) => {
2887+
tcx.sess
2888+
.struct_span_err(
2889+
attr.span,
2890+
"expected `used`, `used(compiler)` or `used(linker)`",
2891+
)
2892+
.emit();
2893+
}
2894+
None => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED,
2895+
}
28602896
} else if attr.has_name(sym::cmse_nonsecure_entry) {
28612897
if !matches!(tcx.fn_sig(id).abi(), abi::Abi::C { .. }) {
28622898
struct_span_err!(

src/test/codegen/used_with_arg.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![crate_type = "lib"]
2+
#![feature(used_with_arg)]
3+
4+
// CHECK: @llvm.used = appending global [1 x i8*]{{.*}}USED_LINKER
5+
#[used(linker)]
6+
static mut USED_LINKER: [usize; 1] = [0];
7+
8+
// CHECK-NEXT: @llvm.compiler.used = appending global [1 x i8*]{{.*}}USED_COMPILER
9+
#[used(compiler)]
10+
static mut USED_COMPILER: [usize; 1] = [0];
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#![feature(used_with_arg)]
2+
3+
#[used(linker)]
4+
static mut USED_LINKER: [usize; 1] = [0];
5+
6+
#[used(compiler)]
7+
static mut USED_COMPILER: [usize; 1] = [0];
8+
9+
#[used(compiler)] //~ ERROR `used(compiler)` and `used(linker)` can't be used together
10+
#[used(linker)]
11+
static mut USED_COMPILER_LINKER2: [usize; 1] = [0];
12+
13+
#[used(compiler)] //~ ERROR `used(compiler)` and `used(linker)` can't be used together
14+
#[used(linker)]
15+
#[used(compiler)]
16+
#[used(linker)]
17+
static mut USED_COMPILER_LINKER3: [usize; 1] = [0];
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error: `used(compiler)` and `used(linker)` can't be used together
2+
--> $DIR/used_with_arg.rs:9:1
3+
|
4+
LL | #[used(compiler)]
5+
| ^^^^^^^^^^^^^^^^^
6+
LL | #[used(linker)]
7+
| ^^^^^^^^^^^^^^^
8+
9+
error: `used(compiler)` and `used(linker)` can't be used together
10+
--> $DIR/used_with_arg.rs:13:1
11+
|
12+
LL | #[used(compiler)]
13+
| ^^^^^^^^^^^^^^^^^
14+
LL | #[used(linker)]
15+
| ^^^^^^^^^^^^^^^
16+
17+
error: aborting due to 2 previous errors
18+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![feature(used_with_arg)]
2+
3+
#[used(compiler, linker)] //~ expected `used`, `used(compiler)` or `used(linker)`
4+
static mut USED_COMPILER_LINKER: [usize; 1] = [0];
5+
6+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: expected `used`, `used(compiler)` or `used(linker)`
2+
--> $DIR/used_with_multi_args.rs:3:1
3+
|
4+
LL | #[used(compiler, linker)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#[used(linker)] //~ ERROR `#[used(linker)]` is currently unstable
2+
static mut USED_LINKER: [usize; 1] = [0];
3+
4+
#[used(compiler)] //~ ERROR `#[used(compiler)]` is currently unstable
5+
static mut USED_COMPILER: [usize; 1] = [0];
6+
7+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0658]: `#[used(linker)]` is currently unstable
2+
--> $DIR/feature-gate-used_with_arg.rs:1:1
3+
|
4+
LL | #[used(linker)]
5+
| ^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #93798 <https://github.com/rust-lang/rust/issues/93798> for more information
8+
= help: add `#![feature(used_with_arg)]` to the crate attributes to enable
9+
10+
error[E0658]: `#[used(compiler)]` is currently unstable
11+
--> $DIR/feature-gate-used_with_arg.rs:4:1
12+
|
13+
LL | #[used(compiler)]
14+
| ^^^^^^^^^^^^^^^^^
15+
|
16+
= note: see issue #93798 <https://github.com/rust-lang/rust/issues/93798> for more information
17+
= help: add `#![feature(used_with_arg)]` to the crate attributes to enable
18+
19+
error: aborting due to 2 previous errors
20+
21+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)