libGimbal 0.1.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_compiler.h
Go to the documentation of this file.
1/*! \file
2 * \brief Helper Definitions for language, compiler, and platform
3 * \ingroup preprocessor
4 * \sa gimbal_macro_utilities.h
5 *
6 * \author Falco Girgis
7 */
8
9#ifndef GIMBAL_COMPILER_H
10#define GIMBAL_COMPILER_H
11
12#define __STDC_WANT_LIB_EXT1__ 1
13#include <stdio.h>
14#include <string.h>
15#include <stdlib.h>
16#include <stddef.h>
17#include <stdint.h>
18
19// C Version
20#ifdef __STDC_VERSION__
21# define GBL_C89 1
22# if (__STDC_VERSION__ >= 199409L)
23# define GBL_C95 1
24# endif
25# if (__STDC_VERSION__ >= 199901L)
26# define GBL_C99 1
27# endif
28# if (__STDC_VERSION__ >= 201112L)
29# define GBL_C11 1
30# endif
31# if (__STDC_VERSION__ >= 201710L)
32# define GBL_C17 1
33# endif
34# if (__STDC_VERSION__ >= 202311L)
35# define GBL_C23 1
36# endif
37#endif
38
39//C++ Version
40#ifdef __cplusplus
41# if (__cplusplus >= 199711L)
42# define GBL_CPP98 1
43# endif
44# if (__cplusplus >= 201103L)
45# define GBL_CPP11 1
46# endif
47# if (__cplusplus >= 201402L)
48# define GBL_CPP14 1
49# endif
50# if (__cplusplus >= 201703L)
51# define GBL_CPP17 1
52# endif
53# if (__cplusplus >= 202002L)
54# define GBL_CPP20 1
55# endif
56# if (__cplusplus >= 202302L)
57# define GBL_CPP23 1
58# endif
59#endif
60
61
62#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
63 // Common for all Windows platforms
64# define GBL_WIN 1
65# ifdef _WIN64
66 // 64-bit Windows only
67# define GBL_WIN64 1
68# else
69 // 32-bit Windows only
70# define GBL_WIN32 1
71# endif
72#elif __APPLE__
73 // Common to all Apple platforms
74# define GBL_APPLE
75# include <TargetConditionals.h>
76# if TARGET_IPHONE_SIMULATOR
77 // iOS, tvOS, or watchOS Simulator
78# define GBL_IOS_SIMULATOR 1
79# elif TARGET_OS_MACCATALYST
80 // Mac's Catalyst (ports iOS API into Mac, like UIKit).
81# define GBL_MACCATALYST 1
82# elif TARGET_OS_IPHONE
83 // iOS, tvOS, or watchOS device
84# define GBL_IOS 1
85# elif TARGET_OS_MAC
86 // Other kinds of Apple platforms
87# define GBL_MACOS 1
88# else
89# error "Unknown Apple platform"
90# endif
91#elif __ANDROID__
92 // Below __linux__ check should be enough to handle Android,
93 // but something may be unique to Android.
94# define GBL_ANDROID 1
95#elif defined(__DREAMCAST__)
96# define GBL_DREAMCAST 1
97#elif defined(__PSP__)
98# define GBL_PSP 1
99#elif defined(VITA)
100# define GBL_PSVITA 1
101#elif __linux__
102# define GBL_LINUX 1
103#elif __unix__ // all unices not caught above
104 // Unix
105# define GBL_UNUX 1
106#elif defined(_POSIX_VERSION)
107 // POSIX
108# define GBL_POSIX
109#endif
110
111#ifdef _MSC_VER
112# define GBL_MSVC 1
113#elif defined(__ICC)
114# define GBL_ICC 1
115#elif defined(__clang__)
116# define GBL_CLANG 1
117#elif defined(__MINGW32__)
118# define GBL_MINGW32 1
119#elif defined(__MINGW64__)
120# define GBL_MINGW64 1
121#elif defined(__EMSCRIPTEN__)
122# define GBL_EMSCRIPTEN 1
123#elif defined(__GNUC__)
124# define GBL_GCC 1
125#elif defined(__ghs__)
126# define GBL_GREENHILL 1
127#elif defined(__CC_ARM)
128# define GBL_ARMCC 1
129#elif defined(__IAR_SYSTEMS__ICC__)
130# define GBL_IAR 1
131#endif
132
133#if defined(__x86_64__) || defined(_M_X64)
134# define GBL_X86_64 1
135#elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
136# define GBL_X86_32 1
137#elif defined(__ARM_ARCH_2__)
138# define GBL_ARM2 1
139#elif defined(__ARM_ARCH_3__) || defined(__ARM_ARCH_3M__)
140# define GBL_ARM3 1
141#elif defined(__ARM_ARCH_4T__) || defined(__TARGET_ARM_4T)
142# define GBL_ARM4T 1
143#elif defined(__ARM_ARCH_5_) || defined(__ARM_ARCH_5E_)
144# define GBL_ARM5 1
145#elif defined(__ARM_ARCH_6T2_) || defined(__ARM_ARCH_6T2_)
146# define GBL_ARM6T2 1
147#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__)
148# define GBL_ARM6 1
149#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
150# define GBL_ARM7 1
151#elif defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
152# define GBL_ARM7A 1
153#elif defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
154# define GBL_ARM7R 1
155#elif defined(__ARM_ARCH_7M__)
156# define GBL_ARM7M 1
157#elif defined(__ARM_ARCH_7S__)
158# define GBL_ARM7S 1
159#elif defined(__aarch64__) || defined(_M_ARM64)
160# define GBL_ARM64 1
161#elif defined(mips) || defined(__mips__) || defined(__mips)
162# define GBL_MIPS 1
163#elif defined(__sh__)
164# define GBL_SUPERH 1
165#elif defined(__powerpc) || defined(__powerpc__) || defined(__powerpc64__) || defined(__POWERPC__) || defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC)
166# define GBL_POWERPC 1
167#elif defined(__PPC64__) || defined(__ppc64__) || defined(_ARCH_PPC64)
168# define GBL_POWERPC64 1
169#elif defined(__sparc__) || defined(__sparc)
170# define GBL_SPARC 1
171#elif defined(__m68k__)
172# define GBL_M68K 1
173#endif
174
175#ifdef GBL_CPP11
176# define GBL_NULL nullptr
177#else
178# define GBL_NULL NULL
179#endif
180
181#if UINTPTR_MAX == 0xffff
182# define GBL_16BIT
183#elif UINTPTR_MAX == 0xffffffff
184# define GBL_32BIT
185#elif UINTPTR_MAX == 0xffffffffffffffff
186# define GBL_64BIT
187#else
188 /* wtf, you're on your own, bro */
189#endif
190
191// Shared library symbol imports/exports
192#ifdef _MSC_VER
193# define GBL_EXPORT_SHARED __declspec(dllexport)
194# define GBL_IMPORT_SHARED __declspec(dllimport)
195#elif defined(__clang__) || defined(__GNUC__)
196# define GBL_EXPORT_SHARED __attribute__((visibility("default")))
197# define GBL_IMPORT_SHARED
198#else
199# define GBL_EXPORT_SHARED
200# define GBL_IMPORT_SHARED
201#endif
202
203#ifdef __cplusplus
204# define GBL_INITIALIZER(f)
205 static void f(void);
206 struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_;
207 static void f(void)
208#elif defined(_MSC_VER)
209# pragma section(".CRT$XCU",read)
210# define GBL_INITIALIZER2_(f,p)
211 static void f(void);
212 __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f;
213 __pragma(comment(linker,"/include:" p #f "_"))
214 static void f(void)
215# ifdef _WIN64
216 #define GBL_INITIALIZER(f) GBL_INITIALIZER2_(f,"")
217# else
218 #define GBL_INITIALIZER(f) GBL_INITIALIZER2_(f,"_")
219# endif
220#else
221# define GBL_INITIALIZER(f)
222 static void f(void) __attribute__((constructor));
223 static void f(void)
224#endif
225
226// Thread-local storage
227#ifdef _MSC_VER
228# define GBL_THREAD_LOCAL __declspec(thread)
229#else
230# if defined(__DREAMCAST__)
231# define GBL_THREAD_LOCAL _Thread_local
232# elif defined(__PSP__)
233# define GBL_THREAD_LOCAL
234# else
235# define GBL_THREAD_LOCAL __thread
236# endif
237#endif
238
239//====== C++ FEATURE SUPPORT ==============
240
241// RTTI
242#ifdef __cpp_rtti
243# define GBL_CPP_RTTI 1
244#elif defined(__clang__)
245# if __has_feature(cxx_rtti)
246# define GBL_CPP_RTTI 1
247# else
248# define GBL_CPP_RTTI 0
249# endif
250#elif defined(__GNUG__) && defined(__GXX_RTTI)
251# define GBL_CPP_RTTI 1
252#elif defined(_MSC_VER) && defined(_CPPRTTI)
253# define GBL_CPP_RTTI 1
254#else
255# define GBL_CPP_RTTI 0
256#endif
257
258// Exceptions
259#ifdef __cpp_exceptions
260# define GBL_CPP_EXCEPTIONS 1
261# define GBL_NOEXCEPT noexcept
262#else
263# define GBL_CPP_EXCEPTIONS 0
264# define GBL_NOEXCEPT
265#endif
266
267#ifdef GBL_CPP11
268# define GBL_CONSTEXPR constexpr
269# ifdef GBL_CPP20
270# define GBL_CONSTEVAL consteval
271# else
272# define GBL_CONSTEVAL constexpr
273# endif
274#else
275# define GBL_CONSTEXPR
276# define GBL_CONSTEVAL
277#endif
278
279// Concepts
280#ifdef __cpp_concepts
281# define GBL_CPP_CONCEPTS 1
282#else
283# define GBL_CPP_CONCEPTS 0
284#endif
285
286
287// Source Location
288#ifdef __cpp_lib_source_location
289# define GBL_CPP_SOURCE_LOCATION 1
290#else
291# define GBL_CPP_SOURCE_LOCATION 0
292#endif
293
294// Deprecated
295#if defined(__has_cpp_attribute)
296# if __has_cpp_attribute(deprecated)
297# define GBL_DEPRECATED(msg) [[deprecated(msg)]]
298# else
299# define GBL_DEPRECATED(msg)
300# endif
301#else
302# define GBL_DEPRECATED(msg)
303#endif
304
305// Fallthrough
306#if defined(__has_cpp_attribute)
307# if __has_cpp_attribute(fallthrough)
308# define GBL_FALLTHROUGH [[fallthrough]]
309# else
310# define GBL_FALLTHROUGH
311# endif
312#else
313# define GBL_FALLTHROUGH
314#endif
315
316// Likely
317#if defined(__has_cpp_attribute)
318# if __has_cpp_attribute(likely)
319# define GBL_LIKELY [[likely]]
320# else
321# define GBL_LIKELY
322# endif
323#else
324# define GBL_LIKELY
325#endif
326
327
328// Maybe_Unused
329#if defined(__has_cpp_attribute)
330# if __has_cpp_attribute(maybe_unused)
331# define GBL_MAYBE_UNUSED [[maybe_unused]]
332# else
333# define GBL_MAYBE_UNUSED
334# endif
335#elif defined(__clang__) || defined(__GNUC__)
336# define GBL_MAYBE_UNUSED __attribute__((unused))
337#else
338# define GBL_MAYBE_UNUSED
339#endif
340
341// No_Unique_Address
342#if defined(__has_cpp_attribute)
343# if __has_cpp_attribute(no_unique_address)
344# define GBL_NO_UNIQUE_ADDRESS [[no_unique_address]]
345# else
346# define GBL_NO_UNIQUE_ADDRESS
347# endif
348#else
349# define GBL_NO_UNIQUE_ADDRESS
350#endif
351
352// No_Discard
353#if defined(__has_cpp_attribute)
354# if __has_cpp_attribute(nodiscard)
355# define GBL_NODISCARD [[nodiscard]]
356# else
357# define GBL_NODISCARD
358# endif
359#else
360# define GBL_NODISCARD
361#endif
362
363// No_Return (Cpp)
364#if defined(__has_cpp_attribute)
365# if __has_cpp_attribute(noreturn)
366# define GBL_NORETURN [[noreturn]]
367# else
368# define GBL_NORETURN
369# endif
370# else
371# ifdef GBL_C11
372# define GBL_NORETURN _Noreturn
373# else
374# define GBL_NORETURN
375# endif
376#endif
377
378// Unlikely
379#if defined(__has_cpp_attribute)
380# if __has_cpp_attribute(unlikely)
381# define GBL_UNLIKELY [[unlikely]]
382# else
383# define GBL_UNLIKELY
384# endif
385#else
386# define GBL_UNLIKELY
387#endif
388
389#if __cpp_static_assert
390# if __cpp_static_assert > 201400
391# define GBL_STATIC_ASSERT(cond) static_assert(cond)
392# else
393# define GBL_STATIC_ASSERT(cond) static_assert(cond, #cond)
394# endif
395# define GBL_STATIC_ASSERT_MSG(cond, msg) static_assert(cond, msg)
396#elif defined(GBL_C11)
397# define GBL_STATIC_ASSERT(cond) _Static_assert(cond, #cond);
398# define GBL_STATIC_ASSERT_MSG(cond, msg) _Static_assert(cond, msg);
399#else
400# define GBL_STATIC_ASSERT(cond)
401# define GBL_STATIC_ASSERT_MSG(cond, msg)
402#endif
403
404#ifdef GBL_C99
405# define GBL_RESTRICT restrict
406#else
407# define GBL_RESTRICT
408#endif
409
410#ifdef GBL_C99
411# define GBL_STATIC_ARRAY(idx) static idx
412#else
413# define GBL_STATIC_ARRAY(idx) idx
414#endif
415
416#ifdef __cplusplus
417# define GBL_STRUCT_INIT(type, ...) (type{ __VA_ARGS__ })
418#else
419# define GBL_STRUCT_INIT(type, ...) ((type){ __VA_ARGS__ })
420#endif
421
422#ifdef __cplusplus
423# define GBL_ALIGNAS(e) alignas(e)
424# define GBL_ALIGNOF(e) alignof(e)
425#elif defined(GBL_C11)
426# define GBL_ALIGNAS(e) _Alignas(e)
427# define GBL_ALIGNOF(e) _Alignof(e)
428#endif
429
430#if defined(_MSC_VER) || defined(__MINGW64__)
431# define GBL_ALIGNED_ALLOC(a, s) _aligned_malloc(s, a)
432# define GBL_ALIGNED_REALLOC(p, a, s) _aligned_realloc(p, s, a)
433# define GBL_ALIGNED_FREE(p) _aligned_free(p)
434#elif defined(__MINGW32__)
435# define GBL_ALIGNED_ALLOC(a, s) __mingw_aligned_malloc(s, a)
436# define GBL_ALIGNED_REALLOC(p, a, s) __mingw_aligned_realloc(p, s, a)
437# define GBL_ALIGNED_FREE(p) __mingw_aligned_free(p)
438#elif defined(GBL_C11) || defined(GBL_CPP17)
439# include <stdlib.h>
440# define GBL_ALIGNED_ALLOC(a, s) aligned_alloc(a, s)
441# define GBL_ALIGNED_REALLOC(p, a, s) realloc(p, s)
442# define GBL_ALIGNED_FREE(p) free(p)
443#endif
444
445#if GBL_CONFIG_PREFETCH_ENABLED
446# ifndef GBL_PREFETCH
447# if defined(_MSC_VER) || defined(__MINGW64__)
448# if defined(_M_ARM64) || defined(_M_ARM64EC)
449# include <intrin.h>
450# else
451# include <immintrin.h>
452# endif
453# define GBL_PREFETCH(addr) _mm_prefetch(addr, _MM_HINT_T0)
454# elif defined(__GNUC__)
455# define GBL_PREFETCH __builtin_prefetch
456# endif
457# else
458# define GBL_PREFETCH(...)
459# endif
460#else
461# define GBL_PREFETCH(...)
462#endif
463
464#ifdef __cplusplus
465# define GBL_INLINE_ inline
466#else
467# define GBL_INLINE_ static inline
468#endif
469
470#ifdef __cplusplus
471# define GBL_INLINE GBL_MAYBE_UNUSED GBL_INLINE_
472#else
473# define GBL_INLINE GBL_MAYBE_UNUSED GBL_INLINE_
474#endif
475
476#ifdef __GNUC__
477# define GBL_FORCE_INLINE __attribute__((always_inline)) GBL_INLINE_
478#elif defined(_MSC_VER)
479# define GBL_FORCE_INLINE __forceinline
480#else
481# define GBL_FORCE_INLINE GBL_INLINE
482#endif
483
484// ====== NONSTANDARD COMPILER-SPECIFIC C FUNCTIONS ==========
485
486// "Safer" C11 functions with boundaries
487#if 0
488#ifdef __STDC_WANT_LIB_EXT1__
489#define GBL_C11_EXT1 1
490#define GBL_VPRINTF vprintf_s
491#define GBL_VFPRINTF vfprintf_s
492#define GBL_VSPRINTF vsprintf_s
493#define GBL_VSNPRINTF vsnprintf_s
494#define GBL_MEMSET memset_s
495#define GBL_MEMCPY memcpy_s
496#else
497#define GBL_C11_EXT1 0
498#define GBL_VPRINTF vprintf
499#define GBL_VFPRINTF vfprintf
500#define GBL_VSPRINTF vsprintf
501#define GBL_VSNPRINTF vsnprintf
502#define GBL_MEMSET memset
503#define GBL_MEMCPY memcpy
504#endif
505#endif
506
507// alloca()
508#ifndef GBL_ALLOCA
509# if defined(__APPLE__) || defined(__GLIBC__) ||
510 defined(__sun) || defined(__CYGWIN__) ||
511 defined(__EMSCRIPTEN__) || defined(VITA) ||
512 defined(__DREAMCAST__) || defined(PSP)
513# include <alloca.h> // Sane platforms
514# elif defined(_WIN32)
515# include <malloc.h> // Windoez
516# ifndef alloca
517# define alloca _alloca // Clang with MS Codegen
518# endif
519# else
520# include <stdlib.h> // BSD extension
521# endif
522# define GBL_ALLOCA alloca
523#endif
524
525#if __APPLE__ // at very least fucking MacOS headers are missing it!
526# define GBL_QUICK_EXIT(c) exit(c)
527#elif defined(GBL_CPP11)
528# define GBL_QUICK_EXIT(c) quick_exit(c)
529#elif defined(GBL_C11)
530# define GBL_QUICK_EXIT(c) quick_exit(c)
531#else
532# define GBL_QUICK_EXIT(c) exit(c)
533#endif
534
535#ifndef GBL_PRAGMA_MACRO_PUSH
536# define GBL_PRAGMA_MACRO_PUSH(X) push_macro(X)
537#endif
538
539#ifndef GBL_PRAGMA_MACRO_POP
540# define GBL_PRAGMA_MACRO_POP(X) pop_macro(X)
541#endif
542
543#ifdef _MSC_VER
544# define GBL_MAX_ALIGN_T double
545#else
546# define GBL_MAX_ALIGN_T max_align_t
547#endif
548
549#define GBL_ALLOC_MIN_SIZE GBL_ALIGNOF(GBL_MAX_ALIGN_T)
550
551/* ==========================================================
552 * Provide simple macro statement wrappers (adapted from Perl):
553 * G_STMT_START { statements; } G_STMT_END;
554 * can be used as a single statement, as in
555 * if (x) G_STMT_START { ... } G_STMT_END; else ...
556 *
557 * For gcc we will wrap the statements within `({' and `})' braces.
558 * For SunOS they will be wrapped within `if (1)' and `else (void) 0',
559 * and otherwise within `do' and `while (0)'.
560 * ========================================================
561 * Graciously stolen from GLib. Imitation is the most sincere form of flattery.
562 * --Falco Girgis
563 */
564/* REMOVED WHILE TRYING TO AVOID CLANG WARNINGS AND TO BE STANDARD COMPLIANT
565 * # if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
566# define GBL_STMT_START (void) __extension__ (
567# define GBL_STMT_END )
568# */
569#if !(defined (GBL_STMT_START) && defined (GBL_STMT_END))
570# if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
571# define GBL_STMT_START do
572# define GBL_STMT_END while(0)
573# else
574# if (defined (sun) || defined (__sun__))
575# define GBL_STMT_START if(1)
576# define GBL_STMT_END else(void)0
577# else
578# define GBL_STMT_START do
579# define GBL_STMT_END while(0)
580# endif
581# endif
582#endif
583
584#define GBL_NULL_TERMINATED
585
586// Low-Level BitMask Operations
587#ifdef GBL_CPP20
588# include <bit>
589# define GBL_BITMASK_CLZ(mask) std::countl_zero(mask)
590# define GBL_BITMASK_CTZ(mask) std::countr_zero(mask)
591 inline constexpr auto GBL_BITMASK_FFS(auto mask) noexcept {
592 const auto idx = GBL_BITMASK_CLZ(mask);
593 return idx? idx + 1 : 0;
594 }
595# define GBL_BITMASK_POPCOUNT(mask) std::popcount(mask)
596#else
597# define GBL_BITMASK_POPCOUNT_SW(mask)
598 (((mask) >= sizeof(unsigned long) * CHAR_BIT) ?
599 (unsigned long) -1 : (1u << (mask)) - 1)
600
601# if defined(__clang__) || defined(__GNUC__)
602# define GBL_BITMASK_CLZ(mask) __builtin_clz(mask) // count leading zeroes
603# define GBL_BITMASK_CTZ(mask) __builtin_ctz(mask) // count trailing zeroes
604# define GBL_BITMASK_FFS(mask) __builtin_ffs(mask) // find first set
605# define GBL_BITMASK_POPCOUNT(mask) __builtin_popcount(mask) // count number of 1s
606# elif defined(_MSC_VER)
607# include <intrin.h>
608 GBL_CONSTEXPR GBL_INLINE unsigned GBL_BITMASK_CLZ(unsigned mask) GBL_NOEXCEPT {
609 unsigned long idx = 0;
610 return _BitScanReverse(&idx, mask)? ((sizeof(unsigned) * 8) - idx) : 0;
611 }
612 GBL_CONSTEXPR GBL_INLINE unsigned GBL_BITMASK_CTZ(unsigned mask) GBL_NOEXCEPT {
613 unsigned long idx = 0;
614 return _BitScanForward(&idx, mask)? idx : 0;
615 }
616 GBL_CONSTEXPR GBL_INLINE unsigned GBL_BITMASK_FFS(unsigned mask) GBL_NOEXCEPT {
617 const unsigned idx = GBL_BITMASK_CTZ(mask);
618 return idx? idx + 1 : 0;
619 }
620# define GBL_BITMASK_POPCOUNT(mask) GBL_BITMASK_POPCOUNT_SW(mask)
621# else
622# define GBL_BITMASK_CLZ(mask) // implement me in software later TODO
623# define GBL_BITMASK_CTZ(mask)
624# define GBL_BITMASK_FFS(mask)
625# define GBL_BITMASK_POPCOUNT(mask) GBL_BITMASK_POPCOUNT_SW(mask)
626# endif
627#endif
628
629#endif // GIMBAL_COMPILER_H
#define GBL_MAX_ALIGN_T
#define GBL_MAYBE_UNUSED
#define GBL_INLINE_