//! LLVM Target Information — complete target description for all
//! supported architectures. Provides TargetInfo, ABIInfo, CPU feature
//! detection, and target registry.
//!
//! Clean-room behavioral reconstruction. No LLVM source consulted.
use std::collections::{HashMap, HashSet};
use std::fmt;
use super::data_layout::DataLayout;
use super::triple::{Arch, Triple, OS};
// ═══════════════════════════════════════════════════════════════════════════
// Target Feature
// ═══════════════════════════════════════════════════════════════════════════
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TargetFeature {
pub name: String,
pub description: String,
pub default_enabled: bool,
pub implies: Vec<String>,
}
impl TargetFeature {
pub fn new(name: &str, desc: &str, default: bool) -> Self {
Self {
name: name.to_string(),
description: desc.to_string(),
default_enabled: default,
implies: Vec::new(),
}
}
}
// ═══════════════════════════════════════════════════════════════════════════
// CPU Info
// ═══════════════════════════════════════════════════════════════════════════
#[derive(Debug, Clone)]
pub struct CpuInfo {
pub name: String,
pub features: HashSet<String>,
pub tuning_cpu: Option<String>,
}
// ═══════════════════════════════════════════════════════════════════════════
// ABI Info
// ═══════════════════════════════════════════════════════════════════════════
#[derive(Debug, Clone)]
pub struct ABIInfo {
pub pointer_size: u32,
pub size_t_size: u32,
pub stack_alignment: u32,
pub int_reg_width: u32,
pub char_is_signed: bool,
pub wchar_is_32bit: bool,
pub long_double_is_128: bool,
}
impl ABIInfo {
pub fn x86_64_linux() -> Self {
Self {
pointer_size: 64,
size_t_size: 64,
stack_alignment: 128,
int_reg_width: 64,
char_is_signed: true,
wchar_is_32bit: true,
long_double_is_128: false,
}
}
pub fn aarch64_linux() -> Self {
Self {
pointer_size: 64,
size_t_size: 64,
stack_alignment: 128,
int_reg_width: 64,
char_is_signed: false,
wchar_is_32bit: true,
long_double_is_128: true,
}
}
pub fn x86_64_windows() -> Self {
Self {
pointer_size: 64,
size_t_size: 64,
stack_alignment: 128,
int_reg_width: 64,
char_is_signed: true,
wchar_is_32bit: false,
long_double_is_128: false,
}
}
pub fn arm32_linux() -> Self {
Self {
pointer_size: 32,
size_t_size: 32,
stack_alignment: 64,
int_reg_width: 32,
char_is_signed: false,
wchar_is_32bit: true,
long_double_is_128: false,
}
}
pub fn riscv64_linux() -> Self {
Self {
pointer_size: 64,
size_t_size: 64,
stack_alignment: 128,
int_reg_width: 64,
char_is_signed: true,
wchar_is_32bit: true,
long_double_is_128: true,
}
}
pub fn riscv32_linux() -> Self {
Self {
pointer_size: 32,
size_t_size: 32,
stack_alignment: 64,
int_reg_width: 32,
char_is_signed: true,
wchar_is_32bit: true,
long_double_is_128: false,
}
}
pub fn wasm32() -> Self {
Self {
pointer_size: 32,
size_t_size: 32,
stack_alignment: 16,
int_reg_width: 32,
char_is_signed: true,
wchar_is_32bit: true,
long_double_is_128: false,
}
}
}
// ═══════════════════════════════════════════════════════════════════════════
// Target Info
// ═══════════════════════════════════════════════════════════════════════════
#[derive(Debug, Clone)]
pub struct TargetInfo {
pub triple: Triple,
pub data_layout: DataLayout,
pub abi: ABIInfo,
pub cpu: String,
pub features: HashMap<String, bool>,
pub supported_cpus: HashMap<String, CpuInfo>,
pub supported_features: HashMap<String, TargetFeature>,
}
impl TargetInfo {
pub fn from_triple(triple: Triple) -> Self {
let data_layout = Self::default_data_layout(&triple);
let abi = Self::default_abi(&triple);
let cpu = Self::default_cpu(&triple);
let (cpus, features) = Self::target_specific_info(&triple);
Self {
triple,
data_layout,
abi,
cpu,
features: HashMap::new(),
supported_cpus: cpus,
supported_features: features,
}
}
fn default_data_layout(triple: &Triple) -> DataLayout {
match triple.arch {
Arch::X86_64 => DataLayout::parse("e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128")
.unwrap_or_default(),
Arch::AArch64 => {
DataLayout::parse("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128")
.unwrap_or_default()
}
Arch::ARM => DataLayout::parse("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64")
.unwrap_or_default(),
Arch::RISCV64 => {
DataLayout::parse("e-m:e-p:64:64-i64:64-i128:128-n64-S128").unwrap_or_default()
}
Arch::RISCV32 => DataLayout::parse("e-m:e-p:32:32-i64:64-n32-S128").unwrap_or_default(),
Arch::WebAssembly32 => {
DataLayout::parse("e-m:e-p:32:32-i64:64-n32:64-S128").unwrap_or_default()
}
Arch::WebAssembly64 => {
DataLayout::parse("e-m:e-p:64:64-i64:64-n32:64-S128").unwrap_or_default()
}
Arch::SystemZ => {
DataLayout::parse("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64")
.unwrap_or_default()
}
_ => DataLayout::default(),
}
}
fn default_abi(triple: &Triple) -> ABIInfo {
match (triple.arch, triple.os) {
(Arch::X86_64, OS::Win32) => ABIInfo::x86_64_windows(),
(Arch::X86_64, _) => ABIInfo::x86_64_linux(),
(Arch::AArch64, _) => ABIInfo::aarch64_linux(),
(Arch::ARM, _) => ABIInfo::arm32_linux(),
(Arch::RISCV64, _) => ABIInfo::riscv64_linux(),
(Arch::RISCV32, _) => ABIInfo::riscv32_linux(),
(Arch::WebAssembly32 | Arch::WebAssembly64, _) => ABIInfo::wasm32(),
_ => ABIInfo::x86_64_linux(),
}
}
fn default_cpu(triple: &Triple) -> String {
match triple.arch {
Arch::X86_64 => "x86-64".into(),
Arch::X86 => "i686".into(),
Arch::AArch64 => "generic".into(),
Arch::ARM => "generic".into(),
Arch::RISCV64 => "generic-rv64".into(),
Arch::RISCV32 => "generic-rv32".into(),
Arch::SystemZ => "z14".into(),
Arch::Mips64 => "mips64".into(),
_ => "generic".into(),
}
}
fn target_specific_info(
triple: &Triple,
) -> (HashMap<String, CpuInfo>, HashMap<String, TargetFeature>) {
match triple.arch {
Arch::X86_64 | Arch::X86 => Self::x86_info(),
Arch::AArch64 | Arch::ARM => Self::arm_info(),
Arch::RISCV64 | Arch::RISCV32 => Self::riscv_info(),
_ => (HashMap::new(), HashMap::new()),
}
}
fn x86_info() -> (HashMap<String, CpuInfo>, HashMap<String, TargetFeature>) {
let mut cpus = HashMap::new();
for (name, feats) in [
("generic", ""),
("x86-64", "sse2"),
("x86-64-v2", "sse3,sse4.1,sse4.2,ssse3,popcnt"),
("x86-64-v3", "avx,avx2,bmi,bmi2,fma,lzcnt,movbe"),
("x86-64-v4", "avx512f,avx512bw,avx512cd,avx512dq,avx512vl"),
("znver4", "avx512f,avx512bw"),
("alderlake", "avx2"),
("sapphirerapids", "avx512f,avx512bw"),
] {
cpus.insert(
name.to_string(),
CpuInfo {
name: name.to_string(),
features: feats
.split(',')
.filter(|s| !s.is_empty())
.map(|s| s.to_string())
.collect(),
tuning_cpu: None,
},
);
}
let mut feats = HashMap::new();
for (name, desc, default) in [
("sse", "SSE", true),
("sse2", "SSE2", true),
("sse3", "SSE3", false),
("sse4.1", "SSE4.1", false),
("sse4.2", "SSE4.2", false),
("avx", "AVX", false),
("avx2", "AVX2", false),
("avx512f", "AVX-512F", false),
("avx512bw", "AVX-512BW", false),
("avx512dq", "AVX-512DQ", false),
("bmi", "BMI", false),
("bmi2", "BMI2", false),
("fma", "FMA", false),
("popcnt", "POPCNT", false),
("lzcnt", "LZCNT", false),
("cmov", "CMOV", true),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
(cpus, feats)
}
fn arm_info() -> (HashMap<String, CpuInfo>, HashMap<String, TargetFeature>) {
let mut cpus = HashMap::new();
for name in [
"generic",
"cortex-a53",
"cortex-a72",
"cortex-a76",
"cortex-x1",
"apple-m1",
"apple-m2",
] {
cpus.insert(
name.to_string(),
CpuInfo {
name: name.to_string(),
features: HashSet::new(),
tuning_cpu: None,
},
);
}
let mut feats = HashMap::new();
for (name, desc, default) in [
("neon", "NEON", true),
("v8a", "ARMv8-A", true),
("crc", "CRC", false),
("crypto", "Crypto", false),
("sve", "SVE", false),
("sve2", "SVE2", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
(cpus, feats)
}
fn riscv_info() -> (HashMap<String, CpuInfo>, HashMap<String, TargetFeature>) {
let mut cpus = HashMap::new();
for name in ["generic-rv64", "generic-rv32", "sifive-u74", "sifive-e76"] {
cpus.insert(
name.to_string(),
CpuInfo {
name: name.to_string(),
features: HashSet::new(),
tuning_cpu: None,
},
);
}
let mut feats = HashMap::new();
for (name, desc, default) in [
("m", "Multiply/Divide", true),
("a", "Atomic", true),
("f", "Single FP", true),
("d", "Double FP", true),
("c", "Compressed", true),
("v", "Vector", false),
("zbb", "Bit-Manip", false),
("zbc", "Carry-less", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
(cpus, feats)
}
pub fn has_cpu(&self, name: &str) -> bool {
self.supported_cpus.contains_key(name)
}
pub fn get_cpu(&self, name: &str) -> Option<&CpuInfo> {
self.supported_cpus.get(name)
}
pub fn enable_feature(&mut self, name: &str) {
self.features.insert(name.to_string(), true);
}
pub fn disable_feature(&mut self, name: &str) {
self.features.insert(name.to_string(), false);
}
pub fn has_feature(&self, name: &str) -> bool {
self.features.get(name).copied().unwrap_or(false)
}
pub fn parse_feature_string(&mut self, s: &str) {
for part in s.split(',') {
let part = part.trim();
if part.is_empty() {
continue;
}
if let Some(feat) = part.strip_prefix('+') {
self.enable_feature(feat);
} else if let Some(feat) = part.strip_prefix('-') {
self.disable_feature(feat);
}
}
}
}
impl Default for TargetInfo {
fn default() -> Self {
Self::from_triple(Triple::default())
}
}
impl fmt::Display for TargetInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Target: {}\nCPU: {}\nFeatures: {:?}\nDL: {}",
self.triple, self.cpu, self.features, self.data_layout
)
}
}
// ═══════════════════════════════════════════════════════════════════════════
// Target Registry
// ═══════════════════════════════════════════════════════════════════════════
pub struct TargetRegistry {
targets: HashMap<String, TargetInfo>,
}
impl TargetRegistry {
pub fn new() -> Self {
Self {
targets: HashMap::new(),
}
}
pub fn register(&mut self, info: TargetInfo) {
self.targets.insert(info.triple.to_string(), info);
}
pub fn lookup(&self, triple: &str) -> Option<&TargetInfo> {
self.targets.get(triple)
}
pub fn target_count(&self) -> usize {
self.targets.len()
}
pub fn default_targets() -> Self {
let mut reg = Self::new();
for t in [
"x86_64-unknown-linux-gnu",
"aarch64-unknown-linux-gnu",
"armv7-unknown-linux-gnueabihf",
"riscv64-unknown-linux-gnu",
"x86_64-pc-windows-msvc",
] {
reg.register(TargetInfo::from_triple(Triple::parse(t)));
}
reg
}
}
// ═══════════════════════════════════════════════════════════════════════════
// TargetRegistry Extensions — register, lookup by arch, iteration
// ═══════════════════════════════════════════════════════════════════════════
impl TargetRegistry {
/// Register a target by its arch name (not triple).
pub fn register_target(&mut self, arch: &str, info: TargetInfo) {
self.targets.insert(arch.to_string(), info);
}
/// Look up a target by architecture name.
pub fn lookup_target(&self, arch: &str) -> Option<&TargetInfo> {
self.targets.get(arch)
}
/// Return the number of registered targets.
pub fn get_target_count(&self) -> usize {
self.targets.len()
}
/// Iterate over all registered targets, calling `f` for each.
pub fn for_each_target<F: FnMut(&TargetInfo)>(&self, mut f: F) {
for info in self.targets.values() {
f(info);
}
}
/// Check if a target with the given arch name exists.
pub fn has_target(&self, arch: &str) -> bool {
self.targets.contains_key(arch)
}
}
// ═══════════════════════════════════════════════════════════════════════════
// ABI Detection — getDefaultABI, getABIName, EH/Debug/COMDAT support
// ═══════════════════════════════════════════════════════════════════════════
/// Get the default ABI for a given OS and architecture combination.
pub fn get_default_abi(os: OS, arch: Arch) -> ABIInfo {
match (arch, os) {
(Arch::X86_64, OS::Win32) => ABIInfo::x86_64_windows(),
(Arch::X86_64, _) => ABIInfo::x86_64_linux(),
(Arch::X86, OS::Win32) => ABIInfo {
pointer_size: 32, size_t_size: 32, stack_alignment: 64,
int_reg_width: 32, char_is_signed: true,
wchar_is_32bit: false, long_double_is_128: false,
},
(Arch::X86, _) => ABIInfo {
pointer_size: 32, size_t_size: 32, stack_alignment: 64,
int_reg_width: 32, char_is_signed: true,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::AArch64, OS::IOS) | (Arch::AArch64, OS::TvOS) | (Arch::AArch64, OS::WatchOS) => ABIInfo {
pointer_size: 64, size_t_size: 64, stack_alignment: 128,
int_reg_width: 64, char_is_signed: false,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::AArch64, _) => ABIInfo::aarch64_linux(),
(Arch::AArch64_32, _) => ABIInfo {
pointer_size: 32, size_t_size: 32, stack_alignment: 128,
int_reg_width: 64, char_is_signed: false,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::ARM, OS::Win32) => ABIInfo {
pointer_size: 32, size_t_size: 32, stack_alignment: 64,
int_reg_width: 32, char_is_signed: false,
wchar_is_32bit: false, long_double_is_128: false,
},
(Arch::ARM, _) => ABIInfo::arm32_linux(),
(Arch::Thumb, _) => ABIInfo {
pointer_size: 32, size_t_size: 32, stack_alignment: 64,
int_reg_width: 32, char_is_signed: false,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::RISCV64, _) => ABIInfo::riscv64_linux(),
(Arch::RISCV32, _) => ABIInfo::riscv32_linux(),
(Arch::WebAssembly32 | Arch::WebAssembly64, _) => ABIInfo::wasm32(),
(Arch::PowerPC64, _) => ABIInfo {
pointer_size: 64, size_t_size: 64, stack_alignment: 128,
int_reg_width: 64, char_is_signed: false,
wchar_is_32bit: true, long_double_is_128: true,
},
(Arch::PowerPC64le, _) => ABIInfo {
pointer_size: 64, size_t_size: 64, stack_alignment: 128,
int_reg_width: 64, char_is_signed: false,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::PowerPC, _) => ABIInfo {
pointer_size: 32, size_t_size: 32, stack_alignment: 64,
int_reg_width: 32, char_is_signed: false,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::SystemZ, _) => ABIInfo {
pointer_size: 64, size_t_size: 64, stack_alignment: 64,
int_reg_width: 64, char_is_signed: true,
wchar_is_32bit: true, long_double_is_128: true,
},
(Arch::Mips64 | Arch::Mips64el, _) => ABIInfo {
pointer_size: 64, size_t_size: 64, stack_alignment: 128,
int_reg_width: 64, char_is_signed: true,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::Mips | Arch::Mipsel, _) => ABIInfo {
pointer_size: 32, size_t_size: 32, stack_alignment: 64,
int_reg_width: 32, char_is_signed: true,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::Sparcv9, _) => ABIInfo {
pointer_size: 64, size_t_size: 64, stack_alignment: 128,
int_reg_width: 64, char_is_signed: true,
wchar_is_32bit: true, long_double_is_128: true,
},
(Arch::Sparc, _) => ABIInfo {
pointer_size: 32, size_t_size: 32, stack_alignment: 64,
int_reg_width: 32, char_is_signed: true,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::BPF | Arch::BPFEB | Arch::BPF64, _) => ABIInfo {
pointer_size: 64, size_t_size: 64, stack_alignment: 8,
int_reg_width: 64, char_is_signed: true,
wchar_is_32bit: false, long_double_is_128: false,
},
(Arch::Hexagon, _) => ABIInfo {
pointer_size: 32, size_t_size: 32, stack_alignment: 64,
int_reg_width: 32, char_is_signed: true,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::AVR, _) => ABIInfo {
pointer_size: 16, size_t_size: 16, stack_alignment: 8,
int_reg_width: 8, char_is_signed: true,
wchar_is_32bit: false, long_double_is_128: false,
},
(Arch::MSP430, _) => ABIInfo {
pointer_size: 16, size_t_size: 16, stack_alignment: 8,
int_reg_width: 16, char_is_signed: true,
wchar_is_32bit: false, long_double_is_128: false,
},
(Arch::Lanai, _) => ABIInfo {
pointer_size: 32, size_t_size: 32, stack_alignment: 64,
int_reg_width: 32, char_is_signed: true,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::NVPTX | Arch::NVPTX64, _) => ABIInfo {
pointer_size: 64, size_t_size: 64, stack_alignment: 16,
int_reg_width: 64, char_is_signed: true,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::AMDGPU, _) => ABIInfo {
pointer_size: 64, size_t_size: 64, stack_alignment: 256,
int_reg_width: 32, char_is_signed: true,
wchar_is_32bit: false, long_double_is_128: false,
},
(Arch::ARC, _) => ABIInfo {
pointer_size: 32, size_t_size: 32, stack_alignment: 64,
int_reg_width: 32, char_is_signed: true,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::CSKY, _) => ABIInfo {
pointer_size: 32, size_t_size: 32, stack_alignment: 64,
int_reg_width: 32, char_is_signed: true,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::Xtensa, _) => ABIInfo {
pointer_size: 32, size_t_size: 32, stack_alignment: 64,
int_reg_width: 32, char_is_signed: true,
wchar_is_32bit: true, long_double_is_128: false,
},
(Arch::LoongArch64, _) => ABIInfo {
pointer_size: 64, size_t_size: 64, stack_alignment: 128,
int_reg_width: 64, char_is_signed: true,
wchar_is_32bit: true, long_double_is_128: true,
},
(Arch::VE, _) => ABIInfo {
pointer_size: 64, size_t_size: 64, stack_alignment: 128,
int_reg_width: 64, char_is_signed: true,
wchar_is_32bit: true, long_double_is_128: true,
},
_ => ABIInfo::x86_64_linux(),
}
}
/// Return a human-readable ABI name for the given OS + arch combination.
pub fn get_abi_name(os: OS, arch: Arch) -> &'static str {
match (arch, os) {
(Arch::X86_64, OS::Win32) => "Windows x64",
(Arch::X86_64, OS::Linux) => "System V AMD64",
(Arch::X86_64, OS::Darwin) | (Arch::X86_64, OS::MacOSX) => "Apple x86-64",
(Arch::AArch64, OS::Linux) => "AAPCS64",
(Arch::AArch64, OS::Darwin) | (Arch::AArch64, OS::MacOSX) => "Apple ARM64",
(Arch::AArch64, OS::IOS) => "iOS ARM64",
(Arch::ARM, OS::Linux) => "AAPCS",
(Arch::ARM, OS::Win32) => "Windows ARM",
(Arch::Thumb, _) => "AAPCS (Thumb)",
(Arch::RISCV64, _) => "LP64D",
(Arch::RISCV32, _) => "ILP32D",
(Arch::PowerPC64, _) => "ELFv1",
(Arch::PowerPC64le, _) => "ELFv2",
(Arch::SystemZ, _) => "s390x-abi",
(_, OS::Win32) => "Windows",
_ => "Generic",
}
}
/// Check whether exception handling is supported on the given target.
pub fn supports_eh(os: OS, arch: Arch) -> bool {
match arch {
Arch::X86_64 | Arch::X86 | Arch::AArch64 | Arch::ARM | Arch::Thumb
| Arch::PowerPC64 | Arch::PowerPC64le | Arch::PowerPC
| Arch::SystemZ | Arch::Mips64 | Arch::Mips64el | Arch::Mips | Arch::Mipsel
| Arch::RISCV64 | Arch::RISCV32 | Arch::LoongArch64 | Arch::Sparcv9
| Arch::Sparc => match os {
OS::Win32 | OS::Linux | OS::Darwin | OS::MacOSX | OS::FreeBSD
| OS::NetBSD | OS::OpenBSD | OS::DragonFly
| OS::Fuchsia | OS::Haiku => true,
_ => false,
},
_ => false,
}
}
/// Check whether debug information is supported on the given target.
pub fn supports_debug(os: OS, arch: Arch) -> bool {
match arch {
Arch::Unknown | Arch::MSP430 | Arch::BPF | Arch::BPFEB | Arch::BPF64 => false,
_ => match os {
OS::NaCl | OS::Emscripten => false,
_ => true,
},
}
}
/// Check whether COMDAT sections are supported on the given target.
pub fn supports_comdat(os: OS, _arch: Arch) -> bool {
match os {
OS::Win32 | OS::Linux | OS::Darwin | OS::MacOSX | OS::FreeBSD
| OS::NetBSD | OS::OpenBSD | OS::DragonFly | OS::Fuchsia => true,
_ => false,
}
}
// ═══════════════════════════════════════════════════════════════════════════
// Host CPU Detection — getHostCPUName, detectHostCPUFeatures
// ═══════════════════════════════════════════════════════════════════════════
/// Detect the host CPU name by reading /proc/cpuinfo (Linux) or sysctl (macOS).
/// Returns a best-effort string like "x86-64-v3", "apple-m2", "cortex-a76".
pub fn get_host_cpu_name() -> Option<String> {
#[cfg(target_arch = "x86_64")]
{
if let Ok(data) = std::fs::read_to_string("/proc/cpuinfo") {
let mut has_avx2 = false;
let mut has_avx512f = false;
let mut has_avx512bw = false;
for line in data.lines() {
let line_lower = line.to_lowercase();
if line_lower.contains("flags") {
let flags = line_lower.split(':').nth(1).unwrap_or("");
for flag in flags.split_whitespace() {
match flag {
"avx512f" => has_avx512f = true,
"avx512bw" => has_avx512bw = true,
"avx2" => has_avx2 = true,
_ => {}
}
}
}
if let Some(model) = line.strip_prefix("model name") {
let cpu = model.split(':').nth(1).unwrap_or("").trim();
return Some(cpu.to_string());
}
}
if has_avx512f && has_avx512bw {
return Some("x86-64-v4".to_string());
} else if has_avx2 {
return Some("x86-64-v3".to_string());
}
}
}
#[cfg(target_arch = "aarch64")]
{
if let Ok(data) = std::fs::read_to_string("/proc/cpuinfo") {
for line in data.lines() {
if let Some(part) = line.strip_prefix("CPU part") {
let part_trim = part.split(':').nth(1).unwrap_or("").trim();
return Some(format!("cortex-a{}", part_trim));
}
}
}
#[cfg(target_os = "macos")]
{
use std::process::Command;
if let Ok(output) = Command::new("sysctl").args(["-n", "machdep.cpu.brand_string"]).output() {
if let Ok(s) = String::from_utf8(output.stdout) {
let s = s.trim();
if s.contains("M1") { return Some("apple-m1".to_string()); }
if s.contains("M2") { return Some("apple-m2".to_string()); }
if s.contains("M3") { return Some("apple-m3".to_string()); }
if s.contains("M4") { return Some("apple-m4".to_string()); }
return Some(s.to_string());
}
}
}
}
#[cfg(target_arch = "riscv64")]
{
if let Ok(data) = std::fs::read_to_string("/proc/cpuinfo") {
for line in data.lines() {
if line.starts_with("uarch") || line.starts_with("mvendorid") {
if line.contains("sifive") { return Some("sifive-u74".to_string()); }
if line.contains("thead") { return Some("c910".to_string()); }
}
}
}
}
None
}
/// Detect host CPU features based on the current architecture.
pub fn detect_host_cpu_features() -> HashSet<String> {
let mut features = HashSet::new();
#[cfg(target_arch = "x86_64")]
{
if let Ok(data) = std::fs::read_to_string("/proc/cpuinfo") {
for line in data.lines() {
if line.to_lowercase().contains("flags") {
if let Some(flags) = line.split(':').nth(1) {
for flag in flags.split_whitespace() {
features.insert(flag.to_string());
}
}
}
}
}
}
#[cfg(target_arch = "aarch64")]
{
if let Ok(data) = std::fs::read_to_string("/proc/cpuinfo") {
for line in data.lines() {
if line.to_lowercase().contains("features") {
if let Some(flags) = line.split(':').nth(1) {
for flag in flags.split_whitespace() {
features.insert(flag.to_string());
}
}
}
}
}
}
#[cfg(target_arch = "riscv64")]
{
if let Ok(data) = std::fs::read_to_string("/proc/cpuinfo") {
for line in data.lines() {
if line.starts_with("isa") {
if let Some(isa_str) = line.split(':').nth(1) {
let isa = isa_str.trim();
for ch in isa.chars().skip(2) {
match ch {
'm' => { features.insert("m".to_string()); }
'a' => { features.insert("a".to_string()); }
'f' => { features.insert("f".to_string()); }
'd' => { features.insert("d".to_string()); }
'c' => { features.insert("c".to_string()); }
'v' => { features.insert("v".to_string()); }
_ => {}
}
}
}
}
}
}
}
features
}
/// Attempt to map the host CPU name to a known CPU model string.
pub fn map_host_cpu_to_model(name: &str) -> &str {
let lower = name.to_lowercase();
if lower.contains("znver5") || lower.contains("turin") { return "znver5"; }
if lower.contains("znver4") || lower.contains("genoa") { return "znver4"; }
if lower.contains("znver3") || lower.contains("milan") { return "znver3"; }
if lower.contains("znver2") || lower.contains("rome") { return "znver2"; }
if lower.contains("znver1") || lower.contains("naples") { return "znver1"; }
if lower.contains("sapphirerapids") || lower.contains("sapphire rapids") { return "sapphirerapids"; }
if lower.contains("graniterapids") || lower.contains("granite rapids") { return "graniterapids"; }
if lower.contains("icelake") || lower.contains("ice lake") { return "icelake-server"; }
if lower.contains("cascadelake") { return "cascadelake"; }
if lower.contains("skylake") || lower.contains("sky lake") { return "skylake"; }
if lower.contains("alderlake") || lower.contains("alder lake") { return "alderlake"; }
if lower.contains("raptorlake") || lower.contains("raptor lake") { return "raptorlake"; }
if lower.contains("meteorlake") || lower.contains("meteor lake") { return "meteorlake"; }
if lower.contains("haswell") { return "haswell"; }
if lower.contains("broadwell") { return "broadwell"; }
if lower.contains("sandybridge") || lower.contains("sandy bridge") { return "sandybridge"; }
if lower.contains("ivybridge") || lower.contains("ivy bridge") { return "ivybridge"; }
if lower.contains("nehalem") { return "nehalem"; }
if lower.contains("westmere") { return "westmere"; }
if lower.contains("apple m1") { return "apple-m1"; }
if lower.contains("apple m2") { return "apple-m2"; }
if lower.contains("apple m3") { return "apple-m3"; }
if lower.contains("apple m4") { return "apple-m4"; }
if lower.contains("cortex-a78") { return "cortex-a78"; }
if lower.contains("cortex-a77") { return "cortex-a77"; }
if lower.contains("cortex-a76") { return "cortex-a76"; }
if lower.contains("cortex-a75") { return "cortex-a75"; }
if lower.contains("cortex-a73") { return "cortex-a73"; }
if lower.contains("cortex-a72") { return "cortex-a72"; }
if lower.contains("cortex-a57") { return "cortex-a57"; }
if lower.contains("cortex-a55") { return "cortex-a55"; }
if lower.contains("cortex-a53") { return "cortex-a53"; }
if lower.contains("cortex-x4") { return "cortex-x4"; }
if lower.contains("cortex-x3") { return "cortex-x3"; }
if lower.contains("cortex-x2") { return "cortex-x2"; }
if lower.contains("cortex-x1") { return "cortex-x1"; }
if lower.contains("neoverse-v2") { return "neoverse-v2"; }
if lower.contains("neoverse-v1") { return "neoverse-v1"; }
if lower.contains("neoverse-n2") { return "neoverse-n2"; }
if lower.contains("neoverse-n1") { return "neoverse-n1"; }
if lower.contains("sifive-u74") { return "sifive-u74"; }
if lower.contains("sifive-e76") { return "sifive-e76"; }
if lower.contains("c910") { return "c910"; }
if lower.contains("c906") { return "c906"; }
if lower.contains("c920") { return "c920"; }
name
}
// ═══════════════════════════════════════════════════════════════════════════
// Subtarget Feature String Parsing — parseFeatureString, setFeatureString
// ═══════════════════════════════════════════════════════════════════════════
/// Parse a feature string like "+sse,-avx,+movbe" into a HashMap.
pub fn parse_feature_string(features: &str) -> HashMap<String, bool> {
let mut result = HashMap::new();
for part in features.split(',') {
let part = part.trim();
if part.is_empty() {
continue;
}
if let Some(feat) = part.strip_prefix('+') {
result.insert(feat.to_string(), true);
} else if let Some(feat) = part.strip_prefix('-') {
result.insert(feat.to_string(), false);
} else {
result.insert(part.to_string(), true);
}
}
result
}
/// Set a feature string on a TargetInfo, enabling/disabling features as specified.
pub fn set_feature_string(info: &mut TargetInfo, features: &str) {
let parsed = parse_feature_string(features);
for (name, enabled) in parsed {
info.features.insert(name, enabled);
}
}
/// Verify that a feature string is valid for the given architecture (all features exist).
pub fn validate_feature_string(info: &TargetInfo, features: &str) -> bool {
for part in features.split(',') {
let part = part.trim();
if part.is_empty() {
continue;
}
let feat_name = if part.starts_with('+') || part.starts_with('-') {
&part[1..]
} else {
part
};
if !info.supported_features.contains_key(feat_name) {
return false;
}
}
true
}
/// Expand implied features: for each enabled feature, also enable its dependencies.
pub fn expand_implied_features(info: &mut TargetInfo) {
let mut to_enable: Vec<String> = Vec::new();
for (name, enabled) in &info.features {
if *enabled {
if let Some(feat) = info.supported_features.get(name) {
for implied in &feat.implies {
if !info.features.contains_key(implied) || !info.features.get(implied).copied().unwrap_or(false) {
to_enable.push(implied.clone());
}
}
}
}
}
for feat in to_enable {
info.features.insert(feat, true);
}
}
// ═══════════════════════════════════════════════════════════════════════════
// Complete X86 Feature Table — all ISA extensions
// ═══════════════════════════════════════════════════════════════════════════
/// Build the complete X86 CPU feature table with implications.
pub fn x86_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
let entries: &[(&str, &str, bool, &[&str])] = &[
("mmx", "MMX", false, &[]),
("sse", "SSE", true, &["mmx"]),
("sse2", "SSE2", true, &["sse"]),
("sse3", "SSE3", false, &["sse2"]),
("ssse3", "SSSE3", false, &["sse3"]),
("sse4.1", "SSE4.1", false, &["ssse3"]),
("sse4.2", "SSE4.2", false, &["sse4.1"]),
("avx", "AVX", false, &["sse4.2"]),
("avx2", "AVX2", false, &["avx"]),
("avx512f", "AVX-512 Foundation", false, &["avx2"]),
("avx512bw", "AVX-512 BW", false, &["avx512f"]),
("avx512cd", "AVX-512 CD", false, &["avx512f"]),
("avx512dq", "AVX-512 DQ", false, &["avx512f"]),
("avx512er", "AVX-512 ER", false, &["avx512f"]),
("avx512ifma", "AVX-512 IFMA", false, &["avx512f"]),
("avx512pf", "AVX-512 PF", false, &["avx512f"]),
("avx512vbmi", "AVX-512 VBMI", false, &["avx512bw"]),
("avx512vl", "AVX-512 VL", false, &["avx512f"]),
("avx512bf16", "AVX-512 BF16", false, &["avx512f"]),
("avx512vp2intersect", "AVX-512 VP2INTERSECT", false, &["avx512f"]),
("avx512vnni", "AVX-512 VNNI", false, &["avx512f"]),
("avx512bitalg", "AVX-512 BITALG", false, &["avx512bw"]),
("avx512vbmi2", "AVX-512 VBMI2", false, &["avx512bw"]),
("fma", "FMA3", false, &["avx"]),
("fma4", "FMA4", false, &[]),
("xop", "XOP", false, &["fma4"]),
("f16c", "F16C", false, &["avx"]),
("aes", "AES", false, &["sse2"]),
("pclmul", "PCLMUL", false, &["sse2"]),
("sha", "SHA", false, &["sse2"]),
("sgx", "SGX", false, &[]),
("mwaitx", "MWAITX", false, &[]),
("clflushopt", "CLFLUSHOPT", false, &[]),
("clwb", "CLWB", false, &[]),
("pku", "PKU", false, &[]),
("fsgsbase", "FSGSBASE", false, &[]),
("rdrnd", "RDRND", false, &[]),
("rdseed", "RDSEED", false, &[]),
("bmi", "BMI", false, &[]),
("bmi2", "BMI2", false, &[]),
("tbm", "TBM", false, &[]),
("lzcnt", "LZCNT", false, &[]),
("popcnt", "POPCNT", false, &[]),
("movbe", "MOVBE", false, &[]),
("cx16", "CMPXCHG16B", false, &[]),
("rtm", "RTM", false, &[]),
("hle", "HLE", false, &[]),
("adx", "ADX", false, &[]),
("prefetchwt1", "PREFETCHWT1", false, &[]),
("clzero", "CLZERO", false, &[]),
("rdpru", "RDPRU", false, &[]),
("wbnoinvd", "WBNOINVD", false, &[]),
("cldemote", "CLDEMOTE", false, &[]),
("ptwrite", "PTWRITE", false, &[]),
("waitpkg", "WAITPKG", false, &[]),
("serialize", "SERIALIZE", false, &[]),
("tsxldtrk", "TSXLDTRK", false, &[]),
("uintr", "UINTR", false, &[]),
("cet", "CET", false, &[]),
("kl", "KEYLOCKER", false, &[]),
("widekl", "WIDEKL", false, &[]),
("raoint", "RAOINT", false, &[]),
("cmpccxadd", "CMPCCXADD", false, &[]),
("amx-bf16", "AMX-BF16", false, &[]),
("amx-complex", "AMX-COMPLEX", false, &[]),
("amx-fp16", "AMX-FP16", false, &[]),
("amx-int8", "AMX-INT8", false, &[]),
("amx-tile", "AMX-TILE", false, &[]),
("enqcmd", "ENQCMD", false, &[]),
("gfni", "GFNI", false, &["sse2"]),
("vaes", "VAES", false, &["aes", "avx"]),
("vpclmulqdq", "VPCLMULQDQ", false, &["pclmul", "avx"]),
("avxvnni", "AVX-VNNI", false, &["avx2"]),
("avxifma", "AVX-IFMA", false, &["avx2"]),
("avxneconvert", "AVX-NE-CONVERT", false, &["avx2"]),
("avxvnniint8", "AVX-VNNI-INT8", false, &["avx2"]),
("prefetchi", "PREFETCHI", false, &[]),
("sm3", "SM3", false, &["avx"]),
("sm4", "SM4", false, &["avx"]),
("sha512", "SHA512", false, &["avx"]),
("cmov", "CMOV", true, &[]),
("sahf", "SAHF", true, &[]),
("x87", "x87 FPU", true, &[]),
("prfchw", "PREFETCHW", false, &[]),
("xsave", "XSAVE", true, &[]),
("xsavec", "XSAVEC", false, &["xsave"]),
("xsaves", "XSAVES", false, &["xsavec"]),
("xsaveopt", "XSAVEOPT", false, &["xsave"]),
];
for &(name, desc, default, implies) in entries {
let mut feat = TargetFeature::new(name, desc, default);
feat.implies = implies.iter().map(|s| s.to_string()).collect();
feats.insert(name.to_string(), feat);
}
feats
}
/// Build the complete X86 CPU model table.
pub fn x86_cpu_table() -> HashMap<String, CpuInfo> {
let mut cpus = HashMap::new();
let entries: &[(&str, &[&str])] = &[
("generic", &[]),
("i386", &[]),
("i486", &[]),
("i586", &[]),
("pentium", &[]),
("pentium-mmx", &["mmx"]),
("i686", &["cmov"]),
("pentiumpro", &["cmov"]),
("pentium2", &["mmx", "cmov"]),
("pentium3", &["mmx", "sse", "cmov"]),
("pentium-m", &["mmx", "sse", "sse2", "cmov"]),
("pentium4", &["mmx", "sse", "sse2", "cmov"]),
("pentium4m", &["mmx", "sse", "sse2", "cmov"]),
("prescott", &["mmx", "sse", "sse2", "sse3", "cmov"]),
("nocona", &["mmx", "sse", "sse2", "sse3", "cx16", "cmov"]),
("core2", &["mmx", "sse", "sse2", "sse3", "ssse3", "cx16", "cmov"]),
("penryn", &["mmx", "sse", "sse2", "sse3", "ssse3", "sse4.1", "cx16", "cmov"]),
("nehalem", &["mmx", "sse", "sse2", "sse3", "ssse3", "sse4.1", "sse4.2", "popcnt", "cx16", "cmov"]),
("westmere", &["mmx", "sse", "sse2", "sse3", "ssse3", "sse4.1", "sse4.2", "popcnt", "aes", "pclmul", "cx16", "cmov"]),
("sandybridge", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","aes","pclmul","cx16","cmov"]),
("ivybridge", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","aes","pclmul","f16c","cx16","cmov","rdrnd"]),
("haswell", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd"]),
("broadwell", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","adx"]),
("skylake", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","adx","xsavec","xsaves","clflushopt","sgx"]),
("skylake-avx512", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","avx512f","avx512bw","avx512cd","avx512dq","avx512vl","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","adx","xsavec","xsaves","clflushopt","clwb","pku","sgx"]),
("cannonlake", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","avx512f","avx512bw","avx512cd","avx512dq","avx512vl","avx512vbmi","avx512ifma","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","adx","xsavec","xsaves","clflushopt","clwb","pku","sgx","sha"]),
("icelake-client", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","avx512f","avx512bw","avx512cd","avx512dq","avx512vl","avx512vbmi","avx512ifma","avx512vbmi2","avx512bitalg","avx512vnni","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","adx","xsavec","xsaves","clflushopt","clwb","pku","sgx","sha","gfni","vaes","vpclmulqdq"]),
("icelake-server", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","avx512f","avx512bw","avx512cd","avx512dq","avx512vl","avx512vbmi","avx512ifma","avx512vbmi2","avx512bitalg","avx512vnni","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","adx","xsavec","xsaves","clflushopt","clwb","pku","sgx","sha","gfni","vaes","vpclmulqdq","pconfig","wbnoinvd"]),
("cascadelake", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","avx512f","avx512bw","avx512cd","avx512dq","avx512vl","avx512vnni","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","adx","xsavec","xsaves","clflushopt","clwb","pku","sgx"]),
("cooperlake", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","avx512f","avx512bw","avx512cd","avx512dq","avx512vl","avx512vnni","avx512bf16","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","adx","xsavec","xsaves","clflushopt","clwb","pku","sgx"]),
("tigerlake", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","avx512f","avx512bw","avx512cd","avx512dq","avx512vl","avx512vbmi","avx512ifma","avx512vbmi2","avx512bitalg","avx512vnni","avx512vp2intersect","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","adx","xsavec","xsaves","clflushopt","clwb","pku","sgx","sha","gfni","vaes","vpclmulqdq","movdiri","movdir64b","cldemote","ptwrite","waitpkg","serialize","tsxldtrk"]),
("sapphirerapids", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","avx512f","avx512bw","avx512cd","avx512dq","avx512vl","avx512vbmi","avx512ifma","avx512vbmi2","avx512bitalg","avx512vnni","avx512vp2intersect","avx512bf16","avx512fp16","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","adx","xsavec","xsaves","clflushopt","clwb","pku","sgx","sha","gfni","vaes","vpclmulqdq","cldemote","ptwrite","waitpkg","serialize","tsxldtrk","uintr","enqcmd","amx-bf16","amx-int8","amx-tile"]),
("alderlake", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","adx","xsavec","xsaves","clflushopt","clwb","pku","sgx","sha","gfni","vaes","vpclmulqdq","serialize","cldemote","ptwrite","waitpkg"]),
("raptorlake", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","adx","xsavec","xsaves","clflushopt","clwb","pku","sgx","sha","gfni","vaes","vpclmulqdq","serialize","cldemote","ptwrite","waitpkg"]),
("meteorlake", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","adx","xsavec","xsaves","clflushopt","clwb","pku","sgx","sha","gfni","vaes","vpclmulqdq","serialize","cldemote","ptwrite","waitpkg","avxvnni","avxifma","avxneconvert","avxvnniint8"]),
("graniterapids", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","avx512f","avx512bw","avx512cd","avx512dq","avx512vl","avx512vbmi","avx512ifma","avx512vbmi2","avx512bitalg","avx512vnni","avx512bf16","avx512fp16","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","adx","xsavec","xsaves","clflushopt","clwb","pku","sgx","sha","gfni","vaes","vpclmulqdq","serialize","tsxldtrk","uintr","enqcmd","amx-bf16","amx-int8","amx-tile","amx-fp16","amx-complex","prefetchi"]),
("x86-64", &["mmx","sse","sse2","cmov","x87"]),
("x86-64-v2", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","cx16","cmov","x87"]),
("x86-64-v3", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","avx","avx2","bmi","bmi2","fma","lzcnt","movbe","popcnt","cx16","f16c","cmov","x87"]),
("x86-64-v4", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","avx","avx2","avx512f","avx512bw","avx512cd","avx512dq","avx512vl","bmi","bmi2","fma","lzcnt","movbe","popcnt","cx16","f16c","cmov","x87"]),
("znver1", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","avx","avx2","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","popcnt","movbe","cx16","rdrnd","xsavec","xsaves","clflushopt","clzero","adx","rdseed","sha","cmov","x87","sahf","prfchw"]),
("znver2", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","avx","avx2","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","popcnt","movbe","cx16","rdrnd","xsavec","xsaves","clflushopt","clwb","clzero","adx","rdseed","sha","rdpru","wbnoinvd","cmov","x87","sahf","prfchw"]),
("znver3", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","avx","avx2","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","popcnt","movbe","cx16","rdrnd","xsavec","xsaves","clflushopt","clwb","clzero","adx","rdseed","sha","rdpru","wbnoinvd","cmov","x87","sahf","prfchw","pku","vaes","vpclmulqdq","gfni"]),
("znver4", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","avx","avx2","avx512f","avx512bw","avx512cd","avx512dq","avx512vl","avx512vbmi","avx512ifma","avx512vbmi2","avx512bitalg","avx512vnni","avx512bf16","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","popcnt","movbe","cx16","rdrnd","xsavec","xsaves","clflushopt","clwb","clzero","adx","rdseed","sha","rdpru","wbnoinvd","cmov","x87","sahf","prfchw","pku","vaes","vpclmulqdq","gfni"]),
("znver5", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","avx","avx2","avx512f","avx512bw","avx512cd","avx512dq","avx512vl","avx512vbmi","avx512ifma","avx512vbmi2","avx512bitalg","avx512vnni","avx512bf16","avx512vp2intersect","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","popcnt","movbe","cx16","rdrnd","xsavec","xsaves","clflushopt","clwb","clzero","adx","rdseed","sha","rdpru","wbnoinvd","cmov","x87","sahf","prfchw","pku","vaes","vpclmulqdq","gfni","avx512fp16"]),
("btver1", &["mmx","sse","sse2","sse3","ssse3","sse4.1","avx","aes","pclmul","popcnt","lzcnt","cx16","cmov","x87","sahf","prfchw"]),
("btver2", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","avx","aes","pclmul","bmi","f16c","popcnt","lzcnt","movbe","cx16","cmov","x87","sahf","prfchw","xsave","xsaveopt"]),
("atom", &["mmx","sse","sse2","sse3","ssse3","cx16","cmov","movbe"]),
("silvermont", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","aes","pclmul","cx16","cmov","movbe","rdrnd"]),
("goldmont", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","aes","pclmul","cx16","cmov","movbe","rdrnd","rdseed","sha","xsavec","xsaves","clflushopt"]),
("goldmont-plus", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","aes","pclmul","cx16","cmov","movbe","rdrnd","rdseed","sha","xsavec","xsaves","clflushopt","rdpru"]),
("tremont", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","aes","pclmul","cx16","cmov","movbe","rdrnd","rdseed","sha","xsavec","xsaves","clflushopt","clwb","rdpru","gfni","cldemote","waitpkg"]),
("sierraforest", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","avxifma","avxneconvert","avxvnni","avxvnniint8","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","sha","xsavec","xsaves","clflushopt","clwb","rdpru","gfni","vaes","vpclmulqdq","cldemote","waitpkg","serialize","prefetchi"]),
("grandridge", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","avxifma","avxneconvert","avxvnni","avxvnniint8","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","sha","xsavec","xsaves","clflushopt","clwb","rdpru","gfni","vaes","vpclmulqdq","cldemote","waitpkg","serialize","prefetchi"]),
("clearwaterforest", &["mmx","sse","sse2","sse3","ssse3","sse4.1","sse4.2","popcnt","avx","avx2","avxifma","avxneconvert","avxvnni","avxvnniint8","avx512f","avx512bw","avx512cd","avx512dq","avx512vl","aes","pclmul","fma","f16c","bmi","bmi2","lzcnt","movbe","cx16","cmov","rdrnd","rdseed","sha","xsavec","xsaves","clflushopt","clwb","rdpru","gfni","vaes","vpclmulqdq","cldemote","waitpkg","serialize","prefetchi"]),
("lakemont", &["cmov"]),
];
for &(name, feats) in entries {
cpus.insert(
name.to_string(),
CpuInfo {
name: name.to_string(),
features: feats.iter().map(|s| s.to_string()).collect(),
tuning_cpu: None,
},
);
}
cpus
}
// ═══════════════════════════════════════════════════════════════════════════
// ARM Feature Table — NEON, VFP, Crypto, SVE, SME, etc.
// ═══════════════════════════════════════════════════════════════════════════
pub fn arm_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
let entries: &[(&str, &str, bool, &[&str])] = &[
("vfp2", "VFPv2", false, &[]),
("vfp3", "VFPv3", false, &["vfp2"]),
("vfp4", "VFPv4", false, &["vfp3"]),
("fp-armv8", "FP ARMv8", false, &["vfp4"]),
("neon", "NEON", true, &["vfp3"]),
("v8a", "ARMv8-A", true, &[]),
("v8.1a", "ARMv8.1-A", false, &["v8a"]),
("v8.2a", "ARMv8.2-A", false, &["v8.1a"]),
("v8.3a", "ARMv8.3-A", false, &["v8.2a"]),
("v8.4a", "ARMv8.4-A", false, &["v8.3a"]),
("v8.5a", "ARMv8.5-A", false, &["v8.4a"]),
("v8.6a", "ARMv8.6-A", false, &["v8.5a"]),
("v8.7a", "ARMv8.7-A", false, &["v8.6a"]),
("v8.8a", "ARMv8.8-A", false, &["v8.7a"]),
("v8.9a", "ARMv8.9-A", false, &["v8.8a"]),
("v9a", "ARMv9-A", false, &["v8.5a"]),
("v9.1a", "ARMv9.1-A", false, &["v8.6a"]),
("v9.2a", "ARMv9.2-A", false, &["v8.7a"]),
("v9.3a", "ARMv9.3-A", false, &["v8.8a"]),
("v9.4a", "ARMv9.4-A", false, &["v8.9a"]),
("crypto", "Crypto", false, &["neon"]),
("crc", "CRC", false, &[]),
("ras", "RAS", false, &[]),
("lse", "LSE", false, &[]),
("fp16", "FP16", false, &["fp-armv8"]),
("fullfp16", "Full FP16", false, &["fp16"]),
("fp16fml", "FP16 FML", false, &["fp16"]),
("dotprod", "Dot Product", false, &["neon"]),
("rcpc", "RCPC", false, &[]),
("rcpc2", "RCPC2", false, &["rcpc"]),
("sb", "SB", false, &[]),
("ssbs", "SSBS", false, &[]),
("bti", "BTI", false, &[]),
("pauth", "PAuth", false, &[]),
("mte", "MTE", false, &[]),
("sve", "SVE", false, &["neon"]),
("sve2", "SVE2", false, &["sve"]),
("sme", "SME", false, &["sve2"]),
("sme2", "SME2", false, &["sme"]),
("i8mm", "I8MM", false, &["neon"]),
("f32mm", "F32MM", false, &["sve"]),
("f64mm", "F64MM", false, &["sve"]),
("bf16", "BF16", false, &["neon"]),
("sve-bf16", "SVE-BF16", false, &["sve", "bf16"]),
("sme-f64f64", "SME-F64F64", false, &["sme"]),
("sme-i16i64", "SME-I16I64", false, &["sme"]),
("tme", "TME", false, &[]),
("memtag", "MemTag", false, &[]),
("mops", "MOPS", false, &[]),
("hbc", "HBC", false, &[]),
("wfxt", "WFxT", false, &[]),
("dit", "DIT", false, &[]),
("jscvt", "JSCVT", false, &[]),
("fcma", "FCMA", false, &["neon"]),
("rdm", "RDM", false, &["neon"]),
("sha2", "SHA2", false, &["neon"]),
("sha3", "SHA3", false, &["neon"]),
("sm3", "SM3", false, &["neon"]),
("sm4", "SM4", false, &["neon"]),
("aes", "AES", false, &["neon"]),
("pmull", "PMULL", false, &["neon"]),
("d128", "128-bit D", false, &[]),
("nopauth", "No PAuth", false, &[]),
("nomte", "No MTE", false, &[]),
("strict-align", "Strict Align", false, &[]),
("reserve-x18", "Reserve X18", false, &[]),
];
for &(name, desc, default, implies) in entries {
let mut feat = TargetFeature::new(name, desc, default);
feat.implies = implies.iter().map(|s| s.to_string()).collect();
feats.insert(name.to_string(), feat);
}
feats
}
pub fn arm_cpu_table() -> HashMap<String, CpuInfo> {
let mut cpus = HashMap::new();
let entries: &[(&str, &[&str])] = &[
("generic", &["neon","v8a","fp-armv8"]),
("cortex-a35", &["neon","v8a","crc","crypto","fp-armv8"]),
("cortex-a53", &["neon","v8a","crc","crypto","fp-armv8"]),
("cortex-a55", &["neon","v8.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc"]),
("cortex-a57", &["neon","v8a","crc","crypto","fp-armv8"]),
("cortex-a65", &["neon","v8.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs"]),
("cortex-a65ae", &["neon","v8.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs"]),
("cortex-a72", &["neon","v8a","crc","crypto","fp-armv8"]),
("cortex-a73", &["neon","v8a","crc","crypto","fp-armv8"]),
("cortex-a75", &["neon","v8.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc"]),
("cortex-a76", &["neon","v8.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs"]),
("cortex-a76ae", &["neon","v8.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs"]),
("cortex-a77", &["neon","v8.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs"]),
("cortex-a78", &["neon","v8.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs"]),
("cortex-a78c", &["neon","v8.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs"]),
("cortex-a510", &["neon","v9a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","i8mm","bf16","sve2"]),
("cortex-a520", &["neon","v9.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","i8mm","bf16","sve2"]),
("cortex-a710", &["neon","v9a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","i8mm","bf16","sve2"]),
("cortex-a715", &["neon","v9a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","i8mm","bf16","sve2"]),
("cortex-a720", &["neon","v9.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","i8mm","bf16","sve2"]),
("cortex-x1", &["neon","v8.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs"]),
("cortex-x2", &["neon","v9a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","i8mm","bf16","sve2"]),
("cortex-x3", &["neon","v9a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","i8mm","bf16","sve2"]),
("cortex-x4", &["neon","v9.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","i8mm","bf16","sve2"]),
("neoverse-n1", &["neon","v8.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs"]),
("neoverse-n2", &["neon","v9a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","i8mm","bf16","sve2"]),
("neoverse-v1", &["neon","v8.4a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","i8mm","bf16","sve"]),
("neoverse-v2", &["neon","v9a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","i8mm","bf16","sve2"]),
("apple-m1", &["neon","v8.5a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","lse","fp16fml"]),
("apple-m2", &["neon","v8.6a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","lse","fp16fml","i8mm","bf16"]),
("apple-m3", &["neon","v8.6a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","lse","fp16fml","i8mm","bf16"]),
("apple-m4", &["neon","v9.2a","crc","crypto","fp-armv8","dotprod","fp16","rcpc","ssbs","bti","pauth","lse","fp16fml","i8mm","bf16","sme"]),
];
for &(name, feats) in entries {
cpus.insert(name.to_string(), CpuInfo {
name: name.to_string(),
features: feats.iter().map(|s| s.to_string()).collect(),
tuning_cpu: None,
});
}
cpus
}
// ═══════════════════════════════════════════════════════════════════════════
// RISC-V Feature Table
// ═══════════════════════════════════════════════════════════════════════════
pub fn riscv_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
let entries: &[(&str, &str, bool, &[&str])] = &[
("m", "Multiply/Divide", true, &[]),
("a", "Atomic", true, &[]),
("f", "Single-Precision FP", true, &[]),
("d", "Double-Precision FP", true, &["f"]),
("c", "Compressed Instructions", true, &[]),
("v", "Vector Extension (RVV 1.0)", false, &["d"]),
("zba", "Address Generation", false, &[]),
("zbb", "Basic Bit-Manipulation", false, &[]),
("zbc", "Carry-less Multiplication", false, &[]),
("zbs", "Single-Bit Instructions", false, &[]),
("zbkb", "Bit-Manipulation for Crypto", false, &["zbb"]),
("zbkc", "Carry-less for Crypto", false, &["zbc"]),
("zbkx", "Crossbar Permutation", false, &[]),
("zfh", "Half-Precision FP", false, &["f"]),
("zfhmin", "Minimal Half-Precision FP", false, &["f"]),
("zicbom", "Cache Block Operation Management", false, &[]),
("zicboz", "Cache Block Zero", false, &[]),
("zicbop", "Cache Block Operation Prefetch", false, &[]),
("zicond", "Integer Conditional Operations", false, &[]),
("zk", "Standard Scalar Crypto", false, &[]),
("zkn", "NIST Suite", false, &["zk"]),
("zknd", "NIST Suite: AES Decrypt", false, &["zkn"]),
("zkne", "NIST Suite: AES Encrypt", false, &["zkn"]),
("zknh", "NIST Suite: SHA256 Hash", false, &["zkn"]),
("zks", "ShangMi Suite", false, &["zk"]),
("zksed", "ShangMi: SM4 Encrypt/Decrypt", false, &["zks"]),
("zksh", "ShangMi: SM3 Hash", false, &["zks"]),
("zkr", "Entropy Source", false, &["zk"]),
("zkt", "Data Independent Execution Latency", false, &[]),
("zvbb", "Vector Bit-Manipulation", false, &["v","zbb"]),
("zvbc", "Vector Carry-less", false, &["v","zbc"]),
("zvkg", "Vector GCM", false, &["v"]),
("zvkn", "Vector NIST Suite", false, &["v"]),
("zvkned", "Vector AES", false, &["zvkn"]),
("zvknh", "Vector SHA", false, &["zvkn"]),
("zvks", "Vector ShangMi", false, &["v"]),
("zvksed", "Vector SM4", false, &["zvks"]),
("zvksh", "Vector SM3", false, &["zvks"]),
("zvfh", "Vector FP16", false, &["v","zfh"]),
("zve32f", "Vector 32-bit FP", false, &["f"]),
("zve32x", "Vector 32-bit Integer", false, &[]),
("zve64d", "Vector 64-bit DP", false, &["d"]),
("zve64f", "Vector 64-bit FP", false, &["f"]),
("zve64x", "Vector 64-bit Integer", false, &[]),
("zvl32b", "Vector Length 32", false, &[]),
("zvl64b", "Vector Length 64", false, &[]),
("zvl128b", "Vector Length 128", false, &[]),
("zvl256b", "Vector Length 256", false, &[]),
("zvl512b", "Vector Length 512", false, &[]),
("zvl1024b", "Vector Length 1024", false, &[]),
("zvl2048b", "Vector Length 2048", false, &[]),
("zvl4096b", "Vector Length 4096", false, &[]),
("zvl8192b", "Vector Length 8192", false, &[]),
("zvl16384b", "Vector Length 16384", false, &[]),
("zvl32768b", "Vector Length 32768", false, &[]),
("zvl65536b", "Vector Length 65536", false, &[]),
("zawrs", "Wait-on-Reservation-Set", false, &[]),
("zfa", "Additional FP", false, &["f"]),
("ztso", "Total Store Ordering", false, &[]),
("zicfilp", "Forward-edge CFI", false, &[]),
("zicfiss", "Shadow Stack", false, &[]),
("svinval", "Invalidate by Virtual Address", false, &[]),
("svnapot", "NAPOT Translation Continuity", false, &[]),
("svpbmt", "Page-Based Memory Types", false, &[]),
("h", "Hypervisor", false, &[]),
("xcvbitmanip", "Bitmanip", false, &[]),
("xcvmac", "MAC ops", false, &[]),
("xcvsimd", "SIMD ops", false, &[]),
("xtheadba", "T-Head BA", false, &[]),
("xtheadbb", "T-Head BB", false, &[]),
("xtheadbs", "T-Head BS", false, &[]),
("xtheadcmo", "T-Head CMO", false, &[]),
("xtheadcondmov", "T-Head CondMov", false, &[]),
("xtheadfmemidx", "T-Head FMemIdx", false, &[]),
("xtheadmac", "T-Head MAC", false, &[]),
("xtheadmemidx", "T-Head MemIdx", false, &[]),
("xtheadmempair", "T-Head MemPair", false, &[]),
("xtheadsync", "T-Head Sync", false, &[]),
("xtheadvector", "T-Head Vector", false, &[]),
("xtheadvdot", "T-Head VDot", false, &[]),
];
for &(name, desc, default, implies) in entries {
let mut feat = TargetFeature::new(name, desc, default);
feat.implies = implies.iter().map(|s| s.to_string()).collect();
feats.insert(name.to_string(), feat);
}
feats
}
pub fn riscv_cpu_table() -> HashMap<String, CpuInfo> {
let mut cpus = HashMap::new();
let entries: &[(&str, &[&str])] = &[
("generic-rv32", &["m","a","f","d","c"]),
("generic-rv64", &["m","a","f","d","c"]),
("sifive-e20", &["m","c"]),
("sifive-e21", &["m","a","c"]),
("sifive-e24", &["m","a","c"]),
("sifive-e31", &["m","a","c"]),
("sifive-e34", &["m","a","c"]),
("sifive-e76", &["m","a","f","d","c"]),
("sifive-s21", &["m","a","c"]),
("sifive-s51", &["m","a","c"]),
("sifive-s54", &["m","a","f","d","c"]),
("sifive-s76", &["m","a","f","d","c"]),
("sifive-u54", &["m","a","f","d","c"]),
("sifive-u74", &["m","a","f","d","c"]),
("c910", &["m","a","f","d","c","zba","zbb","zbc","zbs"]),
("c906", &["m","a","f","d","c"]),
("c920", &["m","a","f","d","c","zba","zbb","zbc","zbs","v"]),
("c908", &["m","a","f","d","c","zba","zbb","zbc","zbs","v"]),
("xiangshan-nanhu", &["m","a","f","d","c","zba","zbb","zbc","zbs","v"]),
("spacemit-x60", &["m","a","f","d","c","zba","zbb","zbc","zbs","v"]),
("ventana-vt1", &["m","a","f","d","c","zba","zbb","zbc","zbs"]),
];
for &(name, feats) in entries {
cpus.insert(name.to_string(), CpuInfo {
name: name.to_string(),
features: feats.iter().map(|s| s.to_string()).collect(),
tuning_cpu: None,
});
}
cpus
}
// ═══════════════════════════════════════════════════════════════════════════
// MIPS, PowerPC, SystemZ, Sparc, BPF Feature Tables
// ═══════════════════════════════════════════════════════════════════════════
pub fn mips_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("mips1", "MIPS I", true),
("mips2", "MIPS II", false),
("mips3", "MIPS III", false),
("mips4", "MIPS IV", false),
("mips5", "MIPS V", false),
("mips32", "MIPS32", true),
("mips32r2", "MIPS32r2", false),
("mips32r3", "MIPS32r3", false),
("mips32r5", "MIPS32r5", false),
("mips32r6", "MIPS32r6", false),
("mips64", "MIPS64", false),
("mips64r2", "MIPS64r2", false),
("mips64r3", "MIPS64r3", false),
("mips64r5", "MIPS64r5", false),
("mips64r6", "MIPS64r6", false),
("cnmips", "Octeon", false),
("cnmipsp", "Octeon+", false),
("micromips", "microMIPS", false),
("mips16", "MIPS16", false),
("dsp", "DSP", false),
("dspr2", "DSP r2", false),
("msa", "MSA", false),
("virt", "Virtualization", false),
("ginv", "GINV", false),
("crc", "CRC", false),
("eve", "EVE", false),
("nooddspreg", "No Odd SP Reg", false),
("nomicromips", "No microMIPS", false),
("nomips16", "No MIPS16", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
pub fn powerpc_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("altivec", "AltiVec", false),
("vsx", "VSX", false),
("power8-vector", "POWER8 Vector", false),
("power9-vector", "POWER9 Vector", false),
("power10-vector", "POWER10 Vector", false),
("htm", "HTM", false),
("spe", "SPE", false),
("efpu", "EFPU", false),
("fpu", "FPU", true),
("hard-float", "Hard Float", true),
("soft-float", "Soft Float", false),
("quadword-atomics", "Quadword Atomics", false),
("paired-vector-memops", "Paired Vector MemOps", false),
("mma", "MMA", false),
("prefix-instrs", "Prefixed Instructions", false),
("pcrel", "PC-Relative", false),
("rop-protect", "ROP Protection", false),
("privileged", "Privileged", false),
("isell", "ISEL load", false),
("fprnd", "FPRND", false),
("popcntd", "POPCNTD", false),
("direct-move", "Direct Move", false),
("partword-atomics", "Partword Atomics", false),
("predictable-select", "Predictable Select", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
pub fn systemz_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("z10", "z10", false),
("z196", "z196", false),
("zEC12", "zEC12", false),
("z13", "z13", false),
("z14", "z14", false),
("z15", "z15", false),
("z16", "z16", false),
("arch8", "Architecture 8", true),
("arch9", "Architecture 9", false),
("arch10", "Architecture 10", false),
("arch11", "Architecture 11", false),
("arch12", "Architecture 12", false),
("arch13", "Architecture 13", false),
("arch14", "Architecture 14", false),
("vector", "Vector Facility", false),
("vector-enhancements1", "Vector Enhancements 1", false),
("vector-enhancements2", "Vector Enhancements 2", false),
("transactional-execution", "Transactional Execution", false),
("nnp-assist", "NNP Assist", false),
("guarded-storage", "Guarded Storage", false),
("reset-reference-bits-multiple", "Reset Reference Bits", false),
("soft-float", "Soft Float", false),
("dfp", "Decimal FP", false),
("highword", "High Word", false),
("interlocked-access1", "Interlocked Access 1", false),
("population-count", "Population Count", false),
("message-security-assist-extension-3" ,"Msg Security 3", false),
("message-security-assist-extension-4" ,"Msg Security 4", false),
("message-security-assist-extension-5" ,"Msg Security 5", false),
("message-security-assist-extension-7" ,"Msg Security 7", false),
("message-security-assist-extension-8" ,"Msg Security 8", false),
("message-security-assist-extension-9" ,"Msg Security 9", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
pub fn sparc_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("v8", "V8", true),
("v9", "V9", false),
("vis", "VIS", false),
("vis2", "VIS2", false),
("vis3", "VIS3", false),
("vis4", "VIS4", false),
("soft-float", "Soft Float", false),
("hard-float", "Hard Float", true),
("detect-round-change", "Detect Round Change", false),
("no-fmuls", "No FMULS", false),
("no-fsmuld", "No FSMULD", false),
("popc", "POPC", false),
("sub", "SUB", false),
("mul", "MUL", false),
("div", "DIV", false),
("asi", "ASI", false),
("ima", "IMA", false),
("niagara", "Niagara", false),
("niagara2", "Niagara 2", false),
("niagara3", "Niagara 3", false),
("niagara4", "Niagara 4", false),
("leon", "LEON", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
pub fn bpf_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("alu32", "ALU32", false),
("dwarfris", "DwarfRIS", false),
("solana", "Solana", false),
("sdiv", "SDIV", false),
("sdiv_smod", "SDIV/SMOD", false),
("alu32/wrapper", "ALU32 Wrapper", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
// ═══════════════════════════════════════════════════════════════════════════
// AVR, Hexagon, MSP430, NVPTX, AMDGPU, Lanai, WebAssembly Feature Tables
// ═══════════════════════════════════════════════════════════════════════════
pub fn avr_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("avr1", "AVR1", false),
("avr2", "AVR2", false),
("avr25", "AVR25", false),
("avr3", "AVR3", false),
("avr31", "AVR31", false),
("avr35", "AVR35", false),
("avr4", "AVR4", true),
("avr5", "AVR5", false),
("avr51", "AVR51", false),
("avr6", "AVR6", false),
("avrtiny", "AVR Tiny", false),
("xmega", "XMEGA", false),
("xmega2", "XMEGA2", false),
("xmega3", "XMEGA3", false),
("xmega4", "XMEGA4", false),
("xmega5", "XMEGA5", false),
("xmega6", "XMEGA6", false),
("xmega7", "XMEGA7", false),
("mul", "MUL", false),
("jmpcall", "JMP/CALL", false),
("ijmpcall", "IJMP/ICALL", false),
("elpm", "ELPM", false),
("sram", "SRAM", false),
("eijmpcall", "EIJMP/EICALL", false),
("movw", "MOVW", false),
("lpmx", "LPM Rd,Z+", false),
("break", "BREAK", false),
("des", "DES", false),
("spm", "SPM", false),
("spmx", "SPM Z+", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
pub fn hexagon_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("hexagonv5", "Hexagon V5", true),
("hexagonv55", "Hexagon V55", false),
("hexagonv60", "Hexagon V60", false),
("hexagonv62", "Hexagon V62", false),
("hexagonv65", "Hexagon V65", false),
("hexagonv66", "Hexagon V66", false),
("hexagonv67", "Hexagon V67", false),
("hexagonv67t", "Hexagon V67T", false),
("hexagonv68", "Hexagon V68", false),
("hexagonv69", "Hexagon V69", false),
("hexagonv71", "Hexagon V71", false),
("hexagonv73", "Hexagon V73", false),
("hexagonv75", "Hexagon V75", false),
("hvx", "HVX", false),
("hvx-length64b", "HVX 64B", false),
("hvx-length128b", "HVX 128B", false),
("hvx-v66", "HVX V66", false),
("hvx-v67", "HVX V67", false),
("hvx-v68", "HVX V68", false),
("hvx-qfloat", "HVX QFloat", false),
("hvx-ieee-fp", "HVX IEEE FP", false),
("cabac", "CABAC", false),
("audio", "Audio", false),
("compound", "Compound", false),
("noreturnstack", "No Return Stack", false),
("nvscheduling", "No V Scheduling", false),
("packets", "Packets", false),
("duplex", "Duplex", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
pub fn msp430_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("msp430", "MSP430", true),
("msp430x", "MSP430X", false),
("ext", "Extension", false),
("hwmult16", "16-bit HW Multiplier", false),
("hwmult32", "32-bit HW Multiplier", false),
("hwmultf5", "F5 HW Multiplier", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
pub fn nvptx_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("sm_20", "SM 2.0", false),
("sm_21", "SM 2.1", false),
("sm_30", "SM 3.0", true),
("sm_32", "SM 3.2", false),
("sm_35", "SM 3.5", false),
("sm_37", "SM 3.7", false),
("sm_50", "SM 5.0", false),
("sm_52", "SM 5.2", false),
("sm_53", "SM 5.3", false),
("sm_60", "SM 6.0", false),
("sm_61", "SM 6.1", false),
("sm_62", "SM 6.2", false),
("sm_70", "SM 7.0", false),
("sm_72", "SM 7.2", false),
("sm_75", "SM 7.5", false),
("sm_80", "SM 8.0", false),
("sm_86", "SM 8.6", false),
("sm_87", "SM 8.7", false),
("sm_89", "SM 8.9", false),
("sm_90", "SM 9.0", false),
("sm_90a", "SM 9.0a", false),
("sm_100", "SM 10.0", false),
("sm_100a", "SM 10.0a", false),
("sm_120", "SM 12.0", false),
("ptx60", "PTX 6.0", false),
("ptx61", "PTX 6.1", false),
("ptx63", "PTX 6.3", false),
("ptx64", "PTX 6.4", false),
("ptx65", "PTX 6.5", false),
("ptx70", "PTX 7.0", false),
("ptx71", "PTX 7.1", false),
("ptx72", "PTX 7.2", false),
("ptx73", "PTX 7.3", false),
("ptx74", "PTX 7.4", false),
("ptx75", "PTX 7.5", false),
("ptx76", "PTX 7.6", false),
("ptx77", "PTX 7.7", false),
("ptx78", "PTX 7.8", false),
("ptx80", "PTX 8.0", false),
("ptx81", "PTX 8.1", false),
("ptx82", "PTX 8.2", false),
("ptx83", "PTX 8.3", false),
("ptx84", "PTX 8.4", false),
("ptx85", "PTX 8.5", false),
("ptx86", "PTX 8.6", false),
("ptx87", "PTX 8.7", false),
("+ptx", "Generate PTX", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
pub fn amdgpu_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("gfx600", "GFX6.0.0 (Tahiti)", false),
("gfx601", "GFX6.0.1 (Hainan/Pitcairn)", false),
("gfx602", "GFX6.0.2", false),
("gfx700", "GFX7.0.0 (Kaveri)", false),
("gfx701", "GFX7.0.1 (Hawaii)", false),
("gfx702", "GFX7.0.2", false),
("gfx703", "GFX7.0.3 (Kabini/Mullins)", false),
("gfx704", "GFX7.0.4 (Bonaire)", false),
("gfx705", "GFX7.0.5", false),
("gfx801", "GFX8.0.1 (Carrizo)", false),
("gfx802", "GFX8.0.2 (Tonga/Iceland)", false),
("gfx803", "GFX8.0.3 (Fiji/Polaris)", false),
("gfx805", "GFX8.0.5 (TongaPro)", false),
("gfx810", "GFX8.1.0 (Stoney)", false),
("gfx900", "GFX9.0.0 (Vega)", false),
("gfx902", "GFX9.0.2 (Raven)", false),
("gfx904", "GFX9.0.4", false),
("gfx906", "GFX9.0.6 (Vega20)", false),
("gfx908", "GFX9.0.8 (Arcturus)", false),
("gfx909", "GFX9.0.9", false),
("gfx90a", "GFX9.0.10 (Aldebaran)", false),
("gfx90c", "GFX9.0.12", false),
("gfx940", "GFX9.4.0", false),
("gfx941", "GFX9.4.1", false),
("gfx942", "GFX9.4.2", false),
("gfx1010", "GFX10.1.0 (Navi10)", false),
("gfx1011", "GFX10.1.1 (Navi12)", false),
("gfx1012", "GFX10.1.2 (Navi14)", false),
("gfx1030", "GFX10.3.0 (Sienna Cichlid)", false),
("gfx1031", "GFX10.3.1 (Navi21)", false),
("gfx1032", "GFX10.3.2 (Navi22)", false),
("gfx1033", "GFX10.3.3 (Navi23)", false),
("gfx1034", "GFX10.3.4 (Navi24)", false),
("gfx1035", "GFX10.3.5 (Rembrandt)", false),
("gfx1036", "GFX10.3.6 (Raphael)", false),
("gfx1100", "GFX11.0.0 (Navi31)", false),
("gfx1101", "GFX11.0.1 (Navi32)", false),
("gfx1102", "GFX11.0.2 (Navi33)", false),
("gfx1103", "GFX11.0.3 (Phoenix)", false),
("gfx1150", "GFX11.5.0", false),
("gfx1151", "GFX11.5.1", false),
("gfx1200", "GFX12.0.0", false),
("gfx1201", "GFX12.0.1", false),
("xnack", "XNACK", false),
("sram-ecc", "SRAM ECC", false),
("tgsplit", "TGSPLIT", false),
("cumode", "CU Mode", false),
("wavefrontsize16", "Wavefront 16", false),
("wavefrontsize32", "Wavefront 32", false),
("wavefrontsize64", "Wavefront 64", false),
("flat-for-global", "Flat for Global", false),
("enable-prt-strict-null", "PRT Strict Null", false),
("no-sdst-halt", "No SDST Halt", false),
("disable-kernelarg-load-alignment", "No KernelArg Load Align", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
pub fn lanai_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("v11", "Lanai v11", true),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
pub fn wasm_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("simd128", "SIMD 128", false),
("atomics", "Atomics", false),
("bulk-memory", "Bulk Memory", false),
("multivalue", "Multivalue", false),
("mutable-globals", "Mutable Globals", true),
("nontrapping-fptoint", "Non-trapping fp-to-int", false),
("sign-ext", "Sign Extension", true),
("exception-handling", "Exception Handling", false),
("tail-call", "Tail Call", false),
("reference-types", "Reference Types", false),
("extended-const", "Extended Constants", false),
("relaxed-simd", "Relaxed SIMD", false),
("multimemory", "Multi-Memory", false),
("threads", "Threads", false),
("shared-eh", "Shared EH", false),
("gc", "GC", false),
("function-references", "Function References", false),
("call-indirect-overlong", "Call Indirect Overlong", false),
("half-precision", "Half Precision", false),
("flexible-vectors", "Flexible Vectors", false),
("wide-arithmetic", "Wide Arithmetic", false),
("custom-page-sizes", "Custom Page Sizes", false),
("stack-switching", "Stack Switching", false),
("nontrapping-bulk-memory", "Nontrapping Bulk Memory", false),
("memory64", "Memory64", false),
("annotations", "Annotations", false),
("custom", "Custom", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
// ═══════════════════════════════════════════════════════════════════════════
// ARC, CSKY, Xtensa Feature Tables
// ═══════════════════════════════════════════════════════════════════════════
pub fn arc_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("arcem", "ARC EM", true),
("archs", "ARC HS", false),
("arc700", "ARC 700", false),
("barrel_shifter", "Barrel Shifter", false),
("norm", "NORM", false),
("swap", "SWAP", false),
("div_rem", "DIV/REM", false),
("mpy", "MPY", false),
("mpy_dmp", "MPY_DMP", false),
("mpy_mac", "MPY_MAC", false),
("mpy_plus_dmp", "MPY_PLUS_DMP", false),
("mpy_plus_mac", "MPY_PLUS_MAC", false),
("mpy_plus_qmacw", "MPY_PLUS_QMACW", false),
("mpy_option_5", "MPY Option 5", false),
("mpy_option_6", "MPY Option 6", false),
("mpy_option_7", "MPY Option 7", false),
("mpy_option_8", "MPY Option 8", false),
("mpy_option_9", "MPY Option 9", false),
("fpuda", "FPUDA", false),
("fpud", "FPUD", false),
("fpus", "FPUS", false),
("t-llvm", "T-LLVM", false),
("atomics", "Atomics", false),
("bbit", "BBIT", false),
("code-density", "Code Density", false),
("fpu", "FPU", false),
("norm-sqrt", "NORM/SQRT", false),
("shift-assist", "Shift Assist", false),
("unaligned-mem", "Unaligned Memory", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
pub fn csky_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("ck801", "CK801", false),
("ck802", "CK802", false),
("ck803", "CK803", false),
("ck803s", "CK803S", true),
("ck804", "CK804", false),
("ck805", "CK805", false),
("ck807", "CK807", false),
("ck810", "CK810", false),
("ck860", "CK860", false),
("e1", "E1", false),
("e2", "E2", false),
("2e3", "2E3", false),
("3e7", "3E7", false),
("7e10", "7E10", false),
("10e60", "10E60", false),
("fpuv2_sf", "FPUv2 SF", false),
("fpuv2_df", "FPUv2 DF", false),
("fpuv3_hi", "FPUv3 HI", false),
("fpuv3_hf", "FPUv3 HF", false),
("fpuv3_sf", "FPUv3 SF", false),
("fpuv3_df", "FPUv3 DF", false),
("hard-float", "Hard Float", false),
("hard-float-abi", "Hard Float ABI", false),
("edsp", "EDSP", false),
("vdsp", "VDSP", false),
("doloop", "Doloop", false),
("nvic", "NVIC", false),
("high-registers", "High Registers", false),
("trust", "Trust", false),
("cache", "Cache", false),
("cache-lock", "Cache Lock", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
pub fn xtensa_feature_table() -> HashMap<String, TargetFeature> {
let mut feats = HashMap::new();
for &(name, desc, default) in &[
("density", "Code Density", false),
("windowed", "Windowed Registers", false),
("bool", "Boolean", false),
("loop", "Loop", false),
("sext", "Sign Extend", false),
("nsa", "NSA", false),
("mul32", "32-bit MUL", false),
("mul32high", "32-bit MUL High", false),
("div32", "32-bit DIV", false),
("mac16", "16-bit MAC", false),
("dfp", "Double FP", false),
("s32c1i", "S32C1I", false),
("threadptr", "THREADPTR", false),
("extended_l32r", "Extended L32R", false),
("prerelease", "Prerelease", false),
("misc_sr", "Misc SR", false),
("debug", "Debug", false),
("exception", "Exception", false),
("highpri_interrupts", "High-Pri Interrupts", false),
("coprocessor", "Coprocessor", false),
("interrupt", "Interrupt", false),
("rvector", "RVector", false),
("timer_interrupt", "Timer Interrupt", false),
("gpr_windowed", "GPR Windowed", false),
("gpr_call0", "GPR Call0", false),
] {
feats.insert(name.to_string(), TargetFeature::new(name, desc, default));
}
feats
}
// ═══════════════════════════════════════════════════════════════════════════
// Tests
// ═══════════════════════════════════════════════════════════════════════════
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_x86_64() {
let info = TargetInfo::from_triple(Triple::parse("x86_64-unknown-linux-gnu"));
assert_eq!(info.cpu, "x86-64");
assert_eq!(info.abi.pointer_size, 64);
assert!(info.has_cpu("x86-64-v3"));
}
#[test]
fn test_aarch64() {
let info = TargetInfo::from_triple(Triple::parse("aarch64-unknown-linux-gnu"));
assert_eq!(info.abi.pointer_size, 64);
}
#[test]
fn test_windows() {
let info = TargetInfo::from_triple(Triple::parse("x86_64-pc-windows-msvc"));
assert!(!info.abi.wchar_is_32bit);
}
#[test]
fn test_features() {
let mut info = TargetInfo::from_triple(Triple::parse("x86_64-unknown-linux-gnu"));
info.parse_feature_string("+avx2,-sse3");
assert!(info.has_feature("avx2"));
assert!(!info.has_feature("sse3"));
}
#[test]
fn test_registry() {
let reg = TargetRegistry::default_targets();
assert!(reg.target_count() >= 5);
assert!(reg.lookup("x86_64-unknown-linux-gnu").is_some());
}
}
// ═══════════════════════════════════════════════════════════════════════════
// Backend helpers (used by mc_target.rs)
// ═══════════════════════════════════════════════════════════════════════════
pub fn aarch64_reg_name(reg_id: u32) -> String {
match reg_id {
0..=30 => format!("x{}", reg_id),
31 => "sp".into(),
32..=63 => format!("w{}", reg_id - 32),
_ => format!("r{}", reg_id),
}
}
pub fn arm32_reg_name(reg_id: u32) -> String {
match reg_id {
0..=12 => format!("r{}", reg_id),
13 => "sp".into(),
14 => "lr".into(),
15 => "pc".into(),
_ => format!("r{}", reg_id),
}
}
pub fn aarch64_mnemonic(opcode: u32) -> &'static str {
match opcode {
0 => "nop", 1 => "mov", 2 => "add", 3 => "sub", 4 => "mul",
5 => "and", 6 => "orr", 7 => "eor", 8 => "lsl", 9 => "lsr",
10 => "asr", 11 => "ldr", 12 => "str", 13 => "stp", 14 => "ldp",
15 => "b", 16 => "bl", 17 => "ret", 18 => "cmp", 19 => "adrp",
20 => "adr", 21 => "csel", 22 => "csinv",
_ => "unknown",
}
}
pub fn arm32_mnemonic(opcode: u32) -> &'static str {
match opcode {
0 => "nop", 1 => "mov", 2 => "movw", 3 => "movt", 4 => "add",
5 => "sub", 6 => "mul", 7 => "and", 8 => "orr", 9 => "eor",
10 => "ldr", 11 => "str", 12 => "b", 13 => "bl", 14 => "bx", 15 => "cmp",
16 => "push", 17 => "pop",
_ => "unknown",
}
}