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