Skip to main content

hir_ty/
target_feature.rs

1//! Stuff for handling `#[target_feature]` (needed for unsafe check).
2
3use std::sync::LazyLock;
4use std::{borrow::Cow, ops::Deref};
5
6use hir_def::FunctionId;
7use hir_def::attrs::AttrFlags;
8use intern::Symbol;
9use rustc_hash::{FxHashMap, FxHashSet};
10
11use crate::db::HirDatabase;
12
13#[derive(Debug, Default, Clone)]
14pub struct TargetFeatures<'db> {
15    pub(crate) enabled: Cow<'db, FxHashSet<Symbol>>,
16}
17
18impl<'db> TargetFeatures<'db> {
19    pub fn from_fn(db: &'db dyn HirDatabase, owner: FunctionId) -> Self {
20        let mut result = TargetFeatures::from_fn_no_implications(db, owner);
21        result.expand_implications();
22        result
23    }
24
25    fn expand_implications(&mut self) {
26        let all_implications = LazyLock::force(&TARGET_FEATURE_IMPLICATIONS);
27        let enabled = self.enabled.to_mut();
28        let mut queue = enabled.iter().cloned().collect::<Vec<_>>();
29        while let Some(feature) = queue.pop() {
30            if let Some(implications) = all_implications.get(&feature) {
31                for implication in implications {
32                    if enabled.insert(implication.clone()) {
33                        queue.push(implication.clone());
34                    }
35                }
36            }
37        }
38    }
39
40    /// Retrieves the target features from the attributes, and does not expand the target features implied by them.
41    pub(crate) fn from_fn_no_implications(db: &'db dyn HirDatabase, owner: FunctionId) -> Self {
42        let enabled = AttrFlags::target_features(db, owner);
43        Self { enabled: Cow::Borrowed(enabled) }
44    }
45}
46
47// List of the target features each target feature implies.
48// Ideally we'd depend on rustc for this, but rustc_target doesn't compile on stable,
49// and t-compiler prefers for it to stay this way.
50
51static TARGET_FEATURE_IMPLICATIONS: LazyLock<FxHashMap<Symbol, Box<[Symbol]>>> =
52    LazyLock::new(|| {
53        let mut result = FxHashMap::<Symbol, FxHashSet<Symbol>>::default();
54        for &(feature_str, ref _stability, implications) in
55            TARGET_FEATURE_IMPLICATIONS_RAW.iter().flat_map(Deref::deref)
56        {
57            let feature = Symbol::intern(feature_str);
58            let implications = implications.iter().copied().map(Symbol::intern);
59            // Some target features appear in two archs, e.g. Arm and x86.
60            // Sometimes they contain different implications, e.g. `aes`.
61            // We should probably choose by the active arch, but for now just merge them.
62            result.entry(feature).or_default().extend(implications);
63        }
64        let mut result = result
65            .into_iter()
66            .map(|(feature, implications)| (feature, Box::from_iter(implications)))
67            .collect::<FxHashMap<_, _>>();
68        result.shrink_to_fit();
69        result
70    });
71
72#[expect(dead_code, reason = "stubs for rustc_target")]
73enum Stability {
74    Stable,
75    Unstable(()),
76    InternalOnly { reason: &'static str, hard_error: bool },
77}
78use Stability::*;
79
80type ImpliedFeatures = &'static [&'static str];
81
82// spellchecker:off
83
84#[expect(non_upper_case_globals, reason = "stubs for rustc_target")]
85mod sym {
86    // ARM
87    pub(super) const arm_target_feature: () = ();
88    // AArch64
89    pub(super) const aarch64_unstable_target_feature: () = ();
90    pub(super) const aarch64_ver_target_feature: () = ();
91    // x86
92    pub(super) const x86_amx_intrinsics: () = ();
93    pub(super) const apx_target_feature: () = ();
94    pub(super) const avx10_target_feature: () = ();
95    pub(super) const clflushopt_target_feature: () = ();
96    pub(super) const fma4_target_feature: () = ();
97    pub(super) const ermsb_target_feature: () = ();
98    pub(super) const lahfsahf_target_feature: () = ();
99    pub(super) const movrs_target_feature: () = ();
100    pub(super) const prfchw_target_feature: () = ();
101    pub(super) const rtm_target_feature: () = ();
102    pub(super) const x87_target_feature: () = ();
103    pub(super) const xop_target_feature: () = ();
104    pub(super) const movdir64b_target_feature: () = ();
105    pub(super) const movdiri_target_feature: () = ();
106    // Hexagon
107    pub(super) const hexagon_target_feature: () = ();
108    // PowerPC
109    pub(super) const powerpc_target_feature: () = ();
110    // MIPS
111    pub(super) const mips_target_feature: () = ();
112    // NVPTX
113    pub(super) const nvptx_target_feature: () = ();
114    // RISC-V
115    pub(super) const riscv_target_feature: () = ();
116    // WASM
117    pub(super) const wasm_target_feature: () = ();
118    // BPF
119    pub(super) const bpf_target_feature: () = ();
120    // CSKY
121    pub(super) const csky_target_feature: () = ();
122    // LoongArch
123    pub(super) const loongarch_target_feature: () = ();
124    // s390x
125    pub(super) const s390x_target_feature: () = ();
126    // SPARC
127    pub(super) const sparc_target_feature: () = ();
128    // m68k
129    pub(super) const m68k_target_feature: () = ();
130    // AVR
131    pub(super) const avr_target_feature: () = ();
132    // Xtensa
133    pub(super) const xtensa_target_feature: () = ();
134}
135
136// The following code is copied verbatim from compiler/rustc_target/src/target_features.rs.
137
138static ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
139    // tidy-alphabetical-start
140    ("aclass", Unstable(sym::arm_target_feature), &[]),
141    ("acquire-release", Unstable(sym::arm_target_feature), &[]),
142    ("aes", Unstable(sym::arm_target_feature), &["neon"]),
143    (
144        "atomics-32",
145        // Not implied by any CPU model or other feature.
146        Stability::InternalOnly {
147            reason: "unsound because it changes the ABI of atomic operations",
148            hard_error: false,
149        },
150        &[],
151    ),
152    ("crc", Unstable(sym::arm_target_feature), &[]),
153    ("d32", Unstable(sym::arm_target_feature), &[]),
154    ("dotprod", Unstable(sym::arm_target_feature), &["neon"]),
155    ("dsp", Unstable(sym::arm_target_feature), &[]),
156    ("fp-armv8", Unstable(sym::arm_target_feature), &["vfp4"]),
157    ("fp16", Unstable(sym::arm_target_feature), &["neon"]),
158    ("fp64", Unstable(sym::arm_target_feature), &[]),
159    ("fpregs", Unstable(sym::arm_target_feature), &[]),
160    ("i8mm", Unstable(sym::arm_target_feature), &["neon"]),
161    ("mclass", Unstable(sym::arm_target_feature), &[]),
162    ("mve", Unstable(sym::arm_target_feature), &["v8.1m.main", "dsp", "fpregs"]),
163    ("mve.fp", Unstable(sym::arm_target_feature), &["mve"]),
164    ("neon", Unstable(sym::arm_target_feature), &["vfp3"]),
165    ("rclass", Unstable(sym::arm_target_feature), &[]),
166    ("sha2", Unstable(sym::arm_target_feature), &["neon"]),
167    // This can be *disabled* on non-`hf` targets to enable the use
168    // of hardfloats while keeping the softfloat ABI.
169    // FIXME before stabilization: Should we expose this as a `hard-float` target feature instead of
170    // matching the odd negative feature LLVM uses?
171    ("soft-float", Unstable(sym::arm_target_feature), &[]),
172    // This is needed for inline assembly, but shouldn't be stabilized as-is
173    // since it should be enabled per-function using #[instruction_set], not
174    // #[target_feature].
175    ("thumb-mode", Unstable(sym::arm_target_feature), &[]),
176    ("thumb2", Unstable(sym::arm_target_feature), &[]),
177    ("trustzone", Unstable(sym::arm_target_feature), &[]),
178    ("v5te", Unstable(sym::arm_target_feature), &[]),
179    ("v6", Unstable(sym::arm_target_feature), &["v5te"]),
180    ("v6k", Unstable(sym::arm_target_feature), &["v6"]),
181    ("v6m", Unstable(sym::arm_target_feature), &["v6"]),
182    ("v6t2", Unstable(sym::arm_target_feature), &["v6k", "v8m", "thumb2"]),
183    ("v7", Unstable(sym::arm_target_feature), &["v6t2"]),
184    ("v8", Unstable(sym::arm_target_feature), &["v7", "acquire-release"]),
185    ("v8.1m.main", Unstable(sym::arm_target_feature), &["v8m.main"]),
186    ("v8m", Unstable(sym::arm_target_feature), &["v6m"]),
187    ("v8m.main", Unstable(sym::arm_target_feature), &["v7"]),
188    ("vfp2", Unstable(sym::arm_target_feature), &["vfp2sp", "fp64"]),
189    ("vfp2sp", Unstable(sym::arm_target_feature), &["fpregs"]),
190    ("vfp3", Unstable(sym::arm_target_feature), &["vfp2", "d32"]),
191    ("vfp4", Unstable(sym::arm_target_feature), &["vfp3"]),
192    ("virtualization", Unstable(sym::arm_target_feature), &[]),
193    // tidy-alphabetical-end
194];
195
196static AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
197    // tidy-alphabetical-start
198    // FEAT_AES & FEAT_PMULL
199    ("aes", Stable, &["neon"]),
200    // FEAT_BF16
201    ("bf16", Stable, &[]),
202    // FEAT_BTI
203    ("bti", Stable, &[]),
204    // FEAT_CRC
205    ("crc", Stable, &[]),
206    // FEAT_CSSC
207    ("cssc", Unstable(sym::aarch64_unstable_target_feature), &[]),
208    // FEAT_DIT
209    ("dit", Stable, &[]),
210    // FEAT_DotProd
211    ("dotprod", Stable, &["neon"]),
212    // FEAT_DPB
213    ("dpb", Stable, &[]),
214    // FEAT_DPB2
215    ("dpb2", Stable, &["dpb"]),
216    // FEAT_ECV
217    ("ecv", Unstable(sym::aarch64_unstable_target_feature), &[]),
218    // FEAT_F32MM
219    ("f32mm", Stable, &["sve"]),
220    // FEAT_F64MM
221    ("f64mm", Stable, &["sve"]),
222    // FEAT_FAMINMAX
223    ("faminmax", Unstable(sym::aarch64_unstable_target_feature), &[]),
224    // FEAT_FCMA
225    ("fcma", Stable, &["neon"]),
226    // FEAT_FHM
227    ("fhm", Stable, &["fp16"]),
228    // FEAT_FLAGM
229    ("flagm", Stable, &[]),
230    // FEAT_FLAGM2
231    ("flagm2", Unstable(sym::aarch64_unstable_target_feature), &[]),
232    // We forbid directly toggling just `fp-armv8`; it must be toggled with `neon`.
233    (
234        "fp-armv8",
235        // Pinned down by [`Target::abi_required_features`] when needed.
236        Stability::InternalOnly { reason: "Rust ties `fp-armv8` to `neon`", hard_error: false },
237        &[],
238    ),
239    // FEAT_FP8
240    ("fp8", Unstable(sym::aarch64_unstable_target_feature), &["faminmax", "lut", "bf16"]),
241    // FEAT_FP8DOT2
242    ("fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["fp8dot4"]),
243    // FEAT_FP8DOT4
244    ("fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["fp8fma"]),
245    // FEAT_FP8FMA
246    ("fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["fp8"]),
247    // FEAT_FP16
248    // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608
249    ("fp16", Stable, &["neon"]),
250    // FEAT_FRINTTS
251    ("frintts", Stable, &[]),
252    // FEAT_HBC
253    ("hbc", Unstable(sym::aarch64_unstable_target_feature), &[]),
254    // FEAT_I8MM
255    ("i8mm", Stable, &[]),
256    // FEAT_JSCVT
257    // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608
258    ("jsconv", Stable, &["neon"]),
259    // FEAT_LOR
260    ("lor", Stable, &[]),
261    // FEAT_LSE
262    ("lse", Stable, &[]),
263    // FEAT_LSE2
264    ("lse2", Unstable(sym::aarch64_unstable_target_feature), &[]),
265    // FEAT_LSE128
266    ("lse128", Unstable(sym::aarch64_unstable_target_feature), &["lse"]),
267    // FEAT_LUT
268    ("lut", Unstable(sym::aarch64_unstable_target_feature), &[]),
269    // FEAT_MOPS
270    ("mops", Unstable(sym::aarch64_unstable_target_feature), &[]),
271    // FEAT_MTE & FEAT_MTE2
272    ("mte", Stable, &[]),
273    // FEAT_AdvSimd & FEAT_FP
274    ("neon", Stable, &[]),
275    // Backend option to turn atomic operations into an intrinsic call when `lse` is not known to be
276    // available, so the intrinsic can do runtime LSE feature detection rather than unconditionally
277    // using slower non-LSE operations. Unstable since it doesn't need to user-togglable.
278    ("outline-atomics", Unstable(sym::aarch64_unstable_target_feature), &[]),
279    // FEAT_PAUTH (address authentication)
280    ("paca", Stable, &[]),
281    // FEAT_PAUTH (generic authentication)
282    ("pacg", Stable, &[]),
283    // FEAT_PAN
284    ("pan", Stable, &[]),
285    // FEAT_PAuth_LR
286    ("pauth-lr", Unstable(sym::aarch64_unstable_target_feature), &[]),
287    // FEAT_PMUv3
288    ("pmuv3", Stable, &[]),
289    // FEAT_RNG
290    ("rand", Stable, &[]),
291    // FEAT_RAS & FEAT_RASv1p1
292    ("ras", Stable, &[]),
293    // FEAT_LRCPC
294    ("rcpc", Stable, &[]),
295    // FEAT_LRCPC2
296    ("rcpc2", Stable, &["rcpc"]),
297    // FEAT_LRCPC3
298    ("rcpc3", Unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]),
299    // FEAT_RDM
300    ("rdm", Stable, &["neon"]),
301    (
302        "reserve-x18",
303        // Not implied by any CPU model or other feature; the compiler flag is a target modifier.
304        InternalOnly { reason: "use `-Zfixed-x18` compiler flag instead", hard_error: false },
305        &[],
306    ),
307    // FEAT_SB
308    ("sb", Stable, &[]),
309    // FEAT_SHA1 & FEAT_SHA256
310    ("sha2", Stable, &["neon"]),
311    // FEAT_SHA512 & FEAT_SHA3
312    ("sha3", Stable, &["sha2"]),
313    // FEAT_SM3 & FEAT_SM4
314    ("sm4", Stable, &["neon"]),
315    // FEAT_SME
316    ("sme", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]),
317    // FEAT_SME_B16B16
318    ("sme-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16", "sme2", "sve-b16b16"]),
319    // FEAT_SME_F8F16
320    ("sme-f8f16", Unstable(sym::aarch64_unstable_target_feature), &["sme-f8f32"]),
321    // FEAT_SME_F8F32
322    ("sme-f8f32", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]),
323    // FEAT_SME_F16F16
324    ("sme-f16f16", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]),
325    // FEAT_SME_F64F64
326    ("sme-f64f64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]),
327    // FEAT_SME_FA64
328    ("sme-fa64", Unstable(sym::aarch64_unstable_target_feature), &["sme", "sve2"]),
329    // FEAT_SME_I16I64
330    ("sme-i16i64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]),
331    // FEAT_SME_LUTv2
332    ("sme-lutv2", Unstable(sym::aarch64_unstable_target_feature), &[]),
333    // FEAT_SME2
334    ("sme2", Unstable(sym::aarch64_unstable_target_feature), &["sme"]),
335    // FEAT_SME2p1
336    ("sme2p1", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]),
337    // FEAT_SPE
338    ("spe", Stable, &[]),
339    // FEAT_SSBS & FEAT_SSBS2
340    ("ssbs", Stable, &[]),
341    // FEAT_SSVE_FP8FDOT2
342    ("ssve-fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8dot4"]),
343    // FEAT_SSVE_FP8FDOT4
344    ("ssve-fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8fma"]),
345    // FEAT_SSVE_FP8FMA
346    ("ssve-fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]),
347    // FEAT_SVE
348    // It was decided that SVE requires Neon: https://github.com/rust-lang/rust/pull/91608
349    //
350    // LLVM doesn't enable Neon for SVE. ARM indicates that they're separate, but probably always
351    // exist together: https://developer.arm.com/documentation/102340/0100/New-features-in-SVE2
352    //
353    // "For backwards compatibility, Neon and VFP are required in the latest architectures."
354    ("sve", Stable, &["neon", "fp16"]),
355    // FEAT_SVE_B16B16 (SVE or SME Z-targeting instructions)
356    ("sve-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]),
357    // FEAT_SVE2
358    ("sve2", Stable, &["sve"]),
359    // FEAT_SVE_AES & FEAT_SVE_PMULL128
360    ("sve2-aes", Stable, &["sve2", "aes"]),
361    // FEAT_SVE2_BitPerm
362    ("sve2-bitperm", Stable, &["sve2"]),
363    // FEAT_SVE2_SHA3
364    ("sve2-sha3", Stable, &["sve2", "sha3"]),
365    // FEAT_SVE2_SM4
366    ("sve2-sm4", Stable, &["sve2", "sm4"]),
367    // FEAT_SVE2p1
368    ("sve2p1", Unstable(sym::aarch64_unstable_target_feature), &["sve2"]),
369    // FEAT_TME
370    ("tme", Stable, &[]),
371    (
372        "v8.1a",
373        Unstable(sym::aarch64_ver_target_feature),
374        &["crc", "lse", "rdm", "pan", "lor", "vh"],
375    ),
376    ("v8.2a", Unstable(sym::aarch64_ver_target_feature), &["v8.1a", "ras", "dpb"]),
377    (
378        "v8.3a",
379        Unstable(sym::aarch64_ver_target_feature),
380        &["v8.2a", "rcpc", "paca", "pacg", "jsconv"],
381    ),
382    ("v8.4a", Unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]),
383    ("v8.5a", Unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]),
384    ("v8.6a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]),
385    ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &["v8.6a", "wfxt"]),
386    ("v8.8a", Unstable(sym::aarch64_ver_target_feature), &["v8.7a", "hbc", "mops"]),
387    ("v8.9a", Unstable(sym::aarch64_ver_target_feature), &["v8.8a", "cssc"]),
388    ("v9.1a", Unstable(sym::aarch64_ver_target_feature), &["v9a", "v8.6a"]),
389    ("v9.2a", Unstable(sym::aarch64_ver_target_feature), &["v9.1a", "v8.7a"]),
390    ("v9.3a", Unstable(sym::aarch64_ver_target_feature), &["v9.2a", "v8.8a"]),
391    ("v9.4a", Unstable(sym::aarch64_ver_target_feature), &["v9.3a", "v8.9a"]),
392    ("v9.5a", Unstable(sym::aarch64_ver_target_feature), &["v9.4a"]),
393    ("v9a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a"]),
394    // FEAT_VHE
395    ("vh", Stable, &[]),
396    // FEAT_WFxT
397    ("wfxt", Unstable(sym::aarch64_unstable_target_feature), &[]),
398    // tidy-alphabetical-end
399];
400
401static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
402    // tidy-alphabetical-start
403    ("adx", Stable, &[]),
404    ("aes", Stable, &["sse2"]),
405    ("amx-avx512", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
406    ("amx-bf16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
407    ("amx-complex", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
408    ("amx-fp8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
409    ("amx-fp16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
410    ("amx-int8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
411    ("amx-movrs", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
412    ("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]),
413    ("apxf", Unstable(sym::apx_target_feature), &[]),
414    ("avx", Stable, &["sse4.2"]),
415    ("avx2", Stable, &["avx"]),
416    (
417        "avx10.1",
418        Unstable(sym::avx10_target_feature),
419        &[
420            "avx512bf16",
421            "avx512bitalg",
422            "avx512bw",
423            "avx512cd",
424            "avx512dq",
425            "avx512f",
426            "avx512fp16",
427            "avx512ifma",
428            "avx512vbmi",
429            "avx512vbmi2",
430            "avx512vl",
431            "avx512vnni",
432            "avx512vpopcntdq",
433        ],
434    ),
435    (
436        "avx10.2",
437        Unstable(sym::avx10_target_feature),
438        &["avx10.1", "avxvnni", "avxvnniint8", "avxvnniint16"],
439    ),
440    ("avx512bf16", Stable, &["avx512bw"]),
441    ("avx512bitalg", Stable, &["avx512bw"]),
442    ("avx512bw", Stable, &["avx512f"]),
443    ("avx512cd", Stable, &["avx512f"]),
444    ("avx512dq", Stable, &["avx512f"]),
445    ("avx512f", Stable, &["avx2", "fma", "f16c"]),
446    ("avx512fp16", Stable, &["avx512bw"]),
447    ("avx512ifma", Stable, &["avx512f"]),
448    ("avx512vbmi", Stable, &["avx512bw"]),
449    ("avx512vbmi2", Stable, &["avx512bw"]),
450    ("avx512vl", Stable, &["avx512f"]),
451    ("avx512vnni", Stable, &["avx512f"]),
452    ("avx512vp2intersect", Stable, &["avx512f"]),
453    ("avx512vpopcntdq", Stable, &["avx512f"]),
454    ("avxifma", Stable, &["avx2"]),
455    ("avxneconvert", Stable, &["avx2"]),
456    ("avxvnni", Stable, &["avx2"]),
457    ("avxvnniint8", Stable, &["avx2"]),
458    ("avxvnniint16", Stable, &["avx2"]),
459    ("bmi1", Stable, &[]),
460    ("bmi2", Stable, &[]),
461    ("clflushopt", Unstable(sym::clflushopt_target_feature), &[]),
462    ("cmpxchg16b", Stable, &[]),
463    ("ermsb", Unstable(sym::ermsb_target_feature), &[]),
464    ("f16c", Stable, &["avx"]),
465    ("fma", Stable, &["avx"]),
466    ("fma4", Unstable(sym::fma4_target_feature), &["avx", "sse4a"]),
467    ("fxsr", Stable, &[]),
468    ("gfni", Stable, &["sse2"]),
469    ("kl", Stable, &["sse2"]),
470    ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
471    ("lzcnt", Stable, &[]),
472    ("movbe", Stable, &[]),
473    ("movdir64b", Unstable(sym::movdir64b_target_feature), &[]),
474    ("movdiri", Unstable(sym::movdiri_target_feature), &[]),
475    ("movrs", Unstable(sym::movrs_target_feature), &[]),
476    ("pclmulqdq", Stable, &["sse2"]),
477    ("popcnt", Stable, &[]),
478    ("prfchw", Unstable(sym::prfchw_target_feature), &[]),
479    ("rdrand", Stable, &[]),
480    ("rdseed", Stable, &[]),
481    (
482        "retpoline-external-thunk",
483        // Not implied by any CPU model or other feature; the compiler flag is a target modifier.
484        Stability::InternalOnly {
485            reason: "use `-Zretpoline-external-thunk` compiler flag instead",
486            hard_error: false,
487        },
488        &[],
489    ),
490    (
491        "retpoline-indirect-branches",
492        // Not implied by any CPU model or other feature; the compiler flag is a target modifier.
493        Stability::InternalOnly {
494            reason: "use `-Zretpoline` compiler flag instead",
495            hard_error: false,
496        },
497        &[],
498    ),
499    (
500        "retpoline-indirect-calls",
501        // Not implied by any CPU model or other feature; the compiler flag is a target modifier.
502        Stability::InternalOnly {
503            reason: "use `-Zretpoline` compiler flag instead",
504            hard_error: false,
505        },
506        &[],
507    ),
508    ("rtm", Unstable(sym::rtm_target_feature), &[]),
509    ("sha", Stable, &["sse2"]),
510    ("sha512", Stable, &["avx2"]),
511    ("sm3", Stable, &["avx"]),
512    ("sm4", Stable, &["avx2"]),
513    (
514        "soft-float",
515        // Pinned down by [`Target::abi_required_features`].
516        Stability::InternalOnly { reason: "use a soft-float target instead", hard_error: false },
517        &[],
518    ),
519    ("sse", Stable, &[]),
520    ("sse2", Stable, &["sse"]),
521    ("sse3", Stable, &["sse2"]),
522    ("sse4.1", Stable, &["ssse3"]),
523    ("sse4.2", Stable, &["sse4.1"]),
524    ("sse4a", Stable, &["sse3"]),
525    ("ssse3", Stable, &["sse3"]),
526    ("tbm", Stable, &[]),
527    ("vaes", Stable, &["avx2", "aes"]),
528    ("vpclmulqdq", Stable, &["avx", "pclmulqdq"]),
529    ("widekl", Stable, &["kl"]),
530    ("x87", Unstable(sym::x87_target_feature), &[]),
531    ("xop", Unstable(sym::xop_target_feature), &["fma4", "avx", "sse4a"]),
532    ("xsave", Stable, &[]),
533    ("xsavec", Stable, &["xsave"]),
534    ("xsaveopt", Stable, &["xsave"]),
535    ("xsaves", Stable, &["xsave"]),
536    // tidy-alphabetical-end
537];
538
539const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
540    // tidy-alphabetical-start
541    ("audio", Unstable(sym::hexagon_target_feature), &[]),
542    ("hvx", Unstable(sym::hexagon_target_feature), &[]),
543    ("hvx-ieee-fp", Unstable(sym::hexagon_target_feature), &["hvx"]),
544    ("hvx-length64b", Unstable(sym::hexagon_target_feature), &["hvx"]),
545    ("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]),
546    ("hvx-qfloat", Unstable(sym::hexagon_target_feature), &["hvx"]),
547    ("hvxv60", Unstable(sym::hexagon_target_feature), &["hvx"]),
548    ("hvxv62", Unstable(sym::hexagon_target_feature), &["hvxv60"]),
549    ("hvxv65", Unstable(sym::hexagon_target_feature), &["hvxv62"]),
550    ("hvxv66", Unstable(sym::hexagon_target_feature), &["hvxv65", "zreg"]),
551    ("hvxv67", Unstable(sym::hexagon_target_feature), &["hvxv66"]),
552    ("hvxv68", Unstable(sym::hexagon_target_feature), &["hvxv67"]),
553    ("hvxv69", Unstable(sym::hexagon_target_feature), &["hvxv68"]),
554    ("hvxv71", Unstable(sym::hexagon_target_feature), &["hvxv69"]),
555    ("hvxv73", Unstable(sym::hexagon_target_feature), &["hvxv71"]),
556    ("hvxv75", Unstable(sym::hexagon_target_feature), &["hvxv73"]),
557    ("hvxv79", Unstable(sym::hexagon_target_feature), &["hvxv75"]),
558    ("v60", Unstable(sym::hexagon_target_feature), &[]),
559    ("v62", Unstable(sym::hexagon_target_feature), &["v60"]),
560    ("v65", Unstable(sym::hexagon_target_feature), &["v62"]),
561    ("v66", Unstable(sym::hexagon_target_feature), &["v65"]),
562    ("v67", Unstable(sym::hexagon_target_feature), &["v66"]),
563    ("v68", Unstable(sym::hexagon_target_feature), &["v67"]),
564    ("v69", Unstable(sym::hexagon_target_feature), &["v68"]),
565    ("v71", Unstable(sym::hexagon_target_feature), &["v69"]),
566    ("v73", Unstable(sym::hexagon_target_feature), &["v71"]),
567    ("v75", Unstable(sym::hexagon_target_feature), &["v73"]),
568    ("v79", Unstable(sym::hexagon_target_feature), &["v75"]),
569    ("zreg", Unstable(sym::hexagon_target_feature), &[]),
570    // tidy-alphabetical-end
571];
572
573static POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
574    // If you are thinking of adding "efpu2" here, please double-check that it really does not
575    // affect the ABI.
576    // tidy-alphabetical-start
577    ("altivec", Unstable(sym::powerpc_target_feature), &[]),
578    (
579        "hard-float",
580        // Pinned down by [`Target::abi_required_features`].
581        InternalOnly { reason: "unsupported ABI-configuration feature", hard_error: false },
582        &[],
583    ),
584    ("msync", Unstable(sym::powerpc_target_feature), &[]),
585    ("partword-atomics", Unstable(sym::powerpc_target_feature), &[]),
586    ("power8-altivec", Unstable(sym::powerpc_target_feature), &["altivec"]),
587    ("power8-crypto", Unstable(sym::powerpc_target_feature), &["power8-altivec"]),
588    ("power8-vector", Unstable(sym::powerpc_target_feature), &["vsx", "power8-altivec"]),
589    ("power9-altivec", Unstable(sym::powerpc_target_feature), &["power8-altivec"]),
590    ("power9-vector", Unstable(sym::powerpc_target_feature), &["power8-vector", "power9-altivec"]),
591    ("power10-vector", Unstable(sym::powerpc_target_feature), &["power9-vector"]),
592    ("quadword-atomics", Unstable(sym::powerpc_target_feature), &[]),
593    (
594        "spe",
595        // Pinned down by [`Target::abi_required_features`].
596        InternalOnly { reason: "unsupported ABI-configuration feature", hard_error: false },
597        &[],
598    ),
599    ("vsx", Unstable(sym::powerpc_target_feature), &["altivec"]),
600    // tidy-alphabetical-end
601];
602
603const MIPS_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
604    // tidy-alphabetical-start
605    ("fp64", Unstable(sym::mips_target_feature), &[]),
606    // FIXME(#150253): msa requires either fp64 or no hard float support at all: LLVM requires fp64
607    // FIXME(#150253): msa requires revision 5 or greater (mips32r5/mips64r5 in LLVM)
608    ("msa", Unstable(sym::mips_target_feature), &[]),
609    ("virt", Unstable(sym::mips_target_feature), &[]),
610    // tidy-alphabetical-end
611];
612
613const NVPTX_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
614    // tidy-alphabetical-start
615    ("sm_70", Unstable(sym::nvptx_target_feature), &[]),
616    ("sm_72", Unstable(sym::nvptx_target_feature), &["sm_70"]),
617    ("sm_75", Unstable(sym::nvptx_target_feature), &["sm_72"]),
618    ("sm_80", Unstable(sym::nvptx_target_feature), &["sm_75"]),
619    ("sm_86", Unstable(sym::nvptx_target_feature), &["sm_80"]),
620    ("sm_87", Unstable(sym::nvptx_target_feature), &["sm_86"]),
621    ("sm_89", Unstable(sym::nvptx_target_feature), &["sm_87"]),
622    ("sm_90", Unstable(sym::nvptx_target_feature), &["sm_89"]),
623    ("sm_90a", Unstable(sym::nvptx_target_feature), &["sm_90"]),
624    // tidy-alphabetical-end
625    // tidy-alphabetical-start
626    ("sm_100", Unstable(sym::nvptx_target_feature), &["sm_90"]),
627    ("sm_100a", Unstable(sym::nvptx_target_feature), &["sm_100"]),
628    ("sm_101", Unstable(sym::nvptx_target_feature), &["sm_100"]),
629    ("sm_101a", Unstable(sym::nvptx_target_feature), &["sm_101"]),
630    ("sm_120", Unstable(sym::nvptx_target_feature), &["sm_101"]),
631    ("sm_120a", Unstable(sym::nvptx_target_feature), &["sm_120"]),
632    // tidy-alphabetical-end
633    // tidy-alphabetical-start
634    ("ptx70", Unstable(sym::nvptx_target_feature), &[]),
635    ("ptx71", Unstable(sym::nvptx_target_feature), &["ptx70"]),
636    ("ptx72", Unstable(sym::nvptx_target_feature), &["ptx71"]),
637    ("ptx73", Unstable(sym::nvptx_target_feature), &["ptx72"]),
638    ("ptx74", Unstable(sym::nvptx_target_feature), &["ptx73"]),
639    ("ptx75", Unstable(sym::nvptx_target_feature), &["ptx74"]),
640    ("ptx76", Unstable(sym::nvptx_target_feature), &["ptx75"]),
641    ("ptx77", Unstable(sym::nvptx_target_feature), &["ptx76"]),
642    ("ptx78", Unstable(sym::nvptx_target_feature), &["ptx77"]),
643    ("ptx80", Unstable(sym::nvptx_target_feature), &["ptx78"]),
644    ("ptx81", Unstable(sym::nvptx_target_feature), &["ptx80"]),
645    ("ptx82", Unstable(sym::nvptx_target_feature), &["ptx81"]),
646    ("ptx83", Unstable(sym::nvptx_target_feature), &["ptx82"]),
647    ("ptx84", Unstable(sym::nvptx_target_feature), &["ptx83"]),
648    ("ptx85", Unstable(sym::nvptx_target_feature), &["ptx84"]),
649    ("ptx86", Unstable(sym::nvptx_target_feature), &["ptx85"]),
650    ("ptx87", Unstable(sym::nvptx_target_feature), &["ptx86"]),
651    // tidy-alphabetical-end
652];
653
654static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
655    // tidy-alphabetical-start
656    ("a", Stable, &["zaamo", "zalrsc"]),
657    ("b", Stable, &["zba", "zbb", "zbs"]),
658    ("c", Stable, &["zca"]),
659    ("d", Stable, &["f"]),
660    ("e", Unstable(sym::riscv_target_feature), &[]), // negative feature! needs special care.
661    ("f", Stable, &["zicsr"]),
662    (
663        "forced-atomics",
664        // Not implied by any CPU model or other feature.
665        Stability::InternalOnly {
666            reason: "unsound because it changes the ABI of atomic operations",
667            hard_error: false,
668        },
669        &[],
670    ),
671    // According to the RISC-V spec, the M ISA extension (integer multiplication/division) is supported only when the M bit
672    // of the misa register is 1, while Zmmul means integer multiplication is always supported.
673    //
674    // The Rust/LLVM "m" target feature means something slightly different: with "m" enabled, it is assumed that integer
675    // multiplication and division will always be available (M bit will be 1 in misa), so "m" implies "zmmul".
676    //
677    // See discussion in the PR adding Zmmul: https://github.com/rust-lang/rust/pull/162552
678    ("m", Stable, &["zmmul"]),
679    ("relax", Unstable(sym::riscv_target_feature), &[]),
680    (
681        "rva23u64",
682        Unstable(sym::riscv_target_feature),
683        &[
684            "m",
685            "a",
686            "f",
687            "d",
688            "c",
689            "b",
690            "v",
691            "zicsr",
692            "zicntr",
693            "zihpm",
694            "ziccif",
695            "ziccrse",
696            "ziccamoa",
697            "zicclsm",
698            "zic64b",
699            "za64rs",
700            "zihintpause",
701            "zba",
702            "zbb",
703            "zbs",
704            "zicbom",
705            "zicbop",
706            "zicboz",
707            "zfhmin",
708            "zkt",
709            "zvfhmin",
710            "zvbb",
711            "zvkt",
712            "zihintntl",
713            "zicond",
714            "zimop",
715            "zcmop",
716            "zcb",
717            "zfa",
718            "zawrs",
719            "supm",
720        ],
721    ),
722    ("supm", Unstable(sym::riscv_target_feature), &[]),
723    ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature), &[]),
724    ("unaligned-vector-mem", Unstable(sym::riscv_target_feature), &[]),
725    ("v", Unstable(sym::riscv_target_feature), &["zvl128b", "zve64d"]),
726    ("za64rs", Stable, &["za128rs"]), // Za64rs ⊃ Za128rs
727    ("za128rs", Stable, &[]),
728    ("zaamo", Stable, &[]),
729    ("zabha", Stable, &["zaamo"]),
730    ("zacas", Stable, &["zaamo"]),
731    ("zalrsc", Stable, &[]),
732    ("zama16b", Stable, &[]),
733    ("zawrs", Stable, &[]),
734    ("zba", Stable, &[]),
735    ("zbb", Stable, &[]),
736    ("zbc", Stable, &["zbkc"]), // Zbc ⊃ Zbkc
737    ("zbkb", Stable, &[]),
738    ("zbkc", Stable, &[]),
739    ("zbkx", Stable, &[]),
740    ("zbs", Stable, &[]),
741    ("zca", Stable, &[]),
742    ("zcb", Stable, &["zca"]),
743    ("zcmop", Stable, &["zca"]),
744    ("zdinx", Unstable(sym::riscv_target_feature), &["zfinx"]),
745    ("zfa", Unstable(sym::riscv_target_feature), &["f"]),
746    ("zfbfmin", Unstable(sym::riscv_target_feature), &["f"]), // and a subset of Zfhmin
747    ("zfh", Unstable(sym::riscv_target_feature), &["zfhmin"]),
748    ("zfhmin", Unstable(sym::riscv_target_feature), &["f"]),
749    ("zfinx", Unstable(sym::riscv_target_feature), &["zicsr"]),
750    ("zhinx", Unstable(sym::riscv_target_feature), &["zhinxmin"]),
751    ("zhinxmin", Unstable(sym::riscv_target_feature), &["zfinx"]),
752    ("zic64b", Stable, &[]),
753    ("zicbom", Stable, &[]),
754    ("zicbop", Stable, &[]),
755    ("zicboz", Stable, &[]),
756    ("ziccamoa", Stable, &[]),
757    ("ziccif", Stable, &[]),
758    ("zicclsm", Stable, &[]),
759    ("ziccrse", Stable, &[]),
760    ("zicntr", Stable, &["zicsr"]),
761    ("zicond", Stable, &[]),
762    ("zicsr", Stable, &[]),
763    ("zifencei", Stable, &[]),
764    ("zihintntl", Stable, &[]),
765    ("zihintpause", Stable, &[]),
766    ("zihpm", Stable, &["zicsr"]),
767    ("zimop", Stable, &[]),
768    ("zk", Stable, &["zkn", "zkr", "zkt"]),
769    ("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
770    ("zknd", Stable, &["zkne_or_zknd"]),
771    ("zkne", Stable, &["zkne_or_zknd"]),
772    ("zkne_or_zknd", Unstable(sym::riscv_target_feature), &[]), // Not an extension
773    ("zknh", Stable, &[]),
774    ("zkr", Stable, &[]),
775    ("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
776    ("zksed", Stable, &[]),
777    ("zksh", Stable, &[]),
778    ("zkt", Stable, &[]),
779    ("zmmul", Unstable(sym::riscv_target_feature), &[]),
780    ("ztso", Stable, &[]),
781    ("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]), // Zvbb ⊃ Zvkb
782    ("zvbc", Unstable(sym::riscv_target_feature), &["zve64x"]),
783    ("zve32f", Unstable(sym::riscv_target_feature), &["zve32x", "f"]),
784    ("zve32x", Unstable(sym::riscv_target_feature), &["zvl32b", "zicsr"]),
785    ("zve64d", Unstable(sym::riscv_target_feature), &["zve64f", "d"]),
786    ("zve64f", Unstable(sym::riscv_target_feature), &["zve32f", "zve64x"]),
787    ("zve64x", Unstable(sym::riscv_target_feature), &["zve32x", "zvl64b"]),
788    ("zvfbfmin", Unstable(sym::riscv_target_feature), &["zve32f"]),
789    ("zvfbfwma", Unstable(sym::riscv_target_feature), &["zfbfmin", "zvfbfmin"]),
790    ("zvfh", Unstable(sym::riscv_target_feature), &["zvfhmin", "zve32f", "zfhmin"]), // Zvfh ⊃ Zvfhmin
791    ("zvfhmin", Unstable(sym::riscv_target_feature), &["zve32f"]),
792    ("zvkb", Unstable(sym::riscv_target_feature), &["zve32x"]),
793    ("zvkg", Unstable(sym::riscv_target_feature), &["zve32x"]),
794    ("zvkn", Unstable(sym::riscv_target_feature), &["zvkned", "zvknhb", "zvkb", "zvkt"]),
795    ("zvknc", Unstable(sym::riscv_target_feature), &["zvkn", "zvbc"]),
796    ("zvkned", Unstable(sym::riscv_target_feature), &["zve32x"]),
797    ("zvkng", Unstable(sym::riscv_target_feature), &["zvkn", "zvkg"]),
798    ("zvknha", Unstable(sym::riscv_target_feature), &["zve32x"]),
799    ("zvknhb", Unstable(sym::riscv_target_feature), &["zvknha", "zve64x"]), // Zvknhb ⊃ Zvknha
800    ("zvks", Unstable(sym::riscv_target_feature), &["zvksed", "zvksh", "zvkb", "zvkt"]),
801    ("zvksc", Unstable(sym::riscv_target_feature), &["zvks", "zvbc"]),
802    ("zvksed", Unstable(sym::riscv_target_feature), &["zve32x"]),
803    ("zvksg", Unstable(sym::riscv_target_feature), &["zvks", "zvkg"]),
804    ("zvksh", Unstable(sym::riscv_target_feature), &["zve32x"]),
805    ("zvkt", Unstable(sym::riscv_target_feature), &[]),
806    ("zvl32b", Unstable(sym::riscv_target_feature), &[]),
807    ("zvl64b", Unstable(sym::riscv_target_feature), &["zvl32b"]),
808    ("zvl128b", Unstable(sym::riscv_target_feature), &["zvl64b"]),
809    ("zvl256b", Unstable(sym::riscv_target_feature), &["zvl128b"]),
810    ("zvl512b", Unstable(sym::riscv_target_feature), &["zvl256b"]),
811    ("zvl1024b", Unstable(sym::riscv_target_feature), &["zvl512b"]),
812    ("zvl2048b", Unstable(sym::riscv_target_feature), &["zvl1024b"]),
813    ("zvl4096b", Unstable(sym::riscv_target_feature), &["zvl2048b"]),
814    ("zvl8192b", Unstable(sym::riscv_target_feature), &["zvl4096b"]),
815    ("zvl16384b", Unstable(sym::riscv_target_feature), &["zvl8192b"]),
816    ("zvl32768b", Unstable(sym::riscv_target_feature), &["zvl16384b"]),
817    ("zvl65536b", Unstable(sym::riscv_target_feature), &["zvl32768b"]),
818    // tidy-alphabetical-end
819];
820
821static WASM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
822    // tidy-alphabetical-start
823    ("atomics", Unstable(sym::wasm_target_feature), &[]),
824    ("bulk-memory", Stable, &[]),
825    ("exception-handling", Unstable(sym::wasm_target_feature), &[]),
826    ("extended-const", Stable, &[]),
827    ("gc", Unstable(sym::wasm_target_feature), &["reference-types"]),
828    ("multivalue", Stable, &[]),
829    ("mutable-globals", Stable, &[]),
830    ("nontrapping-fptoint", Stable, &[]),
831    ("reference-types", Stable, &[]),
832    ("relaxed-simd", Stable, &["simd128"]),
833    ("sign-ext", Stable, &[]),
834    ("simd128", Stable, &[]),
835    ("tail-call", Stable, &[]),
836    ("wide-arithmetic", Unstable(sym::wasm_target_feature), &[]),
837    // tidy-alphabetical-end
838];
839
840const BPF_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
841    ("alu32", Unstable(sym::bpf_target_feature), &[]),
842    ("allows-misaligned-mem-access", Unstable(sym::bpf_target_feature), &[]),
843];
844
845static CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
846    // tidy-alphabetical-start
847    ("2e3", Unstable(sym::csky_target_feature), &["e2"]),
848    ("3e3r1", Unstable(sym::csky_target_feature), &[]),
849    ("3e3r2", Unstable(sym::csky_target_feature), &["3e3r1", "doloop"]),
850    ("3e3r3", Unstable(sym::csky_target_feature), &["doloop"]),
851    ("3e7", Unstable(sym::csky_target_feature), &["2e3"]),
852    ("7e10", Unstable(sym::csky_target_feature), &["3e7"]),
853    ("10e60", Unstable(sym::csky_target_feature), &["7e10"]),
854    ("cache", Unstable(sym::csky_target_feature), &[]),
855    ("doloop", Unstable(sym::csky_target_feature), &[]),
856    ("dsp1e2", Unstable(sym::csky_target_feature), &[]),
857    ("dspe60", Unstable(sym::csky_target_feature), &[]),
858    ("e1", Unstable(sym::csky_target_feature), &["elrw"]),
859    ("e2", Unstable(sym::csky_target_feature), &["e2"]),
860    ("edsp", Unstable(sym::csky_target_feature), &[]),
861    ("elrw", Unstable(sym::csky_target_feature), &[]),
862    ("float1e2", Unstable(sym::csky_target_feature), &[]),
863    ("float1e3", Unstable(sym::csky_target_feature), &[]),
864    ("float3e4", Unstable(sym::csky_target_feature), &[]),
865    ("float7e60", Unstable(sym::csky_target_feature), &[]),
866    ("floate1", Unstable(sym::csky_target_feature), &[]),
867    ("hard-tp", Unstable(sym::csky_target_feature), &[]),
868    ("high-registers", Unstable(sym::csky_target_feature), &[]),
869    ("hwdiv", Unstable(sym::csky_target_feature), &[]),
870    ("mp", Unstable(sym::csky_target_feature), &["2e3"]),
871    ("mp1e2", Unstable(sym::csky_target_feature), &["3e7"]),
872    ("nvic", Unstable(sym::csky_target_feature), &[]),
873    ("trust", Unstable(sym::csky_target_feature), &[]),
874    ("vdsp2e60f", Unstable(sym::csky_target_feature), &[]),
875    ("vdspv1", Unstable(sym::csky_target_feature), &[]),
876    ("vdspv2", Unstable(sym::csky_target_feature), &[]),
877    // tidy-alphabetical-end
878    //fpu
879    // tidy-alphabetical-start
880    ("fdivdu", Unstable(sym::csky_target_feature), &[]),
881    ("fpuv2_df", Unstable(sym::csky_target_feature), &[]),
882    ("fpuv2_sf", Unstable(sym::csky_target_feature), &[]),
883    ("fpuv3_df", Unstable(sym::csky_target_feature), &[]),
884    ("fpuv3_hf", Unstable(sym::csky_target_feature), &[]),
885    ("fpuv3_hi", Unstable(sym::csky_target_feature), &[]),
886    ("fpuv3_sf", Unstable(sym::csky_target_feature), &[]),
887    ("hard-float", Unstable(sym::csky_target_feature), &[]),
888    ("hard-float-abi", Unstable(sym::csky_target_feature), &[]),
889    // tidy-alphabetical-end
890];
891
892static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
893    // tidy-alphabetical-start
894    ("32s", Unstable(sym::loongarch_target_feature), &[]),
895    ("d", Stable, &["f"]),
896    ("div32", Stable, &[]),
897    ("f", Stable, &[]),
898    ("frecipe", Stable, &[]),
899    ("lam-bh", Stable, &[]),
900    ("lamcas", Stable, &[]),
901    ("lasx", Stable, &["lsx"]),
902    ("lbt", Stable, &[]),
903    ("ld-seq-sa", Stable, &[]),
904    ("lsx", Stable, &["d"]),
905    ("lvz", Stable, &[]),
906    ("relax", Unstable(sym::loongarch_target_feature), &[]),
907    ("scq", Stable, &[]),
908    ("ual", Unstable(sym::loongarch_target_feature), &[]),
909    // tidy-alphabetical-end
910];
911
912#[rustfmt::skip]
913const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
914    // tidy-alphabetical-start
915    // For "backchain", https://github.com/rust-lang/rust/issues/142412 is a stabilization blocker
916    ("backchain", Unstable(sym::s390x_target_feature), &[]),
917    ("concurrent-functions", Unstable(sym::s390x_target_feature), &[]),
918    ("deflate-conversion", Unstable(sym::s390x_target_feature), &[]),
919    ("enhanced-sort", Unstable(sym::s390x_target_feature), &[]),
920    ("guarded-storage", Unstable(sym::s390x_target_feature), &[]),
921    ("high-word", Unstable(sym::s390x_target_feature), &[]),
922    // LLVM does not define message-security-assist-extension versions 1, 2, 6, 10 and 11.
923    ("message-security-assist-extension3", Unstable(sym::s390x_target_feature), &[]),
924    ("message-security-assist-extension4", Unstable(sym::s390x_target_feature), &[]),
925    ("message-security-assist-extension5", Unstable(sym::s390x_target_feature), &[]),
926    ("message-security-assist-extension8", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3"]),
927    ("message-security-assist-extension9", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3", "message-security-assist-extension4"]),
928    ("message-security-assist-extension12", Unstable(sym::s390x_target_feature), &[]),
929    ("miscellaneous-extensions-2", Stable, &[]),
930    ("miscellaneous-extensions-3", Stable, &[]),
931    ("miscellaneous-extensions-4", Stable, &[]),
932    ("nnp-assist", Stable, &["vector"]),
933    // Pinned down by [`Target::abi_required_features`].
934    ("soft-float", InternalOnly { reason: "unsupported ABI-configuration feature", hard_error: false }, &[]),
935    ("transactional-execution", Unstable(sym::s390x_target_feature), &[]),
936    ("vector", Stable, &[]),
937    ("vector-enhancements-1", Stable, &["vector"]),
938    ("vector-enhancements-2", Stable, &["vector-enhancements-1"]),
939    ("vector-enhancements-3", Stable, &["vector-enhancements-2"]),
940    ("vector-packed-decimal", Stable, &["vector"]),
941    ("vector-packed-decimal-enhancement", Stable, &["vector-packed-decimal"]),
942    ("vector-packed-decimal-enhancement-2", Stable, &["vector-packed-decimal-enhancement"]),
943    ("vector-packed-decimal-enhancement-3", Stable, &["vector-packed-decimal-enhancement-2"]),
944    // tidy-alphabetical-end
945];
946
947const SPARC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
948    // tidy-alphabetical-start
949    ("leoncasa", Unstable(sym::sparc_target_feature), &[]),
950    (
951        "soft-float",
952        InternalOnly { reason: "unsupported ABI-configuration feature", hard_error: false },
953        &[],
954    ),
955    ("v8plus", Unstable(sym::sparc_target_feature), &[]),
956    // FIXME: It's unclear what this feature means when `v8plus` is disabled on 32-bit SPARC. See
957    // the discussion around https://github.com/rust-lang/rust/pull/160949#discussion_r3806194355.
958    ("v9", Unstable(sym::sparc_target_feature), &[]),
959    // tidy-alphabetical-end
960];
961
962static M68K_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
963    // tidy-alphabetical-start
964    ("isa-68000", Unstable(sym::m68k_target_feature), &[]),
965    ("isa-68010", Unstable(sym::m68k_target_feature), &["isa-68000"]),
966    ("isa-68020", Unstable(sym::m68k_target_feature), &["isa-68010"]),
967    ("isa-68030", Unstable(sym::m68k_target_feature), &["isa-68020"]),
968    ("isa-68040", Unstable(sym::m68k_target_feature), &["isa-68030", "isa-68882"]),
969    ("isa-68060", Unstable(sym::m68k_target_feature), &["isa-68040"]),
970    // FPU
971    ("isa-68881", Unstable(sym::m68k_target_feature), &[]),
972    ("isa-68882", Unstable(sym::m68k_target_feature), &["isa-68881"]),
973    // tidy-alphabetical-end
974];
975
976static AVR_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
977    // tidy-alphabetical-start
978    ("addsubiw", Unstable(sym::avr_target_feature), &[]),
979    ("break", Unstable(sym::avr_target_feature), &[]),
980    ("eijmpcall", Unstable(sym::avr_target_feature), &[]),
981    ("elpm", Unstable(sym::avr_target_feature), &[]),
982    ("elpmx", Unstable(sym::avr_target_feature), &[]),
983    ("ijmpcall", Unstable(sym::avr_target_feature), &[]),
984    ("jmpcall", Unstable(sym::avr_target_feature), &[]),
985    ("lowbytefirst", Unstable(sym::avr_target_feature), &[]),
986    ("lpm", Unstable(sym::avr_target_feature), &[]),
987    ("lpmx", Unstable(sym::avr_target_feature), &[]),
988    ("movw", Unstable(sym::avr_target_feature), &[]),
989    ("mul", Unstable(sym::avr_target_feature), &[]),
990    ("rmw", Unstable(sym::avr_target_feature), &[]),
991    ("spm", Unstable(sym::avr_target_feature), &[]),
992    ("spmx", Unstable(sym::avr_target_feature), &[]),
993    (
994        "sram",
995        // Pinned down by [`Target::abi_required_features`].
996        InternalOnly { reason: "devices that have no SRAM are unsupported", hard_error: false },
997        &[],
998    ),
999    ("tinyencoding", Unstable(sym::avr_target_feature), &[]),
1000    // tidy-alphabetical-end
1001];
1002
1003const XTENSA_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
1004    ("bool", Unstable(sym::xtensa_target_feature), &[]),
1005    ("fp", Unstable(sym::xtensa_target_feature), &["bool", "coprocessor"]),
1006    ("coprocessor", Unstable(sym::xtensa_target_feature), &[]),
1007    ("highpriinterrupts", Unstable(sym::xtensa_target_feature), &["interrupt"]),
1008    ("interrupt", Unstable(sym::xtensa_target_feature), &["exception"]),
1009    (
1010        "windowed",
1011        // Pinned down by [`Target::abi_required_features`].
1012        InternalOnly {
1013            reason: "windowed changes the Xtensa calling convention",
1014            hard_error: false,
1015        },
1016        &["exception"],
1017    ),
1018    ("loop", Unstable(sym::xtensa_target_feature), &[]),
1019    ("sext", Unstable(sym::xtensa_target_feature), &[]),
1020    ("nsa", Unstable(sym::xtensa_target_feature), &[]),
1021    ("mul32", Unstable(sym::xtensa_target_feature), &[]),
1022    ("mul32high", Unstable(sym::xtensa_target_feature), &["mul32"]),
1023    ("div32", Unstable(sym::xtensa_target_feature), &[]),
1024    ("mac16", Unstable(sym::xtensa_target_feature), &[]),
1025    ("s32c1i", Unstable(sym::xtensa_target_feature), &[]),
1026    ("threadptr", Unstable(sym::xtensa_target_feature), &[]),
1027    ("extendedl32r", Unstable(sym::xtensa_target_feature), &[]),
1028    ("debug", Unstable(sym::xtensa_target_feature), &["exception"]),
1029    ("exception", Unstable(sym::xtensa_target_feature), &[]),
1030    ("rvector", Unstable(sym::xtensa_target_feature), &["exception"]),
1031    ("prid", Unstable(sym::xtensa_target_feature), &[]),
1032    ("regprotect", Unstable(sym::xtensa_target_feature), &[]),
1033    ("miscsr", Unstable(sym::xtensa_target_feature), &[]),
1034];
1035
1036static TARGET_FEATURE_IMPLICATIONS_RAW: &[&[(&str, Stability, ImpliedFeatures)]] = &[
1037    ARM_FEATURES,
1038    AARCH64_FEATURES,
1039    X86_FEATURES,
1040    HEXAGON_FEATURES,
1041    POWERPC_FEATURES,
1042    MIPS_FEATURES,
1043    NVPTX_FEATURES,
1044    RISCV_FEATURES,
1045    WASM_FEATURES,
1046    BPF_FEATURES,
1047    XTENSA_FEATURES,
1048    CSKY_FEATURES,
1049    LOONGARCH_FEATURES,
1050    IBMZ_FEATURES,
1051    SPARC_FEATURES,
1052    M68K_FEATURES,
1053    AVR_FEATURES,
1054];
1055// spellchecker:on