Gaia-ECS v0.9.3
A simple and powerful entity component system
Loading...
Searching...
No Matches
config_core.h
1#pragma once
2
3#if __has_include(<version.h>)
4 #include <version.h>
5#endif
6#include <cstdint>
7#include <new>
8
9//------------------------------------------------------------------------------
10// DO NOT MODIFY THIS FILE
11//------------------------------------------------------------------------------
12
13//------------------------------------------------------------------------------
14// CMake-only settings
15//------------------------------------------------------------------------------
16
17#if !defined(GAIA_DEVMODE)
18 #define GAIA_DEVMODE 0
19#endif
20#if !defined(GAIA_USE_SANITIZER)
21 #define GAIA_USE_SANITIZER 0
22#endif
23
24//------------------------------------------------------------------------------
25// Features
26//------------------------------------------------------------------------------
27
28#if defined(_MSVC_LANG)
29 #define GAIA_CPP_VERSION(version) (__cplusplus >= (version) || _MSVC_LANG >= (version))
30#else
31 #define GAIA_CPP_VERSION(version) (__cplusplus >= (version))
32#endif
33
34#if GAIA_CPP_VERSION(201703L)
35#else
36// We use some C++17+ features such as folding expressions, compile-time ifs
37// and similar which makes it impossible to use Gaia-ECS with old compilers.
38 #error "To build Gaia-ECS a compiler capable of at least C++17 is necessary"
39#endif
40
41#define GAIA_SAFE_CONSTEXPR constexpr
42
43#define GAIA_USE_STD_SPAN (GAIA_CPP_VERSION(202002L) && __has_include(<span>))
44
45//------------------------------------------------------------------------------
46// Features
47//------------------------------------------------------------------------------
48
49#define GAIA_ECS_HASH_FNV1A 0
50#define GAIA_ECS_HASH_MURMUR2A 1
51
52//------------------------------------------------------------------------------
53// Compiler
54//------------------------------------------------------------------------------
55#define GAIA_COMPILER_CLANG 0
56#define GAIA_COMPILER_GCC 0
57#define GAIA_COMPILER_MSVC 0
58#define GAIA_COMPILER_ICC 0
59#define GAIA_COMPILER_DETECTED 0
60
61#if !GAIA_COMPILER_DETECTED && (defined(__clang__))
62// Clang check is performed first as it might pretend to be MSVC or GCC by
63// defining their predefined macros.
64 #undef GAIA_COMPILER_CLANG
65 #define GAIA_COMPILER_CLANG 1
66 #undef GAIA_COMPILER_DETECTED
67 #define GAIA_COMPILER_DETECTED 1
68
69 // Distinguish clang-cl (MSVC front-end) from regular Clang
70 #if defined(_MSC_VER)
71 #undef GAIA_COMPILER_MSVC
72 #define GAIA_COMPILER_MSVC 1
73 #endif
74#endif
75#if !GAIA_COMPILER_DETECTED && \
76 (defined(__INTEL_COMPILER) || defined(__ICC) || defined(__ICL) || defined(__INTEL_LLVM_COMPILER))
77 #undef GAIA_COMPILER_ICC
78 #define GAIA_COMPILER_ICC 1
79 #undef GAIA_COMPILER_DETECTED
80 #define GAIA_COMPILER_DETECTED 1
81#endif
82#if !GAIA_COMPILER_DETECTED && (defined(__SNC__) || defined(__GNUC__))
83 #undef GAIA_COMPILER_GCC
84 #define GAIA_COMPILER_GCC 1
85 #undef GAIA_COMPILER_DETECTED
86 #define GAIA_COMPILER_DETECTED 1
87 #if __GNUC__ <= 7
88 // In some contexts, e.g. when evaluating PRETTY_FUNCTION, GCC has a bug
89 // where the string is not defined a constexpr and thus can't be evaluated
90 // in constexpr expressions.
91 #undef GAIA_SAFE_CONSTEXPR
92 #define GAIA_SAFE_CONSTEXPR const
93 #endif
94#endif
95#if !GAIA_COMPILER_DETECTED && (defined(_MSC_VER))
96 #undef GAIA_COMPILER_MSVC
97 #define GAIA_COMPILER_MSVC 1
98 #undef GAIA_COMPILER_DETECTED
99 #define GAIA_COMPILER_DETECTED 1
100#endif
101#if !GAIA_COMPILER_DETECTED
102 #error "Unrecognized compiler"
103#endif
104
105//------------------------------------------------------------------------------
106// Platform
107//------------------------------------------------------------------------------
108
109#define GAIA_PLATFORM_UNKNOWN 0
110#define GAIA_PLATFORM_WINDOWS 0
111#define GAIA_PLATFORM_LINUX 0
112#define GAIA_PLATFORM_APPLE 0
113#define GAIA_PLATFORM_FREEBSD 0
114#define GAIA_PLATFORM_WASM 0
115
116#ifdef _WIN32
117 #undef GAIA_PLATFORM_WINDOWS
118 #define GAIA_PLATFORM_WINDOWS 1
119#elif __APPLE__
120// MacOS, iOS, tvOS etc.
121// We could tell the platforms apart using #include "TargetConditionals.h"
122// but that is probably way more than we need to know.
123 #undef GAIA_PLATFORM_APPLE
124 #define GAIA_PLATFORM_APPLE 1
125#elif __linux__
126 #undef GAIA_PLATFORM_LINUX
127 #define GAIA_PLATFORM_LINUX 1
128#elif __FreeBSD__
129 #undef GAIA_PLATFORM_FREEBSD
130 #define GAIA_PLATFORM_FREEBSD 1
131#elif defined(__EMSCRIPTEN__)
132 #undef GAIA_PLATFORM_WASM
133 #define GAIA_PLATFORM_WASM 1
134#else
135 #undef GAIA_PLATFORM_UNKNOWN
136 #define GAIA_PLATFORM_UNKNOWN 1
137#endif
138
139//------------------------------------------------------------------------------
140// Architecture features
141//------------------------------------------------------------------------------
142#define GAIA_64 0
143#if defined(_WIN64) || defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64) || defined(__amd64) || \
144 defined(__aarch64__)
145 #undef GAIA_64
146 #define GAIA_64 1
147#endif
148
149#define GAIA_ARCH_X86 0
150#define GAIA_ARCH_ARM 1
151#define GAIA_ARCH_WASM 2
152
153#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__i386) || \
154 defined(i386) || defined(__x86_64__) || defined(_X86_)
155 #undef GAIA_ARCH
156 #define GAIA_ARCH GAIA_ARCH_X86
157#elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC)
158 #undef GAIA_ARCH
159 #define GAIA_ARCH GAIA_ARCH_ARM
160#elif defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__wasm32__) || defined(__wasm64__)
161 #undef GAIA_ARCH
162 #define GAIA_ARCH GAIA_ARCH_WASM
163#else
164 #error "Unrecognized target architecture."
165#endif
166
167//------------------------------------------------------------------------------
168
169#if GAIA_COMPILER_MSVC && !GAIA_COMPILER_CLANG
170 #define GAIA_PRETTY_FUNCTION __FUNCSIG__
171 #define GAIA_PRETTY_FUNCTION_PREFIX '<'
172 #define GAIA_PRETTY_FUNCTION_SUFFIX '>'
173#else
174 #define GAIA_PRETTY_FUNCTION __PRETTY_FUNCTION__
175 #define GAIA_PRETTY_FUNCTION_PREFIX '='
176 #define GAIA_PRETTY_FUNCTION_SUFFIX ']'
177#endif
178
179#define GAIA_STRINGIZE(x) #x
180#define GAIA_CONCAT_IMPL(x, y) x##y
181#define GAIA_CONCAT(x, y) GAIA_CONCAT_IMPL(x, y)
182
183#define GAIA_FOR(max) for (uint32_t i = 0; i < (max); ++i)
184#define GAIA_FOR_(max, varname) for (uint32_t varname = 0; varname < (max); ++varname)
185#define GAIA_FOR2(min, max) for (uint32_t i = (min); i < (max); ++i)
186#define GAIA_FOR2_(min, max, varname) for (uint32_t varname = (min); varname < (max); ++varname)
187#define GAIA_EACH(container) for (uint32_t i = 0; i < (container).size(); ++i)
188#define GAIA_EACH_(container, varname) for (uint32_t varname = 0; varname < (container).size(); ++varname)
189
190//------------------------------------------------------------------------------
191// Endianess
192// Endianess detection is hell as far as compile-time is concerned.
193// There is a bloat of macros and header files across different compilers,
194// platforms and C++ standard implementations.
195//------------------------------------------------------------------------------
196
197#if GAIA_COMPILER_MSVC
198 // Whether it is ARM or x86 we consider both little endian.
199 // It is very unlikely that any modern "big" CPU would use big endian these days
200 // as it is more efficient to be little endian on HW level.
201 #define GAIA_LITTLE_ENDIAN true
202 #define GAIA_BIG_ENDIAN false
203#else
204 #define GAIA_LITTLE_ENDIAN (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
205 #define GAIA_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
206#endif
207
211namespace gaia {
212 inline bool CheckEndianess() {
213 const uint16_t testWord = 0x1234;
214 const bool isLittleEndian(*reinterpret_cast<const uint8_t*>(&testWord) == 0x34);
215 return isLittleEndian && GAIA_LITTLE_ENDIAN;
216 }
217} // namespace gaia
218
219//------------------------------------------------------------------------------
220
224#define GAIA_MOV(x) static_cast<typename std::remove_reference<decltype(x)>::type&&>(x)
228#define GAIA_FWD(x) static_cast<decltype(x)&&>(x)
230#define GAIA_ACC(x) std::launder(x)
231
232#if (GAIA_COMPILER_MSVC && _MSC_VER >= 1400) || GAIA_COMPILER_GCC || GAIA_COMPILER_CLANG
233 #define GAIA_RESTRICT __restrict
234#else
235 #define GAIA_RESTRICT
236#endif
237
238#if GAIA_CPP_VERSION(202002L)
239 #if __has_cpp_attribute(nodiscard)
240 #define GAIA_NODISCARD [[nodiscard]]
241 #endif
242 #if __has_cpp_attribute(likely)
243 #define GAIA_LIKELY(cond) (cond) [[likely]]
244 #endif
245 #if __has_cpp_attribute(unlikely)
246 #define GAIA_UNLIKELY(cond) (cond) [[unlikely]]
247 #endif
248 #if __has_cpp_attribute(fallthrough)
249 #define GAIA_FALLTHROUGH [[fallthrough]]
250 #endif
251#endif
252#ifndef GAIA_NODISCARD
253 #define GAIA_NODISCARD
254#endif
255#if !defined(GAIA_LIKELY) && (GAIA_COMPILER_GCC || GAIA_COMPILER_CLANG)
256 #define GAIA_LIKELY(cond) (__builtin_expect((cond), 1))
257#endif
258#if !defined(GAIA_UNLIKELY) && (GAIA_COMPILER_GCC || GAIA_COMPILER_CLANG)
259 #define GAIA_UNLIKELY(cond) (__builtin_expect((cond), 0))
260#endif
261#ifndef GAIA_LIKELY
262 #define GAIA_LIKELY(cond) (cond)
263#endif
264#ifndef GAIA_UNLIKELY
265 #define GAIA_UNLIKELY(cond) (cond)
266#endif
267#ifndef GAIA_FALLTHROUGH
268 #define GAIA_FALLTHROUGH
269#endif
270
271// GCC 7 and some later versions had a bug that would artificially restrict alignas for stack
272// variables to 16 bytes.
273// However, using the compiler custom attribute would still work. Therefore, because it is
274// more portable, we shall introduce the GAIA_ALIGNAS macro.
275// Read about the bug here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89357
276#if GAIA_COMPILER_GCC
277 #define GAIA_ALIGNAS(alignment) __attribute__((aligned(alignment)))
278#else
279 #define GAIA_ALIGNAS(alignment) alignas(alignment)
280#endif
281
282#ifndef GAIA_CACHELINE_SIZE
283 #ifdef __cpp_lib_hardware_interference_size
284 #define GAIA_CACHELINE_SIZE std::hardware_constructive_interference_size
285 #elif defined(__GCC_DESTRUCTIVE_SIZE)
286 #define GAIA_CACHELINE_SIZE __GCC_DESTRUCTIVE_SIZE
287 #else
288 #if GAIA_ARCH == GAIA_ARCH_ARM
289 // For ARM cache line sizes are not strict as they depend on implementation,
290 // not architecture. They usually have 64 or 128 byte long cache lines. We pick
291 // the longer one but feel free to use one that suits your needs better.
292 // E.g. you can define the value before you include gaia.h or define the macro
293 // per-project in your build system per target architecture.
294 #define GAIA_CACHELINE_SIZE 128
295 #else
296 #define GAIA_CACHELINE_SIZE 64
297 #endif
298 #endif
299#endif
300
301// Yielding the CPU core. This is meant purely as a CPU function and has little to
302// do with yield functions available for your OS. No CPU time slice is yielded
303// to the operation system like pause(), sched_yield() or std::this_thread::yield()
304// would do. Don't mix them up. This is meant to be used with spinlocks and such,
305// and prevent the CPU from hammering on the cache line too much.
306#if GAIA_ARCH == GAIA_ARCH_X86
307 #include <immintrin.h>
308 #define GAIA_YIELD_CPU _mm_pause()
309#elif GAIA_ARCH == GAIA_ARCH_ARM
310 #if GAIA_COMPILER_CLANG
311 #define GAIA_YIELD_CPU __builtin_arm_yield()
312 #elif GAIA_COMPILER_GCC
313 #define GAIA_YIELD_CPU __asm__ volatile("yield" ::: "memory");
314 #endif
315#endif
316#if !defined(GAIA_YIELD_CPU)
317 #define GAIA_YIELD_CPU \
318 do { \
319 } while (0)
320#endif
321
322#if GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
324 #define GAIA_POPCNT(x) ((uint32_t)__builtin_popcount(static_cast<uint32_t>(x)))
326 #define GAIA_POPCNT64(x) ((uint32_t)__builtin_popcountll(static_cast<unsigned long long>(x)))
327
330 #define GAIA_CLZ(x) ((x) ? (uint32_t)__builtin_ctz(static_cast<uint32_t>(x)) : (uint32_t)32)
333 #define GAIA_CLZ64(x) ((x) ? (uint32_t)__builtin_ctzll(static_cast<unsigned long long>(x)) : (uint32_t)64)
334
337 #define GAIA_CTZ(x) ((x) ? (uint32_t)__builtin_clz(static_cast<uint32_t>(x)) : (uint32_t)32)
340 #define GAIA_CTZ64(x) ((x) ? (uint32_t)__builtin_clzll(static_cast<unsigned long long>(x)) : (uint32_t)64)
341
344 #define GAIA_FFS(x) ((uint32_t)__builtin_ffs(static_cast<int>(x)))
347 #define GAIA_FFS64(x) ((uint32_t)__builtin_ffsll(static_cast<long long>(x)))
348#elif GAIA_COMPILER_MSVC
349 #if _MSC_VER <= 1916
350 #include <intrin.h>
351 #endif
352 // MSVC doesn't implement __popcnt for ARM so we need to do it ourselves
353 #if GAIA_ARCH == GAIA_ARCH_ARM
354 #include <arm_neon.h>
356 #define GAIA_POPCNT(x) \
357 ([](uint32_t value) noexcept { \
358 const __n64 tmp = neon_cnt(__uint64ToN64_v(value)); \
359 return (uint32_t)neon_addv8(tmp).n8_i8[0]; \
360 }(x))
362 #define GAIA_POPCNT64(x) \
363 ([](uint64_t value) noexcept { \
364 const __n64 tmp = neon_cnt(__uint64ToN64_v(value)); \
365 return (uint32_t)neon_addv8(tmp).n8_i8[0]; \
366 }(x))
367 #else
369 #define GAIA_POPCNT(x) ((uint32_t)__popcnt(x))
371 #define GAIA_POPCNT64(x) ((uint32_t)__popcnt64(x))
372 #endif
373
374 #pragma intrinsic(_BitScanForward)
377 #define GAIA_CLZ(x) \
378 ([](uint32_t value) noexcept { \
379 unsigned long index; \
380 return _BitScanForward(&index, value) ? (uint32_t)index : (uint32_t)32; \
381 }(x))
382 #pragma intrinsic(_BitScanForward64)
385 #define GAIA_CLZ64(x) \
386 ([](uint64_t value) noexcept { \
387 unsigned long index; \
388 return _BitScanForward64(&index, value) ? (uint32_t)index : (uint32_t)64; \
389 }(x))
390
391 #pragma intrinsic(_BitScanReverse)
394 #define GAIA_CTZ(x) \
395 ([](uint32_t value) noexcept { \
396 unsigned long index; \
397 return _BitScanReverse(&index, value) ? 31U - (uint32_t)index : (uint32_t)32; \
398 }(x))
399 #pragma intrinsic(_BitScanReverse64)
402 #define GAIA_CTZ64(x) \
403 ([](uint64_t value) noexcept { \
404 unsigned long index; \
405 return _BitScanReverse64(&index, value) ? 63U - (uint32_t)index : (uint32_t)64; \
406 }(x))
407
408 #pragma intrinsic(_BitScanForward)
411 #define GAIA_FFS(x) \
412 ([](uint32_t value) noexcept { \
413 unsigned long index; \
414 if (_BitScanForward(&index, value)) \
415 return (uint32_t)(index + 1); \
416 return (uint32_t)0; \
417 }(x))
418 #pragma intrinsic(_BitScanForward64)
421 #define GAIA_FFS64(x) \
422 ([](uint64_t value) noexcept { \
423 unsigned long index; \
424 if (_BitScanForward64(&index, value)) \
425 return (uint32_t)(index + 1); \
426 return (uint32_t)0; \
427 }(x))
428#else
430 #define GAIA_POPCNT(x) \
431 ([](uint32_t value) noexcept -> uint32_t { \
432 uint32_t bitsSet = 0; \
433 while (value != 0) { \
434 value &= (value - 1); \
435 ++bitsSet; \
436 } \
437 return bitsSet; \
438 }(x))
440 #define GAIA_POPCNT64(x) \
441 ([](uint64_t value) noexcept -> uint32_t { \
442 uint32_t bitsSet = 0; \
443 while (value != 0) { \
444 value &= (value - 1); \
445 ++bitsSet; \
446 } \
447 return bitsSet; \
448 }(x))
449
452 #define GAIA_CLZ(x) \
453 ([](uint32_t value) noexcept -> uint32_t { \
454 if (value == 0) \
455 return 32; \
456 uint32_t index = 0; \
457 while (((value >> index) & 1) == 0) \
458 ++index; \
459 return index; \
460 }(x))
463 #define GAIA_CLZ64(x) \
464 ([](uint64_t value) noexcept -> uint32_t { \
465 if (value == 0) \
466 return 64; \
467 uint32_t index = 0; \
468 while (((value >> index) & 1) == 0) \
469 ++index; \
470 return index; \
471 }(x))
472
475 #define GAIA_CTZ(x) \
476 ([](uint32_t value) noexcept -> uint32_t { \
477 if (value == 0) \
478 return 32; \
479 uint32_t index = 0; \
480 while (((value << index) & 0x80000000) == 0) \
481 ++index; \
482 return index; \
483 }(x))
486 #define GAIA_CTZ64(x) \
487 ([](uint64_t value) noexcept -> uint32_t { \
488 if (value == 0) \
489 return 64; \
490 uint32_t index = 0; \
491 while (((value << index) & 0x8000000000000000LL) == 0) \
492 ++index; \
493 return index; \
494 }(x))
495
498 #define GAIA_FFS(x) \
499 ([](uint32_t value) noexcept -> uint32_t { \
500 if (value == 0) \
501 return 0; \
502 uint32_t index = 0; \
503 while (((value >> index) & 1) == 0) \
504 ++index; \
505 return index + 1; \
506 }(x))
509 #define GAIA_FFS64(x) \
510 ([](uint64_t value) noexcept -> uint32_t { \
511 if (value == 0) \
512 return 0; \
513 uint32_t index = 0; \
514 while (((value >> index) & 1) == 0) \
515 ++index; \
516 return index + 1; \
517 }(x))
518#endif
519
520//------------------------------------------------------------------------------
521
522#if GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
523 #define GAIA_FORCEINLINE inline __attribute__((always_inline))
524 #define GAIA_NOINLINE __attribute__((noinline))
525#elif GAIA_COMPILER_MSVC || GAIA_COMPILER_ICC
526 #define GAIA_FORCEINLINE __forceinline
527 #define GAIA_NOINLINE __declspec(noinline)
528#else
529 #define GAIA_FORCEINLINE inline
530 #define GAIA_NOINLINE
531#endif
532
533#if GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
534 #define GAIA_LAMBDAINLINE __attribute__((always_inline))
535#elif GAIA_COMPILER_MSVC
536 #if _MSC_VER >= 1927 && _MSVC_LANG > 202002L // MSVC 16.7 or newer &&�/std:c++latest
537 #define GAIA_LAMBDAINLINE [[msvc::forceinline]]
538 #else
539 #define GAIA_LAMBDAINLINE
540 #endif
541#else
542 #define GAIA_LAMBDAINLINE
543#endif
544
545#ifdef __has_cpp_attribute
546 #if __has_cpp_attribute(assume) >= 202207L && GAIA_CPP_VERSION(202207L)
547 #define GAIA_ASSUME(...) [[assume(__VA_ARGS__)]]
548 #endif
549#endif
550#ifndef GAIA_ASSUME
551 #if GAIA_COMPILER_CLANG
552 #define GAIA_ASSUME(...) __builtin_assume(__VA_ARGS__)
553 #elif GAIA_COMPILER_MSVC
554 #define GAIA_ASSUME(...) __assume(__VA_ARGS__)
555 #elif (GAIA_COMPILER_GCC && __GNUC__ >= 13)
556 #define GAIA_ASSUME(...) __attribute__((__assume__(__VA_ARGS__)))
557 #endif
558#endif
559#ifndef GAIA_ASSUME
560 #define GAIA_ASSUME(...)
561#endif
562
563//------------------------------------------------------------------------------
564
565#if GAIA_COMPILER_MSVC
566 #define GAIA_IMPORT __declspec(dllimport)
567 #define GAIA_EXPORT __declspec(dllexport)
568 #define GAIA_HIDDEN
569#elif GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
570 #define GAIA_IMPORT __attribute__((visibility("default")))
571 #define GAIA_EXPORT __attribute__((visibility("default")))
572 #define GAIA_HIDDEN __attribute__((visibility("hidden")))
573#endif
574
575#define GAIA_API
576// NOTE: Gaia is currently a header-only library so exporting/importing should not be necessary
577// #if defined(GAIA_USE_DLL) // Use DLL file (defined by the executable)
578// #define GAIA_API GAIA_IMPORT
579// #elif defined(GAIA_GEN_DLL) // Generate DLL file (defined inside DLL)
580// #define GAIA_API GAIA_EXPORT
581// #else
582// #define GAIA_API
583// #endif
584
585//------------------------------------------------------------------------------
586// Warning-related macros and settings
587// We always set warnings as errors and disable ones we don't care about.
588// Sometimes in only limited range of code or around 3rd party includes.
589//------------------------------------------------------------------------------
590
591#if GAIA_COMPILER_MSVC
592 #define GAIA_MSVC_WARNING_PUSH() __pragma(warning(push))
593 #define GAIA_MSVC_WARNING_POP() __pragma(warning(pop))
594 #define GAIA_MSVC_WARNING_DISABLE(warningId) __pragma(warning(disable : warningId))
595 #define GAIA_MSVC_WARNING_ERROR(warningId) __pragma(warning(error : warningId))
596#else
597 #define GAIA_MSVC_WARNING_PUSH()
598 #define GAIA_MSVC_WARNING_POP()
599 #define GAIA_MSVC_WARNING_DISABLE(warningId)
600 #define GAIA_MSVC_WARNING_ERROR(warningId)
601#endif
602
603#if GAIA_COMPILER_CLANG
604 #define DO_PRAGMA_(x) _Pragma(#x)
605 #define DO_PRAGMA(x) DO_PRAGMA_(x)
606 #define GAIA_CLANG_WARNING_PUSH() _Pragma("clang diagnostic push")
607 #define GAIA_CLANG_WARNING_POP() _Pragma("clang diagnostic pop")
608 #define GAIA_CLANG_WARNING_DISABLE(warningId) DO_PRAGMA(clang diagnostic ignored warningId)
609 #define GAIA_CLANG_WARNING_ERROR(warningId) DO_PRAGMA(clang diagnostic error warningId)
610 #define GAIA_CLANG_WARNING_ALLOW(warningId) DO_PRAGMA(clang diagnostic warning warningId)
611#else
612 #define GAIA_CLANG_WARNING_PUSH()
613 #define GAIA_CLANG_WARNING_POP()
614 #define GAIA_CLANG_WARNING_DISABLE(warningId)
615 #define GAIA_CLANG_WARNING_ERROR(warningId)
616 #define GAIA_CLANG_WARNING_ALLOW(warningId)
617#endif
618
619#if GAIA_COMPILER_GCC
620 #define DO_PRAGMA_(x) _Pragma(#x)
621 #define DO_PRAGMA(x) DO_PRAGMA_(x)
622 #define GAIA_GCC_WARNING_PUSH() _Pragma("GCC diagnostic push")
623 #define GAIA_GCC_WARNING_POP() _Pragma("GCC diagnostic pop")
624 #define GAIA_GCC_WARNING_ERROR(warningId) DO_PRAGMA(GCC diagnostic error warningId)
625 #define GAIA_GCC_WARNING_DISABLE(warningId) DO_PRAGMA(GCC diagnostic ignored warningId)
626#else
627 #define GAIA_GCC_WARNING_PUSH()
628 #define GAIA_GCC_WARNING_POP()
629 #define GAIA_GCC_WARNING_DISABLE(warningId)
630#endif
631
632#define GAIA_HAS_NO_INLINE_ASSEMBLY 0
633#if (!defined(__GNUC__) && !defined(__clang__)) || defined(__pnacl__) || defined(__EMSCRIPTEN__)
634 #undef GAIA_HAS_NO_INLINE_ASSEMBLY
635 #define GAIA_HAS_NO_INLINE_ASSEMBLY 1
636#endif
637
638namespace gaia {
639 // The dont_optimize(...) function can be used to prevent a value or
640 // expression from being optimized away by the compiler. This function is
641 // intended to add little to no overhead.
642 // See: https://youtu.be/nXaxk27zwlk?t=2441
643#if !GAIA_HAS_NO_INLINE_ASSEMBLY
644 template <class T>
645 inline void dont_optimize(T const& value) {
646 asm volatile("" : : "r,m"(value) : "memory");
647 }
648
649 template <class T>
650 inline void dont_optimize(T& value) {
651 #if defined(__clang__)
652 asm volatile("" : "+r,m"(value) : : "memory");
653 #else
654 asm volatile("" : "+m,r"(value) : : "memory");
655 #endif
656 }
657#else
658 namespace detail {
659 inline void use_char_pointer(char const volatile* var) {
660 (void)var;
661 }
662 } // namespace detail
663
664 #if defined(_MSC_VER)
665 template <class T>
666 inline void dont_optimize(T const& value) {
667 detail::use_char_pointer(&reinterpret_cast<char const volatile&>(value));
668 ::_ReadWriteBarrier();
669 }
670 #else
671 template <class T>
672 inline void dont_optimize(T const& value) {
673 detail::use_char_pointer(&reinterpret_cast<char const volatile&>(value));
674 }
675 #endif
676#endif
677} // namespace gaia
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9