about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs12
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs7
-rw-r--r--compiler/rustc_passes/src/intrinsicck.rs16
-rw-r--r--compiler/rustc_passes/src/lib.rs1
-rw-r--r--compiler/rustc_span/src/symbol.rs12
-rw-r--r--compiler/rustc_target/src/asm/aarch64.rs8
-rw-r--r--compiler/rustc_target/src/asm/arm.rs32
-rw-r--r--compiler/rustc_target/src/asm/avr.rs3
-rw-r--r--compiler/rustc_target/src/asm/bpf.rs10
-rw-r--r--compiler/rustc_target/src/asm/hexagon.rs3
-rw-r--r--compiler/rustc_target/src/asm/mips.rs3
-rw-r--r--compiler/rustc_target/src/asm/mod.rs74
-rw-r--r--compiler/rustc_target/src/asm/nvptx.rs3
-rw-r--r--compiler/rustc_target/src/asm/powerpc.rs3
-rw-r--r--compiler/rustc_target/src/asm/riscv.rs10
-rw-r--r--compiler/rustc_target/src/asm/s390x.rs3
-rw-r--r--compiler/rustc_target/src/asm/spirv.rs3
-rw-r--r--compiler/rustc_target/src/asm/wasm.rs3
-rw-r--r--compiler/rustc_target/src/asm/x86.rs22
21 files changed, 133 insertions, 105 deletions
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 9c28f3c7f58..89d411d4b36 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -6,7 +6,7 @@ use rustc_data_structures::stable_set::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_session::parse::feature_err;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{sym, Span};
 use rustc_target::asm;
 use std::collections::hash_map::Entry;
 use std::fmt::Write;
@@ -66,7 +66,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             for (abi_name, abi_span) in &asm.clobber_abis {
                 match asm::InlineAsmClobberAbi::parse(
                     asm_arch,
-                    |feature| self.sess.target_features.contains(&Symbol::intern(feature)),
+                    &self.sess.target_features,
                     &self.sess.target,
                     *abi_name,
                 ) {
@@ -134,7 +134,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch {
                             asm::InlineAsmReg::parse(
                                 asm_arch,
-                                |feature| sess.target_features.contains(&Symbol::intern(feature)),
+                                &sess.target_features,
                                 &sess.target,
                                 s,
                             )
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index 93384bc5511..c242c75ed18 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -6,7 +6,7 @@ use std::fmt::Write;
 
 use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_middle::mir::InlineAsmOperand;
-use rustc_span::Symbol;
+use rustc_span::sym;
 use rustc_target::asm::*;
 
 pub(crate) fn codegen_inline_asm<'tcx>(
@@ -182,11 +182,7 @@ struct InlineAssemblyGenerator<'a, 'tcx> {
 impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
     fn allocate_registers(&mut self) {
         let sess = self.tcx.sess;
-        let map = allocatable_registers(
-            self.arch,
-            |feature| sess.target_features.contains(&Symbol::intern(feature)),
-            &sess.target,
-        );
+        let map = allocatable_registers(self.arch, &sess.target_features, &sess.target);
         let mut allocated = FxHashMap::<_, (bool, bool)>::default();
         let mut regs = vec![None; self.operands.len()];
 
@@ -319,9 +315,9 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
         // Allocate stack slots for saving clobbered registers
         let abi_clobber = InlineAsmClobberAbi::parse(
             self.arch,
-            |feature| self.tcx.sess.target_features.contains(&Symbol::intern(feature)),
+            &self.tcx.sess.target_features,
             &self.tcx.sess.target,
-            Symbol::intern("C"),
+            sym::C,
         )
         .unwrap()
         .clobbered_regs();
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index d620b24e067..b4213da6e05 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -5,7 +5,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::{AsmBuilderMethods, AsmMethods, BaseTypeMethods, BuilderMethods, GlobalAsmOperandRef, InlineAsmOperandRef};
 
 use rustc_middle::{bug, ty::Instance};
-use rustc_span::{Span, Symbol};
+use rustc_span::Span;
 use rustc_target::asm::*;
 
 use std::borrow::Cow;
@@ -172,7 +172,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                             let is_target_supported = reg.reg_class().supported_types(asm_arch).iter()
                                 .any(|&(_, feature)| {
                                     if let Some(feature) = feature {
-                                        self.tcx.sess.target_features.contains(&Symbol::intern(feature))
+                                        self.tcx.sess.target_features.contains(&feature)
                                     } else {
                                         true // Register class is unconditionally supported
                                     }
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 8335f841bec..8b696dc6fba 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -13,7 +13,7 @@ use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::{bug, span_bug, ty::Instance};
-use rustc_span::{Pos, Span, Symbol};
+use rustc_span::{Pos, Span};
 use rustc_target::abi::*;
 use rustc_target::asm::*;
 
@@ -45,9 +45,8 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                         for &(_, feature) in reg_class.supported_types(asm_arch) {
                             if let Some(feature) = feature {
                                 let codegen_fn_attrs = self.tcx.codegen_fn_attrs(instance.def_id());
-                                let feature_name = Symbol::intern(feature);
-                                if self.tcx.sess.target_features.contains(&feature_name)
-                                    || codegen_fn_attrs.target_features.contains(&feature_name)
+                                if self.tcx.sess.target_features.contains(&feature)
+                                    || codegen_fn_attrs.target_features.contains(&feature)
                                 {
                                     return true;
                                 }
diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_passes/src/intrinsicck.rs
index 85c568d8623..1031ba01c1b 100644
--- a/compiler/rustc_passes/src/intrinsicck.rs
+++ b/compiler/rustc_passes/src/intrinsicck.rs
@@ -294,9 +294,8 @@ impl<'tcx> ExprVisitor<'tcx> {
         // (!). In that case we still need the earlier check to verify that the
         // register class is usable at all.
         if let Some(feature) = feature {
-            let feat_sym = Symbol::intern(feature);
-            if !self.tcx.sess.target_features.contains(&feat_sym)
-                && !target_features.contains(&feat_sym)
+            if !self.tcx.sess.target_features.contains(&feature)
+                && !target_features.contains(&feature)
             {
                 let msg = &format!("`{}` target feature is not enabled", feature);
                 let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
@@ -377,9 +376,8 @@ impl<'tcx> ExprVisitor<'tcx> {
                     {
                         match feature {
                             Some(feature) => {
-                                let feat_sym = Symbol::intern(feature);
-                                if self.tcx.sess.target_features.contains(&feat_sym)
-                                    || attrs.target_features.contains(&feat_sym)
+                                if self.tcx.sess.target_features.contains(&feature)
+                                    || attrs.target_features.contains(&feature)
                                 {
                                     missing_required_features.clear();
                                     break;
@@ -413,7 +411,11 @@ impl<'tcx> ExprVisitor<'tcx> {
                             let msg = format!(
                                 "register class `{}` requires at least one of the following target features: {}",
                                 reg_class.name(),
-                                features.join(", ")
+                                features
+                                    .iter()
+                                    .map(|f| f.as_str())
+                                    .intersperse(", ")
+                                    .collect::<String>(),
                             );
                             self.tcx.sess.struct_span_err(*op_sp, &msg).emit();
                             // register isn't enabled, don't do more checks
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 3596210036a..2075fee7171 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -6,6 +6,7 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(crate_visibility_modifier)]
+#![feature(iter_intersperse)]
 #![feature(let_else)]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 075a9764d4c..af87399ac95 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -316,6 +316,7 @@ symbols! {
         allow_internal_unsafe,
         allow_internal_unstable,
         allowed,
+        alu32,
         always,
         and,
         and_then,
@@ -362,7 +363,10 @@ symbols! {
         augmented_assignments,
         auto_traits,
         automatically_derived,
+        avx,
         avx512_target_feature,
+        avx512bw,
+        avx512f,
         await_macro,
         bang,
         begin_panic,
@@ -593,6 +597,7 @@ symbols! {
         dylib,
         dyn_metadata,
         dyn_trait,
+        e,
         edition_macro_pats,
         edition_panic,
         eh_catch_typeinfo,
@@ -683,6 +688,7 @@ symbols! {
         format_args_macro,
         format_args_nl,
         format_macro,
+        fp,
         freeze,
         freg,
         frem_fast,
@@ -908,6 +914,7 @@ symbols! {
         neg,
         negate_unsigned,
         negative_impls,
+        neon,
         never,
         never_type,
         never_type_fallback,
@@ -1102,6 +1109,7 @@ symbols! {
         repr_packed,
         repr_simd,
         repr_transparent,
+        reserved_r9: "reserved-r9",
         residual,
         result,
         rhs,
@@ -1296,6 +1304,7 @@ symbols! {
         sqrtf64,
         sreg,
         sreg_low16,
+        sse,
         sse4a_target_feature,
         stable,
         staged_api,
@@ -1362,6 +1371,8 @@ symbols! {
         thread,
         thread_local,
         thread_local_macro,
+        thumb2,
+        thumb_mode: "thumb-mode",
         todo_macro,
         tool_attributes,
         tool_lints,
@@ -1455,6 +1466,7 @@ symbols! {
         vec,
         vec_macro,
         version,
+        vfp2,
         vis,
         visible_private_types,
         volatile,
diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs
index 4bf909ce46d..da875508676 100644
--- a/compiler/rustc_target/src/asm/aarch64.rs
+++ b/compiler/rustc_target/src/asm/aarch64.rs
@@ -1,6 +1,8 @@
 use super::{InlineAsmArch, InlineAsmType};
 use crate::spec::Target;
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_macros::HashStable_Generic;
+use rustc_span::Symbol;
 use std::fmt;
 
 def_reg_class! {
@@ -58,11 +60,11 @@ impl AArch64InlineAsmRegClass {
     pub fn supported_types(
         self,
         _arch: InlineAsmArch,
-    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match self {
             Self::reg => types! { _: I8, I16, I32, I64, F32, F64; },
             Self::vreg | Self::vreg_low16 => types! {
-                "fp": I8, I16, I32, I64, F32, F64,
+                fp: I8, I16, I32, I64, F32, F64,
                     VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2), VecF64(1),
                     VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
             },
@@ -73,7 +75,7 @@ impl AArch64InlineAsmRegClass {
 
 pub fn reserved_x18(
     _arch: InlineAsmArch,
-    _has_feature: impl FnMut(&str) -> bool,
+    _target_features: &FxHashSet<Symbol>,
     target: &Target,
 ) -> Result<(), &'static str> {
     if target.os == "android"
diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs
index b03594b3151..e3615b43c70 100644
--- a/compiler/rustc_target/src/asm/arm.rs
+++ b/compiler/rustc_target/src/asm/arm.rs
@@ -1,6 +1,8 @@
 use super::{InlineAsmArch, InlineAsmType};
 use crate::spec::Target;
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_macros::HashStable_Generic;
+use rustc_span::{sym, Symbol};
 use std::fmt;
 
 def_reg_class! {
@@ -44,31 +46,31 @@ impl ArmInlineAsmRegClass {
     pub fn supported_types(
         self,
         _arch: InlineAsmArch,
-    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match self {
             Self::reg => types! { _: I8, I16, I32, F32; },
-            Self::sreg | Self::sreg_low16 => types! { "vfp2": I32, F32; },
+            Self::sreg | Self::sreg_low16 => types! { vfp2: I32, F32; },
             Self::dreg | Self::dreg_low16 | Self::dreg_low8 => types! {
-                "vfp2": I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2);
+                vfp2: I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2);
             },
             Self::qreg | Self::qreg_low8 | Self::qreg_low4 => types! {
-                "neon": VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4);
+                neon: VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4);
             },
         }
     }
 }
 
 // This uses the same logic as useR7AsFramePointer in LLVM
-fn frame_pointer_is_r7(mut has_feature: impl FnMut(&str) -> bool, target: &Target) -> bool {
-    target.is_like_osx || (!target.is_like_windows && has_feature("thumb-mode"))
+fn frame_pointer_is_r7(target_features: &FxHashSet<Symbol>, target: &Target) -> bool {
+    target.is_like_osx || (!target.is_like_windows && target_features.contains(&sym::thumb_mode))
 }
 
 fn frame_pointer_r11(
     _arch: InlineAsmArch,
-    has_feature: impl FnMut(&str) -> bool,
+    target_features: &FxHashSet<Symbol>,
     target: &Target,
 ) -> Result<(), &'static str> {
-    if !frame_pointer_is_r7(has_feature, target) {
+    if !frame_pointer_is_r7(target_features, target) {
         Err("the frame pointer (r11) cannot be used as an operand for inline asm")
     } else {
         Ok(())
@@ -77,10 +79,10 @@ fn frame_pointer_r11(
 
 fn frame_pointer_r7(
     _arch: InlineAsmArch,
-    has_feature: impl FnMut(&str) -> bool,
+    target_features: &FxHashSet<Symbol>,
     target: &Target,
 ) -> Result<(), &'static str> {
-    if frame_pointer_is_r7(has_feature, target) {
+    if frame_pointer_is_r7(target_features, target) {
         Err("the frame pointer (r7) cannot be used as an operand for inline asm")
     } else {
         Ok(())
@@ -89,10 +91,10 @@ fn frame_pointer_r7(
 
 fn not_thumb1(
     _arch: InlineAsmArch,
-    mut has_feature: impl FnMut(&str) -> bool,
+    target_features: &FxHashSet<Symbol>,
     _target: &Target,
 ) -> Result<(), &'static str> {
-    if has_feature("thumb-mode") && !has_feature("thumb2") {
+    if target_features.contains(&sym::thumb_mode) && !target_features.contains(&sym::thumb2) {
         Err("high registers (r8+) cannot be used in Thumb-1 code")
     } else {
         Ok(())
@@ -101,14 +103,14 @@ fn not_thumb1(
 
 fn reserved_r9(
     arch: InlineAsmArch,
-    mut has_feature: impl FnMut(&str) -> bool,
+    target_features: &FxHashSet<Symbol>,
     target: &Target,
 ) -> Result<(), &'static str> {
-    not_thumb1(arch, &mut has_feature, target)?;
+    not_thumb1(arch, target_features, target)?;
 
     // We detect this using the reserved-r9 feature instead of using the target
     // because the relocation model can be changed with compiler options.
-    if has_feature("reserved-r9") {
+    if target_features.contains(&sym::reserved_r9) {
         Err("the RWPI static base register (r9) cannot be used as an operand for inline asm")
     } else {
         Ok(())
diff --git a/compiler/rustc_target/src/asm/avr.rs b/compiler/rustc_target/src/asm/avr.rs
index 82a4f8bacb3..9a96a61f5b2 100644
--- a/compiler/rustc_target/src/asm/avr.rs
+++ b/compiler/rustc_target/src/asm/avr.rs
@@ -1,5 +1,6 @@
 use super::{InlineAsmArch, InlineAsmType};
 use rustc_macros::HashStable_Generic;
+use rustc_span::Symbol;
 use std::fmt;
 
 def_reg_class! {
@@ -39,7 +40,7 @@ impl AvrInlineAsmRegClass {
     pub fn supported_types(
         self,
         _arch: InlineAsmArch,
-    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match self {
             Self::reg => types! { _: I8; },
             Self::reg_upper => types! { _: I8; },
diff --git a/compiler/rustc_target/src/asm/bpf.rs b/compiler/rustc_target/src/asm/bpf.rs
index ecb6bdc95ce..d94fcb53e24 100644
--- a/compiler/rustc_target/src/asm/bpf.rs
+++ b/compiler/rustc_target/src/asm/bpf.rs
@@ -1,5 +1,7 @@
 use super::{InlineAsmArch, InlineAsmType, Target};
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_macros::HashStable_Generic;
+use rustc_span::{sym, Symbol};
 use std::fmt;
 
 def_reg_class! {
@@ -33,20 +35,20 @@ impl BpfInlineAsmRegClass {
     pub fn supported_types(
         self,
         _arch: InlineAsmArch,
-    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match self {
             Self::reg => types! { _: I8, I16, I32, I64; },
-            Self::wreg => types! { "alu32": I8, I16, I32; },
+            Self::wreg => types! { alu32: I8, I16, I32; },
         }
     }
 }
 
 fn only_alu32(
     _arch: InlineAsmArch,
-    mut has_feature: impl FnMut(&str) -> bool,
+    target_features: &FxHashSet<Symbol>,
     _target: &Target,
 ) -> Result<(), &'static str> {
-    if !has_feature("alu32") {
+    if !target_features.contains(&sym::alu32) {
         Err("register can't be used without the `alu32` target feature")
     } else {
         Ok(())
diff --git a/compiler/rustc_target/src/asm/hexagon.rs b/compiler/rustc_target/src/asm/hexagon.rs
index 74afddb69dc..d20270ac9e9 100644
--- a/compiler/rustc_target/src/asm/hexagon.rs
+++ b/compiler/rustc_target/src/asm/hexagon.rs
@@ -1,5 +1,6 @@
 use super::{InlineAsmArch, InlineAsmType};
 use rustc_macros::HashStable_Generic;
+use rustc_span::Symbol;
 use std::fmt;
 
 def_reg_class! {
@@ -32,7 +33,7 @@ impl HexagonInlineAsmRegClass {
     pub fn supported_types(
         self,
         _arch: InlineAsmArch,
-    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match self {
             Self::reg => types! { _: I8, I16, I32, F32; },
         }
diff --git a/compiler/rustc_target/src/asm/mips.rs b/compiler/rustc_target/src/asm/mips.rs
index b19489aa439..b1e8737b52b 100644
--- a/compiler/rustc_target/src/asm/mips.rs
+++ b/compiler/rustc_target/src/asm/mips.rs
@@ -1,5 +1,6 @@
 use super::{InlineAsmArch, InlineAsmType};
 use rustc_macros::HashStable_Generic;
+use rustc_span::Symbol;
 use std::fmt;
 
 def_reg_class! {
@@ -33,7 +34,7 @@ impl MipsInlineAsmRegClass {
     pub fn supported_types(
         self,
         arch: InlineAsmArch,
-    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match (self, arch) {
             (Self::reg, InlineAsmArch::Mips64) => types! { _: I8, I16, I32, I64, F32, F64; },
             (Self::reg, _) => types! { _: I8, I16, I32, F32; },
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index 9128e54682f..6b82bb337e6 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -81,14 +81,14 @@ macro_rules! def_regs {
 
             pub fn parse(
                 _arch: super::InlineAsmArch,
-                mut _has_feature: impl FnMut(&str) -> bool,
+                _target_features: &rustc_data_structures::fx::FxHashSet<Symbol>,
                 _target: &crate::spec::Target,
                 name: &str,
             ) -> Result<Self, &'static str> {
                 match name {
                     $(
                         $($alias)|* | $reg_name => {
-                            $($filter(_arch, &mut _has_feature, _target)?;)?
+                            $($filter(_arch, _target_features, _target)?;)?
                             Ok(Self::$reg)
                         }
                     )*
@@ -102,7 +102,7 @@ macro_rules! def_regs {
 
         pub(super) fn fill_reg_map(
             _arch: super::InlineAsmArch,
-            mut _has_feature: impl FnMut(&str) -> bool,
+            _target_features: &rustc_data_structures::fx::FxHashSet<Symbol>,
             _target: &crate::spec::Target,
             _map: &mut rustc_data_structures::fx::FxHashMap<
                 super::InlineAsmRegClass,
@@ -112,7 +112,7 @@ macro_rules! def_regs {
             #[allow(unused_imports)]
             use super::{InlineAsmReg, InlineAsmRegClass};
             $(
-                if $($filter(_arch, &mut _has_feature, _target).is_ok() &&)? true {
+                if $($filter(_arch, _target_features, _target).is_ok() &&)? true {
                     if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) {
                         set.insert(InlineAsmReg::$arch($arch_reg::$reg));
                     }
@@ -130,7 +130,7 @@ macro_rules! def_regs {
 macro_rules! types {
     (
         $(_ : $($ty:expr),+;)?
-        $($feature:literal: $($ty2:expr),+;)*
+        $($feature:ident: $($ty2:expr),+;)*
     ) => {
         {
             use super::InlineAsmType::*;
@@ -139,7 +139,7 @@ macro_rules! types {
                     ($ty, None),
                 )*)?
                 $($(
-                    ($ty2, Some($feature)),
+                    ($ty2, Some(rustc_span::sym::$feature)),
                 )*)*
             ]
         }
@@ -289,7 +289,7 @@ impl InlineAsmReg {
 
     pub fn parse(
         arch: InlineAsmArch,
-        has_feature: impl FnMut(&str) -> bool,
+        target_features: &FxHashSet<Symbol>,
         target: &Target,
         name: Symbol,
     ) -> Result<Self, &'static str> {
@@ -298,43 +298,43 @@ impl InlineAsmReg {
         let name = name.as_str();
         Ok(match arch {
             InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
-                Self::X86(X86InlineAsmReg::parse(arch, has_feature, target, name)?)
+                Self::X86(X86InlineAsmReg::parse(arch, target_features, target, name)?)
             }
             InlineAsmArch::Arm => {
-                Self::Arm(ArmInlineAsmReg::parse(arch, has_feature, target, name)?)
+                Self::Arm(ArmInlineAsmReg::parse(arch, target_features, target, name)?)
             }
             InlineAsmArch::AArch64 => {
-                Self::AArch64(AArch64InlineAsmReg::parse(arch, has_feature, target, name)?)
+                Self::AArch64(AArch64InlineAsmReg::parse(arch, target_features, target, name)?)
             }
             InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
-                Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, target, name)?)
+                Self::RiscV(RiscVInlineAsmReg::parse(arch, target_features, target, name)?)
             }
             InlineAsmArch::Nvptx64 => {
-                Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, name)?)
+                Self::Nvptx(NvptxInlineAsmReg::parse(arch, target_features, target, name)?)
             }
             InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
-                Self::PowerPC(PowerPCInlineAsmReg::parse(arch, has_feature, target, name)?)
+                Self::PowerPC(PowerPCInlineAsmReg::parse(arch, target_features, target, name)?)
             }
             InlineAsmArch::Hexagon => {
-                Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, name)?)
+                Self::Hexagon(HexagonInlineAsmReg::parse(arch, target_features, target, name)?)
             }
             InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
-                Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, name)?)
+                Self::Mips(MipsInlineAsmReg::parse(arch, target_features, target, name)?)
             }
             InlineAsmArch::S390x => {
-                Self::S390x(S390xInlineAsmReg::parse(arch, has_feature, target, name)?)
+                Self::S390x(S390xInlineAsmReg::parse(arch, target_features, target, name)?)
             }
             InlineAsmArch::SpirV => {
-                Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, name)?)
+                Self::SpirV(SpirVInlineAsmReg::parse(arch, target_features, target, name)?)
             }
             InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
-                Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, name)?)
+                Self::Wasm(WasmInlineAsmReg::parse(arch, target_features, target, name)?)
             }
             InlineAsmArch::Bpf => {
-                Self::Bpf(BpfInlineAsmReg::parse(arch, has_feature, target, name)?)
+                Self::Bpf(BpfInlineAsmReg::parse(arch, target_features, target, name)?)
             }
             InlineAsmArch::Avr => {
-                Self::Avr(AvrInlineAsmReg::parse(arch, has_feature, target, name)?)
+                Self::Avr(AvrInlineAsmReg::parse(arch, target_features, target, name)?)
             }
         })
     }
@@ -510,7 +510,7 @@ impl InlineAsmRegClass {
     pub fn supported_types(
         self,
         arch: InlineAsmArch,
-    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match self {
             Self::X86(r) => r.supported_types(arch),
             Self::Arm(r) => r.supported_types(arch),
@@ -695,73 +695,73 @@ impl fmt::Display for InlineAsmType {
 // falling back to an external assembler.
 pub fn allocatable_registers(
     arch: InlineAsmArch,
-    has_feature: impl FnMut(&str) -> bool,
+    target_features: &FxHashSet<Symbol>,
     target: &crate::spec::Target,
 ) -> FxHashMap<InlineAsmRegClass, FxHashSet<InlineAsmReg>> {
     match arch {
         InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
             let mut map = x86::regclass_map();
-            x86::fill_reg_map(arch, has_feature, target, &mut map);
+            x86::fill_reg_map(arch, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Arm => {
             let mut map = arm::regclass_map();
-            arm::fill_reg_map(arch, has_feature, target, &mut map);
+            arm::fill_reg_map(arch, target_features, target, &mut map);
             map
         }
         InlineAsmArch::AArch64 => {
             let mut map = aarch64::regclass_map();
-            aarch64::fill_reg_map(arch, has_feature, target, &mut map);
+            aarch64::fill_reg_map(arch, target_features, target, &mut map);
             map
         }
         InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
             let mut map = riscv::regclass_map();
-            riscv::fill_reg_map(arch, has_feature, target, &mut map);
+            riscv::fill_reg_map(arch, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Nvptx64 => {
             let mut map = nvptx::regclass_map();
-            nvptx::fill_reg_map(arch, has_feature, target, &mut map);
+            nvptx::fill_reg_map(arch, target_features, target, &mut map);
             map
         }
         InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
             let mut map = powerpc::regclass_map();
-            powerpc::fill_reg_map(arch, has_feature, target, &mut map);
+            powerpc::fill_reg_map(arch, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Hexagon => {
             let mut map = hexagon::regclass_map();
-            hexagon::fill_reg_map(arch, has_feature, target, &mut map);
+            hexagon::fill_reg_map(arch, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
             let mut map = mips::regclass_map();
-            mips::fill_reg_map(arch, has_feature, target, &mut map);
+            mips::fill_reg_map(arch, target_features, target, &mut map);
             map
         }
         InlineAsmArch::S390x => {
             let mut map = s390x::regclass_map();
-            s390x::fill_reg_map(arch, has_feature, target, &mut map);
+            s390x::fill_reg_map(arch, target_features, target, &mut map);
             map
         }
         InlineAsmArch::SpirV => {
             let mut map = spirv::regclass_map();
-            spirv::fill_reg_map(arch, has_feature, target, &mut map);
+            spirv::fill_reg_map(arch, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
             let mut map = wasm::regclass_map();
-            wasm::fill_reg_map(arch, has_feature, target, &mut map);
+            wasm::fill_reg_map(arch, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Bpf => {
             let mut map = bpf::regclass_map();
-            bpf::fill_reg_map(arch, has_feature, target, &mut map);
+            bpf::fill_reg_map(arch, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Avr => {
             let mut map = avr::regclass_map();
-            avr::fill_reg_map(arch, has_feature, target, &mut map);
+            avr::fill_reg_map(arch, target_features, target, &mut map);
             map
         }
     }
@@ -794,7 +794,7 @@ impl InlineAsmClobberAbi {
     /// clobber ABIs for the target.
     pub fn parse(
         arch: InlineAsmArch,
-        has_feature: impl FnMut(&str) -> bool,
+        target_features: &FxHashSet<Symbol>,
         target: &Target,
         name: Symbol,
     ) -> Result<Self, &'static [&'static str]> {
@@ -819,7 +819,7 @@ impl InlineAsmClobberAbi {
             },
             InlineAsmArch::AArch64 => match name {
                 "C" | "system" | "efiapi" => {
-                    Ok(if aarch64::reserved_x18(arch, has_feature, target).is_err() {
+                    Ok(if aarch64::reserved_x18(arch, target_features, target).is_err() {
                         InlineAsmClobberAbi::AArch64NoX18
                     } else {
                         InlineAsmClobberAbi::AArch64
diff --git a/compiler/rustc_target/src/asm/nvptx.rs b/compiler/rustc_target/src/asm/nvptx.rs
index 43d16ae0f5d..8e1e91e7c5f 100644
--- a/compiler/rustc_target/src/asm/nvptx.rs
+++ b/compiler/rustc_target/src/asm/nvptx.rs
@@ -1,5 +1,6 @@
 use super::{InlineAsmArch, InlineAsmType};
 use rustc_macros::HashStable_Generic;
+use rustc_span::Symbol;
 
 def_reg_class! {
     Nvptx NvptxInlineAsmRegClass {
@@ -33,7 +34,7 @@ impl NvptxInlineAsmRegClass {
     pub fn supported_types(
         self,
         _arch: InlineAsmArch,
-    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match self {
             Self::reg16 => types! { _: I8, I16; },
             Self::reg32 => types! { _: I8, I16, I32, F32; },
diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs
index 51a4303689e..d3ccb30350a 100644
--- a/compiler/rustc_target/src/asm/powerpc.rs
+++ b/compiler/rustc_target/src/asm/powerpc.rs
@@ -1,5 +1,6 @@
 use super::{InlineAsmArch, InlineAsmType};
 use rustc_macros::HashStable_Generic;
+use rustc_span::Symbol;
 use std::fmt;
 
 def_reg_class! {
@@ -36,7 +37,7 @@ impl PowerPCInlineAsmRegClass {
     pub fn supported_types(
         self,
         arch: InlineAsmArch,
-    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match self {
             Self::reg | Self::reg_nonzero => {
                 if arch == InlineAsmArch::PowerPC {
diff --git a/compiler/rustc_target/src/asm/riscv.rs b/compiler/rustc_target/src/asm/riscv.rs
index 314bd01de12..39644d232ba 100644
--- a/compiler/rustc_target/src/asm/riscv.rs
+++ b/compiler/rustc_target/src/asm/riscv.rs
@@ -1,6 +1,8 @@
 use super::{InlineAsmArch, InlineAsmType};
 use crate::spec::Target;
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_macros::HashStable_Generic;
+use rustc_span::{sym, Symbol};
 use std::fmt;
 
 def_reg_class! {
@@ -35,7 +37,7 @@ impl RiscVInlineAsmRegClass {
     pub fn supported_types(
         self,
         arch: InlineAsmArch,
-    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match self {
             Self::reg => {
                 if arch == InlineAsmArch::RiscV64 {
@@ -44,7 +46,7 @@ impl RiscVInlineAsmRegClass {
                     types! { _: I8, I16, I32, F32; }
                 }
             }
-            Self::freg => types! { "f": F32; "d": F64; },
+            Self::freg => types! { f: F32; d: F64; },
             Self::vreg => &[],
         }
     }
@@ -52,10 +54,10 @@ impl RiscVInlineAsmRegClass {
 
 fn not_e(
     _arch: InlineAsmArch,
-    mut has_feature: impl FnMut(&str) -> bool,
+    target_features: &FxHashSet<Symbol>,
     _target: &Target,
 ) -> Result<(), &'static str> {
-    if has_feature("e") {
+    if target_features.contains(&sym::e) {
         Err("register can't be used with the `e` target feature")
     } else {
         Ok(())
diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs
index a74873f1747..0a50064f587 100644
--- a/compiler/rustc_target/src/asm/s390x.rs
+++ b/compiler/rustc_target/src/asm/s390x.rs
@@ -1,5 +1,6 @@
 use super::{InlineAsmArch, InlineAsmType};
 use rustc_macros::HashStable_Generic;
+use rustc_span::Symbol;
 use std::fmt;
 
 def_reg_class! {
@@ -33,7 +34,7 @@ impl S390xInlineAsmRegClass {
     pub fn supported_types(
         self,
         arch: InlineAsmArch,
-    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match (self, arch) {
             (Self::reg, _) => types! { _: I8, I16, I32, I64; },
             (Self::freg, _) => types! { _: F32, F64; },
diff --git a/compiler/rustc_target/src/asm/spirv.rs b/compiler/rustc_target/src/asm/spirv.rs
index da82749e96a..31073da10b2 100644
--- a/compiler/rustc_target/src/asm/spirv.rs
+++ b/compiler/rustc_target/src/asm/spirv.rs
@@ -1,5 +1,6 @@
 use super::{InlineAsmArch, InlineAsmType};
 use rustc_macros::HashStable_Generic;
+use rustc_span::Symbol;
 
 def_reg_class! {
     SpirV SpirVInlineAsmRegClass {
@@ -31,7 +32,7 @@ impl SpirVInlineAsmRegClass {
     pub fn supported_types(
         self,
         _arch: InlineAsmArch,
-    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match self {
             Self::reg => {
                 types! { _: I8, I16, I32, I64, F32, F64; }
diff --git a/compiler/rustc_target/src/asm/wasm.rs b/compiler/rustc_target/src/asm/wasm.rs
index 1b33f8f9632..f095b7c6e11 100644
--- a/compiler/rustc_target/src/asm/wasm.rs
+++ b/compiler/rustc_target/src/asm/wasm.rs
@@ -1,5 +1,6 @@
 use super::{InlineAsmArch, InlineAsmType};
 use rustc_macros::HashStable_Generic;
+use rustc_span::Symbol;
 
 def_reg_class! {
     Wasm WasmInlineAsmRegClass {
@@ -31,7 +32,7 @@ impl WasmInlineAsmRegClass {
     pub fn supported_types(
         self,
         _arch: InlineAsmArch,
-    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match self {
             Self::local => {
                 types! { _: I8, I16, I32, I64, F32, F64; }
diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs
index 5e3828d7d85..01d32570f78 100644
--- a/compiler/rustc_target/src/asm/x86.rs
+++ b/compiler/rustc_target/src/asm/x86.rs
@@ -1,6 +1,8 @@
 use super::{InlineAsmArch, InlineAsmType};
 use crate::spec::Target;
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_macros::HashStable_Generic;
+use rustc_span::Symbol;
 use std::fmt;
 
 def_reg_class! {
@@ -101,7 +103,7 @@ impl X86InlineAsmRegClass {
     pub fn supported_types(
         self,
         arch: InlineAsmArch,
-    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match self {
             Self::reg | Self::reg_abcd => {
                 if arch == InlineAsmArch::X86_64 {
@@ -112,23 +114,23 @@ impl X86InlineAsmRegClass {
             }
             Self::reg_byte => types! { _: I8; },
             Self::xmm_reg => types! {
-                "sse": I32, I64, F32, F64,
+                sse: I32, I64, F32, F64,
                   VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
             },
             Self::ymm_reg => types! {
-                "avx": I32, I64, F32, F64,
+                avx: I32, I64, F32, F64,
                     VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2),
                     VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF32(8), VecF64(4);
             },
             Self::zmm_reg => types! {
-                "avx512f": I32, I64, F32, F64,
+                avx512f: I32, I64, F32, F64,
                     VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2),
                     VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF32(8), VecF64(4),
                     VecI8(64), VecI16(32), VecI32(16), VecI64(8), VecF32(16), VecF64(8);
             },
             Self::kreg => types! {
-                "avx512f": I8, I16;
-                "avx512bw": I32, I64;
+                avx512f: I8, I16;
+                avx512bw: I32, I64;
             },
             Self::mmx_reg | Self::x87_reg => &[],
         }
@@ -137,7 +139,7 @@ impl X86InlineAsmRegClass {
 
 fn x86_64_only(
     arch: InlineAsmArch,
-    _has_feature: impl FnMut(&str) -> bool,
+    _target_features: &FxHashSet<Symbol>,
     _target: &Target,
 ) -> Result<(), &'static str> {
     match arch {
@@ -149,7 +151,7 @@ fn x86_64_only(
 
 fn high_byte(
     arch: InlineAsmArch,
-    _has_feature: impl FnMut(&str) -> bool,
+    _target_features: &FxHashSet<Symbol>,
     _target: &Target,
 ) -> Result<(), &'static str> {
     match arch {
@@ -160,7 +162,7 @@ fn high_byte(
 
 fn rbx_reserved(
     arch: InlineAsmArch,
-    _has_feature: impl FnMut(&str) -> bool,
+    _target_features: &FxHashSet<Symbol>,
     _target: &Target,
 ) -> Result<(), &'static str> {
     match arch {
@@ -174,7 +176,7 @@ fn rbx_reserved(
 
 fn esi_reserved(
     arch: InlineAsmArch,
-    _has_feature: impl FnMut(&str) -> bool,
+    _target_features: &FxHashSet<Symbol>,
     _target: &Target,
 ) -> Result<(), &'static str> {
     match arch {