Gaia-ECS v1.0.0
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_USE_STD_SPAN (GAIA_CPP_VERSION(202002L) && __has_include(<span>))
42
43//------------------------------------------------------------------------------
44// Features
45//------------------------------------------------------------------------------
46
47#define GAIA_ECS_HASH_FNV1A 0
48#define GAIA_ECS_HASH_MURMUR2A 1
49
50//------------------------------------------------------------------------------
51// Compiler
52//------------------------------------------------------------------------------
53#define GAIA_COMPILER_CLANG 0
54#define GAIA_COMPILER_GCC 0
55#define GAIA_COMPILER_MSVC 0
56#define GAIA_COMPILER_ICC 0
57#define GAIA_COMPILER_DETECTED 0
58
59#if !GAIA_COMPILER_DETECTED && (defined(__clang__))
60// Clang check is performed first as it might pretend to be MSVC or GCC by
61// defining their predefined macros.
62 #undef GAIA_COMPILER_CLANG
63 #define GAIA_COMPILER_CLANG 1
64 #undef GAIA_COMPILER_DETECTED
65 #define GAIA_COMPILER_DETECTED 1
66
67 // Distinguish clang-cl (MSVC front-end) from regular Clang
68 #if defined(_MSC_VER)
69 #undef GAIA_COMPILER_MSVC
70 #define GAIA_COMPILER_MSVC 1
71 #endif
72#endif
73#if !GAIA_COMPILER_DETECTED && \
74 (defined(__INTEL_COMPILER) || defined(__ICC) || defined(__ICL) || defined(__INTEL_LLVM_COMPILER))
75 #undef GAIA_COMPILER_ICC
76 #define GAIA_COMPILER_ICC 1
77 #undef GAIA_COMPILER_DETECTED
78 #define GAIA_COMPILER_DETECTED 1
79#endif
80#if !GAIA_COMPILER_DETECTED && (defined(__SNC__) || defined(__GNUC__))
81 #undef GAIA_COMPILER_GCC
82 #define GAIA_COMPILER_GCC 1
83 #undef GAIA_COMPILER_DETECTED
84 #define GAIA_COMPILER_DETECTED 1
85#endif
86#if !GAIA_COMPILER_DETECTED && (defined(_MSC_VER))
87 #undef GAIA_COMPILER_MSVC
88 #define GAIA_COMPILER_MSVC 1
89 #undef GAIA_COMPILER_DETECTED
90 #define GAIA_COMPILER_DETECTED 1
91#endif
92#if !GAIA_COMPILER_DETECTED
93 #error "Unrecognized compiler"
94#endif
95
96//------------------------------------------------------------------------------
97// Platform
98//------------------------------------------------------------------------------
99
100#define GAIA_PLATFORM_UNKNOWN 0
101#define GAIA_PLATFORM_WINDOWS 0
102#define GAIA_PLATFORM_LINUX 0
103#define GAIA_PLATFORM_APPLE 0
104#define GAIA_PLATFORM_FREEBSD 0
105#define GAIA_PLATFORM_WASM 0
106
107#ifdef _WIN32
108 #undef GAIA_PLATFORM_WINDOWS
109 #define GAIA_PLATFORM_WINDOWS 1
110#elif __APPLE__
111// MacOS, iOS, tvOS etc.
112// We could tell the platforms apart using #include "TargetConditionals.h"
113// but that is probably way more than we need to know.
114 #undef GAIA_PLATFORM_APPLE
115 #define GAIA_PLATFORM_APPLE 1
116#elif __linux__
117 #undef GAIA_PLATFORM_LINUX
118 #define GAIA_PLATFORM_LINUX 1
119#elif __FreeBSD__
120 #undef GAIA_PLATFORM_FREEBSD
121 #define GAIA_PLATFORM_FREEBSD 1
122#elif defined(__EMSCRIPTEN__)
123 #undef GAIA_PLATFORM_WASM
124 #define GAIA_PLATFORM_WASM 1
125#else
126 #undef GAIA_PLATFORM_UNKNOWN
127 #define GAIA_PLATFORM_UNKNOWN 1
128#endif
129
130//------------------------------------------------------------------------------
131// Architecture features
132//------------------------------------------------------------------------------
133#define GAIA_64 0
134#if defined(_WIN64) || defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64) || defined(__amd64) || \
135 defined(__aarch64__)
136 #undef GAIA_64
137 #define GAIA_64 1
138#endif
139
140#define GAIA_ARCH_X86 0
141#define GAIA_ARCH_ARM 1
142#define GAIA_ARCH_WASM 2
143
144#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__i386) || \
145 defined(i386) || defined(__x86_64__) || defined(_X86_)
146 #undef GAIA_ARCH
147 #define GAIA_ARCH GAIA_ARCH_X86
148#elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC)
149 #undef GAIA_ARCH
150 #define GAIA_ARCH GAIA_ARCH_ARM
151#elif defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__wasm32__) || defined(__wasm64__)
152 #undef GAIA_ARCH
153 #define GAIA_ARCH GAIA_ARCH_WASM
154#else
155 #error "Unrecognized target architecture."
156#endif
157
158//------------------------------------------------------------------------------
159
160#if GAIA_COMPILER_MSVC && !GAIA_COMPILER_CLANG
161 #define GAIA_PRETTY_FUNCTION __FUNCSIG__
162 #define GAIA_PRETTY_FUNCTION_PREFIX '<'
163 #define GAIA_PRETTY_FUNCTION_SUFFIX '>'
164#else
165 #define GAIA_PRETTY_FUNCTION __PRETTY_FUNCTION__
166 #define GAIA_PRETTY_FUNCTION_PREFIX '='
167 #define GAIA_PRETTY_FUNCTION_SUFFIX ']'
168#endif
169
170#define GAIA_STRINGIZE(x) #x
171#define GAIA_CONCAT_IMPL(x, y) x##y
172#define GAIA_CONCAT(x, y) GAIA_CONCAT_IMPL(x, y)
173
174#define GAIA_FOR(max) for (uint32_t i = 0; i < (max); ++i)
175#define GAIA_FOR_(max, varname) for (uint32_t varname = 0; varname < (max); ++varname)
176#define GAIA_FOR2(min, max) for (uint32_t i = (min); i < (max); ++i)
177#define GAIA_FOR2_(min, max, varname) for (uint32_t varname = (min); varname < (max); ++varname)
178#define GAIA_EACH(container) for (uint32_t i = 0; i < (container).size(); ++i)
179#define GAIA_EACH_(container, varname) for (uint32_t varname = 0; varname < (container).size(); ++varname)
180
181//------------------------------------------------------------------------------
182// Endianess
183// Endianess detection is hell as far as compile-time is concerned.
184// There is a bloat of macros and header files across different compilers,
185// platforms and C++ standard implementations.
186//------------------------------------------------------------------------------
187
188#if GAIA_COMPILER_MSVC
189 // Whether it is ARM or x86 we consider both little endian.
190 // It is very unlikely that any modern "big" CPU would use big endian these days
191 // as it is more efficient to be little endian on HW level.
192 #define GAIA_LITTLE_ENDIAN true
193 #define GAIA_BIG_ENDIAN false
194#else
195 #define GAIA_LITTLE_ENDIAN (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
196 #define GAIA_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
197#endif
198
199namespace gaia {
203 inline bool CheckEndianess() {
204 const uint16_t testWord = 0x1234;
205 const bool isLittleEndian(*reinterpret_cast<const uint8_t*>(&testWord) == 0x34);
206 return isLittleEndian && GAIA_LITTLE_ENDIAN;
207 }
208} // namespace gaia
209
210//------------------------------------------------------------------------------
211
215#define GAIA_MOV(x) static_cast<typename std::remove_reference<decltype(x)>::type&&>(x)
222#define GAIA_FWD(x) static_cast<decltype(x)&&>(x)
227#define GAIA_FWD_AS(T, x) static_cast<T&&>(x)
229#define GAIA_ACC(x) std::launder(x)
230
231#if (GAIA_COMPILER_MSVC && _MSC_VER >= 1400) || GAIA_COMPILER_GCC || GAIA_COMPILER_CLANG
232 #define GAIA_RESTRICT __restrict
233#else
234 #define GAIA_RESTRICT
235#endif
236
237#if GAIA_CPP_VERSION(202002L)
238 #if __has_cpp_attribute(nodiscard)
239 #define GAIA_NODISCARD [[nodiscard]]
240 #endif
241 #if __has_cpp_attribute(likely)
242 #define GAIA_LIKELY(cond) (cond) [[likely]]
243 #endif
244 #if __has_cpp_attribute(unlikely)
245 #define GAIA_UNLIKELY(cond) (cond) [[unlikely]]
246 #endif
247 #if __has_cpp_attribute(fallthrough)
248 #define GAIA_FALLTHROUGH [[fallthrough]]
249 #endif
250#endif
251#ifndef GAIA_NODISCARD
252 #define GAIA_NODISCARD
253#endif
254#if !defined(GAIA_LIKELY) && (GAIA_COMPILER_GCC || GAIA_COMPILER_CLANG)
255 #define GAIA_LIKELY(cond) (__builtin_expect((cond), 1))
256#endif
257#if !defined(GAIA_UNLIKELY) && (GAIA_COMPILER_GCC || GAIA_COMPILER_CLANG)
258 #define GAIA_UNLIKELY(cond) (__builtin_expect((cond), 0))
259#endif
260#ifndef GAIA_LIKELY
261 #define GAIA_LIKELY(cond) (cond)
262#endif
263#ifndef GAIA_UNLIKELY
264 #define GAIA_UNLIKELY(cond) (cond)
265#endif
266#ifndef GAIA_FALLTHROUGH
267 #define GAIA_FALLTHROUGH
268#endif
269
270#ifndef GAIA_CACHELINE_SIZE
271 #ifdef __cpp_lib_hardware_interference_size
272 #define GAIA_CACHELINE_SIZE std::hardware_constructive_interference_size
273 #elif defined(__GCC_DESTRUCTIVE_SIZE)
274 #define GAIA_CACHELINE_SIZE __GCC_DESTRUCTIVE_SIZE
275 #else
276 #if GAIA_ARCH == GAIA_ARCH_ARM
277 // For ARM cache line sizes are not strict as they depend on implementation,
278 // not architecture. They usually have 64 or 128 byte long cache lines. We pick
279 // the longer one but feel free to use one that suits your needs better.
280 // E.g. you can define the value before you include gaia.h or define the macro
281 // per-project in your build system per target architecture.
282 #define GAIA_CACHELINE_SIZE 128
283 #else
284 #define GAIA_CACHELINE_SIZE 64
285 #endif
286 #endif
287#endif
288
289// Yielding the CPU core. This is meant purely as a CPU function and has little to
290// do with yield functions available for your OS. No CPU time slice is yielded
291// to the operation system like pause(), sched_yield() or std::this_thread::yield()
292// would do. Don't mix them up. This is meant to be used with spinlocks and such,
293// and prevent the CPU from hammering on the cache line too much.
294#if GAIA_ARCH == GAIA_ARCH_X86
295 #include <immintrin.h>
296 #define GAIA_YIELD_CPU _mm_pause()
297#elif GAIA_ARCH == GAIA_ARCH_ARM
298 #if GAIA_COMPILER_CLANG
299 #define GAIA_YIELD_CPU __builtin_arm_yield()
300 #elif GAIA_COMPILER_GCC
301 #define GAIA_YIELD_CPU __asm__ volatile("yield" ::: "memory");
302 #endif
303#endif
304#if !defined(GAIA_YIELD_CPU)
305 #define GAIA_YIELD_CPU \
306 do { \
307 } while (0)
308#endif
309
310#if GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
312 #define GAIA_POPCNT(x) ((uint32_t)__builtin_popcount(static_cast<uint32_t>(x)))
314 #define GAIA_POPCNT64(x) ((uint32_t)__builtin_popcountll(static_cast<unsigned long long>(x)))
315
318 #define GAIA_CLZ(x) ((x) ? (uint32_t)__builtin_ctz(static_cast<uint32_t>(x)) : (uint32_t)32)
321 #define GAIA_CLZ64(x) ((x) ? (uint32_t)__builtin_ctzll(static_cast<unsigned long long>(x)) : (uint32_t)64)
322
325 #define GAIA_CTZ(x) ((x) ? (uint32_t)__builtin_clz(static_cast<uint32_t>(x)) : (uint32_t)32)
328 #define GAIA_CTZ64(x) ((x) ? (uint32_t)__builtin_clzll(static_cast<unsigned long long>(x)) : (uint32_t)64)
329
332 #define GAIA_FFS(x) ((uint32_t)__builtin_ffs(static_cast<int>(x)))
335 #define GAIA_FFS64(x) ((uint32_t)__builtin_ffsll(static_cast<long long>(x)))
336#elif GAIA_COMPILER_MSVC
337 #if _MSC_VER <= 1916
338 #include <intrin.h>
339 #endif
340 // MSVC doesn't implement __popcnt for ARM so we need to do it ourselves
341 #if GAIA_ARCH == GAIA_ARCH_ARM
342 #include <arm_neon.h>
344 #define GAIA_POPCNT(x) \
345 ([](uint32_t value) noexcept { \
346 const __n64 tmp = neon_cnt(__uint64ToN64_v(value)); \
347 return (uint32_t)neon_addv8(tmp).n8_i8[0]; \
348 }(x))
350 #define GAIA_POPCNT64(x) \
351 ([](uint64_t value) noexcept { \
352 const __n64 tmp = neon_cnt(__uint64ToN64_v(value)); \
353 return (uint32_t)neon_addv8(tmp).n8_i8[0]; \
354 }(x))
355 #else
357 #define GAIA_POPCNT(x) ((uint32_t)__popcnt(x))
359 #define GAIA_POPCNT64(x) ((uint32_t)__popcnt64(x))
360 #endif
361
362 #pragma intrinsic(_BitScanForward)
365 #define GAIA_CLZ(x) \
366 ([](uint32_t value) noexcept { \
367 unsigned long index; \
368 return _BitScanForward(&index, value) ? (uint32_t)index : (uint32_t)32; \
369 }(x))
370 #pragma intrinsic(_BitScanForward64)
373 #define GAIA_CLZ64(x) \
374 ([](uint64_t value) noexcept { \
375 unsigned long index; \
376 return _BitScanForward64(&index, value) ? (uint32_t)index : (uint32_t)64; \
377 }(x))
378
379 #pragma intrinsic(_BitScanReverse)
382 #define GAIA_CTZ(x) \
383 ([](uint32_t value) noexcept { \
384 unsigned long index; \
385 return _BitScanReverse(&index, value) ? 31U - (uint32_t)index : (uint32_t)32; \
386 }(x))
387 #pragma intrinsic(_BitScanReverse64)
390 #define GAIA_CTZ64(x) \
391 ([](uint64_t value) noexcept { \
392 unsigned long index; \
393 return _BitScanReverse64(&index, value) ? 63U - (uint32_t)index : (uint32_t)64; \
394 }(x))
395
396 #pragma intrinsic(_BitScanForward)
399 #define GAIA_FFS(x) \
400 ([](uint32_t value) noexcept { \
401 unsigned long index; \
402 if (_BitScanForward(&index, value)) \
403 return (uint32_t)(index + 1); \
404 return (uint32_t)0; \
405 }(x))
406 #pragma intrinsic(_BitScanForward64)
409 #define GAIA_FFS64(x) \
410 ([](uint64_t value) noexcept { \
411 unsigned long index; \
412 if (_BitScanForward64(&index, value)) \
413 return (uint32_t)(index + 1); \
414 return (uint32_t)0; \
415 }(x))
416#else
418 #define GAIA_POPCNT(x) \
419 ([](uint32_t value) noexcept -> uint32_t { \
420 uint32_t bitsSet = 0; \
421 while (value != 0) { \
422 value &= (value - 1); \
423 ++bitsSet; \
424 } \
425 return bitsSet; \
426 }(x))
428 #define GAIA_POPCNT64(x) \
429 ([](uint64_t value) noexcept -> uint32_t { \
430 uint32_t bitsSet = 0; \
431 while (value != 0) { \
432 value &= (value - 1); \
433 ++bitsSet; \
434 } \
435 return bitsSet; \
436 }(x))
437
440 #define GAIA_CLZ(x) \
441 ([](uint32_t value) noexcept -> uint32_t { \
442 if (value == 0) \
443 return 32; \
444 uint32_t index = 0; \
445 while (((value >> index) & 1) == 0) \
446 ++index; \
447 return index; \
448 }(x))
451 #define GAIA_CLZ64(x) \
452 ([](uint64_t value) noexcept -> uint32_t { \
453 if (value == 0) \
454 return 64; \
455 uint32_t index = 0; \
456 while (((value >> index) & 1) == 0) \
457 ++index; \
458 return index; \
459 }(x))
460
463 #define GAIA_CTZ(x) \
464 ([](uint32_t value) noexcept -> uint32_t { \
465 if (value == 0) \
466 return 32; \
467 uint32_t index = 0; \
468 while (((value << index) & 0x80000000) == 0) \
469 ++index; \
470 return index; \
471 }(x))
474 #define GAIA_CTZ64(x) \
475 ([](uint64_t value) noexcept -> uint32_t { \
476 if (value == 0) \
477 return 64; \
478 uint32_t index = 0; \
479 while (((value << index) & 0x8000000000000000LL) == 0) \
480 ++index; \
481 return index; \
482 }(x))
483
486 #define GAIA_FFS(x) \
487 ([](uint32_t value) noexcept -> uint32_t { \
488 if (value == 0) \
489 return 0; \
490 uint32_t index = 0; \
491 while (((value >> index) & 1) == 0) \
492 ++index; \
493 return index + 1; \
494 }(x))
497 #define GAIA_FFS64(x) \
498 ([](uint64_t value) noexcept -> uint32_t { \
499 if (value == 0) \
500 return 0; \
501 uint32_t index = 0; \
502 while (((value >> index) & 1) == 0) \
503 ++index; \
504 return index + 1; \
505 }(x))
506#endif
507
508//------------------------------------------------------------------------------
509
510#if GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
511 #define GAIA_FORCEINLINE inline __attribute__((always_inline))
512 #define GAIA_NOINLINE __attribute__((noinline))
513#elif GAIA_COMPILER_MSVC || GAIA_COMPILER_ICC
514 #define GAIA_FORCEINLINE __forceinline
515 #define GAIA_NOINLINE __declspec(noinline)
516#else
517 #define GAIA_FORCEINLINE inline
518 #define GAIA_NOINLINE
519#endif
520
521#if GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
522 #define GAIA_LAMBDAINLINE __attribute__((always_inline))
523#elif GAIA_COMPILER_MSVC
524 #if _MSC_VER >= 1927 && _MSVC_LANG > 202002L // MSVC 16.7 or newer && /std:c++latest
525 #define GAIA_LAMBDAINLINE [[msvc::forceinline]]
526 #else
527 #define GAIA_LAMBDAINLINE
528 #endif
529#else
530 #define GAIA_LAMBDAINLINE
531#endif
532
533#ifdef __has_cpp_attribute
534 #if __has_cpp_attribute(assume) >= 202207L && GAIA_CPP_VERSION(202207L)
535 #define GAIA_ASSUME(...) [[assume(__VA_ARGS__)]]
536 #endif
537#endif
538#ifndef GAIA_ASSUME
539 #if GAIA_COMPILER_CLANG
540 #define GAIA_ASSUME(...) __builtin_assume(__VA_ARGS__)
541 #elif GAIA_COMPILER_MSVC
542 #define GAIA_ASSUME(...) __assume(__VA_ARGS__)
543 #elif (GAIA_COMPILER_GCC && __GNUC__ >= 13)
544 #define GAIA_ASSUME(...) __attribute__((__assume__(__VA_ARGS__)))
545 #endif
546#endif
547#ifndef GAIA_ASSUME
548 #define GAIA_ASSUME(...)
549#endif
550
551#if defined(__cpp_constexpr) && GAIA_CPP_VERSION(201907L)
552 #define GAIA_CONSTEXPR_DTOR constexpr
553#else
554 #define GAIA_CONSTEXPR_DTOR
555#endif
556
557//------------------------------------------------------------------------------
558
559#if GAIA_COMPILER_MSVC
560 #define GAIA_IMPORT __declspec(dllimport)
561 #define GAIA_EXPORT __declspec(dllexport)
562 #define GAIA_HIDDEN
563#elif GAIA_COMPILER_CLANG || GAIA_COMPILER_GCC
564 #define GAIA_IMPORT __attribute__((visibility("default")))
565 #define GAIA_EXPORT __attribute__((visibility("default")))
566 #define GAIA_HIDDEN __attribute__((visibility("hidden")))
567#endif
568
569#define GAIA_API
570// NOTE: Gaia is currently a header-only library so exporting/importing should not be necessary
571// #if defined(GAIA_USE_DLL) // Use DLL file (defined by the executable)
572// #define GAIA_API GAIA_IMPORT
573// #elif defined(GAIA_GEN_DLL) // Generate DLL file (defined inside DLL)
574// #define GAIA_API GAIA_EXPORT
575// #else
576// #define GAIA_API
577// #endif
578
579//------------------------------------------------------------------------------
580// Warning-related macros and settings
581// We always set warnings as errors and disable ones we don't care about.
582// Sometimes in only limited range of code or around 3rd party includes.
583//------------------------------------------------------------------------------
584
585#if GAIA_COMPILER_MSVC
586 #define GAIA_MSVC_WARNING_PUSH() __pragma(warning(push))
587 #define GAIA_MSVC_WARNING_POP() __pragma(warning(pop))
588 #define GAIA_MSVC_WARNING_DISABLE(warningId) __pragma(warning(disable : warningId))
589 #define GAIA_MSVC_WARNING_ERROR(warningId) __pragma(warning(error : warningId))
590#else
591 #define GAIA_MSVC_WARNING_PUSH()
592 #define GAIA_MSVC_WARNING_POP()
593 #define GAIA_MSVC_WARNING_DISABLE(warningId)
594 #define GAIA_MSVC_WARNING_ERROR(warningId)
595#endif
596
597#if GAIA_COMPILER_CLANG
598 #define DO_PRAGMA_(x) _Pragma(#x)
599 #define DO_PRAGMA(x) DO_PRAGMA_(x)
600 #define GAIA_CLANG_WARNING_PUSH() _Pragma("clang diagnostic push")
601 #define GAIA_CLANG_WARNING_POP() _Pragma("clang diagnostic pop")
602 // Ignore unknown warning groups first so version-specific disables stay
603 // portable under -Werror -Wunknown-warning-option (e.g. Clang 18 vs 21).
604 #define GAIA_CLANG_WARNING_DISABLE(warningId) \
605 DO_PRAGMA(clang diagnostic ignored "-Wunknown-warning-option") \
606 DO_PRAGMA(clang diagnostic ignored warningId)
607 #define GAIA_CLANG_WARNING_ERROR(warningId) DO_PRAGMA(clang diagnostic error warningId)
608 #define GAIA_CLANG_WARNING_ALLOW(warningId) DO_PRAGMA(clang diagnostic warning warningId)
609#else
610 #define GAIA_CLANG_WARNING_PUSH()
611 #define GAIA_CLANG_WARNING_POP()
612 #define GAIA_CLANG_WARNING_DISABLE(warningId)
613 #define GAIA_CLANG_WARNING_ERROR(warningId)
614 #define GAIA_CLANG_WARNING_ALLOW(warningId)
615#endif
616
617#if GAIA_COMPILER_GCC
618 #define DO_PRAGMA_(x) _Pragma(#x)
619 #define DO_PRAGMA(x) DO_PRAGMA_(x)
620 #define GAIA_GCC_WARNING_PUSH() _Pragma("GCC diagnostic push")
621 #define GAIA_GCC_WARNING_POP() _Pragma("GCC diagnostic pop")
622 #define GAIA_GCC_WARNING_ERROR(warningId) DO_PRAGMA(GCC diagnostic error warningId)
623 #define GAIA_GCC_WARNING_DISABLE(warningId) DO_PRAGMA(GCC diagnostic ignored warningId)
624#else
625 #define GAIA_GCC_WARNING_PUSH()
626 #define GAIA_GCC_WARNING_POP()
627 #define GAIA_GCC_WARNING_DISABLE(warningId)
628#endif
629
630#define GAIA_HAS_NO_INLINE_ASSEMBLY 0
631#if (!defined(__GNUC__) && !defined(__clang__)) || defined(__pnacl__) || defined(__EMSCRIPTEN__)
632 #undef GAIA_HAS_NO_INLINE_ASSEMBLY
633 #define GAIA_HAS_NO_INLINE_ASSEMBLY 1
634#endif
635
636namespace gaia {
637#if !GAIA_HAS_NO_INLINE_ASSEMBLY
641 template <class T>
642 inline void dont_optimize(T const& value) {
643 asm volatile("" : : "r,m"(value) : "memory");
644 }
645
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)
668 template <class T>
669 inline void dont_optimize(T const& value) {
670 detail::use_char_pointer(&reinterpret_cast<char const volatile&>(value));
671 ::_ReadWriteBarrier();
672 }
673 #else
677 template <class T>
678 inline void dont_optimize(T const& value) {
679 detail::use_char_pointer(&reinterpret_cast<char const volatile&>(value));
680 }
681 #endif
682#endif
683} // namespace gaia