-
Notifications
You must be signed in to change notification settings - Fork 3
/
intrinsics.hpp
228 lines (198 loc) · 8.34 KB
/
intrinsics.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#pragma once
namespace nall {
using uint = unsigned;
enum class Compiler : uint { Clang, GCC, Microsoft, Unknown };
enum class Platform : uint { Windows, MacOS, Linux, BSD, Android, Unknown };
enum class API : uint { Windows, Posix, Unknown };
enum class DisplayServer : uint { Windows, Quartz, Xorg, Unknown };
enum class Architecture : uint { x86, amd64, ARM32, ARM64, PPC32, PPC64, Unknown };
enum class Endian : uint { LSB, MSB, Unknown };
enum class Build : uint { Debug, Stable, Size, Release, Performance };
static inline constexpr auto compiler() -> Compiler;
static inline constexpr auto platform() -> Platform;
static inline constexpr auto api() -> API;
static inline constexpr auto display() -> DisplayServer;
static inline constexpr auto architecture() -> Architecture;
static inline constexpr auto endian() -> Endian;
static inline constexpr auto build() -> Build;
}
/* Compiler detection */
namespace nall {
#if defined(__clang__)
#define COMPILER_CLANG
constexpr auto compiler() -> Compiler { return Compiler::Clang; }
#pragma clang diagnostic warning "-Wreturn-type"
#pragma clang diagnostic ignored "-Wunused-result"
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wempty-body"
#pragma clang diagnostic ignored "-Wparentheses"
#pragma clang diagnostic ignored "-Wswitch"
#pragma clang diagnostic ignored "-Wswitch-bool"
#pragma clang diagnostic ignored "-Wtautological-compare"
#pragma clang diagnostic ignored "-Wabsolute-value"
#pragma clang diagnostic ignored "-Wshift-count-overflow"
#pragma clang diagnostic ignored "-Wtrigraphs"
//temporary
#pragma clang diagnostic ignored "-Winconsistent-missing-override"
//#pragma clang diagnostic error "-Wdeprecated-declarations"
#elif defined(__GNUC__)
#define COMPILER_GCC
constexpr auto compiler() -> Compiler { return Compiler::GCC; }
#pragma GCC diagnostic warning "-Wreturn-type"
#pragma GCC diagnostic ignored "-Wunused-result"
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wpragmas"
#pragma GCC diagnostic ignored "-Wswitch-bool"
#pragma GCC diagnostic ignored "-Wtrigraphs"
#elif defined(_MSC_VER)
#define COMPILER_MICROSOFT
constexpr auto compiler() -> Compiler { return Compiler::Microsoft; }
#pragma warning(disable:4996) //libc "deprecation" warnings
#else
#warning "unable to detect compiler"
#define COMPILER_UNKNOWN
constexpr auto compiler() -> Compiler { return Compiler::Unknown; }
#endif
}
/* Platform detection */
namespace nall {
#if defined(_WIN32)
#define PLATFORM_WINDOWS
#define API_WINDOWS
#define DISPLAY_WINDOWS
constexpr auto platform() -> Platform { return Platform::Windows; }
constexpr auto api() -> API { return API::Windows; }
constexpr auto display() -> DisplayServer { return DisplayServer::Windows; }
#elif defined(__APPLE__)
#define PLATFORM_MACOS
#define API_POSIX
#define DISPLAY_QUARTZ
constexpr auto platform() -> Platform { return Platform::MacOS; }
constexpr auto api() -> API { return API::Posix; }
constexpr auto display() -> DisplayServer { return DisplayServer::Quartz; }
#elif defined(__ANDROID__)
#define PLATFORM_ANDROID
#define API_POSIX
#define DISPLAY_UNKNOWN
constexpr auto platform() -> Platform { return Platform::Android; }
constexpr auto api() -> API { return API::Posix; }
constexpr auto display() -> DisplayServer { return DisplayServer::Unknown; }
#elif defined(linux) || defined(__linux__)
#define PLATFORM_LINUX
#define API_POSIX
#define DISPLAY_XORG
constexpr auto platform() -> Platform { return Platform::Linux; }
constexpr auto api() -> API { return API::Posix; }
constexpr auto display() -> DisplayServer { return DisplayServer::Xorg; }
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined (__DragonFly__)
#define PLATFORM_BSD
#define API_POSIX
#define DISPLAY_XORG
constexpr auto platform() -> Platform { return Platform::BSD; }
constexpr auto api() -> API { return API::Posix; }
constexpr auto display() -> DisplayServer { return DisplayServer::Xorg; }
#else
#warning "unable to detect platform"
#define PLATFORM_UNKNOWN
#define API_UNKNOWN
#define DISPLAY_UNKNOWN
constexpr auto platform() -> Platform { return Platform::Unknown; }
constexpr auto api() -> API { return API::Unknown; }
constexpr auto display() -> DisplayServer { return DisplayServer::Unknown; }
#endif
}
/* Architecture detection */
namespace nall {
#if defined(__i386__) || defined(_M_IX86)
#define ARCHITECTURE_X86
constexpr auto architecture() -> Architecture { return Architecture::x86; }
#elif defined(__amd64__) || defined(_M_AMD64)
#define ARCHITECTURE_AMD64
constexpr auto architecture() -> Architecture { return Architecture::amd64; }
#elif defined(__aarch64__)
#define ARCHITECTURE_ARM64
constexpr auto architecture() -> Architecture { return Architecture::ARM64; }
#elif defined(__arm__)
#define ARCHITECTURE_ARM32
constexpr auto architecture() -> Architecture { return Architecture::ARM32; }
#elif defined(__ppc64__) || defined(_ARCH_PPC64)
#define ARCHITECTURE_PPC64
constexpr auto architecture() -> Architecture { return Architecture::PPC64; }
#elif defined(__ppc__) || defined(_ARCH_PPC) || defined(_M_PPC)
#define ARCHITECTURE_PPC32
constexpr auto architecture() -> Architecture { return Architecture::PPC32; }
#else
#warning "unable to detect architecture"
#define ARCHITECTURE_UNKNOWN
constexpr auto architecture() -> Architecture { return Architecture::Unknown; }
#endif
}
/* Endian detection */
#if defined(PLATFORM_MACOS)
#include <machine/endian.h>
#elif defined(PLATFORM_LINUX)
#include <endian.h>
#elif defined(PLATFORM_BSD)
#include <sys/endian.h>
#endif
namespace nall {
// A note on endian constants: Traditional UNIX provides a header that defines
// constants LITTLE_ENDIAN, BIG_ENDIAN, and BYTE_ORDER (set to LITTLE_ENDIAN or
// BIG_ENDIAN as appropriate). However, C89 says that the compiler/libc should
// not introduce any names unless they start with an underscore, so when you're
// compiling in standards-compilant mode, those constants are named
// __LITTLE_ENDIAN, or sometimes _LITTLE_ENDIAN, or sometimes even LITTLE_ENDIAN
// on platforms that care more about tradition than standards. The platforms
// that rename the constants usually provide some other name you can #define to
// say, "forget C89, yes I really want traditional constant names", but *that*
// name also differs from platform to platform, and it affects more than just
// the endian header.
//
// Rather than wade into that mess, let's just test for all the constants we
// know about.
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) \
|| (defined( _BYTE_ORDER) && defined( _LITTLE_ENDIAN) && _BYTE_ORDER == _LITTLE_ENDIAN) \
|| (defined( BYTE_ORDER) && defined( LITTLE_ENDIAN) && BYTE_ORDER == LITTLE_ENDIAN) \
|| defined(__LITTLE_ENDIAN__) \
|| defined(__i386__) || defined(__amd64__) \
|| defined(_M_IX86) || defined(_M_AMD64)
#define ENDIAN_LSB
constexpr auto endian() -> Endian { return Endian::LSB; }
#elif(defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) \
|| (defined( _BYTE_ORDER) && defined( _BIG_ENDIAN) && _BYTE_ORDER == _BIG_ENDIAN) \
|| (defined( BYTE_ORDER) && defined( BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) \
|| defined(__BIG_ENDIAN__) \
|| defined(__powerpc__) || defined(_M_PPC)
#define ENDIAN_MSB
constexpr auto endian() -> Endian { return Endian::MSB; }
#else
#warning "unable to detect endian"
#define ENDIAN_UNKNOWN
constexpr auto endian() -> Endian { return Endian::Unknown; }
#endif
}
/* Build optimization level detection */
#undef DEBUG
#undef NDEBUG
namespace nall {
#if defined(BUILD_DEBUG)
#define DEBUG
constexpr auto build() -> Build { return Build::Debug; }
#elif defined(BUILD_STABLE)
#define DEBUG
constexpr auto build() -> Build { return Build::Stable; }
#elif defined(BUILD_SIZE)
#define NDEBUG
constexpr auto build() -> Build { return Build::Size; }
#elif defined(BUILD_RELEASE)
#define NDEBUG
constexpr auto build() -> Build { return Build::Release; }
#elif defined(BUILD_PERFORMANCE)
#define NDEBUG
constexpr auto build() -> Build { return Build::Performance; }
#else
//default to debug mode
#define DEBUG
constexpr auto build() -> Build { return Build::Debug; }
#endif
}