wasmer_types/compilation/
target.rs1#![allow(clippy::unused_unit, clippy::use_self)]
10
11use crate::error::ParseCpuFeatureError;
12use enumset::{EnumSet, EnumSetType};
13use std::str::FromStr;
14use std::string::{String, ToString};
15pub use target_lexicon::{
16 Aarch64Architecture, Architecture, BinaryFormat, CallingConvention, Endianness, Environment,
17 OperatingSystem, PointerWidth, Triple, Vendor,
18};
19
20#[allow(missing_docs, clippy::derived_hash_with_manual_eq)]
33#[derive(EnumSetType, Debug, Hash)]
34pub enum CpuFeature {
35 SSE2,
37 SSE3,
38 SSSE3,
39 SSE41,
40 SSE42,
41 POPCNT,
42 AVX,
43 BMI1,
44 BMI2,
45 AVX2,
46 AVX512DQ,
47 AVX512VL,
48 AVX512F,
49 LZCNT,
50 NEON,
52 }
54
55impl CpuFeature {
56 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
57 pub fn for_host() -> EnumSet<Self> {
59 let mut features = EnumSet::new();
60
61 if std::is_x86_feature_detected!("sse2") {
62 features.insert(Self::SSE2);
63 }
64 if std::is_x86_feature_detected!("sse3") {
65 features.insert(Self::SSE3);
66 }
67 if std::is_x86_feature_detected!("ssse3") {
68 features.insert(Self::SSSE3);
69 }
70 if std::is_x86_feature_detected!("sse4.1") {
71 features.insert(Self::SSE41);
72 }
73 if std::is_x86_feature_detected!("sse4.2") {
74 features.insert(Self::SSE42);
75 }
76 if std::is_x86_feature_detected!("popcnt") {
77 features.insert(Self::POPCNT);
78 }
79 if std::is_x86_feature_detected!("avx") {
80 features.insert(Self::AVX);
81 }
82 if std::is_x86_feature_detected!("bmi1") {
83 features.insert(Self::BMI1);
84 }
85 if std::is_x86_feature_detected!("bmi2") {
86 features.insert(Self::BMI2);
87 }
88 if std::is_x86_feature_detected!("avx2") {
89 features.insert(Self::AVX2);
90 }
91 if std::is_x86_feature_detected!("avx512dq") {
92 features.insert(Self::AVX512DQ);
93 }
94 if std::is_x86_feature_detected!("avx512vl") {
95 features.insert(Self::AVX512VL);
96 }
97 if std::is_x86_feature_detected!("avx512f") {
98 features.insert(Self::AVX512F);
99 }
100 if std::is_x86_feature_detected!("lzcnt") {
101 features.insert(Self::LZCNT);
102 }
103 features
104 }
105
106 #[cfg(target_arch = "aarch64")]
107 pub fn for_host() -> EnumSet<Self> {
109 let mut features = EnumSet::new();
110
111 if std::arch::is_aarch64_feature_detected!("neon") {
112 features.insert(Self::NEON);
113 }
114
115 features
116 }
117
118 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")))]
119 pub fn for_host() -> EnumSet<Self> {
121 EnumSet::new()
123 }
124
125 pub fn set() -> EnumSet<Self> {
127 EnumSet::new()
129 }
130}
131
132impl FromStr for CpuFeature {
139 type Err = ParseCpuFeatureError;
140
141 fn from_str(s: &str) -> Result<Self, Self::Err> {
142 match s {
143 "sse2" => Ok(Self::SSE2),
144 "sse3" => Ok(Self::SSE3),
145 "ssse3" => Ok(Self::SSSE3),
146 "sse4.1" => Ok(Self::SSE41),
147 "sse4.2" => Ok(Self::SSE42),
148 "popcnt" => Ok(Self::POPCNT),
149 "avx" => Ok(Self::AVX),
150 "bmi" => Ok(Self::BMI1),
151 "bmi2" => Ok(Self::BMI2),
152 "avx2" => Ok(Self::AVX2),
153 "avx512dq" => Ok(Self::AVX512DQ),
154 "avx512vl" => Ok(Self::AVX512VL),
155 "avx512f" => Ok(Self::AVX512F),
156 "lzcnt" => Ok(Self::LZCNT),
157 "neon" => Ok(Self::NEON),
158 _ => Err(ParseCpuFeatureError::Missing(s.to_string())),
159 }
160 }
161}
162
163impl ToString for CpuFeature {
164 fn to_string(&self) -> String {
165 match self {
166 Self::SSE2 => "sse2",
167 Self::SSE3 => "sse3",
168 Self::SSSE3 => "ssse3",
169 Self::SSE41 => "sse4.1",
170 Self::SSE42 => "sse4.2",
171 Self::POPCNT => "popcnt",
172 Self::AVX => "avx",
173 Self::BMI1 => "bmi",
174 Self::BMI2 => "bmi2",
175 Self::AVX2 => "avx2",
176 Self::AVX512DQ => "avx512dq",
177 Self::AVX512VL => "avx512vl",
178 Self::AVX512F => "avx512f",
179 Self::LZCNT => "lzcnt",
180 Self::NEON => "neon",
181 }
182 .to_string()
183 }
184}
185
186#[derive(Clone, Debug, PartialEq, Eq, Hash)]
189pub struct Target {
190 triple: Triple,
191 cpu_features: EnumSet<CpuFeature>,
192}
193
194impl Target {
195 pub fn new(triple: Triple, cpu_features: EnumSet<CpuFeature>) -> Self {
197 Self {
198 triple,
199 cpu_features,
200 }
201 }
202
203 pub fn triple(&self) -> &Triple {
205 &self.triple
206 }
207
208 pub fn cpu_features(&self) -> &EnumSet<CpuFeature> {
210 &self.cpu_features
211 }
212
213 pub fn is_native(&self) -> bool {
215 let host = Triple::host();
216 host.operating_system == self.triple.operating_system
217 && host.architecture == self.triple.architecture
218 }
219}
220
221impl Default for Target {
223 fn default() -> Self {
224 Self {
225 triple: Triple::host(),
226 cpu_features: CpuFeature::for_host(),
227 }
228 }
229}