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