Skip to main content

rustc_target/
target_features.rs

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