use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_span::{Symbol, sym};
use crate::spec::Target;
pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
pub const RUSTC_SPECIAL_FEATURES: &[&str] = &["backchain"];
#[derive(Debug, Clone)]
pub enum Stability<Toggleability> {
Stable {
allow_toggle: Toggleability,
},
Unstable {
nightly_feature: Symbol,
allow_toggle: Toggleability,
},
Forbidden { reason: &'static str },
}
pub type AllowToggleUncomputed = fn(&Target, bool) -> Result<(), &'static str>;
#[derive(Debug, Clone)]
pub struct AllowToggleComputed {
enable: Result<(), &'static str>,
disable: Result<(), &'static str>,
}
pub type StabilityUncomputed = Stability<AllowToggleUncomputed>;
pub type StabilityComputed = Stability<AllowToggleComputed>;
impl<CTX, Toggleability: HashStable<CTX>> HashStable<CTX> for Stability<Toggleability> {
#[inline]
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
std::mem::discriminant(self).hash_stable(hcx, hasher);
match self {
Stability::Stable { allow_toggle } => {
allow_toggle.hash_stable(hcx, hasher);
}
Stability::Unstable { nightly_feature, allow_toggle } => {
nightly_feature.hash_stable(hcx, hasher);
allow_toggle.hash_stable(hcx, hasher);
}
Stability::Forbidden { reason } => {
reason.hash_stable(hcx, hasher);
}
}
}
}
impl<CTX> HashStable<CTX> for AllowToggleComputed {
#[inline]
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
let AllowToggleComputed { enable, disable } = self;
enable.hash_stable(hcx, hasher);
disable.hash_stable(hcx, hasher);
}
}
impl<Toggleability> Stability<Toggleability> {
pub fn in_cfg(&self) -> bool {
!matches!(self, Stability::Forbidden { .. })
}
pub fn requires_nightly(&self) -> Option<Symbol> {
match *self {
Stability::Unstable { nightly_feature, .. } => Some(nightly_feature),
Stability::Stable { .. } => None,
Stability::Forbidden { .. } => panic!("forbidden features should not reach this far"),
}
}
}
impl StabilityUncomputed {
pub fn compute_toggleability(&self, target: &Target) -> StabilityComputed {
use Stability::*;
let compute = |f: AllowToggleUncomputed| AllowToggleComputed {
enable: f(target, true),
disable: f(target, false),
};
match *self {
Stable { allow_toggle } => Stable { allow_toggle: compute(allow_toggle) },
Unstable { nightly_feature, allow_toggle } => {
Unstable { nightly_feature, allow_toggle: compute(allow_toggle) }
}
Forbidden { reason } => Forbidden { reason },
}
}
pub fn toggle_allowed(&self, target: &Target, enable: bool) -> Result<(), &'static str> {
use Stability::*;
match *self {
Stable { allow_toggle } => allow_toggle(target, enable),
Unstable { allow_toggle, .. } => allow_toggle(target, enable),
Forbidden { reason } => Err(reason),
}
}
}
impl StabilityComputed {
pub fn toggle_allowed(&self, enable: bool) -> Result<(), &'static str> {
let allow_toggle = match self {
Stability::Stable { allow_toggle } => allow_toggle,
Stability::Unstable { allow_toggle, .. } => allow_toggle,
Stability::Forbidden { reason } => return Err(reason),
};
if enable { allow_toggle.enable } else { allow_toggle.disable }
}
}
const STABLE: StabilityUncomputed = Stability::Stable { allow_toggle: |_target, _enable| Ok(()) };
const fn unstable(nightly_feature: Symbol) -> StabilityUncomputed {
Stability::Unstable { nightly_feature, allow_toggle: |_target, _enable| Ok(()) }
}
type ImpliedFeatures = &'static [&'static str];
const ARM_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
("aclass", unstable(sym::arm_target_feature), &[]),
("aes", unstable(sym::arm_target_feature), &["neon"]),
("crc", unstable(sym::arm_target_feature), &[]),
("d32", unstable(sym::arm_target_feature), &[]),
("dotprod", unstable(sym::arm_target_feature), &["neon"]),
("dsp", unstable(sym::arm_target_feature), &[]),
("fp-armv8", unstable(sym::arm_target_feature), &["vfp4"]),
(
"fpregs",
Stability::Unstable {
nightly_feature: sym::arm_target_feature,
allow_toggle: |target: &Target, _enable| {
if target.has_feature("soft-float") {
Ok(())
} else {
Err("unsound on hard-float targets because it changes float ABI")
}
},
},
&[],
),
("i8mm", unstable(sym::arm_target_feature), &["neon"]),
("mclass", unstable(sym::arm_target_feature), &[]),
("neon", unstable(sym::arm_target_feature), &["vfp3"]),
("rclass", unstable(sym::arm_target_feature), &[]),
("sha2", unstable(sym::arm_target_feature), &["neon"]),
("soft-float", Stability::Forbidden { reason: "unsound because it changes float ABI" }, &[]),
("thumb-mode", unstable(sym::arm_target_feature), &[]),
("thumb2", unstable(sym::arm_target_feature), &[]),
("trustzone", unstable(sym::arm_target_feature), &[]),
("v5te", unstable(sym::arm_target_feature), &[]),
("v6", unstable(sym::arm_target_feature), &["v5te"]),
("v6k", unstable(sym::arm_target_feature), &["v6"]),
("v6t2", unstable(sym::arm_target_feature), &["v6k", "thumb2"]),
("v7", unstable(sym::arm_target_feature), &["v6t2"]),
("v8", unstable(sym::arm_target_feature), &["v7"]),
("vfp2", unstable(sym::arm_target_feature), &[]),
("vfp3", unstable(sym::arm_target_feature), &["vfp2", "d32"]),
("vfp4", unstable(sym::arm_target_feature), &["vfp3"]),
("virtualization", unstable(sym::arm_target_feature), &[]),
];
const AARCH64_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
("aes", STABLE, &["neon"]),
("bf16", STABLE, &[]),
("bti", STABLE, &[]),
("crc", STABLE, &[]),
("cssc", unstable(sym::aarch64_unstable_target_feature), &[]),
("dit", STABLE, &[]),
("dotprod", STABLE, &["neon"]),
("dpb", STABLE, &[]),
("dpb2", STABLE, &["dpb"]),
("ecv", unstable(sym::aarch64_unstable_target_feature), &[]),
("f32mm", STABLE, &["sve"]),
("f64mm", STABLE, &["sve"]),
("faminmax", unstable(sym::aarch64_unstable_target_feature), &[]),
("fcma", STABLE, &["neon"]),
("fhm", STABLE, &["fp16"]),
("flagm", STABLE, &[]),
("flagm2", unstable(sym::aarch64_unstable_target_feature), &[]),
("fp-armv8", Stability::Forbidden { reason: "Rust ties `fp-armv8` to `neon`" }, &[]),
("fp16", STABLE, &["neon"]),
("fp8", unstable(sym::aarch64_unstable_target_feature), &["faminmax", "lut", "bf16"]),
("fp8dot2", unstable(sym::aarch64_unstable_target_feature), &["fp8dot4"]),
("fp8dot4", unstable(sym::aarch64_unstable_target_feature), &["fp8fma"]),
("fp8fma", unstable(sym::aarch64_unstable_target_feature), &["fp8"]),
("frintts", STABLE, &[]),
("hbc", unstable(sym::aarch64_unstable_target_feature), &[]),
("i8mm", STABLE, &[]),
("jsconv", STABLE, &["neon"]),
("lor", STABLE, &[]),
("lse", STABLE, &[]),
("lse128", unstable(sym::aarch64_unstable_target_feature), &["lse"]),
("lse2", unstable(sym::aarch64_unstable_target_feature), &[]),
("lut", unstable(sym::aarch64_unstable_target_feature), &[]),
("mops", unstable(sym::aarch64_unstable_target_feature), &[]),
("mte", STABLE, &[]),
(
"neon",
Stability::Stable {
allow_toggle: |target, enable| {
if target.abi == "softfloat" {
Ok(())
} else if enable
&& !target.has_neg_feature("fp-armv8")
&& !target.has_neg_feature("neon")
{
Ok(())
} else {
Err("unsound on hard-float targets because it changes float ABI")
}
},
},
&[],
),
("paca", STABLE, &[]),
("pacg", STABLE, &[]),
("pan", STABLE, &[]),
("pauth-lr", unstable(sym::aarch64_unstable_target_feature), &[]),
("pmuv3", STABLE, &[]),
("rand", STABLE, &[]),
("ras", STABLE, &[]),
("rcpc", STABLE, &[]),
("rcpc2", STABLE, &["rcpc"]),
("rcpc3", unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]),
("rdm", STABLE, &["neon"]),
("reserve-x18", unstable(sym::aarch64_unstable_target_feature), &[]),
("sb", STABLE, &[]),
("sha2", STABLE, &["neon"]),
("sha3", STABLE, &["sha2"]),
("sm4", STABLE, &["neon"]),
("sme", unstable(sym::aarch64_unstable_target_feature), &["bf16"]),
("sme-b16b16", unstable(sym::aarch64_unstable_target_feature), &["bf16", "sme2", "sve-b16b16"]),
("sme-f16f16", unstable(sym::aarch64_unstable_target_feature), &["sme2"]),
("sme-f64f64", unstable(sym::aarch64_unstable_target_feature), &["sme"]),
("sme-f8f16", unstable(sym::aarch64_unstable_target_feature), &["sme-f8f32"]),
("sme-f8f32", unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]),
("sme-fa64", unstable(sym::aarch64_unstable_target_feature), &["sme", "sve2"]),
("sme-i16i64", unstable(sym::aarch64_unstable_target_feature), &["sme"]),
("sme-lutv2", unstable(sym::aarch64_unstable_target_feature), &[]),
("sme2", unstable(sym::aarch64_unstable_target_feature), &["sme"]),
("sme2p1", unstable(sym::aarch64_unstable_target_feature), &["sme2"]),
("spe", STABLE, &[]),
("ssbs", STABLE, &[]),
("ssve-fp8dot2", unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8dot4"]),
("ssve-fp8dot4", unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8fma"]),
("ssve-fp8fma", unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]),
("sve", STABLE, &["neon"]),
("sve-b16b16", unstable(sym::aarch64_unstable_target_feature), &["bf16"]),
("sve2", STABLE, &["sve"]),
("sve2-aes", STABLE, &["sve2", "aes"]),
("sve2-bitperm", STABLE, &["sve2"]),
("sve2-sha3", STABLE, &["sve2", "sha3"]),
("sve2-sm4", STABLE, &["sve2", "sm4"]),
("sve2p1", unstable(sym::aarch64_unstable_target_feature), &["sve2"]),
("tme", STABLE, &[]),
("v8.1a", unstable(sym::aarch64_ver_target_feature), &[
"crc", "lse", "rdm", "pan", "lor", "vh",
]),
("v8.2a", unstable(sym::aarch64_ver_target_feature), &["v8.1a", "ras", "dpb"]),
("v8.3a", unstable(sym::aarch64_ver_target_feature), &[
"v8.2a", "rcpc", "paca", "pacg", "jsconv",
]),
("v8.4a", unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]),
("v8.5a", unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]),
("v8.6a", unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]),
("v8.7a", unstable(sym::aarch64_ver_target_feature), &["v8.6a", "wfxt"]),
("v8.8a", unstable(sym::aarch64_ver_target_feature), &["v8.7a", "hbc", "mops"]),
("v8.9a", unstable(sym::aarch64_ver_target_feature), &["v8.8a", "cssc"]),
("v9.1a", unstable(sym::aarch64_ver_target_feature), &["v9a", "v8.6a"]),
("v9.2a", unstable(sym::aarch64_ver_target_feature), &["v9.1a", "v8.7a"]),
("v9.3a", unstable(sym::aarch64_ver_target_feature), &["v9.2a", "v8.8a"]),
("v9.4a", unstable(sym::aarch64_ver_target_feature), &["v9.3a", "v8.9a"]),
("v9.5a", unstable(sym::aarch64_ver_target_feature), &["v9.4a"]),
("v9a", unstable(sym::aarch64_ver_target_feature), &["v8.5a", "sve2"]),
("vh", STABLE, &[]),
("wfxt", unstable(sym::aarch64_unstable_target_feature), &[]),
];
const AARCH64_TIED_FEATURES: &[&[&str]] = &[
&["paca", "pacg"], ];
const X86_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
("adx", STABLE, &[]),
("aes", STABLE, &["sse2"]),
("amx-bf16", unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-complex", unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-fp16", unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-int8", unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-tile", unstable(sym::x86_amx_intrinsics), &[]),
("avx", STABLE, &["sse4.2"]),
("avx2", STABLE, &["avx"]),
("avx512bf16", unstable(sym::avx512_target_feature), &["avx512bw"]),
("avx512bitalg", unstable(sym::avx512_target_feature), &["avx512bw"]),
("avx512bw", unstable(sym::avx512_target_feature), &["avx512f"]),
("avx512cd", unstable(sym::avx512_target_feature), &["avx512f"]),
("avx512dq", unstable(sym::avx512_target_feature), &["avx512f"]),
("avx512f", unstable(sym::avx512_target_feature), &["avx2", "fma", "f16c"]),
("avx512fp16", unstable(sym::avx512_target_feature), &["avx512bw", "avx512vl", "avx512dq"]),
("avx512ifma", unstable(sym::avx512_target_feature), &["avx512f"]),
("avx512vbmi", unstable(sym::avx512_target_feature), &["avx512bw"]),
("avx512vbmi2", unstable(sym::avx512_target_feature), &["avx512bw"]),
("avx512vl", unstable(sym::avx512_target_feature), &["avx512f"]),
("avx512vnni", unstable(sym::avx512_target_feature), &["avx512f"]),
("avx512vp2intersect", unstable(sym::avx512_target_feature), &["avx512f"]),
("avx512vpopcntdq", unstable(sym::avx512_target_feature), &["avx512f"]),
("avxifma", unstable(sym::avx512_target_feature), &["avx2"]),
("avxneconvert", unstable(sym::avx512_target_feature), &["avx2"]),
("avxvnni", unstable(sym::avx512_target_feature), &["avx2"]),
("avxvnniint16", unstable(sym::avx512_target_feature), &["avx2"]),
("avxvnniint8", unstable(sym::avx512_target_feature), &["avx2"]),
("bmi1", STABLE, &[]),
("bmi2", STABLE, &[]),
("cmpxchg16b", STABLE, &[]),
("ermsb", unstable(sym::ermsb_target_feature), &[]),
("f16c", STABLE, &["avx"]),
("fma", STABLE, &["avx"]),
("fxsr", STABLE, &[]),
("gfni", unstable(sym::avx512_target_feature), &["sse2"]),
("lahfsahf", unstable(sym::lahfsahf_target_feature), &[]),
("lzcnt", STABLE, &[]),
("movbe", STABLE, &[]),
("pclmulqdq", STABLE, &["sse2"]),
("popcnt", STABLE, &[]),
("prfchw", unstable(sym::prfchw_target_feature), &[]),
("rdrand", STABLE, &[]),
("rdseed", STABLE, &[]),
("rtm", unstable(sym::rtm_target_feature), &[]),
("sha", STABLE, &["sse2"]),
("sha512", unstable(sym::sha512_sm_x86), &["avx2"]),
("sm3", unstable(sym::sha512_sm_x86), &["avx"]),
("sm4", unstable(sym::sha512_sm_x86), &["avx2"]),
("soft-float", Stability::Forbidden { reason: "unsound because it changes float ABI" }, &[]),
("sse", STABLE, &[]),
("sse2", STABLE, &["sse"]),
("sse3", STABLE, &["sse2"]),
("sse4.1", STABLE, &["ssse3"]),
("sse4.2", STABLE, &["sse4.1"]),
("sse4a", unstable(sym::sse4a_target_feature), &["sse3"]),
("ssse3", STABLE, &["sse3"]),
("tbm", unstable(sym::tbm_target_feature), &[]),
("vaes", unstable(sym::avx512_target_feature), &["avx2", "aes"]),
("vpclmulqdq", unstable(sym::avx512_target_feature), &["avx", "pclmulqdq"]),
(
"x87",
Stability::Unstable {
nightly_feature: sym::x87_target_feature,
allow_toggle: |target: &Target, _enable| {
if target.has_feature("soft-float") {
Ok(())
} else {
Err("unsound on hard-float targets because it changes float ABI")
}
},
},
&[],
),
("xop", unstable(sym::xop_target_feature), &["avx", "sse4a"]),
("xsave", STABLE, &[]),
("xsavec", STABLE, &["xsave"]),
("xsaveopt", STABLE, &["xsave"]),
("xsaves", STABLE, &["xsave"]),
];
const HEXAGON_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
("hvx", unstable(sym::hexagon_target_feature), &[]),
("hvx-length128b", unstable(sym::hexagon_target_feature), &["hvx"]),
];
const POWERPC_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
("altivec", unstable(sym::powerpc_target_feature), &[]),
("partword-atomics", unstable(sym::powerpc_target_feature), &[]),
("power10-vector", unstable(sym::powerpc_target_feature), &["power9-vector"]),
("power8-altivec", unstable(sym::powerpc_target_feature), &["altivec"]),
("power8-crypto", unstable(sym::powerpc_target_feature), &["power8-altivec"]),
("power8-vector", unstable(sym::powerpc_target_feature), &["vsx", "power8-altivec"]),
("power9-altivec", unstable(sym::powerpc_target_feature), &["power8-altivec"]),
("power9-vector", unstable(sym::powerpc_target_feature), &["power8-vector", "power9-altivec"]),
("quadword-atomics", unstable(sym::powerpc_target_feature), &[]),
("vsx", unstable(sym::powerpc_target_feature), &["altivec"]),
];
const MIPS_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
("fp64", unstable(sym::mips_target_feature), &[]),
("msa", unstable(sym::mips_target_feature), &[]),
("virt", unstable(sym::mips_target_feature), &[]),
];
const RISCV_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
("a", STABLE, &["zaamo", "zalrsc"]),
("c", STABLE, &[]),
(
"d",
Stability::Unstable {
nightly_feature: sym::riscv_target_feature,
allow_toggle: |target, enable| match &*target.llvm_abiname {
"ilp32d" | "lp64d" if !enable => {
Err("feature is required by ABI")
}
"ilp32e" if enable => {
Err("feature is incompatible with ABI")
}
_ => Ok(()),
},
},
&["f"],
),
(
"e",
Stability::Unstable {
nightly_feature: sym::riscv_target_feature,
allow_toggle: |target, enable| {
match &*target.llvm_abiname {
_ if !enable => {
Ok(())
}
"ilp32e" | "lp64e" => {
Ok(())
}
_ => {
Err("feature is incompatible with ABI")
}
}
},
},
&[],
),
(
"f",
Stability::Unstable {
nightly_feature: sym::riscv_target_feature,
allow_toggle: |target, enable| {
match &*target.llvm_abiname {
"ilp32f" | "ilp32d" | "lp64f" | "lp64d" if !enable => {
Err("feature is required by ABI")
}
_ => Ok(()),
}
},
},
&[],
),
(
"forced-atomics",
Stability::Forbidden { reason: "unsound because it changes the ABI of atomic operations" },
&[],
),
("m", STABLE, &[]),
("relax", unstable(sym::riscv_target_feature), &[]),
("unaligned-scalar-mem", unstable(sym::riscv_target_feature), &[]),
("v", unstable(sym::riscv_target_feature), &[]),
("zaamo", unstable(sym::riscv_target_feature), &[]),
("zabha", unstable(sym::riscv_target_feature), &["zaamo"]),
("zalrsc", unstable(sym::riscv_target_feature), &[]),
("zba", STABLE, &[]),
("zbb", STABLE, &[]),
("zbc", STABLE, &[]),
("zbkb", STABLE, &[]),
("zbkc", STABLE, &[]),
("zbkx", STABLE, &[]),
("zbs", STABLE, &[]),
("zdinx", unstable(sym::riscv_target_feature), &["zfinx"]),
("zfh", unstable(sym::riscv_target_feature), &["zfhmin"]),
("zfhmin", unstable(sym::riscv_target_feature), &["f"]),
("zfinx", unstable(sym::riscv_target_feature), &[]),
("zhinx", unstable(sym::riscv_target_feature), &["zhinxmin"]),
("zhinxmin", unstable(sym::riscv_target_feature), &["zfinx"]),
("zk", STABLE, &["zkn", "zkr", "zkt"]),
("zkn", STABLE, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
("zknd", STABLE, &[]),
("zkne", STABLE, &[]),
("zknh", STABLE, &[]),
("zkr", STABLE, &[]),
("zks", STABLE, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
("zksed", STABLE, &[]),
("zksh", STABLE, &[]),
("zkt", STABLE, &[]),
];
const WASM_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
("atomics", unstable(sym::wasm_target_feature), &[]),
("bulk-memory", STABLE, &[]),
("exception-handling", unstable(sym::wasm_target_feature), &[]),
("extended-const", STABLE, &[]),
("multivalue", STABLE, &[]),
("mutable-globals", STABLE, &[]),
("nontrapping-fptoint", STABLE, &[]),
("reference-types", STABLE, &[]),
("relaxed-simd", STABLE, &["simd128"]),
("sign-ext", STABLE, &[]),
("simd128", STABLE, &[]),
("tail-call", STABLE, &[]),
("wide-arithmetic", unstable(sym::wasm_target_feature), &[]),
];
const BPF_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] =
&[("alu32", unstable(sym::bpf_target_feature), &[])];
const CSKY_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
("10e60", unstable(sym::csky_target_feature), &["7e10"]),
("2e3", unstable(sym::csky_target_feature), &["e2"]),
("3e3r1", unstable(sym::csky_target_feature), &[]),
("3e3r2", unstable(sym::csky_target_feature), &["3e3r1", "doloop"]),
("3e3r3", unstable(sym::csky_target_feature), &["doloop"]),
("3e7", unstable(sym::csky_target_feature), &["2e3"]),
("7e10", unstable(sym::csky_target_feature), &["3e7"]),
("cache", unstable(sym::csky_target_feature), &[]),
("doloop", unstable(sym::csky_target_feature), &[]),
("dsp1e2", unstable(sym::csky_target_feature), &[]),
("dspe60", unstable(sym::csky_target_feature), &[]),
("e1", unstable(sym::csky_target_feature), &["elrw"]),
("e2", unstable(sym::csky_target_feature), &["e2"]),
("edsp", unstable(sym::csky_target_feature), &[]),
("elrw", unstable(sym::csky_target_feature), &[]),
("float1e2", unstable(sym::csky_target_feature), &[]),
("float1e3", unstable(sym::csky_target_feature), &[]),
("float3e4", unstable(sym::csky_target_feature), &[]),
("float7e60", unstable(sym::csky_target_feature), &[]),
("floate1", unstable(sym::csky_target_feature), &[]),
("hard-tp", unstable(sym::csky_target_feature), &[]),
("high-registers", unstable(sym::csky_target_feature), &[]),
("hwdiv", unstable(sym::csky_target_feature), &[]),
("mp", unstable(sym::csky_target_feature), &["2e3"]),
("mp1e2", unstable(sym::csky_target_feature), &["3e7"]),
("nvic", unstable(sym::csky_target_feature), &[]),
("trust", unstable(sym::csky_target_feature), &[]),
("vdsp2e60f", unstable(sym::csky_target_feature), &[]),
("vdspv1", unstable(sym::csky_target_feature), &[]),
("vdspv2", unstable(sym::csky_target_feature), &[]),
("fdivdu", unstable(sym::csky_target_feature), &[]),
("fpuv2_df", unstable(sym::csky_target_feature), &[]),
("fpuv2_sf", unstable(sym::csky_target_feature), &[]),
("fpuv3_df", unstable(sym::csky_target_feature), &[]),
("fpuv3_hf", unstable(sym::csky_target_feature), &[]),
("fpuv3_hi", unstable(sym::csky_target_feature), &[]),
("fpuv3_sf", unstable(sym::csky_target_feature), &[]),
("hard-float", unstable(sym::csky_target_feature), &[]),
("hard-float-abi", unstable(sym::csky_target_feature), &[]),
];
const LOONGARCH_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
("d", unstable(sym::loongarch_target_feature), &["f"]),
("f", unstable(sym::loongarch_target_feature), &[]),
("frecipe", unstable(sym::loongarch_target_feature), &[]),
("lasx", unstable(sym::loongarch_target_feature), &["lsx"]),
("lbt", unstable(sym::loongarch_target_feature), &[]),
("lsx", unstable(sym::loongarch_target_feature), &["d"]),
("lvz", unstable(sym::loongarch_target_feature), &[]),
("relax", unstable(sym::loongarch_target_feature), &[]),
("ual", unstable(sym::loongarch_target_feature), &[]),
];
const IBMZ_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
("backchain", unstable(sym::s390x_target_feature), &[]),
("vector", unstable(sym::s390x_target_feature), &[]),
];
const SPARC_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
("leoncasa", unstable(sym::sparc_target_feature), &[]),
("v8plus", unstable(sym::sparc_target_feature), &[]),
("v9", unstable(sym::sparc_target_feature), &[]),
];
const M68K_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
("isa-68000", unstable(sym::m68k_target_feature), &[]),
("isa-68010", unstable(sym::m68k_target_feature), &["isa-68000"]),
("isa-68020", unstable(sym::m68k_target_feature), &["isa-68010"]),
("isa-68030", unstable(sym::m68k_target_feature), &["isa-68020"]),
("isa-68040", unstable(sym::m68k_target_feature), &["isa-68030", "isa-68882"]),
("isa-68060", unstable(sym::m68k_target_feature), &["isa-68040"]),
("isa-68881", unstable(sym::m68k_target_feature), &[]),
("isa-68882", unstable(sym::m68k_target_feature), &["isa-68881"]),
];
pub fn all_rust_features() -> impl Iterator<Item = (&'static str, StabilityUncomputed)> {
std::iter::empty()
.chain(ARM_FEATURES.iter())
.chain(AARCH64_FEATURES.iter())
.chain(X86_FEATURES.iter())
.chain(HEXAGON_FEATURES.iter())
.chain(POWERPC_FEATURES.iter())
.chain(MIPS_FEATURES.iter())
.chain(RISCV_FEATURES.iter())
.chain(WASM_FEATURES.iter())
.chain(BPF_FEATURES.iter())
.chain(CSKY_FEATURES)
.chain(LOONGARCH_FEATURES)
.chain(IBMZ_FEATURES)
.chain(SPARC_FEATURES)
.chain(M68K_FEATURES)
.cloned()
.map(|(f, s, _)| (f, s))
}
const X86_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
&[(128, "sse"), (256, "avx"), (512, "avx512f")]; const AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "neon")];
const ARM_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "neon")];
const POWERPC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "altivec")];
const WASM_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "simd128")];
const S390X_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "vector")];
const RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
&[(128, "v")];
const SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[];
const HEXAGON_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
&[(1024, "hvx-length128b")];
const MIPS_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "msa")];
const CSKY_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "vdspv1")];
const LOONGARCH_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
&[(128, "lsx"), (256, "lasx")];
impl Target {
pub fn rust_target_features(
&self,
) -> &'static [(&'static str, StabilityUncomputed, ImpliedFeatures)] {
match &*self.arch {
"arm" => ARM_FEATURES,
"aarch64" | "arm64ec" => AARCH64_FEATURES,
"x86" | "x86_64" => X86_FEATURES,
"hexagon" => HEXAGON_FEATURES,
"mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_FEATURES,
"powerpc" | "powerpc64" => POWERPC_FEATURES,
"riscv32" | "riscv64" => RISCV_FEATURES,
"wasm32" | "wasm64" => WASM_FEATURES,
"bpf" => BPF_FEATURES,
"csky" => CSKY_FEATURES,
"loongarch64" => LOONGARCH_FEATURES,
"s390x" => IBMZ_FEATURES,
"sparc" | "sparc64" => SPARC_FEATURES,
"m68k" => M68K_FEATURES,
_ => &[],
}
}
pub fn features_for_correct_vector_abi(&self) -> &'static [(u64, &'static str)] {
match &*self.arch {
"x86" | "x86_64" => X86_FEATURES_FOR_CORRECT_VECTOR_ABI,
"aarch64" | "arm64ec" => AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI,
"arm" => ARM_FEATURES_FOR_CORRECT_VECTOR_ABI,
"powerpc" | "powerpc64" => POWERPC_FEATURES_FOR_CORRECT_VECTOR_ABI,
"loongarch64" => LOONGARCH_FEATURES_FOR_CORRECT_VECTOR_ABI,
"riscv32" | "riscv64" => RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI,
"wasm32" | "wasm64" => WASM_FEATURES_FOR_CORRECT_VECTOR_ABI,
"s390x" => S390X_FEATURES_FOR_CORRECT_VECTOR_ABI,
"sparc" | "sparc64" => SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI,
"hexagon" => HEXAGON_FEATURES_FOR_CORRECT_VECTOR_ABI,
"mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_FEATURES_FOR_CORRECT_VECTOR_ABI,
"bpf" | "m68k" => &[], "csky" => CSKY_FEATURES_FOR_CORRECT_VECTOR_ABI,
_ => &[],
}
}
pub fn tied_target_features(&self) -> &'static [&'static [&'static str]] {
match &*self.arch {
"aarch64" | "arm64ec" => AARCH64_TIED_FEATURES,
_ => &[],
}
}
pub fn implied_target_features(
&self,
base_features: impl Iterator<Item = Symbol>,
) -> FxHashSet<Symbol> {
let implied_features = self
.rust_target_features()
.iter()
.map(|(f, _, i)| (Symbol::intern(f), i))
.collect::<FxHashMap<_, _>>();
let mut features = FxHashSet::default();
let mut new_features = base_features.collect::<Vec<Symbol>>();
while let Some(new_feature) = new_features.pop() {
if features.insert(new_feature) {
if let Some(implied_features) = implied_features.get(&new_feature) {
new_features.extend(implied_features.iter().copied().map(Symbol::intern))
}
}
}
features
}
}