Skip to main content

rustc_attr_parsing/attributes/
instruction_set.rs

1use rustc_hir::attrs::InstructionSetAttr;
2
3use super::prelude::*;
4use crate::session_diagnostics;
5
6pub(crate) struct InstructionSetParser;
7
8impl<S: Stage> SingleAttributeParser<S> for InstructionSetParser {
9    const PATH: &[Symbol] = &[sym::instruction_set];
10    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
11        Allow(Target::Fn),
12        Allow(Target::Closure),
13        Allow(Target::Method(MethodKind::Inherent)),
14        Allow(Target::Method(MethodKind::TraitImpl)),
15        Allow(Target::Method(MethodKind::Trait { body: true })),
16    ]);
17    const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
    word: false,
    list: Some(&["set"]),
    one_of: &[],
    name_value_str: None,
    docs: Some("https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute"),
}template!(List: &["set"], "https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute");
18    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
19
20    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
21        const POSSIBLE_SYMBOLS: &[Symbol] = &[sym::arm_a32, sym::arm_t32];
22        const POSSIBLE_ARM_SYMBOLS: &[Symbol] = &[sym::a32, sym::t32];
23        let Some(maybe_meta_item) = args.list().and_then(MetaItemListParser::single) else {
24            let attr_span = cx.attr_span;
25            cx.adcx().expected_specific_argument(attr_span, POSSIBLE_SYMBOLS);
26            return None;
27        };
28
29        let Some(meta_item) = maybe_meta_item.meta_item() else {
30            cx.adcx().expected_specific_argument(maybe_meta_item.span(), POSSIBLE_SYMBOLS);
31            return None;
32        };
33
34        let mut segments = meta_item.path().segments();
35
36        let Some(architecture) = segments.next() else {
37            cx.adcx().expected_specific_argument(meta_item.span(), POSSIBLE_SYMBOLS);
38            return None;
39        };
40
41        let Some(instruction_set) = segments.next() else {
42            cx.adcx().expected_specific_argument(architecture.span, POSSIBLE_SYMBOLS);
43            return None;
44        };
45
46        let instruction_set = match architecture.name {
47            sym::arm => {
48                if !cx.sess.target.has_thumb_interworking {
49                    cx.dcx().emit_err(session_diagnostics::UnsupportedInstructionSet {
50                        span: cx.attr_span,
51                        instruction_set: sym::arm,
52                        current_target: &cx.sess.opts.target_triple,
53                    });
54                    return None;
55                }
56                match instruction_set.name {
57                    sym::a32 => InstructionSetAttr::ArmA32,
58                    sym::t32 => InstructionSetAttr::ArmT32,
59                    _ => {
60                        cx.adcx()
61                            .expected_specific_argument(instruction_set.span, POSSIBLE_ARM_SYMBOLS);
62                        return None;
63                    }
64                }
65            }
66            _ => {
67                cx.adcx().expected_specific_argument(architecture.span, POSSIBLE_SYMBOLS);
68                return None;
69            }
70        };
71
72        Some(AttributeKind::InstructionSet(instruction_set))
73    }
74}