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