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