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