libGimbal 0.2.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 and compiler
3 * \ingroup preprocessor
4 * \sa gimbal_macro_utilities.h
5 *
6 * This header contains an assortment of preprocessor definitions
7 * for the following:
8 * - Compiler type
9 * - C/C++ language revision
10 * - C/C++ language features
11 * - Compiler extensions and features
12 *
13 * \author 2023, 2025 Falco Girgis
14 * \copyright MIT LIicense
15 */
16
17#ifndef GIMBAL_COMPILER_H
18#define GIMBAL_COMPILER_H
19
20#define __STDC_WANT_LIB_EXT1__ 1
21
22#include <stddef.h>
23#include <stdint.h>
24
25// C Version
26#ifdef __STDC_VERSION__
27# define GBL_C89 1
28# if (__STDC_VERSION__ >= 199409L)
29# define GBL_C95 1
30# endif
31# if (__STDC_VERSION__ >= 199901L)
32# define GBL_C99 1
33# endif
34# if (__STDC_VERSION__ >= 201112L)
35# define GBL_C11 1
36# endif
37# if (__STDC_VERSION__ >= 201710L)
38# define GBL_C17 1
39# endif
40# if (__STDC_VERSION__ >= 202311L)
41# define GBL_C23 1
42# endif
43#endif
44
45//C++ Version
46#ifdef __cplusplus
47# if (__cplusplus >= 199711L)
48# define GBL_CPP98 1
49# endif
50# if (__cplusplus >= 201103L)
51# define GBL_CPP11 1
52# endif
53# if (__cplusplus >= 201402L)
54# define GBL_CPP14 1
55# endif
56# if (__cplusplus >= 201703L)
57# define GBL_CPP17 1
58# endif
59# if (__cplusplus >= 202002L)
60# define GBL_CPP20 1
61# endif
62# if (__cplusplus >= 202302L)
63# define GBL_CPP23 1
64# endif
65#endif
66
67#ifdef __GNUC__
68# define GBL_GNUC 1
69#endif
70
71#ifdef _MSC_VER
72# define GBL_MSVC 1
73#elif defined(__ICC)
74# define GBL_ICC 1
75#elif defined(__clang__)
76# define GBL_CLANG 1
77#elif defined(__MINGW32__)
78# define GBL_MINGW32 1
79#elif defined(__MINGW64__)
80# define GBL_MINGW64 1
81#elif defined(__EMSCRIPTEN__)
82# define GBL_EMSCRIPTEN 1
83#elif defined(__GNUC__)
84# define GBL_GCC 1
85#elif defined(__ghs__)
86# define GBL_GREENHILL 1
87#elif defined(__CC_ARM)
88# define GBL_ARMCC 1
89#elif defined(__IAR_SYSTEMS__ICC__)
90# define GBL_IAR 1
91#endif
92
93#ifdef GBL_CPP11
94# define GBL_NULL nullptr
95#else
96# define GBL_NULL NULL
97#endif
98
99// Shared library symbol imports/exports
100#ifdef _MSC_VER
101# define GBL_EXPORT_SHARED __declspec(dllexport)
102# define GBL_IMPORT_SHARED __declspec(dllimport)
103#elif defined(__clang__) || defined(__GNUC__)
104# define GBL_EXPORT_SHARED __attribute__((visibility("default")))
105# define GBL_IMPORT_SHARED
106#else
107# define GBL_EXPORT_SHARED
108# define GBL_IMPORT_SHARED
109#endif
110
111// Floating-point precision directives
112#ifdef _MSC_VER
113# define GBL_FP_FAST
114 _Pragma("float_control(except, off)") /* disable environment sensitivity */
115 _Pragma("fenv_access(off)") /* disable exception semantics */
116 _Pragma("float_control(precise, off)") /* disable precise semantics */
117 _Pragma("fp_contract(on)") /* enable contractions */
118# define GBL_FP_PRECISE
119 _Pragma("float_control(precise, on)") /* enable precise semantics */
120 _Pragma("fenv_access(on)") /* enable environment sensitivity */
121 _Pragma("float_control(except, on)") /* enable exception semantics */
122#else
123# define GBL_FP_FAST __attribute__((optimize("-ffast-math")))
124# define GBL_FP_PRECISE __attribute__((optimize("-fno-fast-math")))
125#endif
126
127//====== C++ FEATURE SUPPORT ==============
128
129// RTTI
130#ifdef __cpp_rtti
131# define GBL_CPP_RTTI 1
132#elif defined(__clang__)
133# if __has_feature(cxx_rtti)
134# define GBL_CPP_RTTI 1
135# else
136# define GBL_CPP_RTTI 0
137# endif
138#elif defined(__GNUG__) && defined(__GXX_RTTI)
139# define GBL_CPP_RTTI 1
140#elif defined(_MSC_VER) && defined(_CPPRTTI)
141# define GBL_CPP_RTTI 1
142#else
143# define GBL_CPP_RTTI 0
144#endif
145
146// Exceptions
147#ifdef __cpp_exceptions
148# define GBL_CPP_EXCEPTIONS 1
149# define GBL_NOEXCEPT noexcept
150#else
151# define GBL_CPP_EXCEPTIONS 0
152# define GBL_NOEXCEPT
153#endif
154
155#ifdef GBL_CPP11
156# define GBL_CONSTEXPR constexpr
157# ifdef GBL_CPP20
158# define GBL_CONSTEVAL consteval
159# else
160# define GBL_CONSTEVAL constexpr
161# endif
162#else
163# define GBL_CONSTEXPR
164# define GBL_CONSTEVAL
165#endif
166
167// Concepts
168#ifdef __cpp_concepts
169# define GBL_CPP_CONCEPTS 1
170#else
171# define GBL_CPP_CONCEPTS 0
172#endif
173
174
175// Source Location
176#ifdef __cpp_lib_source_location
177# define GBL_CPP_SOURCE_LOCATION 1
178#else
179# define GBL_CPP_SOURCE_LOCATION 0
180#endif
181
182// Deprecated
183#if defined(__has_cpp_attribute)
184# if __has_cpp_attribute(deprecated)
185# define GBL_DEPRECATED(msg) [[deprecated(msg)]]
186# else
187# define GBL_DEPRECATED(msg)
188# endif
189#else
190# define GBL_DEPRECATED(msg)
191#endif
192
193// Fallthrough
194#if defined(__has_cpp_attribute)
195# if __has_cpp_attribute(fallthrough)
196# define GBL_FALLTHROUGH [[fallthrough]]
197# else
198# define GBL_FALLTHROUGH
199# endif
200#else
201# define GBL_FALLTHROUGH
202#endif
203
204// Likely
205#if defined(__has_cpp_attribute)
206# if __has_cpp_attribute(likely)
207# define GBL_LIKELY(exp) (exp) [[likely]]
208# endif
209#endif
210#ifndef GBL_LIKELY
211# ifdef GBL_GNUC
212# define GBL_LIKELY(exp) (__builtin_expect(!!(exp), 1))
213# else
214# define GBL_LIKELY(exp) (exp)
215# endif
216#endif
217
218// unlikely
219#if defined(__has_cpp_attribute)
220# if __has_cpp_attribute(unlikely)
221# define GBL_UNLIKELY(exp) (exp) [[unlikely]]
222# endif
223#endif
224#ifndef GBL_UNLIKELY
225# ifdef GBL_GNUC
226# define GBL_UNLIKELY(exp) (__builtin_expect(!!(exp), 0))
227# else
228# define GBL_UNLIKELY(exp) (exp)
229# endif
230#endif
231
232// Maybe_Unused
233#if defined(__has_cpp_attribute)
234# if __has_cpp_attribute(maybe_unused)
235# define GBL_MAYBE_UNUSED [[maybe_unused]]
236# else
237# define GBL_MAYBE_UNUSED
238# endif
239#elif defined(__clang__) || defined(__GNUC__)
240# define GBL_MAYBE_UNUSED __attribute__((unused))
241#else
242# define GBL_MAYBE_UNUSED
243#endif
244
245// No_Unique_Address
246#if defined(__has_cpp_attribute)
247# if __has_cpp_attribute(no_unique_address)
248# define GBL_NO_UNIQUE_ADDRESS [[no_unique_address]]
249# else
250# define GBL_NO_UNIQUE_ADDRESS
251# endif
252#else
253# define GBL_NO_UNIQUE_ADDRESS
254#endif
255
256// No_Discard
257#if defined(__has_cpp_attribute)
258# if __has_cpp_attribute(nodiscard)
259# define GBL_NODISCARD [[nodiscard]]
260# else
261# define GBL_NODISCARD
262# endif
263#else
264# define GBL_NODISCARD
265#endif
266
267// No_Return (Cpp)
268#if defined(__has_cpp_attribute)
269# if __has_cpp_attribute(noreturn)
270# define GBL_NORETURN [[noreturn]]
271# else
272# define GBL_NORETURN
273# endif
274# else
275# ifdef GBL_C11
276# define GBL_NORETURN _Noreturn
277# else
278# define GBL_NORETURN
279# endif
280#endif
281
282#if __cpp_static_assert
283# if __cpp_static_assert > 201400
284# define GBL_STATIC_ASSERT(cond) static_assert(cond)
285# else
286# define GBL_STATIC_ASSERT(cond) static_assert(cond, #cond)
287# endif
288# define GBL_STATIC_ASSERT_MSG(cond, msg) static_assert(cond, msg)
289#elif defined(GBL_C11)
290# define GBL_STATIC_ASSERT(cond) _Static_assert(cond, #cond);
291# define GBL_STATIC_ASSERT_MSG(cond, msg) _Static_assert(cond, msg);
292#else
293# define GBL_STATIC_ASSERT(cond)
294# define GBL_STATIC_ASSERT_MSG(cond, msg)
295#endif
296
297#ifdef GBL_C99
298# define GBL_RESTRICT restrict
299#else
300# define GBL_RESTRICT
301#endif
302
303#ifdef GBL_C99
304# define GBL_STATIC_ARRAY(idx) static idx
305#else
306# define GBL_STATIC_ARRAY(idx) idx
307#endif
308
309#ifdef __cplusplus
310# define GBL_STRUCT_INIT(type, ...) (type{ __VA_ARGS__ })
311#else
312# define GBL_STRUCT_INIT(type, ...) ((type){ __VA_ARGS__ })
313#endif
314
315#ifdef __cplusplus
316# define GBL_ALIGNAS(e) alignas(e)
317# define GBL_ALIGNOF(e) alignof(e)
318#elif defined(GBL_C11)
319# define GBL_ALIGNAS(e) _Alignas(e)
320# define GBL_ALIGNOF(e) _Alignof(e)
321#endif
322
323#ifdef __cplusplus
324# define GBL_INLINE_ inline
325#else
326# define GBL_INLINE_ static inline
327#endif
328
329#ifdef __cplusplus
330# define GBL_INLINE GBL_MAYBE_UNUSED GBL_INLINE_
331#else
332# define GBL_INLINE GBL_MAYBE_UNUSED GBL_INLINE_
333#endif
334
335#ifdef __GNUC__
336# define GBL_FORCE_INLINE __attribute__((always_inline)) GBL_INLINE_
337#elif defined(_MSC_VER)
338# define GBL_FORCE_INLINE __forceinline
339#else
340# define GBL_FORCE_INLINE GBL_INLINE
341#endif
342
343#ifdef __GNUC__
344# define GBL_NO_INLINE __attribute__((noinline))
345#elif defined(_MSC_VER)
346# define GBL_NO_INLINE __declspec(noinline)
347#else
348# define GBL_NO_INLINE
349#endif
350
351// ====== NONSTANDARD COMPILER-SPECIFIC C FUNCTIONS ==========
352
353// "Safer" C11 functions with boundaries
354#if 0
355#ifdef __STDC_WANT_LIB_EXT1__
356#define GBL_C11_EXT1 1
357#define GBL_VPRINTF vprintf_s
358#define GBL_VFPRINTF vfprintf_s
359#define GBL_VSPRINTF vsprintf_s
360#define GBL_VSNPRINTF vsnprintf_s
361#define GBL_MEMSET memset_s
362#define GBL_MEMCPY memcpy_s
363#else
364#define GBL_C11_EXT1 0
365#define GBL_VPRINTF vprintf
366#define GBL_VFPRINTF vfprintf
367#define GBL_VSPRINTF vsprintf
368#define GBL_VSNPRINTF vsnprintf
369#define GBL_MEMSET memset
370#define GBL_MEMCPY memcpy
371#endif
372#endif
373
374#ifndef GBL_PRAGMA_MACRO_PUSH
375# define GBL_PRAGMA_MACRO_PUSH(X) push_macro(X)
376#endif
377
378#ifndef GBL_PRAGMA_MACRO_POP
379# define GBL_PRAGMA_MACRO_POP(X) pop_macro(X)
380#endif
381
382#ifdef _MSC_VER
383# define GBL_MAX_ALIGN_T double
384#else
385# define GBL_MAX_ALIGN_T max_align_t
386#endif
387
388#define GBL_ALLOC_MIN_SIZE GBL_ALIGNOF(GBL_MAX_ALIGN_T)
389
390#define GBL_NULL_TERMINATED
391
392#if GBL_MSVC
393# include <stdlib.h>
394# define GBL_BSWAP_U16(v) _byteswap_ushort(v)
395# define GBL_BSWAP_U32(v) _byteswap_ulong(v)
396# define GBL_BSWAP_U64(v) _byteswap_uint64(v)
397#else
398# define GBL_BSWAP_U16(v) __builtin_bswap16(v)
399# define GBL_BSWAP_U32(v) __builtin_bswap32(v)
400# define GBL_BSWAP_U64(v) __builtin_bswap64(v)
401#endif
402
403// Low-Level BitMask Operations
404#ifdef GBL_CPP20
405# include <bit>
406# define GBL_BITMASK_CLZ(mask) std::countl_zero(mask)
407# define GBL_BITMASK_CTZ(mask) std::countr_zero(mask)
408 inline constexpr auto GBL_BITMASK_FFS(auto mask) noexcept {
409 const auto idx = GBL_BITMASK_CLZ(mask);
410 return idx? idx + 1 : 0;
411 }
412# define GBL_BITMASK_POPCOUNT(mask) std::popcount(mask)
413#else
414# define GBL_BITMASK_POPCOUNT_SW(mask)
415 (((mask) >= sizeof(unsigned long) * CHAR_BIT) ?
416 (unsigned long) -1 : (1u << (mask)) - 1)
417
418# if defined(__clang__) || defined(__GNUC__)
419# define GBL_BITMASK_CLZ(mask) __builtin_clz(mask) // count leading zeroes
420# define GBL_BITMASK_CTZ(mask) __builtin_ctz(mask) // count trailing zeroes
421# define GBL_BITMASK_FFS(mask) __builtin_ffs(mask) // find first set
422# define GBL_BITMASK_POPCOUNT(mask) __builtin_popcount(mask) // count number of 1s
423# elif defined(_MSC_VER)
424# include <intrin.h>
425 GBL_CONSTEXPR GBL_INLINE unsigned GBL_BITMASK_CLZ(unsigned mask) GBL_NOEXCEPT {
426 unsigned long idx = 0;
427 return _BitScanReverse(&idx, mask)? ((sizeof(unsigned) * 8) - idx) : 0;
428 }
429 GBL_CONSTEXPR GBL_INLINE unsigned GBL_BITMASK_CTZ(unsigned mask) GBL_NOEXCEPT {
430 unsigned long idx = 0;
431 return _BitScanForward(&idx, mask)? idx : 0;
432 }
433 GBL_CONSTEXPR GBL_INLINE unsigned GBL_BITMASK_FFS(unsigned mask) GBL_NOEXCEPT {
434 const unsigned idx = GBL_BITMASK_CTZ(mask);
435 return idx? idx + 1 : 0;
436 }
437# define GBL_BITMASK_POPCOUNT(mask) GBL_BITMASK_POPCOUNT_SW(mask)
438# else
439# define GBL_BITMASK_CLZ(mask) // implement me in software later TODO
440# define GBL_BITMASK_CTZ(mask)
441# define GBL_BITMASK_FFS(mask)
442# define GBL_BITMASK_POPCOUNT(mask) GBL_BITMASK_POPCOUNT_SW(mask)
443# endif
444#endif
445
446#endif // GIMBAL_COMPILER_H
#define GBL_MAX_ALIGN_T
#define GBL_UNLIKELY(exp)
#define GBL_MAYBE_UNUSED
#define GBL_LIKELY(exp)
#define GBL_INLINE_