unc_vm_compiler/
target.rs1use crate::error::ParseCpuFeatureError;
3use crate::lib::std::str::FromStr;
4use crate::lib::std::string::{String, ToString};
5use enumset::{EnumSet, EnumSetType};
6pub use target_lexicon::{
7 Architecture, BinaryFormat, CallingConvention, Endianness, OperatingSystem, PointerWidth,
8 Triple,
9};
10
11#[allow(missing_docs, clippy::derived_hash_with_manual_eq)]
24#[derive(EnumSetType, Debug, Hash)]
25pub enum CpuFeature {
26 SSE2,
28 SSE3,
29 SSSE3,
30 SSE41,
31 SSE42,
32 POPCNT,
33 AVX,
34 BMI1,
35 BMI2,
36 AVX2,
37 AVX512DQ,
38 AVX512VL,
39 AVX512F,
40 LZCNT,
41 }
44
45impl CpuFeature {
46 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
47 pub fn for_host() -> EnumSet<Self> {
49 let mut features = EnumSet::new();
50
51 if std::is_x86_feature_detected!("sse2") {
52 features.insert(Self::SSE2);
53 }
54 if std::is_x86_feature_detected!("sse3") {
55 features.insert(Self::SSE3);
56 }
57 if std::is_x86_feature_detected!("ssse3") {
58 features.insert(Self::SSSE3);
59 }
60 if std::is_x86_feature_detected!("sse4.1") {
61 features.insert(Self::SSE41);
62 }
63 if std::is_x86_feature_detected!("sse4.2") {
64 features.insert(Self::SSE42);
65 }
66 if std::is_x86_feature_detected!("popcnt") {
67 features.insert(Self::POPCNT);
68 }
69 if std::is_x86_feature_detected!("avx") {
70 features.insert(Self::AVX);
71 }
72 if std::is_x86_feature_detected!("bmi1") {
73 features.insert(Self::BMI1);
74 }
75 if std::is_x86_feature_detected!("bmi2") {
76 features.insert(Self::BMI2);
77 }
78 if std::is_x86_feature_detected!("avx2") {
79 features.insert(Self::AVX2);
80 }
81 if std::is_x86_feature_detected!("avx512dq") {
82 features.insert(Self::AVX512DQ);
83 }
84 if std::is_x86_feature_detected!("avx512vl") {
85 features.insert(Self::AVX512VL);
86 }
87 if std::is_x86_feature_detected!("avx512f") {
88 features.insert(Self::AVX512F);
89 }
90 if std::is_x86_feature_detected!("lzcnt") {
91 features.insert(Self::LZCNT);
92 }
93 features
94 }
95 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
96 pub fn for_host() -> EnumSet<Self> {
98 EnumSet::new()
100 }
101
102 pub fn set() -> EnumSet<Self> {
104 EnumSet::new()
106 }
107}
108
109impl FromStr for CpuFeature {
116 type Err = ParseCpuFeatureError;
117
118 fn from_str(s: &str) -> Result<Self, Self::Err> {
119 match s {
120 "sse2" => Ok(Self::SSE2),
121 "sse3" => Ok(Self::SSE3),
122 "ssse3" => Ok(Self::SSSE3),
123 "sse4.1" => Ok(Self::SSE41),
124 "sse4.2" => Ok(Self::SSE42),
125 "popcnt" => Ok(Self::POPCNT),
126 "avx" => Ok(Self::AVX),
127 "bmi" => Ok(Self::BMI1),
128 "bmi2" => Ok(Self::BMI2),
129 "avx2" => Ok(Self::AVX2),
130 "avx512dq" => Ok(Self::AVX512DQ),
131 "avx512vl" => Ok(Self::AVX512VL),
132 "avx512f" => Ok(Self::AVX512F),
133 "lzcnt" => Ok(Self::LZCNT),
134 _ => Err(ParseCpuFeatureError::Missing(s.to_string())),
135 }
136 }
137}
138
139impl ToString for CpuFeature {
140 fn to_string(&self) -> String {
141 match self {
142 Self::SSE2 => "sse2",
143 Self::SSE3 => "sse3",
144 Self::SSSE3 => "ssse3",
145 Self::SSE41 => "sse4.1",
146 Self::SSE42 => "sse4.2",
147 Self::POPCNT => "popcnt",
148 Self::AVX => "avx",
149 Self::BMI1 => "bmi",
150 Self::BMI2 => "bmi2",
151 Self::AVX2 => "avx2",
152 Self::AVX512DQ => "avx512dq",
153 Self::AVX512VL => "avx512vl",
154 Self::AVX512F => "avx512f",
155 Self::LZCNT => "lzcnt",
156 }
157 .to_string()
158 }
159}
160
161#[derive(Clone, Debug, PartialEq, Eq, Hash)]
164pub struct Target {
165 triple: Triple,
166 cpu_features: EnumSet<CpuFeature>,
167}
168
169impl Target {
170 pub fn new(triple: Triple, cpu_features: EnumSet<CpuFeature>) -> Self {
172 Self { triple, cpu_features }
173 }
174
175 pub fn triple(&self) -> &Triple {
177 &self.triple
178 }
179
180 pub fn cpu_features(&self) -> &EnumSet<CpuFeature> {
182 &self.cpu_features
183 }
184}
185
186impl Default for Target {
188 fn default() -> Self {
189 Self { triple: Triple::host(), cpu_features: CpuFeature::for_host() }
190 }
191}