| use rustc_feature::AttributeStability; | |
| use rustc_hir::attrs::InstructionSetAttr; | |
| use super::prelude::*; | |
| use crate::session_diagnostics; | |
| pub(crate) struct InstructionSetParser; | |
| impl SingleAttributeParser for InstructionSetParser { | |
| const PATH: &[Symbol] = &[sym::instruction_set]; | |
| const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ | |
| Allow(Target::Fn), | |
| Allow(Target::Closure), | |
| Allow(Target::Method(MethodKind::Inherent)), | |
| Allow(Target::Method(MethodKind::TraitImpl)), | |
| Allow(Target::Method(MethodKind::Trait { body: true })), | |
| ]); | |
| const TEMPLATE: AttributeTemplate = template!(List: &["set"], "https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute"); | |
| const STABILITY: AttributeStability = AttributeStability::Stable; | |
| fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { | |
| const POSSIBLE_SYMBOLS: &[Symbol] = &[sym::arm_a32, sym::arm_t32]; | |
| const POSSIBLE_ARM_SYMBOLS: &[Symbol] = &[sym::a32, sym::t32]; | |
| let maybe_meta_item = cx.expect_single_element_list(args, cx.attr_span)?; | |
| let Some(meta_item) = maybe_meta_item.meta_item_no_args() else { | |
| cx.adcx().expected_specific_argument(maybe_meta_item.span(), POSSIBLE_SYMBOLS); | |
| return None; | |
| }; | |
| let mut segments = meta_item.path().segments(); | |
| let Some(architecture) = segments.next() else { | |
| cx.adcx().expected_specific_argument(meta_item.span(), POSSIBLE_SYMBOLS); | |
| return None; | |
| }; | |
| let Some(instruction_set) = segments.next() else { | |
| cx.adcx().expected_specific_argument(architecture.span, POSSIBLE_SYMBOLS); | |
| return None; | |
| }; | |
| let instruction_set = match architecture.name { | |
| sym::arm => { | |
| if !cx.sess.target.has_thumb_interworking { | |
| cx.dcx().emit_err(session_diagnostics::UnsupportedInstructionSet { | |
| span: cx.attr_span, | |
| instruction_set: sym::arm, | |
| current_target: &cx.sess.opts.target_triple, | |
| }); | |
| return None; | |
| } | |
| match instruction_set.name { | |
| sym::a32 => InstructionSetAttr::ArmA32, | |
| sym::t32 => InstructionSetAttr::ArmT32, | |
| _ => { | |
| cx.adcx() | |
| .expected_specific_argument(instruction_set.span, POSSIBLE_ARM_SYMBOLS); | |
| return None; | |
| } | |
| } | |
| } | |
| _ => { | |
| cx.adcx().expected_specific_argument(architecture.span, POSSIBLE_SYMBOLS); | |
| return None; | |
| } | |
| }; | |
| Some(AttributeKind::InstructionSet(instruction_set)) | |
| } | |
| } |