Zycore 1.5.1.0
Loading...
Searching...
No Matches
Defines.h
Go to the documentation of this file.
1/***************************************************************************************************
2
3 Zyan Core Library (Zycore-C)
4
5 Original Author : Florian Bernd, Joel Hoener
6
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24
25***************************************************************************************************/
26
32#ifndef ZYCORE_DEFINES_H
33#define ZYCORE_DEFINES_H
34
35/* ============================================================================================== */
36/* Meta macros */
37/* ============================================================================================== */
38
47#define ZYAN_MACRO_CONCAT(x, y) x ## y
48
58#define ZYAN_MACRO_CONCAT_EXPAND(x, y) ZYAN_MACRO_CONCAT(x, y)
59
60/* ============================================================================================== */
61/* Compiler detection */
62/* ============================================================================================== */
63
64#if defined(__clang__)
65# define ZYAN_CLANG
66# define ZYAN_GNUC
67#elif defined(__ICC) || defined(__INTEL_COMPILER)
68# define ZYAN_ICC
69#elif defined(__GNUC__) || defined(__GNUG__)
70# define ZYAN_GCC
71# define ZYAN_GNUC
72#elif defined(_MSC_VER)
73# define ZYAN_MSVC
74#elif defined(__BORLANDC__)
75# define ZYAN_BORLAND
76#else
77# define ZYAN_UNKNOWN_COMPILER
78#endif
79
80/* ============================================================================================== */
81/* Platform detection */
82/* ============================================================================================== */
83
84#if defined(_WIN32)
85# define ZYAN_WINDOWS
86#elif defined(__EMSCRIPTEN__)
87# define ZYAN_EMSCRIPTEN
88#elif defined(__wasi__) || defined(__WASI__)
89// via: https://reviews.llvm.org/D57155
90# define ZYAN_WASI
91#elif defined(__APPLE__)
92# define ZYAN_APPLE
93# define ZYAN_POSIX
94#elif defined(__linux)
95# define ZYAN_LINUX
96# define ZYAN_POSIX
97#elif defined(__FreeBSD__)
98# define ZYAN_FREEBSD
99# define ZYAN_POSIX
100#elif defined(__NetBSD__)
101# define ZYAN_NETBSD
102# define ZYAN_POSIX
103#elif defined(sun) || defined(__sun)
104# define ZYAN_SOLARIS
105# define ZYAN_POSIX
106#elif defined(__HAIKU__)
107# define ZYAN_HAIKU
108# define ZYAN_POSIX
109#elif defined(__unix) || defined(__unix__)
110# define ZYAN_UNIX
111# define ZYAN_POSIX
112#elif defined(__posix)
113# define ZYAN_POSIX
114#else
115# define ZYAN_UNKNOWN_PLATFORM
116#endif
117
118/* ============================================================================================== */
119/* Kernel mode detection */
120/* ============================================================================================== */
121
122#if (defined(ZYAN_WINDOWS) && defined(_KERNEL_MODE)) || \
123 (defined(ZYAN_APPLE) && defined(KERNEL)) || \
124 (defined(ZYAN_LINUX) && defined(__KERNEL__)) || \
125 (defined(__FreeBSD_kernel__))
126# define ZYAN_KERNEL
127#else
128# define ZYAN_USER
129#endif
130
131/* ============================================================================================== */
132/* Architecture detection */
133/* ============================================================================================== */
134
135#if defined(_M_AMD64) || defined(__x86_64__)
136# define ZYAN_X64
137#elif defined(_M_IX86) || defined(__i386__)
138# define ZYAN_X86
139#elif defined(_M_ARM64) || defined(__aarch64__)
140# define ZYAN_AARCH64
141#elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__)
142# define ZYAN_ARM
143#elif defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__WASM__)
144# define ZYAN_WASM
145#elif defined(__loongarch__)
146# define ZYAN_LOONGARCH
147#elif defined(__powerpc64__)
148# define ZYAN_PPC64
149#elif defined(__powerpc__)
150# define ZYAN_PPC
151#elif defined(__riscv) && __riscv_xlen == 64
152# define ZYAN_RISCV64
153#else
154# error "Unsupported architecture detected"
155#endif
156
157/* ============================================================================================== */
158/* Debug/Release detection */
159/* ============================================================================================== */
160
161#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
162# ifdef _DEBUG
163# define ZYAN_DEBUG
164# else
165# define ZYAN_RELEASE
166# endif
167#elif defined(ZYAN_GNUC) || defined(ZYAN_ICC)
168# ifdef NDEBUG
169# define ZYAN_RELEASE
170# else
171# define ZYAN_DEBUG
172# endif
173#else
174# define ZYAN_RELEASE
175#endif
176
177/* ============================================================================================== */
178/* Deprecation hint */
179/* ============================================================================================== */
180
181#if defined(ZYAN_GCC) || defined(ZYAN_CLANG)
182# define ZYAN_DEPRECATED __attribute__((__deprecated__))
183#elif defined(ZYAN_MSVC)
184# define ZYAN_DEPRECATED __declspec(deprecated)
185#else
186# define ZYAN_DEPRECATED
187#endif
188
189/* ============================================================================================== */
190/* Generic DLL import/export helpers */
191/* ============================================================================================== */
192
193#if defined(ZYAN_MSVC)
194# define ZYAN_DLLEXPORT __declspec(dllexport)
195# define ZYAN_DLLIMPORT __declspec(dllimport)
196#else
197# define ZYAN_DLLEXPORT
198# define ZYAN_DLLIMPORT
199#endif
200
201/* ============================================================================================== */
202/* Zycore dll{export,import} */
203/* ============================================================================================== */
204
205// This is a cut-down version of what CMake's `GenerateExportHeader` would usually generate. To
206// simplify builds without CMake, we define these things manually instead of relying on CMake
207// to generate the header.
208//
209// For static builds, our CMakeList will define `ZYCORE_STATIC_BUILD`. For shared library builds,
210// our CMake will define `ZYCORE_SHOULD_EXPORT` depending on whether the target is being imported or
211// exported. If CMake isn't used, users can manually define these to fit their use-case.
212
213// Backward compatibility: CMake would previously generate these variables names. However, because
214// they have pretty cryptic names, we renamed them when we got rid of `GenerateExportHeader`. For
215// backward compatibility for users that don't use CMake and previously manually defined these, we
216// translate the old defines here and print a warning.
217#if defined(ZYCORE_STATIC_DEFINE)
218# pragma message("ZYCORE_STATIC_DEFINE was renamed to ZYCORE_STATIC_BUILD.")
219# define ZYCORE_STATIC_BUILD
220#endif
221#if defined(Zycore_EXPORTS)
222# pragma message("Zycore_EXPORTS was renamed to ZYCORE_SHOULD_EXPORT.")
223# define ZYCORE_SHOULD_EXPORT
224#endif
225
229#if defined(ZYCORE_STATIC_BUILD)
230# define ZYCORE_EXPORT
231#else
232# if defined(ZYCORE_SHOULD_EXPORT)
233# define ZYCORE_EXPORT ZYAN_DLLEXPORT
234# else
235# define ZYCORE_EXPORT ZYAN_DLLIMPORT
236# endif
237#endif
238
242#define ZYCORE_NO_EXPORT
243
244/* ============================================================================================== */
245/* Misc compatibility macros */
246/* ============================================================================================== */
247
248#if defined(ZYAN_CLANG)
249# define ZYAN_NO_SANITIZE(what) __attribute__((no_sanitize(what)))
250#else
251# define ZYAN_NO_SANITIZE(what)
252#endif
253
254#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
255# define ZYAN_INLINE __inline
256#else
257# define ZYAN_INLINE static inline
258#endif
259
260#if defined(ZYAN_MSVC)
261# define ZYAN_NOINLINE __declspec(noinline)
262#elif defined(ZYAN_GCC) || defined(ZYAN_CLANG)
263# define ZYAN_NOINLINE __attribute__((noinline))
264#else
265# define ZYAN_NOINLINE
266#endif
267
268/* ============================================================================================== */
269/* Debugging and optimization macros */
270/* ============================================================================================== */
271
275#if defined(ZYAN_NO_LIBC)
276# define ZYAN_ASSERT(condition) (void)(condition)
277#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
278# include <wdm.h>
279# define ZYAN_ASSERT(condition) NT_ASSERT(condition)
280#else
281# include <assert.h>
282# define ZYAN_ASSERT(condition) assert(condition)
283#endif
284
288#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
289# define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x)
290#elif (defined(__cplusplus) && __cplusplus >= 201103L) || \
291 (defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \
292 (defined (_MSC_VER) && (_MSC_VER >= 1800))
293# define ZYAN_STATIC_ASSERT(x) static_assert(x, #x)
294#else
295# define ZYAN_STATIC_ASSERT(x) \
296 typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1]
297#endif
298
302#if defined(ZYAN_RELEASE)
303# if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs.
304# if __has_builtin(__builtin_unreachable)
305# define ZYAN_UNREACHABLE __builtin_unreachable()
306# else
307# define ZYAN_UNREACHABLE for(;;)
308# endif
309# elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4)
310# define ZYAN_UNREACHABLE __builtin_unreachable()
311# elif defined(ZYAN_ICC)
312# ifdef ZYAN_WINDOWS
313# include <stdlib.h> // "missing return statement" workaround
314# define ZYAN_UNREACHABLE __assume(0); (void)abort()
315# else
316# define ZYAN_UNREACHABLE __builtin_unreachable()
317# endif
318# elif defined(ZYAN_MSVC)
319# define ZYAN_UNREACHABLE __assume(0)
320# else
321# define ZYAN_UNREACHABLE for(;;)
322# endif
323#elif defined(ZYAN_NO_LIBC)
324# define ZYAN_UNREACHABLE for(;;)
325#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
326# define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} }
327#else
328# include <stdlib.h>
329# define ZYAN_UNREACHABLE { assert(0); abort(); }
330#endif
331
332/* ============================================================================================== */
333/* Utils */
334/* ============================================================================================== */
335
336/* ---------------------------------------------------------------------------------------------- */
337/* General purpose */
338/* ---------------------------------------------------------------------------------------------- */
339
345#define ZYAN_UNUSED(x) (void)(x)
346
350#if defined(ZYAN_GCC) && __GNUC__ >= 7
351# define ZYAN_FALLTHROUGH ; __attribute__((__fallthrough__))
352#else
353# define ZYAN_FALLTHROUGH
354#endif
355
361#define ZYAN_BITFIELD(x) : x
362
366#define ZYAN_REQUIRES_LIBC
367
374#if defined(__RESHARPER__)
375# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
376 [[gnu::format(printf, format_index, first_to_check)]]
377#elif defined(ZYAN_GCC)
378# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
379 __attribute__((format(printf, format_index, first_to_check)))
380#else
381# define ZYAN_PRINTF_ATTR(format_index, first_to_check)
382#endif
383
390#if defined(__RESHARPER__)
391# define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \
392 [[rscpp::format(wprintf, format_index, first_to_check)]]
393#else
394# define ZYAN_WPRINTF_ATTR(format_index, first_to_check)
395#endif
396
397/* ---------------------------------------------------------------------------------------------- */
398/* Arrays */
399/* ---------------------------------------------------------------------------------------------- */
400
408#define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
409
410/* ---------------------------------------------------------------------------------------------- */
411/* Arithmetic */
412/* ---------------------------------------------------------------------------------------------- */
413
422#define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b))
423
432#define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b))
433
441#define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a))
442
452#define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
453
459#define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0)
460
471#define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
472
483#define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1))
484
492#if defined(ZYAN_LINUX) && defined(ZYAN_KERNEL)
493# include <asm/div64.h> /* do_div */
494# define ZYAN_DIV64(n, divisor) do_div(n, divisor)
495#else
496# define ZYAN_DIV64(n, divisor) (n /= divisor)
497#endif
498
499/* ---------------------------------------------------------------------------------------------- */
500/* Bit operations */
501/* ---------------------------------------------------------------------------------------------- */
502
503/*
504 * Checks, if the bit at index `b` is required to present the ordinal value `n`.
505 *
506 * @param n The ordinal value.
507 * @param b The bit index.
508 *
509 * @return `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or
510 * `ZYAN_FALSE`, if not.
511 *
512 * Note that this macro always returns `ZYAN_FALSE` for `n == 0`.
513 */
514#define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0)
515
516/*
517 * Returns the number of bits required to represent the ordinal value `n`.
518 *
519 * @param n The ordinal value.
520 *
521 * @return The number of bits required to represent the ordinal value `n`.
522 *
523 * Note that this macro returns `0` for `n == 0`.
524 */
525#define ZYAN_BITS_TO_REPRESENT(n) \
526 ( \
527 ZYAN_NEEDS_BIT(n, 0) + ZYAN_NEEDS_BIT(n, 1) + \
528 ZYAN_NEEDS_BIT(n, 2) + ZYAN_NEEDS_BIT(n, 3) + \
529 ZYAN_NEEDS_BIT(n, 4) + ZYAN_NEEDS_BIT(n, 5) + \
530 ZYAN_NEEDS_BIT(n, 6) + ZYAN_NEEDS_BIT(n, 7) + \
531 ZYAN_NEEDS_BIT(n, 8) + ZYAN_NEEDS_BIT(n, 9) + \
532 ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \
533 ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \
534 ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \
535 ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \
536 ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \
537 ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \
538 ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \
539 ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \
540 ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \
541 ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \
542 ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31) \
543 )
544
545/* ---------------------------------------------------------------------------------------------- */
546
547/* ============================================================================================== */
548
549#endif /* ZYCORE_DEFINES_H */