Zycore 1.5.2.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# if defined(_MSC_VER)
68# define ZYAN_CLANG_CL
69# define ZYAN_MSVC
70# endif
71#elif defined(__ICC) || defined(__INTEL_COMPILER)
72# define ZYAN_ICC
73#elif defined(__GNUC__) || defined(__GNUG__)
74# define ZYAN_GCC
75# define ZYAN_GNUC
76#elif defined(_MSC_VER)
77# define ZYAN_MSVC
78#elif defined(__BORLANDC__)
79# define ZYAN_BORLAND
80#else
81# define ZYAN_UNKNOWN_COMPILER
82#endif
83
84/* ============================================================================================== */
85/* Platform detection */
86/* ============================================================================================== */
87
88#if defined(_WIN32)
89# define ZYAN_WINDOWS
90#elif defined(__EMSCRIPTEN__)
91# define ZYAN_EMSCRIPTEN
92#elif defined(__wasi__) || defined(__WASI__)
93// via: https://reviews.llvm.org/D57155
94# define ZYAN_WASI
95#elif defined(__APPLE__)
96# define ZYAN_APPLE
97# define ZYAN_POSIX
98#elif defined(__linux)
99# define ZYAN_LINUX
100# define ZYAN_POSIX
101#elif defined(__FreeBSD__)
102# define ZYAN_FREEBSD
103# define ZYAN_POSIX
104#elif defined(__NetBSD__)
105# define ZYAN_NETBSD
106# define ZYAN_POSIX
107#elif defined(sun) || defined(__sun)
108# define ZYAN_SOLARIS
109# define ZYAN_POSIX
110#elif defined(__HAIKU__)
111# define ZYAN_HAIKU
112# define ZYAN_POSIX
113#elif defined(__unix) || defined(__unix__)
114# define ZYAN_UNIX
115# define ZYAN_POSIX
116#elif defined(__posix)
117# define ZYAN_POSIX
118#else
119# define ZYAN_UNKNOWN_PLATFORM
120#endif
121
122/* ============================================================================================== */
123/* Kernel mode detection */
124/* ============================================================================================== */
125
126#if (defined(ZYAN_WINDOWS) && defined(_KERNEL_MODE)) || \
127 (defined(ZYAN_APPLE) && defined(KERNEL)) || \
128 (defined(ZYAN_LINUX) && defined(__KERNEL__)) || \
129 (defined(__FreeBSD_kernel__))
130# define ZYAN_KERNEL
131#else
132# define ZYAN_USER
133#endif
134
135/* ============================================================================================== */
136/* Architecture detection */
137/* ============================================================================================== */
138
139#if defined(_M_AMD64) || defined(__x86_64__)
140# define ZYAN_X64
141#elif defined(_M_IX86) || defined(__i386__)
142# define ZYAN_X86
143#elif defined(_M_ARM64) || defined(__aarch64__)
144# define ZYAN_AARCH64
145#elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__)
146# define ZYAN_ARM
147#elif defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__WASM__)
148# define ZYAN_WASM
149#elif defined(__loongarch__)
150# define ZYAN_LOONGARCH
151#elif defined(__powerpc64__)
152# define ZYAN_PPC64
153#elif defined(__powerpc__)
154# define ZYAN_PPC
155#elif defined(__riscv) && __riscv_xlen == 64
156# define ZYAN_RISCV64
157#else
158# error "Unsupported architecture detected"
159#endif
160
161/* ============================================================================================== */
162/* Debug/Release detection */
163/* ============================================================================================== */
164
165#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
166# ifdef _DEBUG
167# define ZYAN_DEBUG
168# else
169# define ZYAN_RELEASE
170# endif
171#elif defined(ZYAN_GNUC) || defined(ZYAN_ICC)
172# ifdef NDEBUG
173# define ZYAN_RELEASE
174# else
175# define ZYAN_DEBUG
176# endif
177#else
178# define ZYAN_RELEASE
179#endif
180
181/* ============================================================================================== */
182/* Deprecation hint */
183/* ============================================================================================== */
184
185#if defined(ZYAN_GCC) || defined(ZYAN_CLANG)
186# define ZYAN_DEPRECATED __attribute__((__deprecated__))
187#elif defined(ZYAN_MSVC)
188# define ZYAN_DEPRECATED __declspec(deprecated)
189#else
190# define ZYAN_DEPRECATED
191#endif
192
193/* ============================================================================================== */
194/* Generic DLL import/export helpers */
195/* ============================================================================================== */
196
197#if defined(ZYAN_MSVC) || (defined(ZYAN_WINDOWS) && defined(ZYAN_GNUC))
198# define ZYAN_DLLEXPORT __declspec(dllexport)
199# define ZYAN_DLLIMPORT __declspec(dllimport)
200#else
201# if defined(ZYAN_GNUC)
202# define ZYAN_DLLEXPORT __attribute__((__visibility__("default")))
203# define ZYAN_DLLIMPORT extern
204# else
205# define ZYAN_DLLEXPORT
206# define ZYAN_DLLIMPORT
207# endif
208#endif
209
210/* ============================================================================================== */
211/* Zycore dll{export,import} */
212/* ============================================================================================== */
213
214// This is a cut-down version of what CMake's `GenerateExportHeader` would usually generate. To
215// simplify builds without CMake, we define these things manually instead of relying on CMake
216// to generate the header.
217//
218// For static builds, our CMakeList will define `ZYCORE_STATIC_BUILD`. For shared library builds,
219// our CMake will define `ZYCORE_SHOULD_EXPORT` depending on whether the target is being imported or
220// exported. If CMake isn't used, users can manually define these to fit their use-case.
221
222// Backward compatibility: CMake would previously generate these variables names. However, because
223// they have pretty cryptic names, we renamed them when we got rid of `GenerateExportHeader`. For
224// backward compatibility for users that don't use CMake and previously manually defined these, we
225// translate the old defines here and print a warning.
226#if defined(ZYCORE_STATIC_DEFINE)
227# pragma message("ZYCORE_STATIC_DEFINE was renamed to ZYCORE_STATIC_BUILD.")
228# define ZYCORE_STATIC_BUILD
229#endif
230#if defined(Zycore_EXPORTS)
231# pragma message("Zycore_EXPORTS was renamed to ZYCORE_SHOULD_EXPORT.")
232# define ZYCORE_SHOULD_EXPORT
233#endif
234
238#if defined(ZYCORE_STATIC_BUILD)
239# define ZYCORE_EXPORT
240#else
241# if defined(ZYCORE_SHOULD_EXPORT)
242# define ZYCORE_EXPORT ZYAN_DLLEXPORT
243# else
244# define ZYCORE_EXPORT ZYAN_DLLIMPORT
245# endif
246#endif
247
251#if defined(ZYAN_GNUC)
252# define ZYCORE_NO_EXPORT __attribute__((__visibility__("hidden")))
253#else
254# define ZYCORE_NO_EXPORT
255#endif
256
257/* ============================================================================================== */
258/* Misc compatibility macros */
259/* ============================================================================================== */
260
261#if defined(ZYAN_CLANG)
262# define ZYAN_NO_SANITIZE(what) __attribute__((no_sanitize(what)))
263#else
264# define ZYAN_NO_SANITIZE(what)
265#endif
266
267#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
268# define ZYAN_INLINE __inline
269#else
270# define ZYAN_INLINE static inline
271#endif
272
273#if defined(ZYAN_MSVC)
274# define ZYAN_NOINLINE __declspec(noinline)
275#elif defined(ZYAN_GCC) || defined(ZYAN_CLANG)
276# define ZYAN_NOINLINE __attribute__((noinline))
277#else
278# define ZYAN_NOINLINE
279#endif
280
281/* ============================================================================================== */
282/* Debugging and optimization macros */
283/* ============================================================================================== */
284
288#if defined(ZYAN_NO_LIBC)
289# define ZYAN_ASSERT(condition) (void)(condition)
290#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
291# include <wdm.h>
292# define ZYAN_ASSERT(condition) NT_ASSERT(condition)
293#else
294# include <assert.h>
295# define ZYAN_ASSERT(condition) assert(condition)
296#endif
297
301#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
302# define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x)
303#elif (defined(__cplusplus) && __cplusplus >= 201103L) || \
304 (defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \
305 (defined (_MSC_VER) && (_MSC_VER >= 1800))
306# define ZYAN_STATIC_ASSERT(x) static_assert(x, #x)
307#elif defined(ZYAN_GNUC)
308# define ZYAN_STATIC_ASSERT(x) \
309 __attribute__((unused)) typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1]
310#else
311# define ZYAN_STATIC_ASSERT(x) \
312 typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1]
313#endif
314
318#if defined(ZYAN_RELEASE)
319# if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs.
320# if __has_builtin(__builtin_unreachable)
321# define ZYAN_UNREACHABLE __builtin_unreachable()
322# else
323# define ZYAN_UNREACHABLE for(;;)
324# endif
325# elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4)
326# define ZYAN_UNREACHABLE __builtin_unreachable()
327# elif defined(ZYAN_ICC)
328# ifdef ZYAN_WINDOWS
329# include <stdlib.h> // "missing return statement" workaround
330# define ZYAN_UNREACHABLE __assume(0); (void)abort()
331# else
332# define ZYAN_UNREACHABLE __builtin_unreachable()
333# endif
334# elif defined(ZYAN_MSVC)
335# define ZYAN_UNREACHABLE __assume(0)
336# else
337# define ZYAN_UNREACHABLE for(;;)
338# endif
339#elif defined(ZYAN_NO_LIBC)
340# define ZYAN_UNREACHABLE for(;;)
341#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
342# define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} }
343#else
344# include <stdlib.h>
345# define ZYAN_UNREACHABLE { assert(0); abort(); }
346#endif
347
348/* ============================================================================================== */
349/* Utils */
350/* ============================================================================================== */
351
352/* ---------------------------------------------------------------------------------------------- */
353/* General purpose */
354/* ---------------------------------------------------------------------------------------------- */
355
361#define ZYAN_UNUSED(x) (void)(x)
362
366#if defined(ZYAN_GCC) && __GNUC__ >= 7
367# define ZYAN_FALLTHROUGH ; __attribute__((__fallthrough__))
368#else
369# define ZYAN_FALLTHROUGH
370#endif
371
377#define ZYAN_BITFIELD(x) : x
378
382#define ZYAN_REQUIRES_LIBC
383
390#if defined(__RESHARPER__)
391# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
392 [[gnu::format(printf, format_index, first_to_check)]]
393#elif defined(ZYAN_GCC)
394# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
395 __attribute__((format(printf, format_index, first_to_check)))
396#else
397# define ZYAN_PRINTF_ATTR(format_index, first_to_check)
398#endif
399
406#if defined(__RESHARPER__)
407# define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \
408 [[rscpp::format(wprintf, format_index, first_to_check)]]
409#else
410# define ZYAN_WPRINTF_ATTR(format_index, first_to_check)
411#endif
412
413/* ---------------------------------------------------------------------------------------------- */
414/* Arrays */
415/* ---------------------------------------------------------------------------------------------- */
416
424#define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
425
426/* ---------------------------------------------------------------------------------------------- */
427/* Arithmetic */
428/* ---------------------------------------------------------------------------------------------- */
429
438#define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b))
439
448#define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b))
449
457#define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a))
458
468#define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
469
475#define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0)
476
487#define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
488
499#define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1))
500
508#if defined(ZYAN_LINUX) && defined(ZYAN_KERNEL)
509# include <asm/div64.h> /* do_div */
510# define ZYAN_DIV64(n, divisor) do_div(n, divisor)
511#else
512# define ZYAN_DIV64(n, divisor) (n /= divisor)
513#endif
514
515/* ---------------------------------------------------------------------------------------------- */
516/* Bit operations */
517/* ---------------------------------------------------------------------------------------------- */
518
519/*
520 * Checks, if the bit at index `b` is required to present the ordinal value `n`.
521 *
522 * @param n The ordinal value.
523 * @param b The bit index.
524 *
525 * @return `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or
526 * `ZYAN_FALSE`, if not.
527 *
528 * Note that this macro always returns `ZYAN_FALSE` for `n == 0`.
529 */
530#define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0)
531
532/*
533 * Returns the number of bits required to represent the ordinal value `n`.
534 *
535 * @param n The ordinal value.
536 *
537 * @return The number of bits required to represent the ordinal value `n`.
538 *
539 * Note that this macro returns `0` for `n == 0`.
540 */
541#define ZYAN_BITS_TO_REPRESENT(n) \
542 ( \
543 ZYAN_NEEDS_BIT(n, 0) + ZYAN_NEEDS_BIT(n, 1) + \
544 ZYAN_NEEDS_BIT(n, 2) + ZYAN_NEEDS_BIT(n, 3) + \
545 ZYAN_NEEDS_BIT(n, 4) + ZYAN_NEEDS_BIT(n, 5) + \
546 ZYAN_NEEDS_BIT(n, 6) + ZYAN_NEEDS_BIT(n, 7) + \
547 ZYAN_NEEDS_BIT(n, 8) + ZYAN_NEEDS_BIT(n, 9) + \
548 ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \
549 ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \
550 ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \
551 ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \
552 ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \
553 ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \
554 ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \
555 ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \
556 ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \
557 ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \
558 ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31) \
559 )
560
561/* ---------------------------------------------------------------------------------------------- */
562
563/* ============================================================================================== */
564
565#endif /* ZYCORE_DEFINES_H */