Skip to main content

rustc_target/
target_features.rs

1//! Declares Rust's target feature names for each target.
2//! Note that these are similar to but not always identical to LLVM's feature names,
3//! and Rust adds some features that do not correspond to LLVM features at all.
4use rustc_data_structures::fx::{FxHashMap, FxHashSet};
5use rustc_macros::StableHash;
6use rustc_span::{Symbol, sym};
7
8use crate::spec::{Arch, FloatAbi, LlvmAbi, RustcAbi, Target};
9
10/// Features that control behaviour of rustc, rather than the codegen.
11/// These exist globally and are not in the target-specific lists below.
12pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
13
14/// Stability information for target features.
15#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Stability {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Stability::Stable =>
                ::core::fmt::Formatter::write_str(f, "Stable"),
            Stability::CfgStableToggleUnstable(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "CfgStableToggleUnstable", &__self_0),
            Stability::Unstable(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Unstable", &__self_0),
            Stability::Forbidden { reason: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "Forbidden", "reason", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for Stability { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Stability {
    #[inline]
    fn clone(&self) -> Stability {
        let _: ::core::clone::AssertParamIsClone<Symbol>;
        let _: ::core::clone::AssertParamIsClone<&'static str>;
        *self
    }
}Clone, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for Stability {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    Stability::Stable => {}
                    Stability::CfgStableToggleUnstable(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    Stability::Unstable(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    Stability::Forbidden { reason: ref __binding_0 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
16pub enum Stability {
17    /// This target feature is stable, it can be used in `#[target_feature]` and
18    /// `#[cfg(target_feature)]`.
19    Stable,
20    /// This target feature is cfg-stable. It can be used for `#[cfg(target_feature)]` on stable,
21    /// but using it in `#[target_feature]` requires the given nightly feature.
22    CfgStableToggleUnstable(
23        /// This must be a *language* feature, or else rustc will ICE when reporting a missing
24        /// feature gate!
25        Symbol,
26    ),
27    /// This target feature is unstable. It is only present in `#[cfg(target_feature)]` on
28    /// nightly and using it in `#[target_feature]` requires enabling the given nightly feature.
29    Unstable(
30        /// This must be a *language* feature, or else rustc will ICE when reporting a missing
31        /// feature gate!
32        Symbol,
33    ),
34    /// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be
35    /// set in the target spec. It is never set in `cfg(target_feature)`. Used in
36    /// particular for features are actually ABI configuration flags (not all targets are as nice as
37    /// RISC-V and have an explicit way to set the ABI separate from target features).
38    Forbidden { reason: &'static str },
39}
40use Stability::*;
41
42impl Stability {
43    /// Returns whether the feature can be used in `cfg(target_feature)` ever.
44    /// (It might still be nightly-only even if this returns `true`, so make sure to also check
45    /// `requires_nightly`.)
46    pub fn in_cfg(&self) -> bool {
47        #[allow(non_exhaustive_omitted_patterns)] match self {
    Stability::Stable | Stability::CfgStableToggleUnstable { .. } |
        Stability::Unstable { .. } => true,
    _ => false,
}matches!(
48            self,
49            Stability::Stable
50                | Stability::CfgStableToggleUnstable { .. }
51                | Stability::Unstable { .. }
52        )
53    }
54
55    /// Returns the nightly feature that is required to toggle this target feature via
56    /// `#[target_feature]`/`-Ctarget-feature` or to test it via `cfg(target_feature)`.
57    /// (For `cfg` we only care whether the feature is nightly or not, we don't require
58    /// the feature gate to actually be enabled when using a nightly compiler.)
59    ///
60    /// Before calling this, ensure the feature is even permitted for this use:
61    /// - for `#[target_feature]`/`-Ctarget-feature`, check `toggle_allowed()`
62    /// - for `cfg(target_feature)`, check `in_cfg()`
63    ///
64    /// The `in_cfg` parameter is used to determine whether it will be used in
65    /// `cfg(target_feature)` (true) or `#[target_feature]`/`-Ctarget-feature` (false)
66    pub fn requires_nightly(&self, in_cfg: bool) -> Option<Symbol> {
67        match *self {
68            Stability::Unstable(nightly_feature) => Some(nightly_feature),
69            Stability::CfgStableToggleUnstable(nightly_feature) => {
70                if in_cfg {
71                    None
72                } else {
73                    Some(nightly_feature)
74                }
75            }
76            Stability::Stable { .. } => None,
77            Stability::Forbidden { .. } => {
    ::core::panicking::panic_fmt(format_args!("forbidden features should not reach this far"));
}panic!("forbidden features should not reach this far"),
78        }
79    }
80
81    /// Returns whether the feature is cfg-stable but still requires a nightly feature gate to
82    /// be used in `#[target_feature]`/`-Ctarget-feature`.
83    pub fn is_cfg_stable_toggle_unstable(&self) -> bool {
84        #[allow(non_exhaustive_omitted_patterns)] match self {
    Stability::CfgStableToggleUnstable { .. } => true,
    _ => false,
}matches!(self, Stability::CfgStableToggleUnstable { .. })
85    }
86
87    /// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`.
88    /// (It might still be nightly-only even if this returns `true`, so make sure to also check
89    /// `requires_nightly`.)
90    pub fn toggle_allowed(&self) -> Result<(), &'static str> {
91        match self {
92            Stability::Unstable(_)
93            | Stability::CfgStableToggleUnstable(_)
94            | Stability::Stable { .. } => Ok(()),
95            Stability::Forbidden { reason } => Err(reason),
96        }
97    }
98}
99
100// Here we list target features that rustc "understands": they can be used in `#[target_feature]`
101// and `#[cfg(target_feature)]`. They also do not trigger any warnings when used with
102// `-Ctarget-feature`.
103//
104// Note that even unstable (and even entirely unlisted) features can be used with `-Ctarget-feature`
105// on stable. Using a feature not on the list of Rust target features only emits a warning.
106// Only `cfg(target_feature)` and `#[target_feature]` actually do any stability gating.
107// `cfg(target_feature)` for unstable features just works on nightly without any feature gate.
108// `#[target_feature]` requires a feature gate.
109//
110// When adding features to the below lists
111// check whether they're named already elsewhere in rust
112// e.g. in stdarch and whether the given name matches LLVM's
113// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted.
114// Additionally, if the feature is not available in older version of LLVM supported by the current
115// rust, the same function must be updated to filter out these features to avoid triggering
116// warnings.
117//
118// Also note that all target features listed here must be purely additive: for target_feature 1.1 to
119// be sound, we can never allow features like `+soft-float` (on x86) to be controlled on a
120// per-function level, since we would then allow safe calls from functions with `+soft-float` to
121// functions without that feature!
122//
123// It is important for soundness to consider the interaction of targets features and the function
124// call ABI. For example, disabling the `x87` feature on x86 changes how scalar floats are passed as
125// arguments, so letting people toggle that feature would be unsound. To this end, the
126// `abi_required_features` function computes which target features must and must not be enabled for
127// any given target, and individual features can also be marked as `Forbidden`.
128// See https://github.com/rust-lang/rust/issues/116344 for some more context.
129//
130// The one exception to features that change the ABI is features that enable larger vector
131// registers. Those are permitted to be listed here. The `*_FOR_CORRECT_VECTOR_ABI` arrays store
132// information about which target feature is ABI-required for which vector size; this is used to
133// ensure that vectors can only be passed via `extern "C"` when the right feature is enabled. (For
134// the "Rust" ABI we generally pass vectors by-ref exactly to avoid these issues.)
135// Also see https://github.com/rust-lang/rust/issues/116558.
136//
137// Stabilizing a target feature requires t-lang approval.
138
139// If feature A "implies" feature B, then:
140// - when A gets enabled (via `-Ctarget-feature` or `#[target_feature]`), we also enable B
141// - when B gets disabled (via `-Ctarget-feature`), we also disable A
142//
143// Both of these are also applied transitively.
144type ImpliedFeatures = &'static [&'static str];
145
146static ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
147    // tidy-alphabetical-start
148    ("aclass", Unstable(sym::arm_target_feature), &[]),
149    ("aes", Unstable(sym::arm_target_feature), &["neon"]),
150    (
151        "atomics-32",
152        Stability::Forbidden { reason: "unsound because it changes the ABI of atomic operations" },
153        &[],
154    ),
155    ("crc", Unstable(sym::arm_target_feature), &[]),
156    ("d32", Unstable(sym::arm_target_feature), &[]),
157    ("dotprod", Unstable(sym::arm_target_feature), &["neon"]),
158    ("dsp", Unstable(sym::arm_target_feature), &[]),
159    ("fp-armv8", Unstable(sym::arm_target_feature), &["vfp4"]),
160    ("fp16", Unstable(sym::arm_target_feature), &["neon"]),
161    ("fpregs", Unstable(sym::arm_target_feature), &[]),
162    ("i8mm", Unstable(sym::arm_target_feature), &["neon"]),
163    ("mclass", Unstable(sym::arm_target_feature), &[]),
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    ("v6t2", Unstable(sym::arm_target_feature), &["v6k", "thumb2"]),
182    ("v7", Unstable(sym::arm_target_feature), &["v6t2"]),
183    ("v8", Unstable(sym::arm_target_feature), &["v7"]),
184    ("vfp2", Unstable(sym::arm_target_feature), &[]),
185    ("vfp3", Unstable(sym::arm_target_feature), &["vfp2", "d32"]),
186    ("vfp4", Unstable(sym::arm_target_feature), &["vfp3"]),
187    ("virtualization", Unstable(sym::arm_target_feature), &[]),
188    // tidy-alphabetical-end
189];
190
191static AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
192    // tidy-alphabetical-start
193    // FEAT_AES & FEAT_PMULL
194    ("aes", Stable, &["neon"]),
195    // FEAT_BF16
196    ("bf16", Stable, &[]),
197    // FEAT_BTI
198    ("bti", Stable, &[]),
199    // FEAT_CRC
200    ("crc", Stable, &[]),
201    // FEAT_CSSC
202    ("cssc", Unstable(sym::aarch64_unstable_target_feature), &[]),
203    // FEAT_DIT
204    ("dit", Stable, &[]),
205    // FEAT_DotProd
206    ("dotprod", Stable, &["neon"]),
207    // FEAT_DPB
208    ("dpb", Stable, &[]),
209    // FEAT_DPB2
210    ("dpb2", Stable, &["dpb"]),
211    // FEAT_ECV
212    ("ecv", Unstable(sym::aarch64_unstable_target_feature), &[]),
213    // FEAT_F32MM
214    ("f32mm", Stable, &["sve"]),
215    // FEAT_F64MM
216    ("f64mm", Stable, &["sve"]),
217    // FEAT_FAMINMAX
218    ("faminmax", Unstable(sym::aarch64_unstable_target_feature), &[]),
219    // FEAT_FCMA
220    ("fcma", Stable, &["neon"]),
221    // FEAT_FHM
222    ("fhm", Stable, &["fp16"]),
223    // FEAT_FLAGM
224    ("flagm", Stable, &[]),
225    // FEAT_FLAGM2
226    ("flagm2", Unstable(sym::aarch64_unstable_target_feature), &[]),
227    // We forbid directly toggling just `fp-armv8`; it must be toggled with `neon`.
228    ("fp-armv8", Stability::Forbidden { reason: "Rust ties `fp-armv8` to `neon`" }, &[]),
229    // FEAT_FP8
230    ("fp8", Unstable(sym::aarch64_unstable_target_feature), &["faminmax", "lut", "bf16"]),
231    // FEAT_FP8DOT2
232    ("fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["fp8dot4"]),
233    // FEAT_FP8DOT4
234    ("fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["fp8fma"]),
235    // FEAT_FP8FMA
236    ("fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["fp8"]),
237    // FEAT_FP16
238    // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608
239    ("fp16", Stable, &["neon"]),
240    // FEAT_FRINTTS
241    ("frintts", Stable, &[]),
242    // FEAT_HBC
243    ("hbc", Unstable(sym::aarch64_unstable_target_feature), &[]),
244    // FEAT_I8MM
245    ("i8mm", Stable, &[]),
246    // FEAT_JSCVT
247    // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608
248    ("jsconv", Stable, &["neon"]),
249    // FEAT_LOR
250    ("lor", Stable, &[]),
251    // FEAT_LSE
252    ("lse", Stable, &[]),
253    // FEAT_LSE2
254    ("lse2", Unstable(sym::aarch64_unstable_target_feature), &[]),
255    // FEAT_LSE128
256    ("lse128", Unstable(sym::aarch64_unstable_target_feature), &["lse"]),
257    // FEAT_LUT
258    ("lut", Unstable(sym::aarch64_unstable_target_feature), &[]),
259    // FEAT_MOPS
260    ("mops", Unstable(sym::aarch64_unstable_target_feature), &[]),
261    // FEAT_MTE & FEAT_MTE2
262    ("mte", Stable, &[]),
263    // FEAT_AdvSimd & FEAT_FP
264    ("neon", Stable, &[]),
265    // Backend option to turn atomic operations into an intrinsic call when `lse` is not known to be
266    // available, so the intrinsic can do runtime LSE feature detection rather than unconditionally
267    // using slower non-LSE operations. Unstable since it doesn't need to user-togglable.
268    ("outline-atomics", Unstable(sym::aarch64_unstable_target_feature), &[]),
269    // FEAT_PAUTH (address authentication)
270    ("paca", Stable, &[]),
271    // FEAT_PAUTH (generic authentication)
272    ("pacg", Stable, &[]),
273    // FEAT_PAN
274    ("pan", Stable, &[]),
275    // FEAT_PAuth_LR
276    ("pauth-lr", Unstable(sym::aarch64_unstable_target_feature), &[]),
277    // FEAT_PMUv3
278    ("pmuv3", Stable, &[]),
279    // FEAT_RNG
280    ("rand", Stable, &[]),
281    // FEAT_RAS & FEAT_RASv1p1
282    ("ras", Stable, &[]),
283    // FEAT_LRCPC
284    ("rcpc", Stable, &[]),
285    // FEAT_LRCPC2
286    ("rcpc2", Stable, &["rcpc"]),
287    // FEAT_LRCPC3
288    ("rcpc3", Unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]),
289    // FEAT_RDM
290    ("rdm", Stable, &["neon"]),
291    ("reserve-x18", Forbidden { reason: "use `-Zfixed-x18` compiler flag instead" }, &[]),
292    // FEAT_SB
293    ("sb", Stable, &[]),
294    // FEAT_SHA1 & FEAT_SHA256
295    ("sha2", Stable, &["neon"]),
296    // FEAT_SHA512 & FEAT_SHA3
297    ("sha3", Stable, &["sha2"]),
298    // FEAT_SM3 & FEAT_SM4
299    ("sm4", Stable, &["neon"]),
300    // FEAT_SME
301    ("sme", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]),
302    // FEAT_SME_B16B16
303    ("sme-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16", "sme2", "sve-b16b16"]),
304    // FEAT_SME_F8F16
305    ("sme-f8f16", Unstable(sym::aarch64_unstable_target_feature), &["sme-f8f32"]),
306    // FEAT_SME_F8F32
307    ("sme-f8f32", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]),
308    // FEAT_SME_F16F16
309    ("sme-f16f16", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]),
310    // FEAT_SME_F64F64
311    ("sme-f64f64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]),
312    // FEAT_SME_FA64
313    ("sme-fa64", Unstable(sym::aarch64_unstable_target_feature), &["sme", "sve2"]),
314    // FEAT_SME_I16I64
315    ("sme-i16i64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]),
316    // FEAT_SME_LUTv2
317    ("sme-lutv2", Unstable(sym::aarch64_unstable_target_feature), &[]),
318    // FEAT_SME2
319    ("sme2", Unstable(sym::aarch64_unstable_target_feature), &["sme"]),
320    // FEAT_SME2p1
321    ("sme2p1", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]),
322    // FEAT_SPE
323    ("spe", Stable, &[]),
324    // FEAT_SSBS & FEAT_SSBS2
325    ("ssbs", Stable, &[]),
326    // FEAT_SSVE_FP8FDOT2
327    ("ssve-fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8dot4"]),
328    // FEAT_SSVE_FP8FDOT4
329    ("ssve-fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8fma"]),
330    // FEAT_SSVE_FP8FMA
331    ("ssve-fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]),
332    // FEAT_SVE
333    // It was decided that SVE requires Neon: https://github.com/rust-lang/rust/pull/91608
334    //
335    // LLVM doesn't enable Neon for SVE. ARM indicates that they're separate, but probably always
336    // exist together: https://developer.arm.com/documentation/102340/0100/New-features-in-SVE2
337    //
338    // "For backwards compatibility, Neon and VFP are required in the latest architectures."
339    ("sve", Stable, &["neon"]),
340    // FEAT_SVE_B16B16 (SVE or SME Z-targeting instructions)
341    ("sve-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]),
342    // FEAT_SVE2
343    ("sve2", Stable, &["sve"]),
344    // FEAT_SVE_AES & FEAT_SVE_PMULL128
345    ("sve2-aes", Stable, &["sve2", "aes"]),
346    // FEAT_SVE2_BitPerm
347    ("sve2-bitperm", Stable, &["sve2"]),
348    // FEAT_SVE2_SHA3
349    ("sve2-sha3", Stable, &["sve2", "sha3"]),
350    // FEAT_SVE2_SM4
351    ("sve2-sm4", Stable, &["sve2", "sm4"]),
352    // FEAT_SVE2p1
353    ("sve2p1", Unstable(sym::aarch64_unstable_target_feature), &["sve2"]),
354    // FEAT_TME
355    ("tme", Stable, &[]),
356    (
357        "v8.1a",
358        Unstable(sym::aarch64_ver_target_feature),
359        &["crc", "lse", "rdm", "pan", "lor", "vh"],
360    ),
361    ("v8.2a", Unstable(sym::aarch64_ver_target_feature), &["v8.1a", "ras", "dpb"]),
362    (
363        "v8.3a",
364        Unstable(sym::aarch64_ver_target_feature),
365        &["v8.2a", "rcpc", "paca", "pacg", "jsconv"],
366    ),
367    ("v8.4a", Unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]),
368    ("v8.5a", Unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]),
369    ("v8.6a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]),
370    ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &["v8.6a", "wfxt"]),
371    ("v8.8a", Unstable(sym::aarch64_ver_target_feature), &["v8.7a", "hbc", "mops"]),
372    ("v8.9a", Unstable(sym::aarch64_ver_target_feature), &["v8.8a", "cssc"]),
373    ("v9.1a", Unstable(sym::aarch64_ver_target_feature), &["v9a", "v8.6a"]),
374    ("v9.2a", Unstable(sym::aarch64_ver_target_feature), &["v9.1a", "v8.7a"]),
375    ("v9.3a", Unstable(sym::aarch64_ver_target_feature), &["v9.2a", "v8.8a"]),
376    ("v9.4a", Unstable(sym::aarch64_ver_target_feature), &["v9.3a", "v8.9a"]),
377    ("v9.5a", Unstable(sym::aarch64_ver_target_feature), &["v9.4a"]),
378    ("v9a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "sve2"]),
379    // FEAT_VHE
380    ("vh", Stable, &[]),
381    // FEAT_WFxT
382    ("wfxt", Unstable(sym::aarch64_unstable_target_feature), &[]),
383    // tidy-alphabetical-end
384];
385
386const AARCH64_TIED_FEATURES: &[&[&str]] = &[
387    &["paca", "pacg"], // Together these represent `pauth` in LLVM
388];
389
390static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
391    // tidy-alphabetical-start
392    ("adx", Stable, &[]),
393    ("aes", Stable, &["sse2"]),
394    ("amx-avx512", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
395    ("amx-bf16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
396    ("amx-complex", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
397    ("amx-fp8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
398    ("amx-fp16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
399    ("amx-int8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
400    ("amx-movrs", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
401    ("amx-tf32", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
402    ("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]),
403    ("apxf", Unstable(sym::apx_target_feature), &[]),
404    ("avx", Stable, &["sse4.2"]),
405    ("avx2", Stable, &["avx"]),
406    (
407        "avx10.1",
408        Unstable(sym::avx10_target_feature),
409        &[
410            "avx512bf16",
411            "avx512bitalg",
412            "avx512bw",
413            "avx512cd",
414            "avx512dq",
415            "avx512f",
416            "avx512fp16",
417            "avx512ifma",
418            "avx512vbmi",
419            "avx512vbmi2",
420            "avx512vl",
421            "avx512vnni",
422            "avx512vpopcntdq",
423        ],
424    ),
425    (
426        "avx10.2",
427        Unstable(sym::avx10_target_feature),
428        &["avx10.1", "avxvnni", "avxvnniint8", "avxvnniint16"],
429    ),
430    ("avx512bf16", Stable, &["avx512bw"]),
431    ("avx512bitalg", Stable, &["avx512bw"]),
432    ("avx512bw", Stable, &["avx512f"]),
433    ("avx512cd", Stable, &["avx512f"]),
434    ("avx512dq", Stable, &["avx512f"]),
435    ("avx512f", Stable, &["avx2", "fma", "f16c"]),
436    ("avx512fp16", Stable, &["avx512bw"]),
437    ("avx512ifma", Stable, &["avx512f"]),
438    ("avx512vbmi", Stable, &["avx512bw"]),
439    ("avx512vbmi2", Stable, &["avx512bw"]),
440    ("avx512vl", Stable, &["avx512f"]),
441    ("avx512vnni", Stable, &["avx512f"]),
442    ("avx512vp2intersect", Stable, &["avx512f"]),
443    ("avx512vpopcntdq", Stable, &["avx512f"]),
444    ("avxifma", Stable, &["avx2"]),
445    ("avxneconvert", Stable, &["avx2"]),
446    ("avxvnni", Stable, &["avx2"]),
447    ("avxvnniint8", Stable, &["avx2"]),
448    ("avxvnniint16", Stable, &["avx2"]),
449    ("bmi1", Stable, &[]),
450    ("bmi2", Stable, &[]),
451    ("cmpxchg16b", Stable, &[]),
452    ("ermsb", Unstable(sym::ermsb_target_feature), &[]),
453    ("f16c", Stable, &["avx"]),
454    ("fma", Stable, &["avx"]),
455    ("fma4", Unstable(sym::fma4_target_feature), &["avx", "sse4a"]),
456    ("fxsr", Stable, &[]),
457    ("gfni", Stable, &["sse2"]),
458    ("kl", Stable, &["sse2"]),
459    ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
460    ("lzcnt", Stable, &[]),
461    ("movbe", Stable, &[]),
462    ("movrs", Unstable(sym::movrs_target_feature), &[]),
463    ("pclmulqdq", Stable, &["sse2"]),
464    ("popcnt", Stable, &[]),
465    ("prfchw", Unstable(sym::prfchw_target_feature), &[]),
466    ("rdrand", Stable, &[]),
467    ("rdseed", Stable, &[]),
468    (
469        "retpoline-external-thunk",
470        Stability::Forbidden { reason: "use `-Zretpoline-external-thunk` compiler flag instead" },
471        &[],
472    ),
473    (
474        "retpoline-indirect-branches",
475        Stability::Forbidden { reason: "use `-Zretpoline` compiler flag instead" },
476        &[],
477    ),
478    (
479        "retpoline-indirect-calls",
480        Stability::Forbidden { reason: "use `-Zretpoline` compiler flag instead" },
481        &[],
482    ),
483    ("rtm", Unstable(sym::rtm_target_feature), &[]),
484    ("sha", Stable, &["sse2"]),
485    ("sha512", Stable, &["avx2"]),
486    ("sm3", Stable, &["avx"]),
487    ("sm4", Stable, &["avx2"]),
488    ("soft-float", Stability::Forbidden { reason: "use a soft-float target instead" }, &[]),
489    ("sse", Stable, &[]),
490    ("sse2", Stable, &["sse"]),
491    ("sse3", Stable, &["sse2"]),
492    ("sse4.1", Stable, &["ssse3"]),
493    ("sse4.2", Stable, &["sse4.1"]),
494    ("sse4a", Stable, &["sse3"]),
495    ("ssse3", Stable, &["sse3"]),
496    ("tbm", Stable, &[]),
497    ("vaes", Stable, &["avx2", "aes"]),
498    ("vpclmulqdq", Stable, &["avx", "pclmulqdq"]),
499    ("widekl", Stable, &["kl"]),
500    ("x87", Unstable(sym::x87_target_feature), &[]),
501    ("xop", Unstable(sym::xop_target_feature), &["fma4", "avx", "sse4a"]),
502    ("xsave", Stable, &[]),
503    ("xsavec", Stable, &["xsave"]),
504    ("xsaveopt", Stable, &["xsave"]),
505    ("xsaves", Stable, &["xsave"]),
506    // tidy-alphabetical-end
507];
508
509const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
510    // tidy-alphabetical-start
511    ("audio", Unstable(sym::hexagon_target_feature), &[]),
512    ("hvx", Unstable(sym::hexagon_target_feature), &[]),
513    ("hvx-ieee-fp", Unstable(sym::hexagon_target_feature), &["hvx"]),
514    ("hvx-length64b", Unstable(sym::hexagon_target_feature), &["hvx"]),
515    ("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]),
516    ("hvx-qfloat", Unstable(sym::hexagon_target_feature), &["hvx"]),
517    ("hvxv60", Unstable(sym::hexagon_target_feature), &["hvx"]),
518    ("hvxv62", Unstable(sym::hexagon_target_feature), &["hvxv60"]),
519    ("hvxv65", Unstable(sym::hexagon_target_feature), &["hvxv62"]),
520    ("hvxv66", Unstable(sym::hexagon_target_feature), &["hvxv65", "zreg"]),
521    ("hvxv67", Unstable(sym::hexagon_target_feature), &["hvxv66"]),
522    ("hvxv68", Unstable(sym::hexagon_target_feature), &["hvxv67"]),
523    ("hvxv69", Unstable(sym::hexagon_target_feature), &["hvxv68"]),
524    ("hvxv71", Unstable(sym::hexagon_target_feature), &["hvxv69"]),
525    ("hvxv73", Unstable(sym::hexagon_target_feature), &["hvxv71"]),
526    ("hvxv75", Unstable(sym::hexagon_target_feature), &["hvxv73"]),
527    ("hvxv79", Unstable(sym::hexagon_target_feature), &["hvxv75"]),
528    ("v60", Unstable(sym::hexagon_target_feature), &[]),
529    ("v62", Unstable(sym::hexagon_target_feature), &["v60"]),
530    ("v65", Unstable(sym::hexagon_target_feature), &["v62"]),
531    ("v66", Unstable(sym::hexagon_target_feature), &["v65"]),
532    ("v67", Unstable(sym::hexagon_target_feature), &["v66"]),
533    ("v68", Unstable(sym::hexagon_target_feature), &["v67"]),
534    ("v69", Unstable(sym::hexagon_target_feature), &["v68"]),
535    ("v71", Unstable(sym::hexagon_target_feature), &["v69"]),
536    ("v73", Unstable(sym::hexagon_target_feature), &["v71"]),
537    ("v75", Unstable(sym::hexagon_target_feature), &["v73"]),
538    ("v79", Unstable(sym::hexagon_target_feature), &["v75"]),
539    ("zreg", Unstable(sym::hexagon_target_feature), &[]),
540    // tidy-alphabetical-end
541];
542
543static POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
544    // tidy-alphabetical-start
545    ("altivec", Unstable(sym::powerpc_target_feature), &[]),
546    ("msync", Unstable(sym::powerpc_target_feature), &[]),
547    ("partword-atomics", Unstable(sym::powerpc_target_feature), &[]),
548    ("power8-altivec", Unstable(sym::powerpc_target_feature), &["altivec"]),
549    ("power8-crypto", Unstable(sym::powerpc_target_feature), &["power8-altivec"]),
550    ("power8-vector", Unstable(sym::powerpc_target_feature), &["vsx", "power8-altivec"]),
551    ("power9-altivec", Unstable(sym::powerpc_target_feature), &["power8-altivec"]),
552    ("power9-vector", Unstable(sym::powerpc_target_feature), &["power8-vector", "power9-altivec"]),
553    ("power10-vector", Unstable(sym::powerpc_target_feature), &["power9-vector"]),
554    ("quadword-atomics", Unstable(sym::powerpc_target_feature), &[]),
555    ("vsx", Unstable(sym::powerpc_target_feature), &["altivec"]),
556    // tidy-alphabetical-end
557];
558
559const MIPS_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
560    // tidy-alphabetical-start
561    ("fp64", Unstable(sym::mips_target_feature), &[]),
562    ("msa", Unstable(sym::mips_target_feature), &[]),
563    ("virt", Unstable(sym::mips_target_feature), &[]),
564    // tidy-alphabetical-end
565];
566
567const NVPTX_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
568    // tidy-alphabetical-start
569    ("sm_70", Unstable(sym::nvptx_target_feature), &[]),
570    ("sm_72", Unstable(sym::nvptx_target_feature), &["sm_70"]),
571    ("sm_75", Unstable(sym::nvptx_target_feature), &["sm_72"]),
572    ("sm_80", Unstable(sym::nvptx_target_feature), &["sm_75"]),
573    ("sm_86", Unstable(sym::nvptx_target_feature), &["sm_80"]),
574    ("sm_87", Unstable(sym::nvptx_target_feature), &["sm_86"]),
575    ("sm_89", Unstable(sym::nvptx_target_feature), &["sm_87"]),
576    ("sm_90", Unstable(sym::nvptx_target_feature), &["sm_89"]),
577    ("sm_90a", Unstable(sym::nvptx_target_feature), &["sm_90"]),
578    // tidy-alphabetical-end
579    // tidy-alphabetical-start
580    ("sm_100", Unstable(sym::nvptx_target_feature), &["sm_90"]),
581    ("sm_100a", Unstable(sym::nvptx_target_feature), &["sm_100"]),
582    ("sm_101", Unstable(sym::nvptx_target_feature), &["sm_100"]),
583    ("sm_101a", Unstable(sym::nvptx_target_feature), &["sm_101"]),
584    ("sm_120", Unstable(sym::nvptx_target_feature), &["sm_101"]),
585    ("sm_120a", Unstable(sym::nvptx_target_feature), &["sm_120"]),
586    // tidy-alphabetical-end
587    // tidy-alphabetical-start
588    ("ptx70", Unstable(sym::nvptx_target_feature), &[]),
589    ("ptx71", Unstable(sym::nvptx_target_feature), &["ptx70"]),
590    ("ptx72", Unstable(sym::nvptx_target_feature), &["ptx71"]),
591    ("ptx73", Unstable(sym::nvptx_target_feature), &["ptx72"]),
592    ("ptx74", Unstable(sym::nvptx_target_feature), &["ptx73"]),
593    ("ptx75", Unstable(sym::nvptx_target_feature), &["ptx74"]),
594    ("ptx76", Unstable(sym::nvptx_target_feature), &["ptx75"]),
595    ("ptx77", Unstable(sym::nvptx_target_feature), &["ptx76"]),
596    ("ptx78", Unstable(sym::nvptx_target_feature), &["ptx77"]),
597    ("ptx80", Unstable(sym::nvptx_target_feature), &["ptx78"]),
598    ("ptx81", Unstable(sym::nvptx_target_feature), &["ptx80"]),
599    ("ptx82", Unstable(sym::nvptx_target_feature), &["ptx81"]),
600    ("ptx83", Unstable(sym::nvptx_target_feature), &["ptx82"]),
601    ("ptx84", Unstable(sym::nvptx_target_feature), &["ptx83"]),
602    ("ptx85", Unstable(sym::nvptx_target_feature), &["ptx84"]),
603    ("ptx86", Unstable(sym::nvptx_target_feature), &["ptx85"]),
604    ("ptx87", Unstable(sym::nvptx_target_feature), &["ptx86"]),
605    // tidy-alphabetical-end
606];
607
608static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
609    // tidy-alphabetical-start
610    ("a", Stable, &["zaamo", "zalrsc"]),
611    ("b", Stable, &["zba", "zbb", "zbs"]),
612    ("c", Stable, &["zca"]),
613    ("d", Unstable(sym::riscv_target_feature), &["f"]),
614    ("e", Unstable(sym::riscv_target_feature), &[]),
615    ("f", Unstable(sym::riscv_target_feature), &["zicsr"]),
616    (
617        "forced-atomics",
618        Stability::Forbidden { reason: "unsound because it changes the ABI of atomic operations" },
619        &[],
620    ),
621    ("m", Stable, &[]),
622    ("relax", Unstable(sym::riscv_target_feature), &[]),
623    (
624        "rva23u64",
625        Unstable(sym::riscv_target_feature),
626        &[
627            "m",
628            "a",
629            "f",
630            "d",
631            "c",
632            "b",
633            "v",
634            "zicsr",
635            "zicntr",
636            "zihpm",
637            "ziccif",
638            "ziccrse",
639            "ziccamoa",
640            "zicclsm",
641            "zic64b",
642            "za64rs",
643            "zihintpause",
644            "zba",
645            "zbb",
646            "zbs",
647            "zicbom",
648            "zicbop",
649            "zicboz",
650            "zfhmin",
651            "zkt",
652            "zvfhmin",
653            "zvbb",
654            "zvkt",
655            "zihintntl",
656            "zicond",
657            "zimop",
658            "zcmop",
659            "zcb",
660            "zfa",
661            "zawrs",
662            "supm",
663        ],
664    ),
665    ("supm", Unstable(sym::riscv_target_feature), &[]),
666    ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature), &[]),
667    ("unaligned-vector-mem", Unstable(sym::riscv_target_feature), &[]),
668    ("v", Unstable(sym::riscv_target_feature), &["zvl128b", "zve64d"]),
669    ("za64rs", Stable, &["za128rs"]), // Za64rs ⊃ Za128rs
670    ("za128rs", Stable, &[]),
671    ("zaamo", Stable, &[]),
672    ("zabha", Stable, &["zaamo"]),
673    ("zacas", Stable, &["zaamo"]),
674    ("zalrsc", Stable, &[]),
675    ("zama16b", Stable, &[]),
676    ("zawrs", Stable, &[]),
677    ("zba", Stable, &[]),
678    ("zbb", Stable, &[]),
679    ("zbc", Stable, &["zbkc"]), // Zbc ⊃ Zbkc
680    ("zbkb", Stable, &[]),
681    ("zbkc", Stable, &[]),
682    ("zbkx", Stable, &[]),
683    ("zbs", Stable, &[]),
684    ("zca", Stable, &[]),
685    ("zcb", Stable, &["zca"]),
686    ("zcmop", Stable, &["zca"]),
687    ("zdinx", Unstable(sym::riscv_target_feature), &["zfinx"]),
688    ("zfa", Unstable(sym::riscv_target_feature), &["f"]),
689    ("zfbfmin", Unstable(sym::riscv_target_feature), &["f"]), // and a subset of Zfhmin
690    ("zfh", Unstable(sym::riscv_target_feature), &["zfhmin"]),
691    ("zfhmin", Unstable(sym::riscv_target_feature), &["f"]),
692    ("zfinx", Unstable(sym::riscv_target_feature), &["zicsr"]),
693    ("zhinx", Unstable(sym::riscv_target_feature), &["zhinxmin"]),
694    ("zhinxmin", Unstable(sym::riscv_target_feature), &["zfinx"]),
695    ("zic64b", Stable, &[]),
696    ("zicbom", Stable, &[]),
697    ("zicbop", Stable, &[]),
698    ("zicboz", Stable, &[]),
699    ("ziccamoa", Stable, &[]),
700    ("ziccif", Stable, &[]),
701    ("zicclsm", Stable, &[]),
702    ("ziccrse", Stable, &[]),
703    ("zicntr", Stable, &["zicsr"]),
704    ("zicond", Stable, &[]),
705    ("zicsr", Stable, &[]),
706    ("zifencei", Stable, &[]),
707    ("zihintntl", Stable, &[]),
708    ("zihintpause", Stable, &[]),
709    ("zihpm", Stable, &["zicsr"]),
710    ("zimop", Stable, &[]),
711    ("zk", Stable, &["zkn", "zkr", "zkt"]),
712    ("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
713    ("zknd", Stable, &["zkne_or_zknd"]),
714    ("zkne", Stable, &["zkne_or_zknd"]),
715    ("zkne_or_zknd", Unstable(sym::riscv_target_feature), &[]), // Not an extension
716    ("zknh", Stable, &[]),
717    ("zkr", Stable, &[]),
718    ("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
719    ("zksed", Stable, &[]),
720    ("zksh", Stable, &[]),
721    ("zkt", Stable, &[]),
722    ("ztso", Stable, &[]),
723    ("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]), // Zvbb ⊃ Zvkb
724    ("zvbc", Unstable(sym::riscv_target_feature), &["zve64x"]),
725    ("zve32f", Unstable(sym::riscv_target_feature), &["zve32x", "f"]),
726    ("zve32x", Unstable(sym::riscv_target_feature), &["zvl32b", "zicsr"]),
727    ("zve64d", Unstable(sym::riscv_target_feature), &["zve64f", "d"]),
728    ("zve64f", Unstable(sym::riscv_target_feature), &["zve32f", "zve64x"]),
729    ("zve64x", Unstable(sym::riscv_target_feature), &["zve32x", "zvl64b"]),
730    ("zvfbfmin", Unstable(sym::riscv_target_feature), &["zve32f"]),
731    ("zvfbfwma", Unstable(sym::riscv_target_feature), &["zfbfmin", "zvfbfmin"]),
732    ("zvfh", Unstable(sym::riscv_target_feature), &["zvfhmin", "zve32f", "zfhmin"]), // Zvfh ⊃ Zvfhmin
733    ("zvfhmin", Unstable(sym::riscv_target_feature), &["zve32f"]),
734    ("zvkb", Unstable(sym::riscv_target_feature), &["zve32x"]),
735    ("zvkg", Unstable(sym::riscv_target_feature), &["zve32x"]),
736    ("zvkn", Unstable(sym::riscv_target_feature), &["zvkned", "zvknhb", "zvkb", "zvkt"]),
737    ("zvknc", Unstable(sym::riscv_target_feature), &["zvkn", "zvbc"]),
738    ("zvkned", Unstable(sym::riscv_target_feature), &["zve32x"]),
739    ("zvkng", Unstable(sym::riscv_target_feature), &["zvkn", "zvkg"]),
740    ("zvknha", Unstable(sym::riscv_target_feature), &["zve32x"]),
741    ("zvknhb", Unstable(sym::riscv_target_feature), &["zvknha", "zve64x"]), // Zvknhb ⊃ Zvknha
742    ("zvks", Unstable(sym::riscv_target_feature), &["zvksed", "zvksh", "zvkb", "zvkt"]),
743    ("zvksc", Unstable(sym::riscv_target_feature), &["zvks", "zvbc"]),
744    ("zvksed", Unstable(sym::riscv_target_feature), &["zve32x"]),
745    ("zvksg", Unstable(sym::riscv_target_feature), &["zvks", "zvkg"]),
746    ("zvksh", Unstable(sym::riscv_target_feature), &["zve32x"]),
747    ("zvkt", Unstable(sym::riscv_target_feature), &[]),
748    ("zvl32b", Unstable(sym::riscv_target_feature), &[]),
749    ("zvl64b", Unstable(sym::riscv_target_feature), &["zvl32b"]),
750    ("zvl128b", Unstable(sym::riscv_target_feature), &["zvl64b"]),
751    ("zvl256b", Unstable(sym::riscv_target_feature), &["zvl128b"]),
752    ("zvl512b", Unstable(sym::riscv_target_feature), &["zvl256b"]),
753    ("zvl1024b", Unstable(sym::riscv_target_feature), &["zvl512b"]),
754    ("zvl2048b", Unstable(sym::riscv_target_feature), &["zvl1024b"]),
755    ("zvl4096b", Unstable(sym::riscv_target_feature), &["zvl2048b"]),
756    ("zvl8192b", Unstable(sym::riscv_target_feature), &["zvl4096b"]),
757    ("zvl16384b", Unstable(sym::riscv_target_feature), &["zvl8192b"]),
758    ("zvl32768b", Unstable(sym::riscv_target_feature), &["zvl16384b"]),
759    ("zvl65536b", Unstable(sym::riscv_target_feature), &["zvl32768b"]),
760    // tidy-alphabetical-end
761];
762
763static WASM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
764    // tidy-alphabetical-start
765    ("atomics", Unstable(sym::wasm_target_feature), &[]),
766    ("bulk-memory", Stable, &[]),
767    ("exception-handling", Unstable(sym::wasm_target_feature), &[]),
768    ("extended-const", Stable, &[]),
769    ("gc", Unstable(sym::wasm_target_feature), &["reference-types"]),
770    ("multivalue", Stable, &[]),
771    ("mutable-globals", Stable, &[]),
772    ("nontrapping-fptoint", Stable, &[]),
773    ("reference-types", Stable, &[]),
774    ("relaxed-simd", Stable, &["simd128"]),
775    ("sign-ext", Stable, &[]),
776    ("simd128", Stable, &[]),
777    ("tail-call", Stable, &[]),
778    ("wide-arithmetic", Unstable(sym::wasm_target_feature), &[]),
779    // tidy-alphabetical-end
780];
781
782const BPF_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
783    ("alu32", Unstable(sym::bpf_target_feature), &[]),
784    ("allows-misaligned-mem-access", Unstable(sym::bpf_target_feature), &[]),
785];
786
787static CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
788    // tidy-alphabetical-start
789    ("2e3", Unstable(sym::csky_target_feature), &["e2"]),
790    ("3e3r1", Unstable(sym::csky_target_feature), &[]),
791    ("3e3r2", Unstable(sym::csky_target_feature), &["3e3r1", "doloop"]),
792    ("3e3r3", Unstable(sym::csky_target_feature), &["doloop"]),
793    ("3e7", Unstable(sym::csky_target_feature), &["2e3"]),
794    ("7e10", Unstable(sym::csky_target_feature), &["3e7"]),
795    ("10e60", Unstable(sym::csky_target_feature), &["7e10"]),
796    ("cache", Unstable(sym::csky_target_feature), &[]),
797    ("doloop", Unstable(sym::csky_target_feature), &[]),
798    ("dsp1e2", Unstable(sym::csky_target_feature), &[]),
799    ("dspe60", Unstable(sym::csky_target_feature), &[]),
800    ("e1", Unstable(sym::csky_target_feature), &["elrw"]),
801    ("e2", Unstable(sym::csky_target_feature), &["e2"]),
802    ("edsp", Unstable(sym::csky_target_feature), &[]),
803    ("elrw", Unstable(sym::csky_target_feature), &[]),
804    ("float1e2", Unstable(sym::csky_target_feature), &[]),
805    ("float1e3", Unstable(sym::csky_target_feature), &[]),
806    ("float3e4", Unstable(sym::csky_target_feature), &[]),
807    ("float7e60", Unstable(sym::csky_target_feature), &[]),
808    ("floate1", Unstable(sym::csky_target_feature), &[]),
809    ("hard-tp", Unstable(sym::csky_target_feature), &[]),
810    ("high-registers", Unstable(sym::csky_target_feature), &[]),
811    ("hwdiv", Unstable(sym::csky_target_feature), &[]),
812    ("mp", Unstable(sym::csky_target_feature), &["2e3"]),
813    ("mp1e2", Unstable(sym::csky_target_feature), &["3e7"]),
814    ("nvic", Unstable(sym::csky_target_feature), &[]),
815    ("trust", Unstable(sym::csky_target_feature), &[]),
816    ("vdsp2e60f", Unstable(sym::csky_target_feature), &[]),
817    ("vdspv1", Unstable(sym::csky_target_feature), &[]),
818    ("vdspv2", Unstable(sym::csky_target_feature), &[]),
819    // tidy-alphabetical-end
820    //fpu
821    // tidy-alphabetical-start
822    ("fdivdu", Unstable(sym::csky_target_feature), &[]),
823    ("fpuv2_df", Unstable(sym::csky_target_feature), &[]),
824    ("fpuv2_sf", Unstable(sym::csky_target_feature), &[]),
825    ("fpuv3_df", Unstable(sym::csky_target_feature), &[]),
826    ("fpuv3_hf", Unstable(sym::csky_target_feature), &[]),
827    ("fpuv3_hi", Unstable(sym::csky_target_feature), &[]),
828    ("fpuv3_sf", Unstable(sym::csky_target_feature), &[]),
829    ("hard-float", Unstable(sym::csky_target_feature), &[]),
830    ("hard-float-abi", Unstable(sym::csky_target_feature), &[]),
831    // tidy-alphabetical-end
832];
833
834static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
835    // tidy-alphabetical-start
836    ("32s", Unstable(sym::loongarch_target_feature), &[]),
837    ("d", Stable, &["f"]),
838    ("div32", Stable, &[]),
839    ("f", Stable, &[]),
840    ("frecipe", Stable, &[]),
841    ("lam-bh", Stable, &[]),
842    ("lamcas", Stable, &[]),
843    ("lasx", Stable, &["lsx"]),
844    ("lbt", Stable, &[]),
845    ("ld-seq-sa", Stable, &[]),
846    ("lsx", Stable, &["d"]),
847    ("lvz", Stable, &[]),
848    ("relax", Unstable(sym::loongarch_target_feature), &[]),
849    ("scq", Stable, &[]),
850    ("ual", Unstable(sym::loongarch_target_feature), &[]),
851    // tidy-alphabetical-end
852];
853
854#[rustfmt::skip]
855const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
856    // tidy-alphabetical-start
857    // For "backchain", https://github.com/rust-lang/rust/issues/142412 is a stabilization blocker
858    ("backchain", Unstable(sym::s390x_target_feature), &[]),
859    ("concurrent-functions", Unstable(sym::s390x_target_feature), &[]),
860    ("deflate-conversion", Unstable(sym::s390x_target_feature), &[]),
861    ("enhanced-sort", Unstable(sym::s390x_target_feature), &[]),
862    ("guarded-storage", Unstable(sym::s390x_target_feature), &[]),
863    ("high-word", Unstable(sym::s390x_target_feature), &[]),
864    // LLVM does not define message-security-assist-extension versions 1, 2, 6, 10 and 11.
865    ("message-security-assist-extension3", Unstable(sym::s390x_target_feature), &[]),
866    ("message-security-assist-extension4", Unstable(sym::s390x_target_feature), &[]),
867    ("message-security-assist-extension5", Unstable(sym::s390x_target_feature), &[]),
868    ("message-security-assist-extension8", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3"]),
869    ("message-security-assist-extension9", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3", "message-security-assist-extension4"]),
870    ("message-security-assist-extension12", Unstable(sym::s390x_target_feature), &[]),
871    ("miscellaneous-extensions-2", Stable, &[]),
872    ("miscellaneous-extensions-3", Stable, &[]),
873    ("miscellaneous-extensions-4", Stable, &[]),
874    ("nnp-assist", Stable, &["vector"]),
875    ("soft-float", Forbidden { reason: "unsupported ABI-configuration feature" }, &[]),
876    ("transactional-execution", Unstable(sym::s390x_target_feature), &[]),
877    ("vector", Stable, &[]),
878    ("vector-enhancements-1", Stable, &["vector"]),
879    ("vector-enhancements-2", Stable, &["vector-enhancements-1"]),
880    ("vector-enhancements-3", Stable, &["vector-enhancements-2"]),
881    ("vector-packed-decimal", Stable, &["vector"]),
882    ("vector-packed-decimal-enhancement", Stable, &["vector-packed-decimal"]),
883    ("vector-packed-decimal-enhancement-2", Stable, &["vector-packed-decimal-enhancement"]),
884    ("vector-packed-decimal-enhancement-3", Stable, &["vector-packed-decimal-enhancement-2"]),
885    // tidy-alphabetical-end
886];
887
888const SPARC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
889    // tidy-alphabetical-start
890    ("leoncasa", Unstable(sym::sparc_target_feature), &[]),
891    ("v8plus", Unstable(sym::sparc_target_feature), &[]),
892    ("v9", Unstable(sym::sparc_target_feature), &[]),
893    // tidy-alphabetical-end
894];
895
896static M68K_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
897    // tidy-alphabetical-start
898    ("isa-68000", Unstable(sym::m68k_target_feature), &[]),
899    ("isa-68010", Unstable(sym::m68k_target_feature), &["isa-68000"]),
900    ("isa-68020", Unstable(sym::m68k_target_feature), &["isa-68010"]),
901    ("isa-68030", Unstable(sym::m68k_target_feature), &["isa-68020"]),
902    ("isa-68040", Unstable(sym::m68k_target_feature), &["isa-68030", "isa-68882"]),
903    ("isa-68060", Unstable(sym::m68k_target_feature), &["isa-68040"]),
904    // FPU
905    ("isa-68881", Unstable(sym::m68k_target_feature), &[]),
906    ("isa-68882", Unstable(sym::m68k_target_feature), &["isa-68881"]),
907    // tidy-alphabetical-end
908];
909
910static AVR_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
911    // tidy-alphabetical-start
912    ("addsubiw", Unstable(sym::avr_target_feature), &[]),
913    ("break", Unstable(sym::avr_target_feature), &[]),
914    ("eijmpcall", Unstable(sym::avr_target_feature), &[]),
915    ("elpm", Unstable(sym::avr_target_feature), &[]),
916    ("elpmx", Unstable(sym::avr_target_feature), &[]),
917    ("ijmpcall", Unstable(sym::avr_target_feature), &[]),
918    ("jmpcall", Unstable(sym::avr_target_feature), &[]),
919    ("lowbytefirst", Unstable(sym::avr_target_feature), &[]),
920    ("lpm", Unstable(sym::avr_target_feature), &[]),
921    ("lpmx", Unstable(sym::avr_target_feature), &[]),
922    ("movw", Unstable(sym::avr_target_feature), &[]),
923    ("mul", Unstable(sym::avr_target_feature), &[]),
924    ("rmw", Unstable(sym::avr_target_feature), &[]),
925    ("spm", Unstable(sym::avr_target_feature), &[]),
926    ("spmx", Unstable(sym::avr_target_feature), &[]),
927    ("sram", Forbidden { reason: "devices that have no SRAM are unsupported" }, &[]),
928    ("tinyencoding", Unstable(sym::avr_target_feature), &[]),
929    // tidy-alphabetical-end
930];
931
932/// When rustdoc is running, provide a list of all known features so that all their respective
933/// primitives may be documented.
934///
935/// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator!
936pub fn all_rust_features() -> impl Iterator<Item = (&'static str, Stability)> {
937    std::iter::empty()
938        .chain(ARM_FEATURES.iter())
939        .chain(AARCH64_FEATURES.iter())
940        .chain(X86_FEATURES.iter())
941        .chain(HEXAGON_FEATURES.iter())
942        .chain(POWERPC_FEATURES.iter())
943        .chain(MIPS_FEATURES.iter())
944        .chain(NVPTX_FEATURES.iter())
945        .chain(RISCV_FEATURES.iter())
946        .chain(WASM_FEATURES.iter())
947        .chain(BPF_FEATURES.iter())
948        .chain(CSKY_FEATURES)
949        .chain(LOONGARCH_FEATURES)
950        .chain(IBMZ_FEATURES)
951        .chain(SPARC_FEATURES)
952        .chain(M68K_FEATURES)
953        .chain(AVR_FEATURES)
954        .cloned()
955        .map(|(f, s, _)| (f, s))
956}
957
958// These arrays represent the least-constraining feature that is required for vector types up to a
959// certain size to have their "proper" ABI on each architecture.
960// Note that they must be kept sorted by vector size.
961const X86_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
962    &[(128, "sse"), (256, "avx"), (512, "avx512f")]; // FIXME: might need changes for AVX10.
963const AARCH64_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
964    &[(128, "neon")];
965
966// We might want to add "helium" too.
967const ARM_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
968    &[(128, "neon")];
969
970const AMDGPU_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
971    &[(1024, "")];
972const POWERPC_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
973    &[(128, "altivec")];
974const WASM_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
975    &[(128, "simd128")];
976const S390X_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
977    &[(128, "vector")];
978const RISCV_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] = &[
979    (32, "zvl32b"),
980    (64, "zvl64b"),
981    (128, "zvl128b"),
982    (256, "zvl256b"),
983    (512, "zvl512b"),
984    (1024, "zvl1024b"),
985    (2048, "zvl2048b"),
986    (4096, "zvl4096b"),
987    (8192, "zvl8192b"),
988    (16384, "zvl16384b"),
989    (32768, "zvl32768b"),
990    (65536, "zvl65536b"),
991];
992// Always error on SPARC, as the necessary target features cannot be enabled in Rust at the moment.
993const SPARC_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
994    &[/*(64, "vis")*/];
995
996const HEXAGON_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] = &[
997    (512, "hvx-length64b"),   // HvxVector in 64-byte mode
998    (1024, "hvx-length128b"), // HvxVector in 128-byte mode, or HvxVectorPair in 64-byte mode
999    (2048, "hvx-length128b"), // HvxVectorPair in 128-byte mode
1000];
1001const MIPS_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
1002    &[(128, "msa")];
1003const CSKY_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
1004    &[(128, "vdspv1")];
1005const LOONGARCH_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
1006    &[(128, "lsx"), (256, "lasx")];
1007
1008#[derive(#[automatically_derived]
impl ::core::marker::Copy for FeatureConstraints { }Copy, #[automatically_derived]
impl ::core::clone::Clone for FeatureConstraints {
    #[inline]
    fn clone(&self) -> FeatureConstraints {
        let _: ::core::clone::AssertParamIsClone<&'static [&'static str]>;
        let _: ::core::clone::AssertParamIsClone<&'static [&'static str]>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for FeatureConstraints {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "FeatureConstraints", "required", &self.required, "incompatible",
            &&self.incompatible)
    }
}Debug)]
1009pub struct FeatureConstraints {
1010    /// Features that must be enabled.
1011    pub required: &'static [&'static str],
1012    /// Features that must be disabled.
1013    pub incompatible: &'static [&'static str],
1014}
1015
1016impl Target {
1017    pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] {
1018        match &self.arch {
1019            Arch::Arm => ARM_FEATURES,
1020            Arch::AArch64 | Arch::Arm64EC => AARCH64_FEATURES,
1021            Arch::X86 | Arch::X86_64 => X86_FEATURES,
1022            Arch::Hexagon => HEXAGON_FEATURES,
1023            Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => MIPS_FEATURES,
1024            Arch::Nvptx64 => NVPTX_FEATURES,
1025            Arch::PowerPC | Arch::PowerPC64 => POWERPC_FEATURES,
1026            Arch::RiscV32 | Arch::RiscV64 => RISCV_FEATURES,
1027            Arch::Wasm32 | Arch::Wasm64 => WASM_FEATURES,
1028            Arch::Bpf => BPF_FEATURES,
1029            Arch::CSky => CSKY_FEATURES,
1030            Arch::LoongArch32 | Arch::LoongArch64 => LOONGARCH_FEATURES,
1031            Arch::S390x => IBMZ_FEATURES,
1032            Arch::Sparc | Arch::Sparc64 => SPARC_FEATURES,
1033            Arch::M68k => M68K_FEATURES,
1034            Arch::Avr => AVR_FEATURES,
1035            Arch::AmdGpu | Arch::Msp430 | Arch::SpirV | Arch::Xtensa | Arch::Other(_) => &[],
1036        }
1037    }
1038
1039    pub fn features_for_correct_fixed_length_vector_abi(&self) -> &'static [(u64, &'static str)] {
1040        match &self.arch {
1041            Arch::X86 | Arch::X86_64 => X86_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1042            Arch::AArch64 | Arch::Arm64EC => AARCH64_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1043            Arch::Arm => ARM_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1044            Arch::PowerPC | Arch::PowerPC64 => POWERPC_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1045            Arch::LoongArch32 | Arch::LoongArch64 => {
1046                LOONGARCH_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI
1047            }
1048            Arch::RiscV32 | Arch::RiscV64 => RISCV_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1049            Arch::Wasm32 | Arch::Wasm64 => WASM_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1050            Arch::S390x => S390X_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1051            Arch::Sparc | Arch::Sparc64 => SPARC_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1052            Arch::Hexagon => HEXAGON_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1053            Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => {
1054                MIPS_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI
1055            }
1056            Arch::AmdGpu => AMDGPU_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1057            Arch::Nvptx64 | Arch::Bpf | Arch::M68k | Arch::Avr => &[], // no vector ABI
1058            Arch::CSky => CSKY_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1059            // FIXME: for some tier3 targets, we are overly cautious and always give warnings
1060            // when passing args in vector registers.
1061            Arch::Msp430 | Arch::SpirV | Arch::Xtensa | Arch::Other(_) => &[],
1062        }
1063    }
1064
1065    pub fn features_for_correct_scalable_vector_abi(&self) -> Option<&'static str> {
1066        match &self.arch {
1067            Arch::AArch64 | Arch::Arm64EC => Some("sve"),
1068            // Other targets have no scalable vectors or they are unimplemented.
1069            _ => None,
1070        }
1071    }
1072
1073    pub fn tied_target_features(&self) -> &'static [&'static [&'static str]] {
1074        match &self.arch {
1075            Arch::AArch64 | Arch::Arm64EC => AARCH64_TIED_FEATURES,
1076            _ => &[],
1077        }
1078    }
1079
1080    // Note: the returned set includes `base_feature`.
1081    pub fn implied_target_features<'a>(&self, base_feature: &'a str) -> FxHashSet<&'a str> {
1082        let implied_features =
1083            self.rust_target_features().iter().map(|(f, _, i)| (f, i)).collect::<FxHashMap<_, _>>();
1084
1085        // Implied target features have their own implied target features, so we traverse the
1086        // map until there are no more features to add.
1087        let mut features = FxHashSet::default();
1088        let mut new_features = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [base_feature]))vec![base_feature];
1089        while let Some(new_feature) = new_features.pop() {
1090            if features.insert(new_feature) {
1091                if let Some(implied_features) = implied_features.get(&new_feature) {
1092                    new_features.extend(implied_features.iter().copied())
1093                }
1094            }
1095        }
1096        features
1097    }
1098
1099    /// Returns two lists of features:
1100    /// the first list contains target features that must be enabled for ABI reasons,
1101    /// and the second list contains target feature that must be disabled for ABI reasons.
1102    ///
1103    /// These features are automatically appended to whatever the target spec sets as default
1104    /// features for the target.
1105    ///
1106    /// All features enabled/disabled via `-Ctarget-features` and `#[target_features]` are checked
1107    /// against this. We also check any implied features, based on the information above. If LLVM
1108    /// implicitly enables more implied features than we do, that could bypass this check!
1109    pub fn abi_required_features(&self) -> FeatureConstraints {
1110        const NOTHING: FeatureConstraints = FeatureConstraints { required: &[], incompatible: &[] };
1111        // Some architectures don't have a clean explicit ABI designation; instead, the ABI is
1112        // defined by target features. When that is the case, those target features must be
1113        // "forbidden" in the list above to ensure that there is a consistent answer to the
1114        // questions "which ABI is used".
1115        match &self.arch {
1116            Arch::X86 => {
1117                // We use our own ABI indicator here; LLVM does not have anything native.
1118                // Every case should require or forbid `soft-float`!
1119                match self.rustc_abi {
1120                    None => {
1121                        // Default hardfloat ABI.
1122                        // x87 must be enabled, soft-float must be disabled.
1123                        FeatureConstraints { required: &["x87"], incompatible: &["soft-float"] }
1124                    }
1125                    Some(RustcAbi::X86Sse2) => {
1126                        // Extended hardfloat ABI. x87 and SSE2 must be enabled, soft-float must be disabled.
1127                        FeatureConstraints {
1128                            required: &["x87", "sse2"],
1129                            incompatible: &["soft-float"],
1130                        }
1131                    }
1132                    Some(RustcAbi::Softfloat) => {
1133                        // Softfloat ABI, requires corresponding target feature. That feature trumps
1134                        // `x87` and all other FPU features so those do not matter.
1135                        // Note that this one requirement is the entire implementation of the ABI!
1136                        // LLVM handles the rest.
1137                        FeatureConstraints { required: &["soft-float"], incompatible: &[] }
1138                    }
1139                }
1140            }
1141            Arch::X86_64 => {
1142                // We use our own ABI indicator here; LLVM does not have anything native.
1143                // Every case should require or forbid `soft-float`!
1144                match self.rustc_abi {
1145                    None => {
1146                        // Default hardfloat ABI. On x86-64, this always includes SSE2.
1147                        FeatureConstraints {
1148                            required: &["x87", "sse2"],
1149                            incompatible: &["soft-float"],
1150                        }
1151                    }
1152                    Some(RustcAbi::Softfloat) => {
1153                        // Softfloat ABI, requires corresponding target feature. That feature trumps
1154                        // `x87` and all other FPU features so those do not matter.
1155                        // Note that this one requirement is the entire implementation of the ABI!
1156                        // LLVM handles the rest.
1157                        FeatureConstraints { required: &["soft-float"], incompatible: &[] }
1158                    }
1159                    Some(r) => {
    ::core::panicking::panic_fmt(format_args!("invalid Rust ABI for x86_64: {0:?}",
            r));
}panic!("invalid Rust ABI for x86_64: {r:?}"),
1160                }
1161            }
1162            Arch::Arm => {
1163                // On ARM, ABI handling is reasonably sane; we use `llvm_floatabi` to indicate
1164                // to LLVM which ABI we are going for.
1165                match self.llvm_floatabi.unwrap() {
1166                    FloatAbi::Soft => {
1167                        // Nothing special required, will use soft-float ABI throughout.
1168                        // We can even allow `-soft-float` here; in fact that is useful as it lets
1169                        // people use FPU instructions with a softfloat ABI (corresponds to
1170                        // `-mfloat-abi=softfp` in GCC/clang).
1171                        NOTHING
1172                    }
1173                    FloatAbi::Hard => {
1174                        // Must have `fpregs` and must not have `soft-float`.
1175                        FeatureConstraints { required: &["fpregs"], incompatible: &["soft-float"] }
1176                    }
1177                }
1178            }
1179            Arch::AArch64 | Arch::Arm64EC => {
1180                // Aarch64 has no sane ABI specifier, and LLVM doesn't even have a way to force
1181                // the use of soft-float, so all we can do here is some crude hacks.
1182                match self.rustc_abi {
1183                    Some(RustcAbi::Softfloat) => {
1184                        // LLVM will use float registers when `fp-armv8` is available, e.g. for
1185                        // calls to built-ins. The only way to ensure a consistent softfloat ABI
1186                        // on aarch64 is to never enable `fp-armv8`, so we enforce that.
1187                        // In Rust we tie `neon` and `fp-armv8` together, therefore `neon` is the
1188                        // feature we have to mark as incompatible.
1189                        FeatureConstraints { required: &[], incompatible: &["neon"] }
1190                    }
1191                    None => {
1192                        // Everything else is assumed to use a hardfloat ABI. neon and fp-armv8 must be enabled.
1193                        // `FeatureConstraints` uses Rust feature names, hence only "neon" shows up.
1194                        FeatureConstraints { required: &["neon"], incompatible: &[] }
1195                    }
1196                    Some(r) => {
    ::core::panicking::panic_fmt(format_args!("invalid Rust ABI for aarch64: {0:?}",
            r));
}panic!("invalid Rust ABI for aarch64: {r:?}"),
1197                }
1198            }
1199            Arch::RiscV32 | Arch::RiscV64 => {
1200                // RISC-V handles ABI in a very sane way, being fully explicit via `llvm_abiname`
1201                // about what the intended ABI is.
1202                match &self.llvm_abiname {
1203                    LlvmAbi::Ilp32d | LlvmAbi::Lp64d => {
1204                        // Requires d (which implies f), incompatible with e and zfinx.
1205                        FeatureConstraints { required: &["d"], incompatible: &["e", "zfinx"] }
1206                    }
1207                    LlvmAbi::Ilp32f | LlvmAbi::Lp64f => {
1208                        // Requires f, incompatible with e and zfinx.
1209                        FeatureConstraints { required: &["f"], incompatible: &["e", "zfinx"] }
1210                    }
1211                    LlvmAbi::Ilp32 | LlvmAbi::Lp64 => {
1212                        // Requires nothing, incompatible with e.
1213                        FeatureConstraints { required: &[], incompatible: &["e"] }
1214                    }
1215                    LlvmAbi::Ilp32e => {
1216                        // ilp32e is documented to be incompatible with features that need aligned
1217                        // load/stores > 32 bits, like `d`. (One could also just generate more
1218                        // complicated code to align the stack when needed, but the RISCV
1219                        // architecture manual just explicitly rules out this combination so we
1220                        // might as well.)
1221                        // Note that the `e` feature is not required: the ABI treats the extra
1222                        // registers as caller-save, so it is safe to use them only in some parts of
1223                        // a program while the rest doesn't know they even exist.
1224                        FeatureConstraints { required: &[], incompatible: &["d"] }
1225                    }
1226                    LlvmAbi::Lp64e => {
1227                        // As above, `e` is not required.
1228                        NOTHING
1229                    }
1230                    _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1231                }
1232            }
1233            Arch::LoongArch32 | Arch::LoongArch64 => {
1234                // LoongArch handles ABI in a very sane way, being fully explicit via `llvm_abiname`
1235                // about what the intended ABI is.
1236                match &self.llvm_abiname {
1237                    LlvmAbi::Ilp32d | LlvmAbi::Lp64d => {
1238                        // Requires d (which implies f), incompatible with nothing.
1239                        FeatureConstraints { required: &["d"], incompatible: &[] }
1240                    }
1241                    LlvmAbi::Ilp32f | LlvmAbi::Lp64f => {
1242                        // Requires f, incompatible with nothing.
1243                        FeatureConstraints { required: &["f"], incompatible: &[] }
1244                    }
1245                    LlvmAbi::Ilp32s | LlvmAbi::Lp64s => {
1246                        // The soft-float ABI does not require any features and is also not
1247                        // incompatible with any features. Rust targets explicitly specify the
1248                        // LLVM ABI names, which allows for enabling hard-float support even on
1249                        // soft-float targets, and ensures that the ABI behavior is as expected.
1250                        NOTHING
1251                    }
1252                    _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1253                }
1254            }
1255            Arch::S390x => {
1256                // Same as x86, We use our own ABI indicator here;
1257                // LLVM does not have anything native and will switch ABI based
1258                // on the soft-float target feature.
1259                // Every case should require or forbid `soft-float`!
1260                // The "vector" target feature may only be used without soft-float
1261                // because the float and vector registers overlap and the
1262                // standard s390x C ABI may pass vectors via these registers.
1263                match self.rustc_abi {
1264                    None => {
1265                        // Default hardfloat ABI.
1266                        FeatureConstraints { required: &[], incompatible: &["soft-float"] }
1267                    }
1268                    Some(RustcAbi::Softfloat) => {
1269                        // Softfloat ABI, requires corresponding target feature.
1270                        // llvm will switch to soft-float ABI just based on this feature.
1271                        FeatureConstraints { required: &["soft-float"], incompatible: &["vector"] }
1272                    }
1273                    Some(r) => {
1274                        {
    ::core::panicking::panic_fmt(format_args!("invalid Rust ABI for s390x: {0:?}",
            r));
};panic!("invalid Rust ABI for s390x: {r:?}");
1275                    }
1276                }
1277            }
1278            Arch::Avr => {
1279                // SRAM is minimum requirement for C/C++ in both avr-gcc and Clang,
1280                // and backends of them only support assembly for devices have no SRAM.
1281                // See the discussion in https://github.com/rust-lang/rust/pull/146900 for more.
1282                FeatureConstraints { required: &["sram"], incompatible: &[] }
1283            }
1284            _ => NOTHING,
1285        }
1286    }
1287}