Skip to main content

rustc_attr_parsing/attributes/
instruction_set.rs

1use rustc_attr_ir::InstructionSetAttr;
2use rustc_feature::AttributeStability;
3
4use super::prelude::*;
5use crate::diagnostics;
6
7pub(crate) struct InstructionSetParser;
8
9impl SingleAttributeParser for InstructionSetParser {
10    const PATH: &[Symbol] = &[sym::instruction_set];
11    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[
12        Allow(Target::Fn),
13        Allow(Target::Closure),
14        Allow(Target::Method(MethodKind::Inherent)),
15        Allow(Target::Method(MethodKind::TraitImpl)),
16        Allow(Target::Method(MethodKind::Trait { body: true })),
17        Error(Target::Param),
18    ]);
19    const TEMPLATE: AttributeTemplate = crate::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");
20    const STABILITY: AttributeStability = AttributeStability::Stable;
21
22    fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
23        const POSSIBLE_SYMBOLS: &[Symbol] = &[sym::arm_a32, sym::arm_t32];
24        const POSSIBLE_ARM_SYMBOLS: &[Symbol] = &[sym::a32, sym::t32];
25        let maybe_meta_item = cx.expect_single_element_list(args, cx.attr_span)?;
26
27        let Some(meta_item) = maybe_meta_item.meta_item_no_args() else {
28            cx.adcx().expected_specific_argument(maybe_meta_item.span(), POSSIBLE_SYMBOLS);
29            return None;
30        };
31
32        let mut segments = meta_item.path().segments();
33
34        let Some(architecture) = segments.next() else {
35            cx.adcx().expected_specific_argument(meta_item.span(), POSSIBLE_SYMBOLS);
36            return None;
37        };
38
39        let Some(instruction_set) = segments.next() else {
40            cx.adcx().expected_specific_argument(architecture.span, POSSIBLE_SYMBOLS);
41            return None;
42        };
43
44        let instruction_set = match architecture.name {
45            sym::arm => {
46                if !cx.sess.target.has_thumb_interworking {
47                    cx.dcx().emit_err(diagnostics::UnsupportedInstructionSet {
48                        span: cx.attr_span,
49                        instruction_set: sym::arm,
50                        current_target: &cx.sess.opts.target_triple,
51                    });
52                    return None;
53                }
54                match instruction_set.name {
55                    sym::a32 => InstructionSetAttr::ArmA32,
56                    sym::t32 => InstructionSetAttr::ArmT32,
57                    _ => {
58                        cx.adcx()
59                            .expected_specific_argument(instruction_set.span, POSSIBLE_ARM_SYMBOLS);
60                        return None;
61                    }
62                }
63            }
64            _ => {
65                cx.adcx().expected_specific_argument(architecture.span, POSSIBLE_SYMBOLS);
66                return None;
67            }
68        };
69
70        Some(AttributeKind::InstructionSet(instruction_set))
71    }
72}