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