libGimbal 0.2.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_platform.h
Go to the documentation of this file.
1/*! \file
2 * \brief Platform and architecture definitions
3 * \ingroup preprocessor
4 *
5 * \author 2026 Falco Girgis
6 * \author 2026 Agustín Bellagamba
7 * \copyright MIT License
8 */
9#ifndef GIMBAL_PLATFORM_H
10#define GIMBAL_PLATFORM_H
11
14#include <stdint.h>
15
16// ======== Operating System ========
17
18#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
19 // Common for all Windows platforms
20# define GBL_WIN 1
21# ifdef _WIN64
22 // 64-bit Windows only
23# define GBL_WIN64 1
24# else
25 // 32-bit Windows only
26# define GBL_WIN32 1
27# endif
28#elif __APPLE__
29 // Common to all Apple platforms
30# define GBL_APPLE
31# include <TargetConditionals.h>
32# if TARGET_IPHONE_SIMULATOR
33 // iOS, tvOS, or watchOS Simulator
34# define GBL_IOS_SIMULATOR 1
35# elif TARGET_OS_MACCATALYST
36 // Mac's Catalyst (ports iOS API into Mac, like UIKit).
37# define GBL_MACCATALYST 1
38# elif TARGET_OS_IPHONE
39 // iOS, tvOS, or watchOS device
40# define GBL_IOS 1
41# elif TARGET_OS_MAC
42 // Other kinds of Apple platforms
43# define GBL_MACOS 1
44# else
45# error "Unknown Apple platform"
46# endif
47#elif __ANDROID__
48 // Below __linux__ check should be enough to handle Android,
49 // but something may be unique to Android.
50# define GBL_ANDROID 1
51#elif defined(__DREAMCAST__)
52# define GBL_DREAMCAST 1
53#elif defined(__GAMECUBE__)
54# define GBL_GAMECUBE 1
55#elif defined(__PSP__)
56# define GBL_PSP 1
57#elif defined(VITA)
58# define GBL_PSVITA 1
59#elif __linux__
60# define GBL_LINUX 1
61#elif __unix__ // all unices not caught above
62 // Unix
63# define GBL_UNIX 1
64#elif defined(_POSIX_VERSION)
65 // POSIX
66# define GBL_POSIX
67#endif
68
69// ======== CPU Architecture ========
70
71#if defined(__x86_64__) || defined(_M_X64)
72# define GBL_X86_64 1
73#elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
74# define GBL_X86_32 1
75#elif defined(__ARM_ARCH_2__)
76# define GBL_ARM2 1
77#elif defined(__ARM_ARCH_3__) || defined(__ARM_ARCH_3M__)
78# define GBL_ARM3 1
79#elif defined(__ARM_ARCH_4T__) || defined(__TARGET_ARM_4T)
80# define GBL_ARM4T 1
81#elif defined(__ARM_ARCH_5_) || defined(__ARM_ARCH_5E_)
82# define GBL_ARM5 1
83#elif defined(__ARM_ARCH_6T2_) || defined(__ARM_ARCH_6T2_)
84# define GBL_ARM6T2 1
85#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__)
86# define GBL_ARM6 1
87#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
88# define GBL_ARM7 1
89#elif defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
90# define GBL_ARM7A 1
91#elif defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
92# define GBL_ARM7R 1
93#elif defined(__ARM_ARCH_7M__)
94# define GBL_ARM7M 1
95#elif defined(__ARM_ARCH_7S__)
96# define GBL_ARM7S 1
97#elif defined(__aarch64__) || defined(_M_ARM64)
98# define GBL_ARM64 1
99#elif defined(mips) || defined(__mips__) || defined(__mips)
100# define GBL_MIPS 1
101#elif defined(__sh__)
102# define GBL_SUPERH 1
103#elif defined(__powerpc) || defined(__powerpc__) || defined(__powerpc64__) || defined(__POWERPC__) || defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC)
104# define GBL_POWERPC 1
105#elif defined(__PPC64__) || defined(__ppc64__) || defined(_ARCH_PPC64)
106# define GBL_POWERPC64 1
107#elif defined(__sparc__) || defined(__sparc)
108# define GBL_SPARC 1
109#elif defined(__m68k__)
110# define GBL_M68K 1
111#endif
112
113// ======== Pointer Width ========
114
115#if UINTPTR_MAX == 0xffff
116# define GBL_16BIT
117#elif UINTPTR_MAX == 0xffffffff
118# define GBL_32BIT
119#elif UINTPTR_MAX == 0xffffffffffffffff
120# define GBL_64BIT
121#else
122 /* wtf, you're on your own, bro */
123#endif
124
125// ======== Compiler Support ========
126
127#ifdef _WIN64
128# define GBL_INITIALIZER_PREFIX_ ""
129#else
130# define GBL_INITIALIZER_PREFIX_ "_"
131#endif
132
133#if defined(__DREAMCAST__) || defined(__GAMECUBE__)
134# define GBL_THREAD_LOCAL_ _Thread_local
135#elif defined(__PSP__)
136# define GBL_THREAD_LOCAL_
137#else
138# define GBL_THREAD_LOCAL_ __thread
139#endif
140
141#ifdef __cplusplus
142# define GBL_INITIALIZER(f)
143 static void f(void);
144 struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_;
145 static void f(void)
146#elif defined(_MSC_VER)
147# pragma section(".CRT$XCU",read)
148# define GBL_INITIALIZER2_(f,p)
149 static void f(void);
150 __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f;
151 __pragma(comment(linker,"/include:" p #f "_"))
152 static void f(void)
153# define GBL_INITIALIZER(f) GBL_INITIALIZER2_(f, GBL_INITIALIZER_PREFIX_)
154#else
155# define GBL_INITIALIZER(f)
156 static void f(void) __attribute__((constructor));
157 static void f(void)
158#endif
159
160// ======== Thread-local storage ========
161#if defined(TINYCTHREAD_ENABLE_THREADS) && !TINYCTHREAD_ENABLE_THREADS
162# define GBL_THREAD_LOCAL
163#elif defined(_MSC_VER)
164# define GBL_THREAD_LOCAL __declspec(thread)
165#else
166# define GBL_THREAD_LOCAL GBL_THREAD_LOCAL_
167#endif
168
169#if defined(_MSC_VER) || defined(__MINGW64__)
170# define GBL_ALIGNED_ALLOC(a, s) _aligned_malloc(s, a)
171# define GBL_ALIGNED_REALLOC(p, a, s) _aligned_realloc(p, s, a)
172# define GBL_ALIGNED_FREE(p) _aligned_free(p)
173#elif defined(__MINGW32__)
174# define GBL_ALIGNED_ALLOC(a, s) __mingw_aligned_malloc(s, a)
175# define GBL_ALIGNED_REALLOC(p, a, s) __mingw_aligned_realloc(p, s, a)
176# define GBL_ALIGNED_FREE(p) __mingw_aligned_free(p)
177#elif defined(GBL_C11) || defined(GBL_CPP17)
178# include <stdlib.h>
179# define GBL_ALIGNED_ALLOC(a, s) aligned_alloc(a, s)
180# define GBL_ALIGNED_REALLOC(p, a, s) realloc(p, s)
181# define GBL_ALIGNED_FREE(p) free(p)
182#endif
183
184#if GBL_CONFIG_PREFETCH_ENABLED
185# ifndef GBL_PREFETCH
186# if defined(_MSC_VER) || defined(__MINGW64__)
187# if defined(_M_ARM64) || defined(_M_ARM64EC)
188# include <intrin.h>
189# else
190# include <immintrin.h>
191# endif
192# define GBL_PREFETCH(addr) _mm_prefetch(addr, _MM_HINT_T0)
193# elif defined(__GNUC__)
194# define GBL_PREFETCH __builtin_prefetch
195# endif
196# else
197# define GBL_PREFETCH(...)
198# endif
199#else
200# define GBL_PREFETCH(...)
201#endif
202
203// ======== alloca() ========
204#ifndef GBL_ALLOCA
205# if defined(__APPLE__) || defined(__GLIBC__) ||
206 defined(__sun) || defined(__CYGWIN__) ||
207 defined(__EMSCRIPTEN__) || defined(VITA) ||
208 defined(__DREAMCAST__) || defined(PSP) ||
209 defined(__GAMECUBE__) || defined(GEKKO) ||
210 defined(__DEVKITARM__)
211# include <alloca.h> // Sane platforms
212# elif defined(_WIN32)
213# include <malloc.h> // Windoez
214# ifndef alloca
215# define alloca _alloca // Clang with MS Codegen
216# endif
217# else
218# include <stdlib.h> // BSD extension
219# endif
220# define GBL_ALLOCA alloca
221#endif
222
223#if __APPLE__ // at very least fucking MacOS headers are missing it!
224# define GBL_QUICK_EXIT(c) exit(c)
225#elif defined(GBL_CPP11)
226# define GBL_QUICK_EXIT(c) quick_exit(c)
227#elif defined(GBL_C11)
228# define GBL_QUICK_EXIT(c) quick_exit(c)
229#else
230# define GBL_QUICK_EXIT(c) exit(c)
231#endif
232
233/* ==========================================================
234 * Provide simple macro statement wrappers (adapted from Perl):
235 * G_STMT_START { statements; } G_STMT_END;
236 * can be used as a single statement, as in
237 * if (x) G_STMT_START { ... } G_STMT_END; else ...
238 *
239 * For gcc we will wrap the statements within `({' and `})' braces.
240 * For SunOS they will be wrapped within `if (1)' and `else (void) 0',
241 * and otherwise within `do' and `while (0)'.
242 * ========================================================
243 * Graciously stolen from GLib. Imitation is the most sincere form of flattery.
244 * --Falco Girgis
245 */
246/* REMOVED WHILE TRYING TO AVOID CLANG WARNINGS AND TO BE STANDARD COMPLIANT
247 * # if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
248# define GBL_STMT_START (void) __extension__ (
249# define GBL_STMT_END )
250# */
251#if !(defined (GBL_STMT_START) && defined (GBL_STMT_END))
252# if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
253# define GBL_STMT_START do
254# define GBL_STMT_END while(0)
255# else
256# if (defined (sun) || defined (__sun__))
257# define GBL_STMT_START if(1)
258# define GBL_STMT_END else(void)0
259# else
260# define GBL_STMT_START do
261# define GBL_STMT_END while(0)
262# endif
263# endif
264#endif
265
266// ======== Size Types ========
267
268#ifdef GBL_64BIT
269# define GBL_SIZE_TYPE GBL_UINT64_TYPE
270# define GBL_SIZE_BITS 64
271#else
272# define GBL_SIZE_TYPE GBL_UINT32_TYPE
273# define GBL_SIZE_BITS 32
274#endif
275
276// ======== Variant ========
277
278#if !defined(GBL_DREAMCAST) && !defined(GBL_GAMECUBE) && !defined(GBL_PSP)
279# define GBL_VARIANT_CONSTRUCT_GENERIC_PLATFORM_ENTRIES()
280#else
281# define GBL_VARIANT_CONSTRUCT_GENERIC_PLATFORM_ENTRIES()
282 (int, GblVariant_constructInt32),
283#endif
284
285
286// ======== Time ========
287
288#include <time.h>
289
290#if !defined(GBL_NO_TIMESPEC_)
291# if defined(ANDROID) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(VITA) || defined(PSP)
292# define GBL_NO_TIMESPEC_
293# endif
294#endif
295
296#ifdef GBL_NO_TIMESPEC_
297# ifndef TIME_UTC
298# define TIME_UTC 1
299# endif
300
301GBL_INLINE int gblTimespecGet_(struct timespec* pSpec, int base) {
302 if(base != TIME_UTC)
303 return 0;
304
305 if(clock_gettime(CLOCK_REALTIME, pSpec) == -1)
306 return 0;
307
308 return TIME_UTC;
309}
310
311# define timespec_get gblTimespecGet_
312#endif
313
314// ======== C++ ========
315
316#ifdef GBL_CPP_17
317# if defined(__APPLE__) || defined(__ANDROID__) || defined(__wasm__)
318# define GBL_PMR_HEADER_ <experimental/memory_resource>
319# define GBL_PMR_NAMESPACE_ std::experimental::pmr
320# else
321# define GBL_PMR_HEADER_ <memory_resource>
322# define GBL_PMR_NAMESPACE_ std::pmr
323# define GBL_PMR_VECTOR
324# define GBL_PMR_STRING
325# define GBL_LEX_CMP_3WAY
326# endif
327#endif
328
329#ifdef GBL_PMR_VECTOR
330# define GBL_PMR_VECTOR_ONLY_ GBL_EVAL0
331#else
332# define GBL_PMR_VECTOR_ONLY_ GBL_MACRO_CALL_NULL
333#endif
334
335#ifdef GBL_PMR_STRING
336# define GBL_PMR_STRING_ONLY_ GBL_EVAL0
337#else
338# define GBL_PMR_STRING_ONLY_ GBL_MACRO_CALL_NULL
339#endif
340
341#ifdef GBL_LEX_CMP_3WAY
342# define GBL_LEXICOGRAPHICAL_COMPARE_ std::lexicographical_compare_three_way
343#else
344# define GBL_LEXICOGRAPHICAL_COMPARE_ std::lexicographical_compare
345#endif
346
347// ======== Endianness ========
348
349#if GBL_BIG_ENDIAN
350# define GBL_BIT_FIELDS_ENDIAN_XFORM_(...) (__VA_ARGS__)
351#else
352# define GBL_BIT_FIELDS_ENDIAN_XFORM_(...) (GBL_REVERSE(__VA_ARGS__))
353#endif
354
355// Select the big-endian or little-endian alternative at preprocessing time.
356#if GBL_BIG_ENDIAN
357# define GBL_ENDIAN_SELECT_ GBL_ARG_1
358# define GBL_FROM_BIG_ENDIAN_U32_(value) (value)
359# define GBL_TO_LITTLE_ENDIAN_U16_(value) GBL_BSWAP_U16(value)
360# define GBL_TO_LITTLE_ENDIAN_U32_(value) GBL_BSWAP_U32(value)
361#else
362# define GBL_ENDIAN_SELECT_ GBL_ARG_2
363# define GBL_FROM_BIG_ENDIAN_U32_(value) GBL_BSWAP_U32(value)
364# define GBL_TO_LITTLE_ENDIAN_U16_(value) (value)
365# define GBL_TO_LITTLE_ENDIAN_U32_(value) (value)
366#endif
367
368// ======== Unaligned Access ========
369
370// Load a native-endian word from a possibly unaligned address.
371// DO NOT DO UNALIGNED WORD ACCESSES ON THE RISC/EMBEDDED CPUS
372#if !defined(__DREAMCAST__) && !defined(__GAMECUBE__) && !defined(__VITA__)
373GBL_INLINE uint32_t gblLoadUnalignedU32_(const void* pData) {
374 return *(const uint32_t*)pData;
375}
376#else
377# include <string.h>
378
379GBL_INLINE uint32_t gblLoadUnalignedU32_(const void* pData) {
380 uint32_t value;
381 memcpy(&value, pData, sizeof(value));
382 return value;
383}
384#endif
385
386#endif // GIMBAL_PLATFORM_H
#define GBL_BSWAP_U32(v)
#define GBL_INLINE
#define GBL_MACRO_CALL_NULL(...)
#define GBL_ARG_2(_1, _2,...)
#define GBL_REVERSE(...)
#define GBL_THREAD_LOCAL_