Skip to content

Commit 4e42223

Browse files
committed
Port the #[linkage] attribute to the new attribute system
1 parent d9dba3a commit 4e42223

File tree

7 files changed

+144
-60
lines changed

7 files changed

+144
-60
lines changed

compiler/rustc_attr_parsing/src/attributes/link_attrs.rs

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rustc_feature::{AttributeTemplate, template};
2-
use rustc_hir::attrs::AttributeKind;
32
use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
3+
use rustc_hir::attrs::{AttributeKind, LinkageArg};
44
use rustc_span::{Span, Symbol, sym};
55

66
use crate::attributes::{
@@ -129,3 +129,77 @@ impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser {
129129
Some(LinkOrdinal { ordinal, span: cx.attr_span })
130130
}
131131
}
132+
133+
pub(crate) struct LinkageParser;
134+
135+
impl<S: Stage> SingleAttributeParser<S> for LinkageParser {
136+
const PATH: &[Symbol] = &[sym::linkage];
137+
138+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
139+
140+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
141+
142+
const TEMPLATE: AttributeTemplate = template!(NameValueStr: [
143+
"available_externally",
144+
"common",
145+
"extern_weak",
146+
"external",
147+
"internal",
148+
"linkonce",
149+
"linkonce_odr",
150+
"weak",
151+
"weak_odr",
152+
]);
153+
154+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
155+
let Some(name_value) = args.name_value() else {
156+
cx.expected_name_value(cx.attr_span, Some(sym::linkage));
157+
return None;
158+
};
159+
160+
let Some(value) = name_value.value_as_str() else {
161+
cx.expected_string_literal(name_value.value_span, Some(name_value.value_as_lit()));
162+
return None;
163+
};
164+
165+
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
166+
// applicable to variable declarations and may not really make sense for
167+
// Rust code in the first place but allow them anyway and trust that the
168+
// user knows what they're doing. Who knows, unanticipated use cases may pop
169+
// up in the future.
170+
//
171+
// ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
172+
// and don't have to be, LLVM treats them as no-ops.
173+
let linkage = match value {
174+
sym::available_externally => LinkageArg::AvailableExternally,
175+
sym::common => LinkageArg::Common,
176+
sym::extern_weak => LinkageArg::ExternWeak,
177+
sym::external => LinkageArg::External,
178+
sym::internal => LinkageArg::Internal,
179+
sym::linkonce => LinkageArg::Linkonce,
180+
sym::linkonce_odr => LinkageArg::LinkOnceOdr,
181+
sym::weak => LinkageArg::Weak,
182+
sym::weak_odr => LinkageArg::WeakOdr,
183+
184+
_ => {
185+
cx.expected_specific_argument(
186+
name_value.value_span,
187+
vec![
188+
"available_externally",
189+
"common",
190+
"extern_weak",
191+
"external",
192+
"internal",
193+
"linkonce",
194+
"linkonce_odr",
195+
"weak",
196+
"weak_odr",
197+
],
198+
);
199+
return None;
200+
}
201+
};
202+
203+
Some(AttributeKind::Linkage(linkage, cx.attr_span))
204+
}
205+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::attributes::dummy::DummyParser;
2727
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
2828
use crate::attributes::link_attrs::{
2929
ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
30-
LinkSectionParser, StdInternalSymbolParser,
30+
LinkSectionParser, LinkageParser, StdInternalSymbolParser,
3131
};
3232
use crate::attributes::lint_helpers::{
3333
AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
@@ -167,6 +167,7 @@ attribute_parsers!(
167167
Single<LinkNameParser>,
168168
Single<LinkOrdinalParser>,
169169
Single<LinkSectionParser>,
170+
Single<LinkageParser>,
170171
Single<MustUseParser>,
171172
Single<OptimizeParser>,
172173
Single<PathAttributeParser>,

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 35 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::str::FromStr;
33
use rustc_abi::{Align, ExternAbi};
44
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
55
use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr};
6-
use rustc_hir::attrs::{AttributeKind, InlineAttr, InstructionSetAttr, UsedBy};
6+
use rustc_hir::attrs::{AttributeKind, InlineAttr, InstructionSetAttr, LinkageArg, UsedBy};
77
use rustc_hir::def::DefKind;
88
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
99
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
@@ -26,31 +26,6 @@ use crate::target_features::{
2626
check_target_feature_trait_unsafe, check_tied_features, from_target_feature_attr,
2727
};
2828

29-
fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
30-
use rustc_middle::mir::mono::Linkage::*;
31-
32-
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
33-
// applicable to variable declarations and may not really make sense for
34-
// Rust code in the first place but allow them anyway and trust that the
35-
// user knows what they're doing. Who knows, unanticipated use cases may pop
36-
// up in the future.
37-
//
38-
// ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
39-
// and don't have to be, LLVM treats them as no-ops.
40-
match name {
41-
"available_externally" => AvailableExternally,
42-
"common" => Common,
43-
"extern_weak" => ExternalWeak,
44-
"external" => External,
45-
"internal" => Internal,
46-
"linkonce" => LinkOnceAny,
47-
"linkonce_odr" => LinkOnceODR,
48-
"weak" => WeakAny,
49-
"weak_odr" => WeakODR,
50-
_ => tcx.dcx().span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
51-
}
52-
}
53-
5429
/// In some cases, attributes are only valid on functions, but it's the `check_attr`
5530
/// pass that checks that they aren't used anywhere else, rather than this module.
5631
/// In these cases, we bail from performing further checks that are only meaningful for
@@ -103,13 +78,6 @@ fn parse_instruction_set_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option<Instr
10378
}
10479
}
10580

106-
// FIXME(jdonszelmann): remove when linkage becomes a parsed attr
107-
fn parse_linkage_attr(tcx: TyCtxt<'_>, did: LocalDefId, attr: &Attribute) -> Option<Linkage> {
108-
let val = attr.value_str()?;
109-
let linkage = linkage_by_name(tcx, did, val.as_str());
110-
Some(linkage)
111-
}
112-
11381
// FIXME(jdonszelmann): remove when no_sanitize becomes a parsed attr
11482
fn parse_no_sanitize_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option<SanitizerSet> {
11583
let list = attr.meta_item_list()?;
@@ -332,6 +300,40 @@ fn process_builtin_attrs(
332300
AttributeKind::StdInternalSymbol(_) => {
333301
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
334302
}
303+
AttributeKind::Linkage(linkage, _) => {
304+
let linkage = match linkage {
305+
LinkageArg::AvailableExternally => Linkage::AvailableExternally,
306+
LinkageArg::Common => Linkage::Common,
307+
LinkageArg::ExternWeak => Linkage::ExternalWeak,
308+
LinkageArg::External => Linkage::External,
309+
LinkageArg::Internal => Linkage::Internal,
310+
LinkageArg::Linkonce => Linkage::LinkOnceAny,
311+
LinkageArg::LinkOnceOdr => Linkage::LinkOnceODR,
312+
LinkageArg::Weak => Linkage::WeakAny,
313+
LinkageArg::WeakOdr => Linkage::WeakODR,
314+
};
315+
316+
let linkage = Some(linkage);
317+
318+
if tcx.is_foreign_item(did) {
319+
codegen_fn_attrs.import_linkage = linkage;
320+
321+
if tcx.is_mutable_static(did.into()) {
322+
let mut diag = tcx.dcx().struct_span_err(
323+
attr.span(),
324+
"extern mutable statics are not allowed with `#[linkage]`",
325+
);
326+
diag.note(
327+
"marking the extern static mutable would allow changing which \
328+
symbol the static references rather than make the target of the \
329+
symbol mutable",
330+
);
331+
diag.emit();
332+
}
333+
} else {
334+
codegen_fn_attrs.linkage = linkage;
335+
}
336+
}
335337
_ => {}
336338
}
337339
}
@@ -349,28 +351,6 @@ fn process_builtin_attrs(
349351
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
350352
}
351353
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
352-
sym::linkage => {
353-
let linkage = parse_linkage_attr(tcx, did, attr);
354-
355-
if tcx.is_foreign_item(did) {
356-
codegen_fn_attrs.import_linkage = linkage;
357-
358-
if tcx.is_mutable_static(did.into()) {
359-
let mut diag = tcx.dcx().struct_span_err(
360-
attr.span(),
361-
"extern mutable statics are not allowed with `#[linkage]`",
362-
);
363-
diag.note(
364-
"marking the extern static mutable would allow changing which \
365-
symbol the static references rather than make the target of the \
366-
symbol mutable",
367-
);
368-
diag.emit();
369-
}
370-
} else {
371-
codegen_fn_attrs.linkage = linkage;
372-
}
373-
}
374354
sym::no_sanitize => {
375355
interesting_spans.no_sanitize = Some(attr.span());
376356
codegen_fn_attrs.no_sanitize |=

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,21 @@ pub enum CfgEntry {
187187
Version(Option<RustcVersion>, Span),
188188
}
189189

190+
/// Possible values for the `#[linkage]` attribute.
191+
#[derive(Encodable, Decodable, Clone, Debug, PartialEq, Eq, Hash)]
192+
#[derive(HashStable_Generic, PrintAttribute)]
193+
pub enum LinkageArg {
194+
AvailableExternally,
195+
Common,
196+
ExternWeak,
197+
External,
198+
Internal,
199+
Linkonce,
200+
LinkOnceOdr,
201+
Weak,
202+
WeakOdr,
203+
}
204+
190205
/// Represents parsed *built-in* inert attributes.
191206
///
192207
/// ## Overview
@@ -363,6 +378,9 @@ pub enum AttributeKind {
363378
/// Represents `#[loop_match]`.
364379
LoopMatch(Span),
365380

381+
/// Represents `#[linkage]`.
382+
Linkage(LinkageArg, Span),
383+
366384
/// Represents `#[macro_escape]`.
367385
MacroEscape(Span),
368386

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ impl AttributeKind {
4343
Fundamental { .. } => Yes,
4444
Ignore { .. } => No,
4545
Inline(..) => No,
46+
Linkage(..) => No,
4647
LinkName { .. } => Yes, // Needed for rustdoc
4748
LinkOrdinal { .. } => No,
4849
LinkSection { .. } => Yes, // Needed for rustdoc

compiler/rustc_passes/src/check_attr.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
332332
&Attribute::Parsed(AttributeKind::Coroutine(attr_span)) => {
333333
self.check_coroutine(attr_span, target)
334334
}
335+
&Attribute::Parsed(AttributeKind::Linkage(_, attr_span)) => {
336+
self.check_linkage(attr_span, span, target);
337+
}
335338
Attribute::Unparsed(attr_item) => {
336339
style = Some(attr_item.style);
337340
match attr.path().as_slice() {
@@ -395,7 +398,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
395398
[sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
396399
self.check_autodiff(hir_id, attr, span, target)
397400
}
398-
[sym::linkage, ..] => self.check_linkage(attr, span, target),
399401
[
400402
// ok
401403
sym::allow
@@ -2707,15 +2709,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
27072709
}
27082710
}
27092711

2710-
fn check_linkage(&self, attr: &Attribute, span: Span, target: Target) {
2712+
fn check_linkage(&self, attr_span: Span, span: Span, target: Target) {
27112713
match target {
27122714
Target::Fn
27132715
| Target::Method(..)
27142716
| Target::Static
27152717
| Target::ForeignStatic
27162718
| Target::ForeignFn => {}
27172719
_ => {
2718-
self.dcx().emit_err(errors::Linkage { attr_span: attr.span(), span });
2720+
self.dcx().emit_err(errors::Linkage { attr_span, span });
27192721
}
27202722
}
27212723
}

compiler/rustc_span/src/symbol.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ symbols! {
545545
autodiff_forward,
546546
autodiff_reverse,
547547
automatically_derived,
548+
available_externally,
548549
avx,
549550
avx10_target_feature,
550551
avx512_target_feature,
@@ -676,6 +677,7 @@ symbols! {
676677
cold_path,
677678
collapse_debuginfo,
678679
column,
680+
common,
679681
compare_bytes,
680682
compare_exchange,
681683
compare_exchange_weak,
@@ -956,6 +958,7 @@ symbols! {
956958
extern_prelude,
957959
extern_system_varargs,
958960
extern_types,
961+
extern_weak,
959962
external,
960963
external_doc,
961964
f,
@@ -1213,6 +1216,7 @@ symbols! {
12131216
instruction_set,
12141217
integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below
12151218
integral,
1219+
internal,
12161220
internal_features,
12171221
into_async_iter_into_iter,
12181222
into_future,
@@ -1277,6 +1281,8 @@ symbols! {
12771281
likely,
12781282
line,
12791283
link,
1284+
linkonce,
1285+
linkonce_odr,
12801286
link_arg_attribute,
12811287
link_args,
12821288
link_cfg,
@@ -2360,6 +2366,8 @@ symbols! {
23602366
wasm_abi,
23612367
wasm_import_module,
23622368
wasm_target_feature,
2369+
weak,
2370+
weak_odr,
23632371
where_clause_attrs,
23642372
while_let,
23652373
width,

0 commit comments

Comments
 (0)