Line data Source code
1 : #ifdef __PLUMED_HAS_ASMJIT
2 : // This file is part of AsmJit project <https://asmjit.com>
3 : //
4 : // See asmjit.h or LICENSE.md for license and copyright information
5 : // SPDX-License-Identifier: Zlib
6 :
7 : #ifndef ASMJIT_CORE_ENVIRONMENT_H_INCLUDED
8 : #define ASMJIT_CORE_ENVIRONMENT_H_INCLUDED
9 :
10 : #include "archtraits.h"
11 :
12 : #if defined(__APPLE__)
13 : #include <TargetConditionals.h>
14 : #endif
15 :
16 : ASMJIT_BEGIN_NAMESPACE
17 :
18 : //! \addtogroup asmjit_core
19 : //! \{
20 :
21 : //! Vendor.
22 : //!
23 : //! \note AsmJit doesn't use vendor information at the moment. It's provided for future use, if required.
24 : enum class Vendor : uint8_t {
25 : //! Unknown or uninitialized platform vendor.
26 : kUnknown = 0,
27 :
28 : //! Maximum value of `PlatformVendor`.
29 : kMaxValue = kUnknown,
30 :
31 : //! Platform vendor detected at compile-time.
32 : kHost =
33 : #if defined(_DOXYGEN)
34 : DETECTED_AT_COMPILE_TIME
35 : #else
36 : kUnknown
37 : #endif
38 : };
39 :
40 : //! Platform - runtime environment or operating system.
41 : enum class Platform : uint8_t {
42 : //! Unknown or uninitialized platform.
43 : kUnknown = 0,
44 :
45 : //! Windows OS.
46 : kWindows,
47 :
48 : //! Other platform that is not Windows, most likely POSIX based.
49 : kOther,
50 :
51 : //! Linux OS.
52 : kLinux,
53 : //! GNU/Hurd OS.
54 : kHurd,
55 :
56 : //! FreeBSD OS.
57 : kFreeBSD,
58 : //! OpenBSD OS.
59 : kOpenBSD,
60 : //! NetBSD OS.
61 : kNetBSD,
62 : //! DragonFly BSD OS.
63 : kDragonFlyBSD,
64 :
65 : //! Haiku OS.
66 : kHaiku,
67 :
68 : //! Apple OSX.
69 : kOSX,
70 : //! Apple iOS.
71 : kIOS,
72 : //! Apple TVOS.
73 : kTVOS,
74 : //! Apple WatchOS.
75 : kWatchOS,
76 :
77 : //! Emscripten platform.
78 : kEmscripten,
79 :
80 : //! Maximum value of `Platform`.
81 : kMaxValue = kEmscripten,
82 :
83 : //! Platform detected at compile-time (platform of the host).
84 : kHost =
85 : #if defined(_DOXYGEN)
86 : DETECTED_AT_COMPILE_TIME
87 : #elif defined(__EMSCRIPTEN__)
88 : kEmscripten
89 : #elif defined(_WIN32)
90 : kWindows
91 : #elif defined(__linux__)
92 : kLinux
93 : #elif defined(__gnu_hurd__)
94 : kHurd
95 : #elif defined(__FreeBSD__)
96 : kFreeBSD
97 : #elif defined(__OpenBSD__)
98 : kOpenBSD
99 : #elif defined(__NetBSD__)
100 : kNetBSD
101 : #elif defined(__DragonFly__)
102 : kDragonFlyBSD
103 : #elif defined(__HAIKU__)
104 : kHaiku
105 : #elif defined(__APPLE__) && TARGET_OS_OSX
106 : kOSX
107 : #elif defined(__APPLE__) && TARGET_OS_TV
108 : kTVOS
109 : #elif defined(__APPLE__) && TARGET_OS_WATCH
110 : kWatchOS
111 : #elif defined(__APPLE__) && TARGET_OS_IPHONE
112 : kIOS
113 : #else
114 : kOther
115 : #endif
116 : };
117 :
118 : //! Platform ABI (application binary interface).
119 : enum class PlatformABI : uint8_t {
120 : //! Unknown or uninitialied environment.
121 : kUnknown = 0,
122 : //! Microsoft ABI.
123 : kMSVC,
124 : //! GNU ABI.
125 : kGNU,
126 : //! Android Environment / ABI.
127 : kAndroid,
128 : //! Cygwin ABI.
129 : kCygwin,
130 :
131 : //! Maximum value of `PlatformABI`.
132 : kMaxValue,
133 :
134 : //! Host ABI detected at compile-time.
135 : kHost =
136 : #if defined(_DOXYGEN)
137 : DETECTED_AT_COMPILE_TIME
138 : #elif defined(_MSC_VER)
139 : kMSVC
140 : #elif defined(__CYGWIN__)
141 : kCygwin
142 : #elif defined(__MINGW32__) || defined(__GLIBC__)
143 : kGNU
144 : #elif defined(__ANDROID__)
145 : kAndroid
146 : #else
147 : kUnknown
148 : #endif
149 : };
150 :
151 : //! Object format.
152 : //!
153 : //! \note AsmJit doesn't really use anything except \ref ObjectFormat::kUnknown and \ref ObjectFormat::kJIT at
154 : //! the moment. Object file formats are provided for future extensibility and a possibility to generate object
155 : //! files at some point.
156 : enum class ObjectFormat : uint8_t {
157 : //! Unknown or uninitialized object format.
158 : kUnknown = 0,
159 :
160 : //! JIT code generation object, most likely \ref JitRuntime or a custom
161 : //! \ref Target implementation.
162 : kJIT,
163 :
164 : //! Executable and linkable format (ELF).
165 : kELF,
166 : //! Common object file format.
167 : kCOFF,
168 : //! Extended COFF object format.
169 : kXCOFF,
170 : //! Mach object file format.
171 : kMachO,
172 :
173 : //! Maximum value of `ObjectFormat`.
174 : kMaxValue
175 : };
176 :
177 : //! Represents an environment, which is usually related to a \ref Target.
178 : //!
179 : //! Environment has usually an 'arch-subarch-vendor-os-abi' format, which is sometimes called "Triple" (historically
180 : //! it used to be 3 only parts) or "Tuple", which is a convention used by Debian Linux.
181 : //!
182 : //! AsmJit doesn't support all possible combinations or architectures and ABIs, however, it models the environment
183 : //! similarly to other compilers for future extensibility.
184 : class Environment {
185 : public:
186 : //! \name Members
187 : //! \{
188 :
189 : //! Architecture.
190 : Arch _arch;
191 : //! Sub-architecture type.
192 : SubArch _subArch;
193 : //! Vendor type.
194 : Vendor _vendor;
195 : //! Platform.
196 : Platform _platform;
197 : //! Platform ABI.
198 : PlatformABI _platformABI;
199 : //! Object format.
200 : ObjectFormat _objectFormat;
201 : //! Reserved for future use, must be zero.
202 : uint8_t _reserved[2];
203 :
204 : //! \}
205 :
206 : //! \name Construction & Destruction
207 : //! \{
208 :
209 109898 : inline Environment() noexcept :
210 109898 : _arch(Arch::kUnknown),
211 109898 : _subArch(SubArch::kUnknown),
212 109898 : _vendor(Vendor::kUnknown),
213 109898 : _platform(Platform::kUnknown),
214 109898 : _platformABI(PlatformABI::kUnknown),
215 109898 : _objectFormat(ObjectFormat::kUnknown),
216 109898 : _reserved { 0, 0 } {}
217 :
218 : inline explicit Environment(
219 : Arch arch,
220 : SubArch subArch = SubArch::kUnknown,
221 : Vendor vendor = Vendor::kUnknown,
222 : Platform platform = Platform::kUnknown,
223 : PlatformABI abi = PlatformABI::kUnknown,
224 : ObjectFormat objectFormat = ObjectFormat::kUnknown) noexcept {
225 :
226 : init(arch, subArch, vendor, platform, abi, objectFormat);
227 : }
228 :
229 : inline Environment(const Environment& other) noexcept = default;
230 :
231 : //! Returns the host environment constructed from preprocessor macros defined by the compiler.
232 : //!
233 : //! The returned environment should precisely match the target host architecture, sub-architecture, platform,
234 : //! and ABI.
235 : static inline Environment host() noexcept {
236 : return Environment(Arch::kHost, SubArch::kHost, Vendor::kHost, Platform::kHost, PlatformABI::kHost, ObjectFormat::kUnknown);
237 : }
238 :
239 : //! \}
240 :
241 : //! \name Overloaded Operators
242 : //! \{
243 :
244 : inline Environment& operator=(const Environment& other) noexcept = default;
245 :
246 : inline bool operator==(const Environment& other) const noexcept { return equals(other); }
247 : inline bool operator!=(const Environment& other) const noexcept { return !equals(other); }
248 :
249 : //! \}
250 :
251 : //! \name Accessors
252 : //! \{
253 :
254 : //! Tests whether the environment is not set up.
255 : //!
256 : //! Returns true if all members are zero, and thus unknown.
257 : inline bool empty() const noexcept {
258 : // Unfortunately compilers won't optimize fields are checked one by one...
259 : return _packed() == 0;
260 : }
261 :
262 : //! Tests whether the environment is initialized, which means it must have
263 : //! a valid architecture.
264 : inline bool isInitialized() const noexcept {
265 27492 : return _arch != Arch::kUnknown;
266 : }
267 :
268 : inline uint64_t _packed() const noexcept {
269 : uint64_t x;
270 : memcpy(&x, this, 8);
271 : return x;
272 : }
273 :
274 : //! Resets all members of the environment to zero / unknown.
275 : inline void reset() noexcept {
276 27492 : _arch = Arch::kUnknown;
277 27492 : _subArch = SubArch::kUnknown;
278 27492 : _vendor = Vendor::kUnknown;
279 27492 : _platform = Platform::kUnknown;
280 27492 : _platformABI = PlatformABI::kUnknown;
281 27492 : _objectFormat = ObjectFormat::kUnknown;
282 27492 : _reserved[0] = 0;
283 27492 : _reserved[1] = 0;
284 : }
285 :
286 : inline bool equals(const Environment& other) const noexcept {
287 : return _packed() == other._packed();
288 : }
289 :
290 : //! Returns the architecture.
291 503352 : inline Arch arch() const noexcept { return _arch; }
292 : //! Returns the sub-architecture.
293 : inline SubArch subArch() const noexcept { return _subArch; }
294 : //! Returns vendor.
295 : inline Vendor vendor() const noexcept { return _vendor; }
296 : //! Returns target's platform or operating system.
297 : inline Platform platform() const noexcept { return _platform; }
298 : //! Returns target's ABI.
299 : inline PlatformABI platformABI() const noexcept { return _platformABI; }
300 : //! Returns target's object format.
301 : inline ObjectFormat objectFormat() const noexcept { return _objectFormat; }
302 :
303 : inline void init(
304 : Arch arch,
305 : SubArch subArch = SubArch::kUnknown,
306 : Vendor vendor = Vendor::kUnknown,
307 : Platform platform = Platform::kUnknown,
308 : PlatformABI platformABI = PlatformABI::kUnknown,
309 : ObjectFormat objectFormat = ObjectFormat::kUnknown) noexcept {
310 :
311 : _arch = arch;
312 : _subArch = subArch;
313 : _vendor = vendor;
314 : _platform = platform;
315 : _platformABI = platformABI;
316 : _objectFormat = objectFormat;
317 : _reserved[0] = 0;
318 : _reserved[1] = 0;
319 : }
320 :
321 : inline bool isArchX86() const noexcept { return _arch == Arch::kX86; }
322 : inline bool isArchX64() const noexcept { return _arch == Arch::kX64; }
323 : inline bool isArchARM() const noexcept { return isArchARM(_arch); }
324 : inline bool isArchThumb() const noexcept { return isArchThumb(_arch); }
325 : inline bool isArchAArch64() const noexcept { return isArchAArch64(_arch); }
326 : inline bool isArchMIPS32() const noexcept { return isArchMIPS32(_arch); }
327 : inline bool isArchMIPS64() const noexcept { return isArchMIPS64(_arch); }
328 : inline bool isArchRISCV32() const noexcept { return _arch == Arch::kRISCV32; }
329 : inline bool isArchRISCV64() const noexcept { return _arch == Arch::kRISCV64; }
330 :
331 : //! Tests whether the architecture is 32-bit.
332 37131 : inline bool is32Bit() const noexcept { return is32Bit(_arch); }
333 : //! Tests whether the architecture is 64-bit.
334 27492 : inline bool is64Bit() const noexcept { return is64Bit(_arch); }
335 :
336 : //! Tests whether the architecture is little endian.
337 : inline bool isLittleEndian() const noexcept { return isLittleEndian(_arch); }
338 : //! Tests whether the architecture is big endian.
339 : inline bool isBigEndian() const noexcept { return isBigEndian(_arch); }
340 :
341 : //! Tests whether this architecture is of X86 family.
342 74262 : inline bool isFamilyX86() const noexcept { return isFamilyX86(_arch); }
343 : //! Tests whether this architecture family is ARM, THUMB, or AArch64.
344 0 : inline bool isFamilyARM() const noexcept { return isFamilyARM(_arch); }
345 : //! Tests whether this architecture family is AArch32 (ARM or THUMB).
346 : inline bool isFamilyAArch32() const noexcept { return isFamilyAArch32(_arch); }
347 : //! Tests whether this architecture family is AArch64.
348 0 : inline bool isFamilyAArch64() const noexcept { return isFamilyAArch64(_arch); }
349 : //! Tests whether this architecture family is MISP or MIPS64.
350 : inline bool isFamilyMIPS() const noexcept { return isFamilyMIPS(_arch); }
351 : //! Tests whether this architecture family is RISC-V (both 32-bit and 64-bit).
352 : inline bool isFamilyRISCV() const noexcept { return isFamilyRISCV(_arch); }
353 :
354 : //! Tests whether the environment platform is Windows.
355 37131 : inline bool isPlatformWindows() const noexcept { return _platform == Platform::kWindows; }
356 :
357 : //! Tests whether the environment platform is Linux.
358 0 : inline bool isPlatformLinux() const noexcept { return _platform == Platform::kLinux; }
359 :
360 : //! Tests whether the environment platform is Hurd.
361 : inline bool isPlatformHurd() const noexcept { return _platform == Platform::kHurd; }
362 :
363 : //! Tests whether the environment platform is Haiku.
364 : inline bool isPlatformHaiku() const noexcept { return _platform == Platform::kHaiku; }
365 :
366 : //! Tests whether the environment platform is any BSD.
367 : inline bool isPlatformBSD() const noexcept {
368 : return _platform == Platform::kFreeBSD ||
369 : _platform == Platform::kOpenBSD ||
370 0 : _platform == Platform::kNetBSD ||
371 : _platform == Platform::kDragonFlyBSD;
372 : }
373 :
374 : //! Tests whether the environment platform is any Apple platform (OSX, iOS, TVOS, WatchOS).
375 : inline bool isPlatformApple() const noexcept {
376 : return _platform == Platform::kOSX ||
377 : _platform == Platform::kIOS ||
378 0 : _platform == Platform::kTVOS ||
379 : _platform == Platform::kWatchOS;
380 : }
381 :
382 : //! Tests whether the ABI is MSVC.
383 37131 : inline bool isMSVC() const noexcept { return _platformABI == PlatformABI::kMSVC; }
384 : //! Tests whether the ABI is GNU.
385 : inline bool isGNU() const noexcept { return _platformABI == PlatformABI::kGNU; }
386 :
387 : //! Returns a calculated stack alignment for this environment.
388 : ASMJIT_API uint32_t stackAlignment() const noexcept;
389 :
390 : //! Returns a native register size of this architecture.
391 54984 : uint32_t registerSize() const noexcept { return registerSizeFromArch(_arch); }
392 :
393 : //! Sets the architecture to `arch`.
394 : inline void setArch(Arch arch) noexcept { _arch = arch; }
395 : //! Sets the sub-architecture to `subArch`.
396 : inline void setSubArch(SubArch subArch) noexcept { _subArch = subArch; }
397 : //! Sets the vendor to `vendor`.
398 : inline void setVendor(Vendor vendor) noexcept { _vendor = vendor; }
399 : //! Sets the platform to `platform`.
400 : inline void setPlatform(Platform platform) noexcept { _platform = platform; }
401 : //! Sets the ABI to `platformABI`.
402 : inline void setPlatformABI(PlatformABI platformABI) noexcept { _platformABI = platformABI; }
403 : //! Sets the object format to `objectFormat`.
404 27422 : inline void setObjectFormat(ObjectFormat objectFormat) noexcept { _objectFormat = objectFormat; }
405 :
406 : //! \}
407 :
408 : //! \name Static Utilities
409 : //! \{
410 :
411 : static inline bool isDefinedArch(Arch arch) noexcept {
412 : return uint32_t(arch) <= uint32_t(Arch::kMaxValue);
413 : }
414 :
415 : static inline bool isValidArch(Arch arch) noexcept {
416 54984 : return arch != Arch::kUnknown && uint32_t(arch) <= uint32_t(Arch::kMaxValue);
417 : }
418 :
419 : //! Tests whether the given architecture `arch` is 32-bit.
420 : static inline bool is32Bit(Arch arch) noexcept {
421 : return (uint32_t(arch) & uint32_t(Arch::k32BitMask)) == uint32_t(Arch::k32BitMask);
422 : }
423 :
424 : //! Tests whether the given architecture `arch` is 64-bit.
425 : static inline bool is64Bit(Arch arch) noexcept {
426 : return (uint32_t(arch) & uint32_t(Arch::k32BitMask)) == 0;
427 : }
428 :
429 : //! Tests whether the given architecture `arch` is little endian.
430 : static inline bool isLittleEndian(Arch arch) noexcept {
431 : return uint32_t(arch) < uint32_t(Arch::kBigEndian);
432 : }
433 :
434 : //! Tests whether the given architecture `arch` is big endian.
435 : static inline bool isBigEndian(Arch arch) noexcept {
436 : return uint32_t(arch) >= uint32_t(Arch::kBigEndian);
437 : }
438 :
439 : //! Tests whether the given architecture is Thumb or Thumb_BE.
440 : static inline bool isArchThumb(Arch arch) noexcept {
441 0 : return arch == Arch::kThumb || arch == Arch::kThumb_BE;
442 : }
443 :
444 : //! Tests whether the given architecture is ARM or ARM_BE.
445 : static inline bool isArchARM(Arch arch) noexcept {
446 0 : return arch == Arch::kARM || arch == Arch::kARM_BE;
447 : }
448 :
449 : //! Tests whether the given architecture is AArch64 or AArch64_BE.
450 : static inline bool isArchAArch64(Arch arch) noexcept {
451 0 : return arch == Arch::kAArch64 || arch == Arch::kAArch64_BE;
452 : }
453 :
454 : //! Tests whether the given architecture is MIPS32_LE or MIPS32_BE.
455 : static inline bool isArchMIPS32(Arch arch) noexcept {
456 : return arch == Arch::kMIPS32_LE || arch == Arch::kMIPS32_BE;
457 : }
458 :
459 : //! Tests whether the given architecture is MIPS64_LE or MIPS64_BE.
460 : static inline bool isArchMIPS64(Arch arch) noexcept {
461 : return arch == Arch::kMIPS64_LE || arch == Arch::kMIPS64_BE;
462 : }
463 :
464 : //! Tests whether the given architecture family is X86 or X64.
465 : static inline bool isFamilyX86(Arch arch) noexcept {
466 74262 : return arch == Arch::kX86 || arch == Arch::kX64;
467 : }
468 :
469 : //! Tests whether the given architecture family is ARM, THUMB, or AArch64.
470 0 : static inline bool isFamilyARM(Arch arch) noexcept {
471 0 : return isArchARM(arch) || isArchAArch64(arch) || isArchThumb(arch);
472 : }
473 :
474 : //! Tests whether the given architecture family is AArch32 (ARM or THUMB).
475 : static inline bool isFamilyAArch32(Arch arch) noexcept {
476 : return isArchARM(arch) || isArchThumb(arch);
477 : }
478 :
479 : //! Tests whether the given architecture family is AArch64.
480 : static inline bool isFamilyAArch64(Arch arch) noexcept {
481 : return isArchAArch64(arch);
482 : }
483 :
484 : //! Tests whether the given architecture family is MISP or MIPS64.
485 : static inline bool isFamilyMIPS(Arch arch) noexcept {
486 : return isArchMIPS32(arch) || isArchMIPS64(arch);
487 : }
488 :
489 : //! Tests whether the given architecture family is RISC-V (both 32-bit and 64-bit).
490 : static inline bool isFamilyRISCV(Arch arch) noexcept {
491 : return arch == Arch::kRISCV32 || arch == Arch::kRISCV64;
492 : }
493 :
494 : //! Returns a native general purpose register size from the given architecture.
495 : static inline uint32_t registerSizeFromArch(Arch arch) noexcept {
496 396431 : return is32Bit(arch) ? 4u : 8u;
497 : }
498 :
499 : //! \}
500 : };
501 :
502 : static_assert(sizeof(Environment) == 8,
503 : "Environment must occupy exactly 8 bytes.");
504 :
505 : //! \}
506 :
507 : ASMJIT_END_NAMESPACE
508 :
509 : #endif // ASMJIT_CORE_ENVIRONMENT_H_INCLUDED
510 :
511 : #endif // __PLUMED_HAS_ASMJIT
|