1 /*
2 Copyright (c) 2019-2021, Intel Corporation
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16 * Neither the name of Intel Corporation nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /** @file target_enums.cpp
35 @brief Define enums describing target platform.
36 */
37
38 #include "target_enums.h"
39
40 #include "ispc.h"
41 #include "util.h"
42
43 #include <cstring>
44
45 namespace ispc {
46
ParseArch(std::string arch)47 Arch ParseArch(std::string arch) {
48 if (arch == "x86") {
49 return Arch::x86;
50 } else if (arch == "x86_64" || arch == "x86-64") {
51 return Arch::x86_64;
52 } else if (arch == "arm") {
53 return Arch::arm;
54 } else if (arch == "aarch64") {
55 return Arch::aarch64;
56 } else if (arch == "wasm32") {
57 return Arch::wasm32;
58 } else if (arch == "genx32") {
59 return Arch::genx32;
60 } else if (arch == "genx64") {
61 return Arch::genx64;
62 }
63 return Arch::error;
64 }
65
ArchToString(Arch arch)66 std::string ArchToString(Arch arch) {
67 switch (arch) {
68 case Arch::none:
69 return "none";
70 case Arch::x86:
71 return "x86";
72 case Arch::x86_64:
73 return "x86-64";
74 case Arch::arm:
75 return "arm";
76 case Arch::aarch64:
77 return "aarch64";
78 case Arch::wasm32:
79 return "wasm32";
80 case Arch::genx32:
81 return "genx32";
82 case Arch::genx64:
83 return "genx64";
84 case Arch::error:
85 return "error";
86 default:
87 // none and error are not supposed to be printed.
88 Error(SourcePos(), "Invalid arch is processed");
89 exit(1);
90 }
91 return "error";
92 }
93
ParseISPCTarget(std::string target)94 ISPCTarget ParseISPCTarget(std::string target) {
95 // TODO: ensure skx-i32x8 is not enabled and linked for earli LLVM version.
96
97 // The first matching string for each target is the canonical way to name the target,
98 // all other strings are aliases.
99 if (target == "host") {
100 return ISPCTarget::host;
101 } else if (target == "sse2-i32x4" || target == "sse2") {
102 return ISPCTarget::sse2_i32x4;
103 } else if (target == "sse2-i32x8" || target == "sse2-x2") {
104 return ISPCTarget::sse2_i32x8;
105 } else if (target == "sse4-i8x16") {
106 return ISPCTarget::sse4_i8x16;
107 } else if (target == "sse4-i16x8") {
108 return ISPCTarget::sse4_i16x8;
109 } else if (target == "sse4-i32x4" || target == "sse4") {
110 return ISPCTarget::sse4_i32x4;
111 } else if (target == "sse4-i32x8" || target == "sse4-x2" || target == "sse4x2") {
112 return ISPCTarget::sse4_i32x8;
113 } else if (target == "avx1-i32x4") {
114 return ISPCTarget::avx1_i32x4;
115 } else if (target == "avx1-i32x8" || target == "avx" || target == "avx1") {
116 return ISPCTarget::avx1_i32x8;
117 } else if (target == "avx1-i64x4" || target == "avx-i64x4") {
118 return ISPCTarget::avx1_i64x4;
119 } else if (target == "avx1-i32x16" || target == "avx-x2" || target == "avx1-x2") {
120 return ISPCTarget::avx1_i32x16;
121 } else if (target == "avx2-i8x32") {
122 return ISPCTarget::avx2_i8x32;
123 } else if (target == "avx2-i16x16") {
124 return ISPCTarget::avx2_i16x16;
125 } else if (target == "avx2-i32x4") {
126 return ISPCTarget::avx2_i32x4;
127 } else if (target == "avx2-i32x8" || target == "avx2") {
128 return ISPCTarget::avx2_i32x8;
129 } else if (target == "avx2-i64x4") {
130 return ISPCTarget::avx2_i64x4;
131 } else if (target == "avx2-i32x16" || target == "avx2-x2") {
132 return ISPCTarget::avx2_i32x16;
133 } else if (target == "avx512knl-i32x16") {
134 return ISPCTarget::avx512knl_i32x16;
135 } else if (target == "avx512skx-i32x16") {
136 return ISPCTarget::avx512skx_i32x16;
137 } else if (target == "avx512skx-i32x8") {
138 return ISPCTarget::avx512skx_i32x8;
139 } else if (target == "avx512skx-i8x64") {
140 return ISPCTarget::avx512skx_i8x64;
141 } else if (target == "avx512skx-i16x32") {
142 return ISPCTarget::avx512skx_i16x32;
143 } else if (target == "neon-i8x16") {
144 return ISPCTarget::neon_i8x16;
145 } else if (target == "neon-i16x8") {
146 return ISPCTarget::neon_i8x16;
147 } else if (target == "neon-i32x4" || target == "neon") {
148 return ISPCTarget::neon_i32x4;
149 } else if (target == "neon-i32x8") {
150 return ISPCTarget::neon_i32x8;
151 } else if (target == "wasm-i32x4") {
152 return ISPCTarget::wasm_i32x4;
153 } else if (target == "genx-x8") {
154 return ISPCTarget::genx_x8;
155 } else if (target == "genx-x16" || target == "genx") {
156 return ISPCTarget::genx_x16;
157 }
158
159 return ISPCTarget::error;
160 }
161
162 // Given a comma-delimited string with one or more compilation targets of
163 // the form "sse4-i32x4,avx2-i32x8", return a pair. First element of the pair is a vector
164 // of correctly parsed targets, second element of the pair is a strings with targets, which
165 // were not recognized.
ParseISPCTargets(const char * target)166 std::pair<std::vector<ISPCTarget>, std::string> ParseISPCTargets(const char *target) {
167 std::vector<ISPCTarget> targets;
168 std::string error_target;
169 const char *tstart = target;
170 bool done = false;
171 while (!done) {
172 const char *tend = strchr(tstart, ',');
173 if (tend == NULL) {
174 done = true;
175 tend = strchr(tstart, '\0');
176 }
177 std::string target_string = std::string(tstart, tend);
178 ISPCTarget target_parsed = ParseISPCTarget(target_string);
179 if (target_parsed == ISPCTarget::error) {
180 if (!error_target.empty()) {
181 error_target += ",";
182 }
183 error_target += target_string;
184 } else {
185 targets.push_back(target_parsed);
186 }
187 tstart = tend + 1;
188 }
189 return std::make_pair(targets, error_target);
190 }
191
ISPCTargetToString(ISPCTarget target)192 std::string ISPCTargetToString(ISPCTarget target) {
193 switch (target) {
194 case ISPCTarget::host:
195 return "host";
196 case ISPCTarget::sse2_i32x4:
197 return "sse2-i32x4";
198 case ISPCTarget::sse2_i32x8:
199 return "sse2-i32x8";
200 case ISPCTarget::sse4_i8x16:
201 return "sse4-i8x16";
202 case ISPCTarget::sse4_i16x8:
203 return "sse4-i16x8";
204 case ISPCTarget::sse4_i32x4:
205 return "sse4-i32x4";
206 case ISPCTarget::sse4_i32x8:
207 return "sse4-i32x8";
208 case ISPCTarget::avx1_i32x4:
209 return "avx1-i32x4";
210 case ISPCTarget::avx1_i32x8:
211 return "avx1-i32x8";
212 case ISPCTarget::avx1_i32x16:
213 return "avx1-i32x16";
214 case ISPCTarget::avx1_i64x4:
215 return "avx1-i64x4";
216 case ISPCTarget::avx2_i8x32:
217 return "avx2-i8x32";
218 case ISPCTarget::avx2_i16x16:
219 return "avx2-i16x16";
220 case ISPCTarget::avx2_i32x4:
221 return "avx2-i32x4";
222 case ISPCTarget::avx2_i32x8:
223 return "avx2-i32x8";
224 case ISPCTarget::avx2_i32x16:
225 return "avx2-i32x16";
226 case ISPCTarget::avx2_i64x4:
227 return "avx2-i64x4";
228 case ISPCTarget::avx512knl_i32x16:
229 return "avx512knl-i32x16";
230 case ISPCTarget::avx512skx_i32x8:
231 return "avx512skx-i32x8";
232 case ISPCTarget::avx512skx_i32x16:
233 return "avx512skx-i32x16";
234 case ISPCTarget::avx512skx_i8x64:
235 return "avx512skx-i8x64";
236 case ISPCTarget::avx512skx_i16x32:
237 return "avx512skx-i16x32";
238 case ISPCTarget::neon_i8x16:
239 return "neon-i8x16";
240 case ISPCTarget::neon_i16x8:
241 return "neon-i16x8";
242 case ISPCTarget::neon_i32x4:
243 return "neon-i32x4";
244 case ISPCTarget::neon_i32x8:
245 return "neon-i32x8";
246 case ISPCTarget::wasm_i32x4:
247 return "wasm-i32x4";
248 case ISPCTarget::genx_x8:
249 return "genx-x8";
250 case ISPCTarget::genx_x16:
251 return "genx-x16";
252 case ISPCTarget::none:
253 case ISPCTarget::error:
254 // Fall through
255 ;
256 }
257 Error(SourcePos(), "Invalid ISPCTarget is processed");
258 exit(1);
259 }
260
ISPCTargetIsX86(ISPCTarget target)261 bool ISPCTargetIsX86(ISPCTarget target) {
262 switch (target) {
263 case ISPCTarget::sse2_i32x4:
264 case ISPCTarget::sse2_i32x8:
265 case ISPCTarget::sse4_i8x16:
266 case ISPCTarget::sse4_i16x8:
267 case ISPCTarget::sse4_i32x4:
268 case ISPCTarget::sse4_i32x8:
269 case ISPCTarget::avx1_i32x4:
270 case ISPCTarget::avx1_i32x8:
271 case ISPCTarget::avx1_i32x16:
272 case ISPCTarget::avx1_i64x4:
273 case ISPCTarget::avx2_i8x32:
274 case ISPCTarget::avx2_i16x16:
275 case ISPCTarget::avx2_i32x4:
276 case ISPCTarget::avx2_i32x8:
277 case ISPCTarget::avx2_i32x16:
278 case ISPCTarget::avx2_i64x4:
279 case ISPCTarget::avx512knl_i32x16:
280 case ISPCTarget::avx512skx_i32x8:
281 case ISPCTarget::avx512skx_i32x16:
282 case ISPCTarget::avx512skx_i8x64:
283 case ISPCTarget::avx512skx_i16x32:
284 return true;
285 default:
286 return false;
287 }
288 }
289
ISPCTargetIsNeon(ISPCTarget target)290 bool ISPCTargetIsNeon(ISPCTarget target) {
291 switch (target) {
292 case ISPCTarget::neon_i8x16:
293 case ISPCTarget::neon_i16x8:
294 case ISPCTarget::neon_i32x4:
295 case ISPCTarget::neon_i32x8:
296 return true;
297 default:
298 return false;
299 }
300 }
301
ISPCTargetIsWasm(ISPCTarget target)302 bool ISPCTargetIsWasm(ISPCTarget target) {
303 switch (target) {
304 case ISPCTarget::wasm_i32x4:
305 return true;
306 default:
307 return false;
308 }
309 }
310
ISPCTargetIsGen(ISPCTarget target)311 bool ISPCTargetIsGen(ISPCTarget target) {
312 switch (target) {
313 case ISPCTarget::genx_x8:
314 case ISPCTarget::genx_x16:
315 return true;
316 default:
317 return false;
318 }
319 }
320
ParseOS(std::string os)321 TargetOS ParseOS(std::string os) {
322 std::string supportedOses = g->target_registry->getSupportedOSes().c_str();
323 if (supportedOses.find(os) == std::string::npos) {
324 return TargetOS::error;
325 }
326 if (os == "windows") {
327 return TargetOS::windows;
328 } else if (os == "linux") {
329 return TargetOS::linux;
330 } else if (os == "custom_linux") {
331 return TargetOS::custom_linux;
332 } else if (os == "freebsd") {
333 return TargetOS::freebsd;
334 } else if (os == "dragonfly") {
335 return TargetOS::dragonfly;
336 } else if (os == "macos") {
337 return TargetOS::macos;
338 } else if (os == "android") {
339 return TargetOS::android;
340 } else if (os == "ios") {
341 return TargetOS::ios;
342 } else if (os == "ps4") {
343 return TargetOS::ps4;
344 } else if (os == "web") {
345 return TargetOS::web;
346 }
347 return TargetOS::error;
348 }
349
OSToString(TargetOS os)350 std::string OSToString(TargetOS os) {
351 switch (os) {
352 case TargetOS::windows:
353 return "Windows";
354 case TargetOS::linux:
355 return "Linux";
356 case TargetOS::custom_linux:
357 return "Linux (custom)";
358 case TargetOS::freebsd:
359 return "FreeBSD";
360 case TargetOS::dragonfly:
361 return "DragonFly";
362 case TargetOS::macos:
363 return "macOS";
364 case TargetOS::android:
365 return "Android";
366 case TargetOS::ios:
367 return "iOS";
368 case TargetOS::ps4:
369 return "PS4";
370 case TargetOS::web:
371 return "web";
372 case TargetOS::error:
373 return "error";
374 }
375 UNREACHABLE();
376 }
377
OSToLowerString(TargetOS os)378 std::string OSToLowerString(TargetOS os) {
379 switch (os) {
380 case TargetOS::windows:
381 return "windows";
382 case TargetOS::linux:
383 return "linux";
384 case TargetOS::custom_linux:
385 return "custom_linux";
386 case TargetOS::freebsd:
387 return "freebsd";
388 case TargetOS::dragonfly:
389 return "dragonfly";
390 case TargetOS::macos:
391 return "macos";
392 case TargetOS::android:
393 return "android";
394 case TargetOS::ios:
395 return "ios";
396 case TargetOS::ps4:
397 return "ps4";
398 case TargetOS::web:
399 return "web";
400 case TargetOS::error:
401 return "error";
402 }
403 UNREACHABLE();
404 }
405
GetHostOS()406 TargetOS GetHostOS() {
407 #if defined(ISPC_HOST_IS_WINDOWS) && !defined(ISPC_WINDOWS_TARGET_OFF)
408 return TargetOS::windows;
409 #elif defined(ISPC_HOST_IS_LINUX) && !defined(ISPC_LINUX_TARGET_OFF)
410 return TargetOS::linux;
411 #elif defined(ISPC_HOST_IS_FREEBSD) && !defined(ISPC_FREEBSD_TARGET_OFF)
412 return TargetOS::freebsd;
413 #elif defined(ISPC_HOST_IS_DRAGONFLY) && !defined(ISPC_DRAGONFLY_TARGET_OFF)
414 return TargetOS::dragonfly;
415 #elif defined(ISPC_HOST_IS_APPLE) && !defined(ISPC_MACOS_TARGET_OFF)
416 return TargetOS::macos;
417 #else
418 return TargetOS::error;
419 #endif
420 }
421 } // namespace ispc
422