Zycore 1.5.2
Zyan Core Library for C
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
31
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
67#if defined(__has_include)
68# define ZYAN_HAS_INCLUDE(name) __has_include(name)
69#else
70# define ZYAN_HAS_INCLUDE(name) 0
71#endif
72
80#if defined(__has_builtin)
81# define ZYAN_HAS_BUILTIN(symbol) __has_builtin(symbol)
82#else
83# define ZYAN_HAS_BUILTIN(symbol) 0
84#endif
85
86/* ============================================================================================== */
87/* Compiler detection */
88/* ============================================================================================== */
89
90#if defined(__clang__)
91# define ZYAN_CLANG
92# define ZYAN_GNUC
93# if defined(_MSC_VER)
94# define ZYAN_CLANG_CL
95# define ZYAN_MSVC
96# endif
97#elif defined(__ICC) || defined(__INTEL_COMPILER)
98# define ZYAN_ICC
99#elif defined(__GNUC__) || defined(__GNUG__)
100# define ZYAN_GCC
101# define ZYAN_GNUC
102#elif defined(_MSC_VER)
103# define ZYAN_MSVC
104#elif defined(__BORLANDC__)
105# define ZYAN_BORLAND
106#else
107# define ZYAN_UNKNOWN_COMPILER
108#endif
109
110/* ============================================================================================== */
111/* Platform detection */
112/* ============================================================================================== */
113
114#if defined(_WIN32)
115# define ZYAN_WINDOWS
116#elif defined(__EMSCRIPTEN__)
117# define ZYAN_EMSCRIPTEN
118#elif defined(__wasi__) || defined(__WASI__)
119// via: https://reviews.llvm.org/D57155
120# define ZYAN_WASI
121#elif defined(__APPLE__)
122# define ZYAN_APPLE
123# define ZYAN_POSIX
124#elif defined(__linux)
125# define ZYAN_LINUX
126# define ZYAN_POSIX
127#elif defined(__FreeBSD__)
128# define ZYAN_FREEBSD
129# define ZYAN_POSIX
130#elif defined(__NetBSD__)
131# define ZYAN_NETBSD
132# define ZYAN_POSIX
133#elif defined(sun) || defined(__sun)
134# define ZYAN_SOLARIS
135# define ZYAN_POSIX
136#elif defined(__HAIKU__)
137# define ZYAN_HAIKU
138# define ZYAN_POSIX
139#elif defined(__unix) || defined(__unix__)
140# define ZYAN_UNIX
141# define ZYAN_POSIX
142#elif defined(__posix)
143# define ZYAN_POSIX
144#else
145# define ZYAN_UNKNOWN_PLATFORM
146#endif
147
148/* ============================================================================================== */
149/* Kernel mode detection */
150/* ============================================================================================== */
151
152#if (defined(ZYAN_WINDOWS) && defined(_KERNEL_MODE)) || \
153 (defined(ZYAN_APPLE) && defined(KERNEL)) || \
154 (defined(ZYAN_LINUX) && defined(__KERNEL__)) || \
155 (defined(__FreeBSD_kernel__))
156# define ZYAN_KERNEL
157#else
158# define ZYAN_USER
159#endif
160
161/* ============================================================================================== */
162/* Architecture detection */
163/* ============================================================================================== */
164
165#if defined(_M_AMD64) || defined(__x86_64__)
166# define ZYAN_X64
167# define ZYAN_ARCHITECTURE_WIDTH 64
168#elif defined(_M_IX86) || defined(__i386__)
169# define ZYAN_X86
170# define ZYAN_ARCHITECTURE_WIDTH 32
171#elif defined(_M_ARM64) || defined(__aarch64__)
172# define ZYAN_AARCH64
173# define ZYAN_ARCHITECTURE_WIDTH 64
174#elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__)
175# define ZYAN_ARM
176# define ZYAN_ARCHITECTURE_WIDTH 32
177#elif defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__WASM__)
178# define ZYAN_WASM
179# define ZYAN_ARCHITECTURE_WIDTH 32
180#elif defined(__loongarch__)
181# define ZYAN_LOONGARCH
182# define ZYAN_ARCHITECTURE_WIDTH 64
183#elif defined(__powerpc64__)
184# define ZYAN_PPC64
185# define ZYAN_ARCHITECTURE_WIDTH 64
186#elif defined(__powerpc__)
187# define ZYAN_PPC
188# define ZYAN_ARCHITECTURE_WIDTH 32
189#elif defined(__riscv) || defined(__riscv__)
190# if __riscv_xlen == 64
191# define ZYAN_RISCV64
192# define ZYAN_ARCHITECTURE_WIDTH 64
193# else
194# define ZYAN_RISCV32
195# define ZYAN_ARCHITECTURE_WIDTH 32
196# endif
197#elif defined(__arc__)
198# define ZYAN_ARC
199#elif defined(__s390x__)
200# define ZYAN_S390
201#elif defined(__sparc__)
202# define ZYAN_SPARC
203#elif defined(__mips__)
204# define ZYAN_MIPS
205#else
206# error "Unsupported architecture detected"
207#endif
208
209#if !defined(ZYAN_ARCHITECTURE_WIDTH)
210# if defined(__LP64__)
211# define ZYAN_ARCHITECTURE_WIDTH 64
212# else
213# define ZYAN_ARCHITECTURE_WIDTH 32
214# endif
215#endif
216
217/* ============================================================================================== */
218/* Endianness detection */
219/* ============================================================================================== */
220
221#define ZYAN_LITTLE_ENDIAN 0
222#define ZYAN_BIG_ENDIAN 1
223
224#if !defined(ZYAN_NO_LIBC) && ZYAN_HAS_INCLUDE(<stdbit.h>)
225# include <stdbit.h>
226# if __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_LITTLE__
227# define ZYAN_ENDIAN ZYAN_LITTLE_ENDIAN
228# elif __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_BIG__
229# define ZYAN_ENDIAN ZYAN_BIG_ENDIAN
230# else
231# error "Unsupported endianness"
232# endif
233#elif defined(__BYTE_ORDER__)
234# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
235# define ZYAN_ENDIAN ZYAN_LITTLE_ENDIAN
236# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
237# define ZYAN_ENDIAN ZYAN_BIG_ENDIAN
238# else
239# error "Unsupported endianness"
240# endif
241#elif defined(ZYAN_S390) || defined(ZYAN_SPARC) || defined(ZYAN_MIPS)
242# define ZYAN_ENDIAN ZYAN_BIG_ENDIAN
243#else
244# define ZYAN_ENDIAN ZYAN_LITTLE_ENDIAN
245#endif
246
247/* ============================================================================================== */
248/* Debug/Release detection */
249/* ============================================================================================== */
250
251#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
252# ifdef _DEBUG
253# define ZYAN_DEBUG
254# else
255# define ZYAN_RELEASE
256# endif
257#elif defined(ZYAN_GNUC) || defined(ZYAN_ICC)
258# ifdef NDEBUG
259# define ZYAN_RELEASE
260# else
261# define ZYAN_DEBUG
262# endif
263#else
264# define ZYAN_RELEASE
265#endif
266
267/* ============================================================================================== */
268/* Deprecation hint */
269/* ============================================================================================== */
270
271#if defined(ZYAN_GCC) || defined(ZYAN_CLANG)
272# define ZYAN_DEPRECATED __attribute__((__deprecated__))
273#elif defined(ZYAN_MSVC)
274# define ZYAN_DEPRECATED __declspec(deprecated)
275#else
276# define ZYAN_DEPRECATED
277#endif
278
279/* ============================================================================================== */
280/* Generic DLL import/export helpers */
281/* ============================================================================================== */
282
283#if defined(ZYAN_MSVC) || (defined(ZYAN_WINDOWS) && defined(ZYAN_GNUC))
284# define ZYAN_DLLEXPORT __declspec(dllexport)
285# define ZYAN_DLLIMPORT __declspec(dllimport)
286#else
287# if defined(ZYAN_GNUC)
288# define ZYAN_DLLEXPORT __attribute__((__visibility__("default")))
289# define ZYAN_DLLIMPORT extern
290# else
291# define ZYAN_DLLEXPORT
292# define ZYAN_DLLIMPORT
293# endif
294#endif
295
296/* ============================================================================================== */
297/* Zycore dll{export,import} */
298/* ============================================================================================== */
299
300// This is a cut-down version of what CMake's `GenerateExportHeader` would usually generate. To
301// simplify builds without CMake, we define these things manually instead of relying on CMake
302// to generate the header.
303//
304// For static builds, our CMakeList will define `ZYCORE_STATIC_BUILD`. For shared library builds,
305// our CMake will define `ZYCORE_SHOULD_EXPORT` depending on whether the target is being imported or
306// exported. If CMake isn't used, users can manually define these to fit their use-case.
307
308// Backward compatibility: CMake would previously generate these variables names. However, because
309// they have pretty cryptic names, we renamed them when we got rid of `GenerateExportHeader`. For
310// backward compatibility for users that don't use CMake and previously manually defined these, we
311// translate the old defines here and print a warning.
312#if defined(ZYCORE_STATIC_DEFINE)
313# pragma message("ZYCORE_STATIC_DEFINE was renamed to ZYCORE_STATIC_BUILD.")
314# define ZYCORE_STATIC_BUILD
315#endif
316#if defined(Zycore_EXPORTS)
317# pragma message("Zycore_EXPORTS was renamed to ZYCORE_SHOULD_EXPORT.")
318# define ZYCORE_SHOULD_EXPORT
319#endif
320
324#if defined(ZYCORE_STATIC_BUILD)
325# define ZYCORE_EXPORT
326#else
327# if defined(ZYCORE_SHOULD_EXPORT)
328# define ZYCORE_EXPORT ZYAN_DLLEXPORT
329# else
330# define ZYCORE_EXPORT ZYAN_DLLIMPORT
331# endif
332#endif
333
337#if defined(ZYAN_GNUC)
338# define ZYCORE_NO_EXPORT __attribute__((__visibility__("hidden")))
339#else
340# define ZYCORE_NO_EXPORT
341#endif
342
343/* ============================================================================================== */
344/* Misc compatibility macros */
345/* ============================================================================================== */
346
347#if defined(ZYAN_CLANG)
348# define ZYAN_NO_SANITIZE(what) __attribute__((no_sanitize(what)))
349#else
350# define ZYAN_NO_SANITIZE(what)
351#endif
352
353#if defined(ZYAN_BORLAND)
354# define ZYAN_INLINE static __inline
355#else
356# define ZYAN_INLINE static inline
357#endif
358
359#if defined(ZYAN_MSVC)
360# define ZYAN_NOINLINE __declspec(noinline)
361#elif defined(ZYAN_GCC) || defined(ZYAN_CLANG)
362# define ZYAN_NOINLINE __attribute__((noinline))
363#else
364# define ZYAN_NOINLINE
365#endif
366
367/* ============================================================================================== */
368/* Debugging and optimization macros */
369/* ============================================================================================== */
370
374#if defined(ZYAN_NO_LIBC)
375# define ZYAN_ASSERT(condition) (void)(condition)
376#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
377# include <wdm.h>
378# define ZYAN_ASSERT(condition) NT_ASSERT(condition)
379#else
380# include <assert.h>
381# define ZYAN_ASSERT(condition) assert(condition)
382#endif
383
387#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
388# define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x)
389#elif (defined(__cplusplus) && __cplusplus >= 201103L) || \
390 (defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \
391 (defined (_MSC_VER) && (_MSC_VER >= 1800))
392# define ZYAN_STATIC_ASSERT(x) static_assert(x, #x)
393#elif defined(ZYAN_GNUC)
394# define ZYAN_STATIC_ASSERT(x) \
395 __attribute__((unused)) typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1]
396#else
397# define ZYAN_STATIC_ASSERT(x) \
398 typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1]
399#endif
400
404#if defined(ZYAN_RELEASE)
405# if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs.
406# if __has_builtin(__builtin_unreachable)
407# define ZYAN_UNREACHABLE __builtin_unreachable()
408# else
409# define ZYAN_UNREACHABLE for(;;)
410# endif
411# elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4)
412# define ZYAN_UNREACHABLE __builtin_unreachable()
413# elif defined(ZYAN_ICC)
414# ifdef ZYAN_WINDOWS
415# include <stdlib.h> // "missing return statement" workaround
416# define ZYAN_UNREACHABLE __assume(0); (void)abort()
417# else
418# define ZYAN_UNREACHABLE __builtin_unreachable()
419# endif
420# elif defined(ZYAN_MSVC)
421# define ZYAN_UNREACHABLE __assume(0)
422# else
423# define ZYAN_UNREACHABLE for(;;)
424# endif
425#elif defined(ZYAN_NO_LIBC)
426# define ZYAN_UNREACHABLE for(;;)
427#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
428# define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} }
429#else
430# include <stdlib.h>
431# define ZYAN_UNREACHABLE { assert(0); abort(); }
432#endif
433
434/* ============================================================================================== */
435/* Utils */
436/* ============================================================================================== */
437
438/* ---------------------------------------------------------------------------------------------- */
439/* General purpose */
440/* ---------------------------------------------------------------------------------------------- */
441
447#define ZYAN_UNUSED(x) (void)(x)
448
452#if defined(ZYAN_GCC) && __GNUC__ >= 7
453# define ZYAN_FALLTHROUGH ; __attribute__((__fallthrough__))
454#else
455# define ZYAN_FALLTHROUGH
456#endif
457
463#define ZYAN_BITFIELD(x) : x
464
468#define ZYAN_REQUIRES_LIBC
469
476#if defined(__RESHARPER__)
477# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
478 [[gnu::format(printf, format_index, first_to_check)]]
479#elif defined(ZYAN_GCC)
480# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
481 __attribute__((format(printf, format_index, first_to_check)))
482#else
483# define ZYAN_PRINTF_ATTR(format_index, first_to_check)
484#endif
485
492#if defined(__RESHARPER__)
493# define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \
494 [[rscpp::format(wprintf, format_index, first_to_check)]]
495#else
496# define ZYAN_WPRINTF_ATTR(format_index, first_to_check)
497#endif
498
499/* ---------------------------------------------------------------------------------------------- */
500/* Arrays */
501/* ---------------------------------------------------------------------------------------------- */
502
510#define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
511
512/* ---------------------------------------------------------------------------------------------- */
513/* Arithmetic */
514/* ---------------------------------------------------------------------------------------------- */
515
524#define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b))
525
534#define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b))
535
543#define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a))
544
554#define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
555
561#define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0)
562
573#define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
574
585#define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1))
586
594#if defined(ZYAN_LINUX) && defined(ZYAN_KERNEL)
595# include <asm/div64.h> /* do_div */
596# define ZYAN_DIV64(n, divisor) do_div((n), (divisor))
597#else
598# define ZYAN_DIV64(n, divisor) ((n) /= (divisor))
599#endif
600
601/* ---------------------------------------------------------------------------------------------- */
602/* Bit operations */
603/* ---------------------------------------------------------------------------------------------- */
604
605/*
606 * Checks, if the bit at index `b` is required to present the ordinal value `n`.
607 *
608 * @param n The ordinal value.
609 * @param b The bit index.
610 *
611 * @return `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or
612 * `ZYAN_FALSE`, if not.
613 *
614 * Note that this macro always returns `ZYAN_FALSE` for `n == 0`.
615 */
616#define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0)
617
618/*
619 * Returns the number of bits required to represent the ordinal value `n`.
620 *
621 * @param n The ordinal value.
622 *
623 * @return The number of bits required to represent the ordinal value `n`.
624 *
625 * Note that this macro returns `0` for `n == 0`.
626 */
627#define ZYAN_BITS_TO_REPRESENT(n) \
628 ( \
629 ZYAN_NEEDS_BIT(n, 0) + ZYAN_NEEDS_BIT(n, 1) + \
630 ZYAN_NEEDS_BIT(n, 2) + ZYAN_NEEDS_BIT(n, 3) + \
631 ZYAN_NEEDS_BIT(n, 4) + ZYAN_NEEDS_BIT(n, 5) + \
632 ZYAN_NEEDS_BIT(n, 6) + ZYAN_NEEDS_BIT(n, 7) + \
633 ZYAN_NEEDS_BIT(n, 8) + ZYAN_NEEDS_BIT(n, 9) + \
634 ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \
635 ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \
636 ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \
637 ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \
638 ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \
639 ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \
640 ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \
641 ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \
642 ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \
643 ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \
644 ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31) \
645 )
646
647/* ---------------------------------------------------------------------------------------------- */
648
649/* ============================================================================================== */
650
651#endif /* ZYCORE_DEFINES_H */