forked from TerensTare/detector
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdetector.hpp
426 lines (346 loc) · 10.3 KB
/
detector.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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
#ifndef DETECTOR_HPP
#define DETECTOR_HPP
#ifdef __APPLE__
#include <TargetConditionals.h> // needed for detecting if on mac or on ios
#endif
#if __cplusplus >= 201703L
#define DETECT_INLINE inline
#else
#define DETECT_INLINE
#endif
#if (defined(_M_AMD64) || defined(_M_X64) || defined(__amd64)) && \
!defined(__x86_64__)
#define __x86_64__ 1
#endif
namespace detect {
namespace detail {
struct tag_type_t {
tag_type_t() = delete;
~tag_type_t() = delete;
tag_type_t(tag_type_t const &) = delete;
tag_type_t &operator=(tag_type_t const &) = delete;
tag_type_t(tag_type_t &&) = delete;
tag_type_t &operator=(tag_type_t &&) = delete;
};
} // namespace detail
//////////////////////
// os-related stuff //
//////////////////////
struct windows_t final : detail::tag_type_t {
~windows_t() = delete;
};
struct linux_t final : detail::tag_type_t {
~linux_t() = delete;
};
struct macos_t final : detail::tag_type_t {
~macos_t() = delete;
};
struct ios_t final : detail::tag_type_t {
~ios_t() = delete;
};
struct android_t final : detail::tag_type_t {
~android_t() = delete;
};
struct unix_t final : detail::tag_type_t {
~unix_t() = delete;
};
template <typename O> struct is_os;
template <> struct is_os<windows_t> {
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64)
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_os<linux_t> {
#if defined(__linux__) && !defined(__android__)
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_os<macos_t> {
#ifdef TARGET_OS_MAC
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_os<ios_t> {
#if defined(TARGET_IPHONE_SIMULATOR) || defined(TARGET_OS_IPHONE)
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_os<android_t> {
#ifdef __android__
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_os<unix_t> {
#if !defined(__linux__) && defined(__unix__)
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <typename O>
DETECT_INLINE static constexpr bool is_os_v = is_os<O>::value;
DETECT_INLINE static constexpr bool is_windows_v = is_os<windows_t>::value;
DETECT_INLINE static constexpr bool is_linux_v = is_os<linux_t>::value;
DETECT_INLINE static constexpr bool is_macos_v = is_os<macos_t>::value;
DETECT_INLINE static constexpr bool is_ios_v = is_os<ios_t>::value;
DETECT_INLINE static constexpr bool is_android_v = is_os<android_t>::value;
DETECT_INLINE static constexpr bool is_unix_v = is_os<unix_t>::value;
////////////////////////////
// compiler-related stuff //
////////////////////////////
struct gcc_t final : detail::tag_type_t {
~gcc_t() = delete;
};
struct clang_t final : detail::tag_type_t {
~clang_t() = delete;
};
struct msvc_t final : detail::tag_type_t {
~msvc_t() = delete;
};
struct mingw_t final : detail::tag_type_t {
~mingw_t() = delete;
};
template <typename C> struct is_compiler;
template <> struct is_compiler<gcc_t> {
#if defined(__GNUC__) && !defined(__clang__)
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_compiler<clang_t> {
#ifdef __clang__
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_compiler<msvc_t> {
#if defined(_MSC_VER) && !defined(__clang__)
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_compiler<mingw_t> {
#if defined(__MINGW32__) || !defined(__MINGW64__)
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <typename C>
DETECT_INLINE static constexpr bool is_compiler_v = is_compiler<C>::value;
DETECT_INLINE static constexpr bool is_gcc_v = is_compiler<gcc_t>::value;
DETECT_INLINE static constexpr bool is_clang_v = is_compiler<clang_t>::value;
DETECT_INLINE static constexpr bool is_msvc_v = is_compiler<msvc_t>::value;
DETECT_INLINE static constexpr bool is_mingw_v = is_compiler<mingw_t>::value;
////////////////////////////////
// C++ standard-related stuff //
////////////////////////////////
struct cxx_11 final : detail::tag_type_t {
~cxx_11() = delete;
};
struct cxx_14 final : detail::tag_type_t {
~cxx_14() = delete;
};
struct cxx_17 final : detail::tag_type_t {
~cxx_17() = delete;
};
struct cxx_20 final : detail::tag_type_t {
~cxx_20() = delete;
};
template <typename T> struct is_std;
template <> struct is_std<cxx_11> {
#if __cplusplus == 201103L
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_std<cxx_14> {
#if __cplusplus == 201402L
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_std<cxx_17> {
#if __cplusplus == 201703L
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_std<cxx_20> {
#if __cplusplus == 202002L
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <typename T>
DETECT_INLINE static constexpr bool is_std_v = is_std<T>::value;
DETECT_INLINE static constexpr bool is_cxx_11 = is_std<cxx_11>::value;
DETECT_INLINE static constexpr bool is_cxx_14 = is_std<cxx_14>::value;
DETECT_INLINE static constexpr bool is_cxx_17 = is_std<cxx_17>::value;
DETECT_INLINE static constexpr bool is_cxx_20 = is_std<cxx_20>::value;
/////////////////////////////////
// debug/release related stuff //
/////////////////////////////////
struct debug_t final : detail::tag_type_t {
~debug_t() = delete;
};
struct release_t final : detail::tag_type_t {
~release_t() = delete;
};
template <typename T> struct is_build;
template <> struct is_build<debug_t> {
#if defined(_DEBUG) || defined(DEBUG)
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_build<release_t> {
#if defined(NDEBUG) || !(defined(DEBUG) && defined(_DEBUG))
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <typename T>
DETECT_INLINE static constexpr bool is_build_v = is_build<T>::value;
DETECT_INLINE static constexpr bool is_debug_v = is_build<debug_t>::value;
DETECT_INLINE static constexpr bool is_release_v = is_build<release_t>::value;
///////////////////////
// simd instructions //
///////////////////////
struct x86sse_t final : detail::tag_type_t {
~x86sse_t() = delete;
};
struct x86sse2_t final : detail::tag_type_t {
~x86sse2_t() = delete;
};
struct sse_t final : detail::tag_type_t {
~sse_t() = delete;
};
struct sse2_t final : detail::tag_type_t {
~sse2_t() = delete;
};
struct sse3_t final : detail::tag_type_t {
~sse3_t() = delete;
};
struct ssse3_t final : detail::tag_type_t {
~ssse3_t() = delete;
};
struct sse4_1_t final : detail::tag_type_t {
~sse4_1_t() = delete;
};
struct sse4_2_t final : detail::tag_type_t {
~sse4_2_t() = delete;
};
struct avx_t final : detail::tag_type_t {
~avx_t() = delete;
};
struct avx2_t final : detail::tag_type_t {
~avx2_t() = delete;
};
template <typename S> struct is_simd;
template <> struct is_simd<x86sse_t> {
#if defined(_M_IX86_FP) && (_M_IX86_FP == 1)
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_simd<x86sse2_t> {
#if defined(_M_IX86_FP) && (_M_IX86_FP == 2)
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_simd<sse_t> {
#ifdef __SSE__
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_simd<sse2_t> {
#if defined(__SSE2__) || defined(__x86_x64__)
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_simd<sse3_t> {
#ifdef __SSE3__
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_simd<ssse3_t> {
#ifdef __SSSE3__
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_simd<sse4_1_t> {
#ifdef __SSE4_1__
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_simd<sse4_2_t> {
#ifdef __SSE4_2__
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_simd<avx_t> {
#ifdef __AVX__
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <> struct is_simd<avx2_t> {
#ifdef __AVX2__
DETECT_INLINE static constexpr bool value = true;
#else
DETECT_INLINE static constexpr bool value = false;
#endif
};
template <typename S>
DETECT_INLINE constexpr bool is_simd_v = is_simd<S>::value;
DETECT_INLINE constexpr bool is_x86_sse_t = is_simd<x86sse_t>::value;
DETECT_INLINE constexpr bool is_x86_sse2_t = is_simd<x86sse2_t>::value;
DETECT_INLINE constexpr bool is_sse_t = is_simd<sse_t>::value;
DETECT_INLINE constexpr bool is_sse2_t = is_simd<sse2_t>::value;
DETECT_INLINE constexpr bool is_sse3_t = is_simd<sse3_t>::value;
DETECT_INLINE constexpr bool is_ssse3_t = is_simd<ssse3_t>::value;
DETECT_INLINE constexpr bool is_sse4_1_t = is_simd<sse4_1_t>::value;
DETECT_INLINE constexpr bool is_sse4_2_t = is_simd<sse4_2_t>::value;
DETECT_INLINE constexpr bool is_avx_t = is_simd<avx_t>::value;
DETECT_INLINE constexpr bool is_avx2_t = is_simd<avx2_t>::value;
} // namespace detect
#ifdef __x86_64__
#undef __x86_64__
#endif
#endif // !DETECTOR_HPP