| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | //================================================================================================== | ||
| 2 | /* | ||
| 3 | SPY - C++ Informations Broker | ||
| 4 | Copyright : SPY Project Contributors | ||
| 5 | SPDX-License-Identifier: BSL-1.0 | ||
| 6 | */ | ||
| 7 | //================================================================================================== | ||
| 8 | #pragma once | ||
| 9 | |||
| 10 | namespace spy::_ | ||
| 11 | { | ||
| 12 | enum class archs | ||
| 13 | { | ||
| 14 | undefined_ = -1, | ||
| 15 | x86_ = 10, | ||
| 16 | amd64_ = 11, | ||
| 17 | ppc_ = 20, | ||
| 18 | arm_ = 30, | ||
| 19 | wasm_ = 40, | ||
| 20 | riscv_ = 50 | ||
| 21 | }; | ||
| 22 | |||
| 23 | template<archs Arch> struct arch_info | ||
| 24 | { | ||
| 25 | static constexpr archs vendor = Arch; | ||
| 26 | |||
| 27 | inline constexpr explicit operator bool() const noexcept; | ||
| 28 | |||
| 29 | 6 | template<archs A2> constexpr bool operator==(arch_info<A2> const&) const noexcept | |
| 30 | { | ||
| 31 | 6 | return A2 == vendor; | |
| 32 | } | ||
| 33 | |||
| 34 | template<_::stream OS> friend auto& operator<<(OS& os, arch_info const&) | ||
| 35 | { | ||
| 36 | if(Arch == archs::x86_) return os << "X86"; | ||
| 37 | if(Arch == archs::amd64_) return os << "AMD64"; | ||
| 38 | if(Arch == archs::ppc_) return os << "PowerPC"; | ||
| 39 | if(Arch == archs::arm_) return os << "ARM"; | ||
| 40 | if(Arch == archs::wasm_) return os << "WebAssembly"; | ||
| 41 | if(Arch == archs::riscv_) return os << "RISC-V"; | ||
| 42 | |||
| 43 | return os << "Undefined Architecture"; | ||
| 44 | } | ||
| 45 | }; | ||
| 46 | } | ||
| 47 | |||
| 48 | namespace spy | ||
| 49 | { | ||
| 50 | #if defined(i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || \ | ||
| 51 | defined(__i686__) || defined(__i386) || defined(_M_IX86) || defined(_X86_) || \ | ||
| 52 | defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__) | ||
| 53 | using arch_type = _::arch_info<_::archs::x86_>; | ||
| 54 | #define SPY_ARCH_IS_X86 | ||
| 55 | #elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__amd64) || \ | ||
| 56 | defined(_M_X64) | ||
| 57 | #define SPY_ARCH_IS_AMD64 | ||
| 58 | using arch_type = _::arch_info<_::archs::amd64_>; | ||
| 59 | #elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || \ | ||
| 60 | defined(_M_PPC) || defined(_ARCH_PPC) || defined(__PPCGECKO__) || defined(__PPCBROADWAY__) || \ | ||
| 61 | defined(_XENON) | ||
| 62 | using arch_type = _::arch_info<_::archs::ppc_>; | ||
| 63 | #define SPY_ARCH_IS_PPC | ||
| 64 | #elif defined(__arm__) || defined(__arm64) || defined(__thumb__) || defined(__TARGET_ARCH_ARM) || \ | ||
| 65 | defined(__TARGET_ARCH_THUMB) || defined(_M_ARM) || defined(__ARM_ARCH_ISA_A64) | ||
| 66 | using arch_type = _::arch_info<_::archs::arm_>; | ||
| 67 | #define SPY_ARCH_IS_ARM | ||
| 68 | #elif defined(__wasm__) | ||
| 69 | using arch_type = _::arch_info<_::archs::wasm_>; | ||
| 70 | #define SPY_ARCH_IS_WASM | ||
| 71 | #elif defined(__riscv) | ||
| 72 | using arch_type = _::arch_info<_::archs::riscv_>; | ||
| 73 | #define SPY_ARCH_IS_RISCV | ||
| 74 | #else | ||
| 75 | #define SPY_ARCH_IS_UNKNOWN | ||
| 76 | using arch_type = _::arch_info<_::archs::undefined_>; | ||
| 77 | #endif | ||
| 78 | |||
| 79 | //================================================================================================ | ||
| 80 | //! @ingroup spy_platform | ||
| 81 | //! @brief Architecture reporting value | ||
| 82 | //! | ||
| 83 | //! The `spy::architecture` object can be compared to any other architecture related value to | ||
| 84 | //! verify if the code being compiled is compiled for a given CPU architecture. | ||
| 85 | //! | ||
| 86 | //! Additionally, any of the architecture related value are convertible to `bool`. They evaluates | ||
| 87 | //! to `true` if they matches the correct architecture currently targeted. | ||
| 88 | //! | ||
| 89 | //! @groupheader{Supported Value} | ||
| 90 | //! | ||
| 91 | //! Name | Architecture | ||
| 92 | //! --------------- | ------------- | ||
| 93 | //! `spy::amd64` | Intel X86-64 and similar architectures. | ||
| 94 | //! `spy::arm` | ARM. | ||
| 95 | //! `spy::ppc` | PowerPC. | ||
| 96 | //! `spy::riscv` | RISC-V. | ||
| 97 | //! `spy::wasm` | WASM pseudo-architecture. | ||
| 98 | //! `spy::x86` | Intel X86. | ||
| 99 | //! | ||
| 100 | //! @groupheader{Example} | ||
| 101 | //! @godbolt{samples/architecture.cpp} | ||
| 102 | //================================================================================================ | ||
| 103 | constexpr inline arch_type architecture; | ||
| 104 | } | ||
| 105 | |||
| 106 | namespace spy::_ | ||
| 107 | { | ||
| 108 | template<archs Arch> inline constexpr arch_info<Arch>::operator bool() const noexcept | ||
| 109 | { | ||
| 110 | return spy::architecture == *this; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | namespace spy | ||
| 115 | { | ||
| 116 | //================================================================================================ | ||
| 117 | // Architecture detector stand-alone instances | ||
| 118 | //================================================================================================ | ||
| 119 | constexpr inline auto x86_ = _::arch_info<_::archs::x86_> {}; | ||
| 120 | constexpr inline auto amd64_ = _::arch_info<_::archs::amd64_> {}; | ||
| 121 | constexpr inline auto ppc_ = _::arch_info<_::archs::ppc_> {}; | ||
| 122 | constexpr inline auto arm_ = _::arch_info<_::archs::arm_> {}; | ||
| 123 | constexpr inline auto wasm_ = _::arch_info<_::archs::wasm_> {}; | ||
| 124 | constexpr inline auto riscv_ = _::arch_info<_::archs::riscv_> {}; | ||
| 125 | } | ||
| 126 |