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: crate::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    ("fxsr", Stable, &[]),
426    ("gfni", Stable, &["sse2"]),
427    ("kl", Stable, &["sse2"]),
428    ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
429    ("lzcnt", Stable, &[]),
430    ("movbe", Stable, &[]),
431    ("movrs", Unstable(sym::movrs_target_feature), &[]),
432    ("pclmulqdq", Stable, &["sse2"]),
433    ("popcnt", Stable, &[]),
434    ("prfchw", Unstable(sym::prfchw_target_feature), &[]),
435    ("rdrand", Stable, &[]),
436    ("rdseed", Stable, &[]),
437    (
438        "retpoline-external-thunk",
439        Stability::Forbidden { reason: "use `-Zretpoline-external-thunk` compiler flag instead" },
440        &[],
441    ),
442    (
443        "retpoline-indirect-branches",
444        Stability::Forbidden { reason: "use `-Zretpoline` compiler flag instead" },
445        &[],
446    ),
447    (
448        "retpoline-indirect-calls",
449        Stability::Forbidden { reason: "use `-Zretpoline` compiler flag instead" },
450        &[],
451    ),
452    ("rtm", Unstable(sym::rtm_target_feature), &[]),
453    ("sha", Stable, &["sse2"]),
454    ("sha512", Stable, &["avx2"]),
455    ("sm3", Stable, &["avx"]),
456    ("sm4", Stable, &["avx2"]),
457    ("soft-float", Stability::Forbidden { reason: "use a soft-float target instead" }, &[]),
458    ("sse", Stable, &[]),
459    ("sse2", Stable, &["sse"]),
460    ("sse3", Stable, &["sse2"]),
461    ("sse4.1", Stable, &["ssse3"]),
462    ("sse4.2", Stable, &["sse4.1"]),
463    ("sse4a", Stable, &["sse3"]),
464    ("ssse3", Stable, &["sse3"]),
465    ("tbm", Stable, &[]),
466    ("vaes", Stable, &["avx2", "aes"]),
467    ("vpclmulqdq", Stable, &["avx", "pclmulqdq"]),
468    ("widekl", Stable, &["kl"]),
469    ("x87", Unstable(sym::x87_target_feature), &[]),
470    ("xop", Unstable(sym::xop_target_feature), &[/*"fma4", */ "avx", "sse4a"]),
471    ("xsave", Stable, &[]),
472    ("xsavec", Stable, &["xsave"]),
473    ("xsaveopt", Stable, &["xsave"]),
474    ("xsaves", Stable, &["xsave"]),
475    // tidy-alphabetical-end
476];
477
478const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
479    // tidy-alphabetical-start
480    ("hvx", Unstable(sym::hexagon_target_feature), &[]),
481    ("hvx-ieee-fp", Unstable(sym::hexagon_target_feature), &["hvx"]),
482    ("hvx-length64b", Unstable(sym::hexagon_target_feature), &["hvx"]),
483    ("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]),
484    ("hvx-qfloat", Unstable(sym::hexagon_target_feature), &["hvx"]),
485    ("hvxv60", Unstable(sym::hexagon_target_feature), &["hvx"]),
486    ("hvxv62", Unstable(sym::hexagon_target_feature), &["hvxv60"]),
487    ("hvxv65", Unstable(sym::hexagon_target_feature), &["hvxv62"]),
488    ("hvxv66", Unstable(sym::hexagon_target_feature), &["hvxv65", "zreg"]),
489    ("hvxv67", Unstable(sym::hexagon_target_feature), &["hvxv66"]),
490    ("hvxv68", Unstable(sym::hexagon_target_feature), &["hvxv67"]),
491    ("hvxv69", Unstable(sym::hexagon_target_feature), &["hvxv68"]),
492    ("hvxv71", Unstable(sym::hexagon_target_feature), &["hvxv69"]),
493    ("hvxv73", Unstable(sym::hexagon_target_feature), &["hvxv71"]),
494    ("hvxv75", Unstable(sym::hexagon_target_feature), &["hvxv73"]),
495    ("hvxv79", Unstable(sym::hexagon_target_feature), &["hvxv75"]),
496    ("zreg", Unstable(sym::hexagon_target_feature), &[]),
497    // tidy-alphabetical-end
498];
499
500static POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
501    // tidy-alphabetical-start
502    ("altivec", Unstable(sym::powerpc_target_feature), &[]),
503    ("msync", Unstable(sym::powerpc_target_feature), &[]),
504    ("partword-atomics", Unstable(sym::powerpc_target_feature), &[]),
505    ("power8-altivec", Unstable(sym::powerpc_target_feature), &["altivec"]),
506    ("power8-crypto", Unstable(sym::powerpc_target_feature), &["power8-altivec"]),
507    ("power8-vector", Unstable(sym::powerpc_target_feature), &["vsx", "power8-altivec"]),
508    ("power9-altivec", Unstable(sym::powerpc_target_feature), &["power8-altivec"]),
509    ("power9-vector", Unstable(sym::powerpc_target_feature), &["power8-vector", "power9-altivec"]),
510    ("power10-vector", Unstable(sym::powerpc_target_feature), &["power9-vector"]),
511    ("quadword-atomics", Unstable(sym::powerpc_target_feature), &[]),
512    ("vsx", Unstable(sym::powerpc_target_feature), &["altivec"]),
513    // tidy-alphabetical-end
514];
515
516const MIPS_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
517    // tidy-alphabetical-start
518    ("fp64", Unstable(sym::mips_target_feature), &[]),
519    ("msa", Unstable(sym::mips_target_feature), &[]),
520    ("virt", Unstable(sym::mips_target_feature), &[]),
521    // tidy-alphabetical-end
522];
523
524const NVPTX_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
525    // tidy-alphabetical-start
526    ("sm_20", Unstable(sym::nvptx_target_feature), &[]),
527    ("sm_21", Unstable(sym::nvptx_target_feature), &["sm_20"]),
528    ("sm_30", Unstable(sym::nvptx_target_feature), &["sm_21"]),
529    ("sm_32", Unstable(sym::nvptx_target_feature), &["sm_30"]),
530    ("sm_35", Unstable(sym::nvptx_target_feature), &["sm_32"]),
531    ("sm_37", Unstable(sym::nvptx_target_feature), &["sm_35"]),
532    ("sm_50", Unstable(sym::nvptx_target_feature), &["sm_37"]),
533    ("sm_52", Unstable(sym::nvptx_target_feature), &["sm_50"]),
534    ("sm_53", Unstable(sym::nvptx_target_feature), &["sm_52"]),
535    ("sm_60", Unstable(sym::nvptx_target_feature), &["sm_53"]),
536    ("sm_61", Unstable(sym::nvptx_target_feature), &["sm_60"]),
537    ("sm_62", Unstable(sym::nvptx_target_feature), &["sm_61"]),
538    ("sm_70", Unstable(sym::nvptx_target_feature), &["sm_62"]),
539    ("sm_72", Unstable(sym::nvptx_target_feature), &["sm_70"]),
540    ("sm_75", Unstable(sym::nvptx_target_feature), &["sm_72"]),
541    ("sm_80", Unstable(sym::nvptx_target_feature), &["sm_75"]),
542    ("sm_86", Unstable(sym::nvptx_target_feature), &["sm_80"]),
543    ("sm_87", Unstable(sym::nvptx_target_feature), &["sm_86"]),
544    ("sm_89", Unstable(sym::nvptx_target_feature), &["sm_87"]),
545    ("sm_90", Unstable(sym::nvptx_target_feature), &["sm_89"]),
546    ("sm_90a", Unstable(sym::nvptx_target_feature), &["sm_90"]),
547    // tidy-alphabetical-end
548    // tidy-alphabetical-start
549    ("sm_100", Unstable(sym::nvptx_target_feature), &["sm_90"]),
550    ("sm_100a", Unstable(sym::nvptx_target_feature), &["sm_100"]),
551    ("sm_101", Unstable(sym::nvptx_target_feature), &["sm_100"]),
552    ("sm_101a", Unstable(sym::nvptx_target_feature), &["sm_101"]),
553    ("sm_120", Unstable(sym::nvptx_target_feature), &["sm_101"]),
554    ("sm_120a", Unstable(sym::nvptx_target_feature), &["sm_120"]),
555    // tidy-alphabetical-end
556    // tidy-alphabetical-start
557    ("ptx32", Unstable(sym::nvptx_target_feature), &[]),
558    ("ptx40", Unstable(sym::nvptx_target_feature), &["ptx32"]),
559    ("ptx41", Unstable(sym::nvptx_target_feature), &["ptx40"]),
560    ("ptx42", Unstable(sym::nvptx_target_feature), &["ptx41"]),
561    ("ptx43", Unstable(sym::nvptx_target_feature), &["ptx42"]),
562    ("ptx50", Unstable(sym::nvptx_target_feature), &["ptx43"]),
563    ("ptx60", Unstable(sym::nvptx_target_feature), &["ptx50"]),
564    ("ptx61", Unstable(sym::nvptx_target_feature), &["ptx60"]),
565    ("ptx62", Unstable(sym::nvptx_target_feature), &["ptx61"]),
566    ("ptx63", Unstable(sym::nvptx_target_feature), &["ptx62"]),
567    ("ptx64", Unstable(sym::nvptx_target_feature), &["ptx63"]),
568    ("ptx65", Unstable(sym::nvptx_target_feature), &["ptx64"]),
569    ("ptx70", Unstable(sym::nvptx_target_feature), &["ptx65"]),
570    ("ptx71", Unstable(sym::nvptx_target_feature), &["ptx70"]),
571    ("ptx72", Unstable(sym::nvptx_target_feature), &["ptx71"]),
572    ("ptx73", Unstable(sym::nvptx_target_feature), &["ptx72"]),
573    ("ptx74", Unstable(sym::nvptx_target_feature), &["ptx73"]),
574    ("ptx75", Unstable(sym::nvptx_target_feature), &["ptx74"]),
575    ("ptx76", Unstable(sym::nvptx_target_feature), &["ptx75"]),
576    ("ptx77", Unstable(sym::nvptx_target_feature), &["ptx76"]),
577    ("ptx78", Unstable(sym::nvptx_target_feature), &["ptx77"]),
578    ("ptx80", Unstable(sym::nvptx_target_feature), &["ptx78"]),
579    ("ptx81", Unstable(sym::nvptx_target_feature), &["ptx80"]),
580    ("ptx82", Unstable(sym::nvptx_target_feature), &["ptx81"]),
581    ("ptx83", Unstable(sym::nvptx_target_feature), &["ptx82"]),
582    ("ptx84", Unstable(sym::nvptx_target_feature), &["ptx83"]),
583    ("ptx85", Unstable(sym::nvptx_target_feature), &["ptx84"]),
584    ("ptx86", Unstable(sym::nvptx_target_feature), &["ptx85"]),
585    ("ptx87", Unstable(sym::nvptx_target_feature), &["ptx86"]),
586    // tidy-alphabetical-end
587];
588
589static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
590    // tidy-alphabetical-start
591    ("a", Stable, &["zaamo", "zalrsc"]),
592    ("b", Stable, &["zba", "zbb", "zbs"]),
593    ("c", Stable, &["zca"]),
594    ("d", Unstable(sym::riscv_target_feature), &["f"]),
595    ("e", Unstable(sym::riscv_target_feature), &[]),
596    ("f", Unstable(sym::riscv_target_feature), &["zicsr"]),
597    (
598        "forced-atomics",
599        Stability::Forbidden { reason: "unsound because it changes the ABI of atomic operations" },
600        &[],
601    ),
602    ("m", Stable, &[]),
603    ("relax", Unstable(sym::riscv_target_feature), &[]),
604    (
605        "rva23u64",
606        Unstable(sym::riscv_target_feature),
607        &[
608            "m",
609            "a",
610            "f",
611            "d",
612            "c",
613            "b",
614            "v",
615            "zicsr",
616            "zicntr",
617            "zihpm",
618            "ziccif",
619            "ziccrse",
620            "ziccamoa",
621            "zicclsm",
622            "zic64b",
623            "za64rs",
624            "zihintpause",
625            "zba",
626            "zbb",
627            "zbs",
628            "zicbom",
629            "zicbop",
630            "zicboz",
631            "zfhmin",
632            "zkt",
633            "zvfhmin",
634            "zvbb",
635            "zvkt",
636            "zihintntl",
637            "zicond",
638            "zimop",
639            "zcmop",
640            "zcb",
641            "zfa",
642            "zawrs",
643            "supm",
644        ],
645    ),
646    ("supm", Unstable(sym::riscv_target_feature), &[]),
647    ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature), &[]),
648    ("unaligned-vector-mem", Unstable(sym::riscv_target_feature), &[]),
649    ("v", Unstable(sym::riscv_target_feature), &["zvl128b", "zve64d"]),
650    ("za64rs", Stable, &["za128rs"]), // Za64rs ⊃ Za128rs
651    ("za128rs", Stable, &[]),
652    ("zaamo", Stable, &[]),
653    ("zabha", Stable, &["zaamo"]),
654    ("zacas", Stable, &["zaamo"]),
655    ("zalrsc", Stable, &[]),
656    ("zama16b", Stable, &[]),
657    ("zawrs", Stable, &[]),
658    ("zba", Stable, &[]),
659    ("zbb", Stable, &[]),
660    ("zbc", Stable, &["zbkc"]), // Zbc ⊃ Zbkc
661    ("zbkb", Stable, &[]),
662    ("zbkc", Stable, &[]),
663    ("zbkx", Stable, &[]),
664    ("zbs", Stable, &[]),
665    ("zca", Stable, &[]),
666    ("zcb", Stable, &["zca"]),
667    ("zcmop", Stable, &["zca"]),
668    ("zdinx", Unstable(sym::riscv_target_feature), &["zfinx"]),
669    ("zfa", Unstable(sym::riscv_target_feature), &["f"]),
670    ("zfbfmin", Unstable(sym::riscv_target_feature), &["f"]), // and a subset of Zfhmin
671    ("zfh", Unstable(sym::riscv_target_feature), &["zfhmin"]),
672    ("zfhmin", Unstable(sym::riscv_target_feature), &["f"]),
673    ("zfinx", Unstable(sym::riscv_target_feature), &["zicsr"]),
674    ("zhinx", Unstable(sym::riscv_target_feature), &["zhinxmin"]),
675    ("zhinxmin", Unstable(sym::riscv_target_feature), &["zfinx"]),
676    ("zic64b", Stable, &[]),
677    ("zicbom", Stable, &[]),
678    ("zicbop", Stable, &[]),
679    ("zicboz", Stable, &[]),
680    ("ziccamoa", Stable, &[]),
681    ("ziccif", Stable, &[]),
682    ("zicclsm", Stable, &[]),
683    ("ziccrse", Stable, &[]),
684    ("zicntr", Stable, &["zicsr"]),
685    ("zicond", Stable, &[]),
686    ("zicsr", Stable, &[]),
687    ("zifencei", Stable, &[]),
688    ("zihintntl", Stable, &[]),
689    ("zihintpause", Stable, &[]),
690    ("zihpm", Stable, &["zicsr"]),
691    ("zimop", Stable, &[]),
692    ("zk", Stable, &["zkn", "zkr", "zkt"]),
693    ("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
694    ("zknd", Stable, &["zkne_or_zknd"]),
695    ("zkne", Stable, &["zkne_or_zknd"]),
696    ("zkne_or_zknd", Unstable(sym::riscv_target_feature), &[]), // Not an extension
697    ("zknh", Stable, &[]),
698    ("zkr", Stable, &[]),
699    ("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
700    ("zksed", Stable, &[]),
701    ("zksh", Stable, &[]),
702    ("zkt", Stable, &[]),
703    ("ztso", Stable, &[]),
704    ("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]), // Zvbb ⊃ Zvkb
705    ("zvbc", Unstable(sym::riscv_target_feature), &["zve64x"]),
706    ("zve32f", Unstable(sym::riscv_target_feature), &["zve32x", "f"]),
707    ("zve32x", Unstable(sym::riscv_target_feature), &["zvl32b", "zicsr"]),
708    ("zve64d", Unstable(sym::riscv_target_feature), &["zve64f", "d"]),
709    ("zve64f", Unstable(sym::riscv_target_feature), &["zve32f", "zve64x"]),
710    ("zve64x", Unstable(sym::riscv_target_feature), &["zve32x", "zvl64b"]),
711    ("zvfbfmin", Unstable(sym::riscv_target_feature), &["zve32f"]),
712    ("zvfbfwma", Unstable(sym::riscv_target_feature), &["zfbfmin", "zvfbfmin"]),
713    ("zvfh", Unstable(sym::riscv_target_feature), &["zvfhmin", "zve32f", "zfhmin"]), // Zvfh ⊃ Zvfhmin
714    ("zvfhmin", Unstable(sym::riscv_target_feature), &["zve32f"]),
715    ("zvkb", Unstable(sym::riscv_target_feature), &["zve32x"]),
716    ("zvkg", Unstable(sym::riscv_target_feature), &["zve32x"]),
717    ("zvkn", Unstable(sym::riscv_target_feature), &["zvkned", "zvknhb", "zvkb", "zvkt"]),
718    ("zvknc", Unstable(sym::riscv_target_feature), &["zvkn", "zvbc"]),
719    ("zvkned", Unstable(sym::riscv_target_feature), &["zve32x"]),
720    ("zvkng", Unstable(sym::riscv_target_feature), &["zvkn", "zvkg"]),
721    ("zvknha", Unstable(sym::riscv_target_feature), &["zve32x"]),
722    ("zvknhb", Unstable(sym::riscv_target_feature), &["zvknha", "zve64x"]), // Zvknhb ⊃ Zvknha
723    ("zvks", Unstable(sym::riscv_target_feature), &["zvksed", "zvksh", "zvkb", "zvkt"]),
724    ("zvksc", Unstable(sym::riscv_target_feature), &["zvks", "zvbc"]),
725    ("zvksed", Unstable(sym::riscv_target_feature), &["zve32x"]),
726    ("zvksg", Unstable(sym::riscv_target_feature), &["zvks", "zvkg"]),
727    ("zvksh", Unstable(sym::riscv_target_feature), &["zve32x"]),
728    ("zvkt", Unstable(sym::riscv_target_feature), &[]),
729    ("zvl32b", Unstable(sym::riscv_target_feature), &[]),
730    ("zvl64b", Unstable(sym::riscv_target_feature), &["zvl32b"]),
731    ("zvl128b", Unstable(sym::riscv_target_feature), &["zvl64b"]),
732    ("zvl256b", Unstable(sym::riscv_target_feature), &["zvl128b"]),
733    ("zvl512b", Unstable(sym::riscv_target_feature), &["zvl256b"]),
734    ("zvl1024b", Unstable(sym::riscv_target_feature), &["zvl512b"]),
735    ("zvl2048b", Unstable(sym::riscv_target_feature), &["zvl1024b"]),
736    ("zvl4096b", Unstable(sym::riscv_target_feature), &["zvl2048b"]),
737    ("zvl8192b", Unstable(sym::riscv_target_feature), &["zvl4096b"]),
738    ("zvl16384b", Unstable(sym::riscv_target_feature), &["zvl8192b"]),
739    ("zvl32768b", Unstable(sym::riscv_target_feature), &["zvl16384b"]),
740    ("zvl65536b", Unstable(sym::riscv_target_feature), &["zvl32768b"]),
741    // tidy-alphabetical-end
742];
743
744static WASM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
745    // tidy-alphabetical-start
746    ("atomics", Unstable(sym::wasm_target_feature), &[]),
747    ("bulk-memory", Stable, &[]),
748    ("exception-handling", Unstable(sym::wasm_target_feature), &[]),
749    ("extended-const", Stable, &[]),
750    ("gc", Unstable(sym::wasm_target_feature), &["reference-types"]),
751    ("multivalue", Stable, &[]),
752    ("mutable-globals", Stable, &[]),
753    ("nontrapping-fptoint", Stable, &[]),
754    ("reference-types", Stable, &[]),
755    ("relaxed-simd", Stable, &["simd128"]),
756    ("sign-ext", Stable, &[]),
757    ("simd128", Stable, &[]),
758    ("tail-call", Stable, &[]),
759    ("wide-arithmetic", Unstable(sym::wasm_target_feature), &[]),
760    // tidy-alphabetical-end
761];
762
763const BPF_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
764    ("alu32", Unstable(sym::bpf_target_feature), &[]),
765    ("allows-misaligned-mem-access", Unstable(sym::bpf_target_feature), &[]),
766];
767
768static CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
769    // tidy-alphabetical-start
770    ("2e3", Unstable(sym::csky_target_feature), &["e2"]),
771    ("3e3r1", Unstable(sym::csky_target_feature), &[]),
772    ("3e3r2", Unstable(sym::csky_target_feature), &["3e3r1", "doloop"]),
773    ("3e3r3", Unstable(sym::csky_target_feature), &["doloop"]),
774    ("3e7", Unstable(sym::csky_target_feature), &["2e3"]),
775    ("7e10", Unstable(sym::csky_target_feature), &["3e7"]),
776    ("10e60", Unstable(sym::csky_target_feature), &["7e10"]),
777    ("cache", Unstable(sym::csky_target_feature), &[]),
778    ("doloop", Unstable(sym::csky_target_feature), &[]),
779    ("dsp1e2", Unstable(sym::csky_target_feature), &[]),
780    ("dspe60", Unstable(sym::csky_target_feature), &[]),
781    ("e1", Unstable(sym::csky_target_feature), &["elrw"]),
782    ("e2", Unstable(sym::csky_target_feature), &["e2"]),
783    ("edsp", Unstable(sym::csky_target_feature), &[]),
784    ("elrw", Unstable(sym::csky_target_feature), &[]),
785    ("float1e2", Unstable(sym::csky_target_feature), &[]),
786    ("float1e3", Unstable(sym::csky_target_feature), &[]),
787    ("float3e4", Unstable(sym::csky_target_feature), &[]),
788    ("float7e60", Unstable(sym::csky_target_feature), &[]),
789    ("floate1", Unstable(sym::csky_target_feature), &[]),
790    ("hard-tp", Unstable(sym::csky_target_feature), &[]),
791    ("high-registers", Unstable(sym::csky_target_feature), &[]),
792    ("hwdiv", Unstable(sym::csky_target_feature), &[]),
793    ("mp", Unstable(sym::csky_target_feature), &["2e3"]),
794    ("mp1e2", Unstable(sym::csky_target_feature), &["3e7"]),
795    ("nvic", Unstable(sym::csky_target_feature), &[]),
796    ("trust", Unstable(sym::csky_target_feature), &[]),
797    ("vdsp2e60f", Unstable(sym::csky_target_feature), &[]),
798    ("vdspv1", Unstable(sym::csky_target_feature), &[]),
799    ("vdspv2", Unstable(sym::csky_target_feature), &[]),
800    // tidy-alphabetical-end
801    //fpu
802    // tidy-alphabetical-start
803    ("fdivdu", Unstable(sym::csky_target_feature), &[]),
804    ("fpuv2_df", Unstable(sym::csky_target_feature), &[]),
805    ("fpuv2_sf", Unstable(sym::csky_target_feature), &[]),
806    ("fpuv3_df", Unstable(sym::csky_target_feature), &[]),
807    ("fpuv3_hf", Unstable(sym::csky_target_feature), &[]),
808    ("fpuv3_hi", Unstable(sym::csky_target_feature), &[]),
809    ("fpuv3_sf", Unstable(sym::csky_target_feature), &[]),
810    ("hard-float", Unstable(sym::csky_target_feature), &[]),
811    ("hard-float-abi", Unstable(sym::csky_target_feature), &[]),
812    // tidy-alphabetical-end
813];
814
815static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
816    // tidy-alphabetical-start
817    ("32s", Unstable(sym::loongarch_target_feature), &[]),
818    ("d", Stable, &["f"]),
819    ("div32", Unstable(sym::loongarch_target_feature), &[]),
820    ("f", Stable, &[]),
821    ("frecipe", Stable, &[]),
822    ("lam-bh", Unstable(sym::loongarch_target_feature), &[]),
823    ("lamcas", Unstable(sym::loongarch_target_feature), &[]),
824    ("lasx", Stable, &["lsx"]),
825    ("lbt", Stable, &[]),
826    ("ld-seq-sa", Unstable(sym::loongarch_target_feature), &[]),
827    ("lsx", Stable, &["d"]),
828    ("lvz", Stable, &[]),
829    ("relax", Unstable(sym::loongarch_target_feature), &[]),
830    ("scq", Unstable(sym::loongarch_target_feature), &[]),
831    ("ual", Unstable(sym::loongarch_target_feature), &[]),
832    // tidy-alphabetical-end
833];
834
835#[rustfmt::skip]
836const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
837    // tidy-alphabetical-start
838    // For "backchain", https://github.com/rust-lang/rust/issues/142412 is a stabilization blocker
839    ("backchain", Unstable(sym::s390x_target_feature), &[]),
840    ("concurrent-functions", Unstable(sym::s390x_target_feature), &[]),
841    ("deflate-conversion", Unstable(sym::s390x_target_feature), &[]),
842    ("enhanced-sort", Unstable(sym::s390x_target_feature), &[]),
843    ("guarded-storage", Unstable(sym::s390x_target_feature), &[]),
844    ("high-word", Unstable(sym::s390x_target_feature), &[]),
845    // LLVM does not define message-security-assist-extension versions 1, 2, 6, 10 and 11.
846    ("message-security-assist-extension3", Unstable(sym::s390x_target_feature), &[]),
847    ("message-security-assist-extension4", Unstable(sym::s390x_target_feature), &[]),
848    ("message-security-assist-extension5", Unstable(sym::s390x_target_feature), &[]),
849    ("message-security-assist-extension8", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3"]),
850    ("message-security-assist-extension9", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3", "message-security-assist-extension4"]),
851    ("message-security-assist-extension12", Unstable(sym::s390x_target_feature), &[]),
852    ("miscellaneous-extensions-2", Stable, &[]),
853    ("miscellaneous-extensions-3", Stable, &[]),
854    ("miscellaneous-extensions-4", Stable, &[]),
855    ("nnp-assist", Stable, &["vector"]),
856    ("soft-float", Forbidden { reason: "unsupported ABI-configuration feature" }, &[]),
857    ("transactional-execution", Unstable(sym::s390x_target_feature), &[]),
858    ("vector", Stable, &[]),
859    ("vector-enhancements-1", Stable, &["vector"]),
860    ("vector-enhancements-2", Stable, &["vector-enhancements-1"]),
861    ("vector-enhancements-3", Stable, &["vector-enhancements-2"]),
862    ("vector-packed-decimal", Stable, &["vector"]),
863    ("vector-packed-decimal-enhancement", Stable, &["vector-packed-decimal"]),
864    ("vector-packed-decimal-enhancement-2", Stable, &["vector-packed-decimal-enhancement"]),
865    ("vector-packed-decimal-enhancement-3", Stable, &["vector-packed-decimal-enhancement-2"]),
866    // tidy-alphabetical-end
867];
868
869const SPARC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
870    // tidy-alphabetical-start
871    ("leoncasa", Unstable(sym::sparc_target_feature), &[]),
872    ("v8plus", Unstable(sym::sparc_target_feature), &[]),
873    ("v9", Unstable(sym::sparc_target_feature), &[]),
874    // tidy-alphabetical-end
875];
876
877static M68K_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
878    // tidy-alphabetical-start
879    ("isa-68000", Unstable(sym::m68k_target_feature), &[]),
880    ("isa-68010", Unstable(sym::m68k_target_feature), &["isa-68000"]),
881    ("isa-68020", Unstable(sym::m68k_target_feature), &["isa-68010"]),
882    ("isa-68030", Unstable(sym::m68k_target_feature), &["isa-68020"]),
883    ("isa-68040", Unstable(sym::m68k_target_feature), &["isa-68030", "isa-68882"]),
884    ("isa-68060", Unstable(sym::m68k_target_feature), &["isa-68040"]),
885    // FPU
886    ("isa-68881", Unstable(sym::m68k_target_feature), &[]),
887    ("isa-68882", Unstable(sym::m68k_target_feature), &["isa-68881"]),
888    // tidy-alphabetical-end
889];
890
891static AVR_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
892    // tidy-alphabetical-start
893    ("addsubiw", Unstable(sym::avr_target_feature), &[]),
894    ("break", Unstable(sym::avr_target_feature), &[]),
895    ("eijmpcall", Unstable(sym::avr_target_feature), &[]),
896    ("elpm", Unstable(sym::avr_target_feature), &[]),
897    ("elpmx", Unstable(sym::avr_target_feature), &[]),
898    ("ijmpcall", Unstable(sym::avr_target_feature), &[]),
899    ("jmpcall", Unstable(sym::avr_target_feature), &[]),
900    ("lowbytefirst", Unstable(sym::avr_target_feature), &[]),
901    ("lpm", Unstable(sym::avr_target_feature), &[]),
902    ("lpmx", Unstable(sym::avr_target_feature), &[]),
903    ("movw", Unstable(sym::avr_target_feature), &[]),
904    ("mul", Unstable(sym::avr_target_feature), &[]),
905    ("rmw", Unstable(sym::avr_target_feature), &[]),
906    ("spm", Unstable(sym::avr_target_feature), &[]),
907    ("spmx", Unstable(sym::avr_target_feature), &[]),
908    ("sram", Forbidden { reason: "devices that have no SRAM are unsupported" }, &[]),
909    ("tinyencoding", Unstable(sym::avr_target_feature), &[]),
910    // tidy-alphabetical-end
911];
912
913/// When rustdoc is running, provide a list of all known features so that all their respective
914/// primitives may be documented.
915///
916/// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator!
917pub fn all_rust_features() -> impl Iterator<Item = (&'static str, Stability)> {
918    std::iter::empty()
919        .chain(ARM_FEATURES.iter())
920        .chain(AARCH64_FEATURES.iter())
921        .chain(X86_FEATURES.iter())
922        .chain(HEXAGON_FEATURES.iter())
923        .chain(POWERPC_FEATURES.iter())
924        .chain(MIPS_FEATURES.iter())
925        .chain(NVPTX_FEATURES.iter())
926        .chain(RISCV_FEATURES.iter())
927        .chain(WASM_FEATURES.iter())
928        .chain(BPF_FEATURES.iter())
929        .chain(CSKY_FEATURES)
930        .chain(LOONGARCH_FEATURES)
931        .chain(IBMZ_FEATURES)
932        .chain(SPARC_FEATURES)
933        .chain(M68K_FEATURES)
934        .chain(AVR_FEATURES)
935        .cloned()
936        .map(|(f, s, _)| (f, s))
937}
938
939// These arrays represent the least-constraining feature that is required for vector types up to a
940// certain size to have their "proper" ABI on each architecture.
941// Note that they must be kept sorted by vector size.
942const X86_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
943    &[(128, "sse"), (256, "avx"), (512, "avx512f")]; // FIXME: might need changes for AVX10.
944const AARCH64_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
945    &[(128, "neon")];
946
947// We might want to add "helium" too.
948const ARM_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
949    &[(128, "neon")];
950
951const AMDGPU_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
952    &[(1024, "")];
953const POWERPC_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
954    &[(128, "altivec")];
955const WASM_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
956    &[(128, "simd128")];
957const S390X_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
958    &[(128, "vector")];
959const RISCV_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] = &[
960    (32, "zvl32b"),
961    (64, "zvl64b"),
962    (128, "zvl128b"),
963    (256, "zvl256b"),
964    (512, "zvl512b"),
965    (1024, "zvl1024b"),
966    (2048, "zvl2048b"),
967    (4096, "zvl4096b"),
968    (8192, "zvl8192b"),
969    (16384, "zvl16384b"),
970    (32768, "zvl32768b"),
971    (65536, "zvl65536b"),
972];
973// Always error on SPARC, as the necessary target features cannot be enabled in Rust at the moment.
974const SPARC_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
975    &[/*(64, "vis")*/];
976
977const HEXAGON_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] = &[
978    (512, "hvx-length64b"),   // HvxVector in 64-byte mode
979    (1024, "hvx-length128b"), // HvxVector in 128-byte mode, or HvxVectorPair in 64-byte mode
980    (2048, "hvx-length128b"), // HvxVectorPair in 128-byte mode
981];
982const MIPS_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
983    &[(128, "msa")];
984const CSKY_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
985    &[(128, "vdspv1")];
986const LOONGARCH_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
987    &[(128, "lsx"), (256, "lasx")];
988
989#[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)]
990pub struct FeatureConstraints {
991    /// Features that must be enabled.
992    pub required: &'static [&'static str],
993    /// Features that must be disabled.
994    pub incompatible: &'static [&'static str],
995}
996
997impl Target {
998    pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] {
999        match &self.arch {
1000            Arch::Arm => ARM_FEATURES,
1001            Arch::AArch64 | Arch::Arm64EC => AARCH64_FEATURES,
1002            Arch::X86 | Arch::X86_64 => X86_FEATURES,
1003            Arch::Hexagon => HEXAGON_FEATURES,
1004            Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => MIPS_FEATURES,
1005            Arch::Nvptx64 => NVPTX_FEATURES,
1006            Arch::PowerPC | Arch::PowerPC64 => POWERPC_FEATURES,
1007            Arch::RiscV32 | Arch::RiscV64 => RISCV_FEATURES,
1008            Arch::Wasm32 | Arch::Wasm64 => WASM_FEATURES,
1009            Arch::Bpf => BPF_FEATURES,
1010            Arch::CSky => CSKY_FEATURES,
1011            Arch::LoongArch32 | Arch::LoongArch64 => LOONGARCH_FEATURES,
1012            Arch::S390x => IBMZ_FEATURES,
1013            Arch::Sparc | Arch::Sparc64 => SPARC_FEATURES,
1014            Arch::M68k => M68K_FEATURES,
1015            Arch::Avr => AVR_FEATURES,
1016            Arch::AmdGpu | Arch::Msp430 | Arch::SpirV | Arch::Xtensa | Arch::Other(_) => &[],
1017        }
1018    }
1019
1020    pub fn features_for_correct_fixed_length_vector_abi(&self) -> &'static [(u64, &'static str)] {
1021        match &self.arch {
1022            Arch::X86 | Arch::X86_64 => X86_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1023            Arch::AArch64 | Arch::Arm64EC => AARCH64_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1024            Arch::Arm => ARM_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1025            Arch::PowerPC | Arch::PowerPC64 => POWERPC_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1026            Arch::LoongArch32 | Arch::LoongArch64 => {
1027                LOONGARCH_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI
1028            }
1029            Arch::RiscV32 | Arch::RiscV64 => RISCV_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1030            Arch::Wasm32 | Arch::Wasm64 => WASM_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1031            Arch::S390x => S390X_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1032            Arch::Sparc | Arch::Sparc64 => SPARC_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1033            Arch::Hexagon => HEXAGON_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1034            Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => {
1035                MIPS_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI
1036            }
1037            Arch::AmdGpu => AMDGPU_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1038            Arch::Nvptx64 | Arch::Bpf | Arch::M68k | Arch::Avr => &[], // no vector ABI
1039            Arch::CSky => CSKY_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI,
1040            // FIXME: for some tier3 targets, we are overly cautious and always give warnings
1041            // when passing args in vector registers.
1042            Arch::Msp430 | Arch::SpirV | Arch::Xtensa | Arch::Other(_) => &[],
1043        }
1044    }
1045
1046    pub fn features_for_correct_scalable_vector_abi(&self) -> Option<&'static str> {
1047        match &self.arch {
1048            Arch::AArch64 | Arch::Arm64EC => Some("sve"),
1049            // Other targets have no scalable vectors or they are unimplemented.
1050            _ => None,
1051        }
1052    }
1053
1054    pub fn tied_target_features(&self) -> &'static [&'static [&'static str]] {
1055        match &self.arch {
1056            Arch::AArch64 | Arch::Arm64EC => AARCH64_TIED_FEATURES,
1057            _ => &[],
1058        }
1059    }
1060
1061    // Note: the returned set includes `base_feature`.
1062    pub fn implied_target_features<'a>(&self, base_feature: &'a str) -> FxHashSet<&'a str> {
1063        let implied_features =
1064            self.rust_target_features().iter().map(|(f, _, i)| (f, i)).collect::<FxHashMap<_, _>>();
1065
1066        // Implied target features have their own implied target features, so we traverse the
1067        // map until there are no more features to add.
1068        let mut features = FxHashSet::default();
1069        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];
1070        while let Some(new_feature) = new_features.pop() {
1071            if features.insert(new_feature) {
1072                if let Some(implied_features) = implied_features.get(&new_feature) {
1073                    new_features.extend(implied_features.iter().copied())
1074                }
1075            }
1076        }
1077        features
1078    }
1079
1080    /// Returns two lists of features:
1081    /// the first list contains target features that must be enabled for ABI reasons,
1082    /// and the second list contains target feature that must be disabled for ABI reasons.
1083    ///
1084    /// These features are automatically appended to whatever the target spec sets as default
1085    /// features for the target.
1086    ///
1087    /// All features enabled/disabled via `-Ctarget-features` and `#[target_features]` are checked
1088    /// against this. We also check any implied features, based on the information above. If LLVM
1089    /// implicitly enables more implied features than we do, that could bypass this check!
1090    pub fn abi_required_features(&self) -> FeatureConstraints {
1091        const NOTHING: FeatureConstraints = FeatureConstraints { required: &[], incompatible: &[] };
1092        // Some architectures don't have a clean explicit ABI designation; instead, the ABI is
1093        // defined by target features. When that is the case, those target features must be
1094        // "forbidden" in the list above to ensure that there is a consistent answer to the
1095        // questions "which ABI is used".
1096        match &self.arch {
1097            Arch::X86 => {
1098                // We use our own ABI indicator here; LLVM does not have anything native.
1099                // Every case should require or forbid `soft-float`!
1100                match self.rustc_abi {
1101                    None => {
1102                        // Default hardfloat ABI.
1103                        // x87 must be enabled, soft-float must be disabled.
1104                        FeatureConstraints { required: &["x87"], incompatible: &["soft-float"] }
1105                    }
1106                    Some(RustcAbi::X86Sse2) => {
1107                        // Extended hardfloat ABI. x87 and SSE2 must be enabled, soft-float must be disabled.
1108                        FeatureConstraints {
1109                            required: &["x87", "sse2"],
1110                            incompatible: &["soft-float"],
1111                        }
1112                    }
1113                    Some(RustcAbi::Softfloat) => {
1114                        // Softfloat ABI, requires corresponding target feature. That feature trumps
1115                        // `x87` and all other FPU features so those do not matter.
1116                        // Note that this one requirement is the entire implementation of the ABI!
1117                        // LLVM handles the rest.
1118                        FeatureConstraints { required: &["soft-float"], incompatible: &[] }
1119                    }
1120                }
1121            }
1122            Arch::X86_64 => {
1123                // We use our own ABI indicator here; LLVM does not have anything native.
1124                // Every case should require or forbid `soft-float`!
1125                match self.rustc_abi {
1126                    None => {
1127                        // Default hardfloat ABI. On x86-64, this always includes SSE2.
1128                        FeatureConstraints {
1129                            required: &["x87", "sse2"],
1130                            incompatible: &["soft-float"],
1131                        }
1132                    }
1133                    Some(RustcAbi::Softfloat) => {
1134                        // Softfloat ABI, requires corresponding target feature. That feature trumps
1135                        // `x87` and all other FPU features so those do not matter.
1136                        // Note that this one requirement is the entire implementation of the ABI!
1137                        // LLVM handles the rest.
1138                        FeatureConstraints { required: &["soft-float"], incompatible: &[] }
1139                    }
1140                    Some(r) => {
    ::core::panicking::panic_fmt(format_args!("invalid Rust ABI for x86_64: {0:?}",
            r));
}panic!("invalid Rust ABI for x86_64: {r:?}"),
1141                }
1142            }
1143            Arch::Arm => {
1144                // On ARM, ABI handling is reasonably sane; we use `llvm_floatabi` to indicate
1145                // to LLVM which ABI we are going for.
1146                match self.llvm_floatabi.unwrap() {
1147                    FloatAbi::Soft => {
1148                        // Nothing special required, will use soft-float ABI throughout.
1149                        // We can even allow `-soft-float` here; in fact that is useful as it lets
1150                        // people use FPU instructions with a softfloat ABI (corresponds to
1151                        // `-mfloat-abi=softfp` in GCC/clang).
1152                        NOTHING
1153                    }
1154                    FloatAbi::Hard => {
1155                        // Must have `fpregs` and must not have `soft-float`.
1156                        FeatureConstraints { required: &["fpregs"], incompatible: &["soft-float"] }
1157                    }
1158                }
1159            }
1160            Arch::AArch64 | Arch::Arm64EC => {
1161                // Aarch64 has no sane ABI specifier, and LLVM doesn't even have a way to force
1162                // the use of soft-float, so all we can do here is some crude hacks.
1163                match self.rustc_abi {
1164                    Some(RustcAbi::Softfloat) => {
1165                        // LLVM will use float registers when `fp-armv8` is available, e.g. for
1166                        // calls to built-ins. The only way to ensure a consistent softfloat ABI
1167                        // on aarch64 is to never enable `fp-armv8`, so we enforce that.
1168                        // In Rust we tie `neon` and `fp-armv8` together, therefore `neon` is the
1169                        // feature we have to mark as incompatible.
1170                        FeatureConstraints { required: &[], incompatible: &["neon"] }
1171                    }
1172                    None => {
1173                        // Everything else is assumed to use a hardfloat ABI. neon and fp-armv8 must be enabled.
1174                        // `FeatureConstraints` uses Rust feature names, hence only "neon" shows up.
1175                        FeatureConstraints { required: &["neon"], incompatible: &[] }
1176                    }
1177                    Some(r) => {
    ::core::panicking::panic_fmt(format_args!("invalid Rust ABI for aarch64: {0:?}",
            r));
}panic!("invalid Rust ABI for aarch64: {r:?}"),
1178                }
1179            }
1180            Arch::RiscV32 | Arch::RiscV64 => {
1181                // RISC-V handles ABI in a very sane way, being fully explicit via `llvm_abiname`
1182                // about what the intended ABI is.
1183                match &self.llvm_abiname {
1184                    LlvmAbi::Ilp32d | LlvmAbi::Lp64d => {
1185                        // Requires d (which implies f), incompatible with e and zfinx.
1186                        FeatureConstraints { required: &["d"], incompatible: &["e", "zfinx"] }
1187                    }
1188                    LlvmAbi::Ilp32f | LlvmAbi::Lp64f => {
1189                        // Requires f, incompatible with e and zfinx.
1190                        FeatureConstraints { required: &["f"], incompatible: &["e", "zfinx"] }
1191                    }
1192                    LlvmAbi::Ilp32 | LlvmAbi::Lp64 => {
1193                        // Requires nothing, incompatible with e.
1194                        FeatureConstraints { required: &[], incompatible: &["e"] }
1195                    }
1196                    LlvmAbi::Ilp32e => {
1197                        // ilp32e is documented to be incompatible with features that need aligned
1198                        // load/stores > 32 bits, like `d`. (One could also just generate more
1199                        // complicated code to align the stack when needed, but the RISCV
1200                        // architecture manual just explicitly rules out this combination so we
1201                        // might as well.)
1202                        // Note that the `e` feature is not required: the ABI treats the extra
1203                        // registers as caller-save, so it is safe to use them only in some parts of
1204                        // a program while the rest doesn't know they even exist.
1205                        FeatureConstraints { required: &[], incompatible: &["d"] }
1206                    }
1207                    LlvmAbi::Lp64e => {
1208                        // As above, `e` is not required.
1209                        NOTHING
1210                    }
1211                    _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1212                }
1213            }
1214            Arch::LoongArch32 | Arch::LoongArch64 => {
1215                // LoongArch handles ABI in a very sane way, being fully explicit via `llvm_abiname`
1216                // about what the intended ABI is.
1217                match &self.llvm_abiname {
1218                    LlvmAbi::Ilp32d | LlvmAbi::Lp64d => {
1219                        // Requires d (which implies f), incompatible with nothing.
1220                        FeatureConstraints { required: &["d"], incompatible: &[] }
1221                    }
1222                    LlvmAbi::Ilp32f | LlvmAbi::Lp64f => {
1223                        // Requires f, incompatible with nothing.
1224                        FeatureConstraints { required: &["f"], incompatible: &[] }
1225                    }
1226                    LlvmAbi::Ilp32s | LlvmAbi::Lp64s => {
1227                        // The soft-float ABI does not require any features and is also not
1228                        // incompatible with any features. Rust targets explicitly specify the
1229                        // LLVM ABI names, which allows for enabling hard-float support even on
1230                        // soft-float targets, and ensures that the ABI behavior is as expected.
1231                        NOTHING
1232                    }
1233                    _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1234                }
1235            }
1236            Arch::S390x => {
1237                // Same as x86, We use our own ABI indicator here;
1238                // LLVM does not have anything native and will switch ABI based
1239                // on the soft-float target feature.
1240                // Every case should require or forbid `soft-float`!
1241                // The "vector" target feature may only be used without soft-float
1242                // because the float and vector registers overlap and the
1243                // standard s390x C ABI may pass vectors via these registers.
1244                match self.rustc_abi {
1245                    None => {
1246                        // Default hardfloat ABI.
1247                        FeatureConstraints { required: &[], incompatible: &["soft-float"] }
1248                    }
1249                    Some(RustcAbi::Softfloat) => {
1250                        // Softfloat ABI, requires corresponding target feature.
1251                        // llvm will switch to soft-float ABI just based on this feature.
1252                        FeatureConstraints { required: &["soft-float"], incompatible: &["vector"] }
1253                    }
1254                    Some(r) => {
1255                        {
    ::core::panicking::panic_fmt(format_args!("invalid Rust ABI for s390x: {0:?}",
            r));
};panic!("invalid Rust ABI for s390x: {r:?}");
1256                    }
1257                }
1258            }
1259            Arch::Avr => {
1260                // SRAM is minimum requirement for C/C++ in both avr-gcc and Clang,
1261                // and backends of them only support assembly for devices have no SRAM.
1262                // See the discussion in https://github.com/rust-lang/rust/pull/146900 for more.
1263                FeatureConstraints { required: &["sram"], incompatible: &[] }
1264            }
1265            _ => NOTHING,
1266        }
1267    }
1268}