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