Zycore  1.5.0.0
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(__unix) || defined(__unix__)
107 # define ZYAN_UNIX
108 # define ZYAN_POSIX
109 #elif defined(__posix)
110 # define ZYAN_POSIX
111 #else
112 # define ZYAN_UNKNOWN_PLATFORM
113 #endif
114 
115 /* ============================================================================================== */
116 /* Kernel mode detection */
117 /* ============================================================================================== */
118 
119 #if (defined(ZYAN_WINDOWS) && defined(_KERNEL_MODE)) || \
120  (defined(ZYAN_APPLE) && defined(KERNEL)) || \
121  (defined(ZYAN_LINUX) && defined(__KERNEL__)) || \
122  (defined(__FreeBSD_kernel__))
123 # define ZYAN_KERNEL
124 #else
125 # define ZYAN_USER
126 #endif
127 
128 /* ============================================================================================== */
129 /* Architecture detection */
130 /* ============================================================================================== */
131 
132 #if defined(_M_AMD64) || defined(__x86_64__)
133 # define ZYAN_X64
134 #elif defined(_M_IX86) || defined(__i386__)
135 # define ZYAN_X86
136 #elif defined(_M_ARM64) || defined(__aarch64__)
137 # define ZYAN_AARCH64
138 #elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__)
139 # define ZYAN_ARM
140 #elif defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__WASM__)
141 # define ZYAN_WASM
142 #elif defined(__loongarch__)
143 # define ZYAN_LOONGARCH
144 #elif defined(__powerpc64__)
145 # define ZYAN_PPC64
146 #elif defined(__powerpc__)
147 # define ZYAN_PPC
148 #elif defined(__riscv) && __riscv_xlen == 64
149 # define ZYAN_RISCV64
150 #else
151 # error "Unsupported architecture detected"
152 #endif
153 
154 /* ============================================================================================== */
155 /* Debug/Release detection */
156 /* ============================================================================================== */
157 
158 #if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
159 # ifdef _DEBUG
160 # define ZYAN_DEBUG
161 # else
162 # define ZYAN_RELEASE
163 # endif
164 #elif defined(ZYAN_GNUC) || defined(ZYAN_ICC)
165 # ifdef NDEBUG
166 # define ZYAN_RELEASE
167 # else
168 # define ZYAN_DEBUG
169 # endif
170 #else
171 # define ZYAN_RELEASE
172 #endif
173 
174 /* ============================================================================================== */
175 /* Deprecation hint */
176 /* ============================================================================================== */
177 
178 #if defined(ZYAN_GCC) || defined(ZYAN_CLANG)
179 # define ZYAN_DEPRECATED __attribute__((__deprecated__))
180 #elif defined(ZYAN_MSVC)
181 # define ZYAN_DEPRECATED __declspec(deprecated)
182 #else
183 # define ZYAN_DEPRECATED
184 #endif
185 
186 /* ============================================================================================== */
187 /* Generic DLL import/export helpers */
188 /* ============================================================================================== */
189 
190 #if defined(ZYAN_MSVC)
191 # define ZYAN_DLLEXPORT __declspec(dllexport)
192 # define ZYAN_DLLIMPORT __declspec(dllimport)
193 #else
194 # define ZYAN_DLLEXPORT
195 # define ZYAN_DLLIMPORT
196 #endif
197 
198 /* ============================================================================================== */
199 /* Zycore dll{export,import} */
200 /* ============================================================================================== */
201 
202 // This is a cut-down version of what CMake's `GenerateExportHeader` would usually generate. To
203 // simplify builds without CMake, we define these things manually instead of relying on CMake
204 // to generate the header.
205 //
206 // For static builds, our CMakeList will define `ZYCORE_STATIC_BUILD`. For shared library builds,
207 // our CMake will define `ZYCORE_SHOULD_EXPORT` depending on whether the target is being imported or
208 // exported. If CMake isn't used, users can manually define these to fit their use-case.
209 
210 // Backward compatibility: CMake would previously generate these variables names. However, because
211 // they have pretty cryptic names, we renamed them when we got rid of `GenerateExportHeader`. For
212 // backward compatibility for users that don't use CMake and previously manually defined these, we
213 // translate the old defines here and print a warning.
214 #if defined(ZYCORE_STATIC_DEFINE)
215 # pragma message("ZYCORE_STATIC_DEFINE was renamed to ZYCORE_STATIC_BUILD.")
216 # define ZYCORE_STATIC_BUILD
217 #endif
218 #if defined(Zycore_EXPORTS)
219 # pragma message("Zycore_EXPORTS was renamed to ZYCORE_SHOULD_EXPORT.")
220 # define ZYCORE_SHOULD_EXPORT
221 #endif
222 
226 #if defined(ZYCORE_STATIC_BUILD)
227 # define ZYCORE_EXPORT
228 #else
229 # if defined(ZYCORE_SHOULD_EXPORT)
230 # define ZYCORE_EXPORT ZYAN_DLLEXPORT
231 # else
232 # define ZYCORE_EXPORT ZYAN_DLLIMPORT
233 # endif
234 #endif
235 
239 #define ZYCORE_NO_EXPORT
240 
241 /* ============================================================================================== */
242 /* Misc compatibility macros */
243 /* ============================================================================================== */
244 
245 #if defined(ZYAN_CLANG)
246 # define ZYAN_NO_SANITIZE(what) __attribute__((no_sanitize(what)))
247 #else
248 # define ZYAN_NO_SANITIZE(what)
249 #endif
250 
251 #if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
252 # define ZYAN_INLINE __inline
253 #else
254 # define ZYAN_INLINE static inline
255 #endif
256 
257 #if defined(ZYAN_MSVC)
258 # define ZYAN_NOINLINE __declspec(noinline)
259 #elif defined(ZYAN_GCC) || defined(ZYAN_CLANG)
260 # define ZYAN_NOINLINE __attribute__((noinline))
261 #else
262 # define ZYAN_NOINLINE
263 #endif
264 
265 /* ============================================================================================== */
266 /* Debugging and optimization macros */
267 /* ============================================================================================== */
268 
272 #if defined(ZYAN_NO_LIBC)
273 # define ZYAN_ASSERT(condition) (void)(condition)
274 #elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
275 # include <wdm.h>
276 # define ZYAN_ASSERT(condition) NT_ASSERT(condition)
277 #else
278 # include <assert.h>
279 # define ZYAN_ASSERT(condition) assert(condition)
280 #endif
281 
285 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
286 # define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x)
287 #elif (defined(__cplusplus) && __cplusplus >= 201103L) || \
288  (defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \
289  (defined (_MSC_VER) && (_MSC_VER >= 1800))
290 # define ZYAN_STATIC_ASSERT(x) static_assert(x, #x)
291 #else
292 # define ZYAN_STATIC_ASSERT(x) \
293  typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1]
294 #endif
295 
299 #if defined(ZYAN_RELEASE)
300 # if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs.
301 # if __has_builtin(__builtin_unreachable)
302 # define ZYAN_UNREACHABLE __builtin_unreachable()
303 # else
304 # define ZYAN_UNREACHABLE for(;;)
305 # endif
306 # elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4)
307 # define ZYAN_UNREACHABLE __builtin_unreachable()
308 # elif defined(ZYAN_ICC)
309 # ifdef ZYAN_WINDOWS
310 # include <stdlib.h> // "missing return statement" workaround
311 # define ZYAN_UNREACHABLE __assume(0); (void)abort()
312 # else
313 # define ZYAN_UNREACHABLE __builtin_unreachable()
314 # endif
315 # elif defined(ZYAN_MSVC)
316 # define ZYAN_UNREACHABLE __assume(0)
317 # else
318 # define ZYAN_UNREACHABLE for(;;)
319 # endif
320 #elif defined(ZYAN_NO_LIBC)
321 # define ZYAN_UNREACHABLE for(;;)
322 #elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
323 # define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} }
324 #else
325 # include <stdlib.h>
326 # define ZYAN_UNREACHABLE { assert(0); abort(); }
327 #endif
328 
329 /* ============================================================================================== */
330 /* Utils */
331 /* ============================================================================================== */
332 
333 /* ---------------------------------------------------------------------------------------------- */
334 /* General purpose */
335 /* ---------------------------------------------------------------------------------------------- */
336 
342 #define ZYAN_UNUSED(x) (void)(x)
343 
347 #if defined(ZYAN_GCC) && __GNUC__ >= 7
348 # define ZYAN_FALLTHROUGH ; __attribute__((__fallthrough__))
349 #else
350 # define ZYAN_FALLTHROUGH
351 #endif
352 
358 #define ZYAN_BITFIELD(x) : x
359 
363 #define ZYAN_REQUIRES_LIBC
364 
371 #if defined(__RESHARPER__)
372 # define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
373  [[gnu::format(printf, format_index, first_to_check)]]
374 #elif defined(ZYAN_GCC)
375 # define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
376  __attribute__((format(printf, format_index, first_to_check)))
377 #else
378 # define ZYAN_PRINTF_ATTR(format_index, first_to_check)
379 #endif
380 
387 #if defined(__RESHARPER__)
388 # define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \
389  [[rscpp::format(wprintf, format_index, first_to_check)]]
390 #else
391 # define ZYAN_WPRINTF_ATTR(format_index, first_to_check)
392 #endif
393 
394 /* ---------------------------------------------------------------------------------------------- */
395 /* Arrays */
396 /* ---------------------------------------------------------------------------------------------- */
397 
405 #define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
406 
407 /* ---------------------------------------------------------------------------------------------- */
408 /* Arithmetic */
409 /* ---------------------------------------------------------------------------------------------- */
410 
419 #define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b))
420 
429 #define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b))
430 
438 #define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a))
439 
449 #define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
450 
456 #define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0)
457 
468 #define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
469 
480 #define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1))
481 
489 #if defined(ZYAN_LINUX) && defined(ZYAN_KERNEL)
490 # include <asm/div64.h> /* do_div */
491 # define ZYAN_DIV64(n, divisor) do_div(n, divisor)
492 #else
493 # define ZYAN_DIV64(n, divisor) (n /= divisor)
494 #endif
495 
496 /* ---------------------------------------------------------------------------------------------- */
497 /* Bit operations */
498 /* ---------------------------------------------------------------------------------------------- */
499 
500 /*
501  * Checks, if the bit at index `b` is required to present the ordinal value `n`.
502  *
503  * @param n The ordinal value.
504  * @param b The bit index.
505  *
506  * @return `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or
507  * `ZYAN_FALSE`, if not.
508  *
509  * Note that this macro always returns `ZYAN_FALSE` for `n == 0`.
510  */
511 #define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0)
512 
513 /*
514  * Returns the number of bits required to represent the ordinal value `n`.
515  *
516  * @param n The ordinal value.
517  *
518  * @return The number of bits required to represent the ordinal value `n`.
519  *
520  * Note that this macro returns `0` for `n == 0`.
521  */
522 #define ZYAN_BITS_TO_REPRESENT(n) \
523  ( \
524  ZYAN_NEEDS_BIT(n, 0) + ZYAN_NEEDS_BIT(n, 1) + \
525  ZYAN_NEEDS_BIT(n, 2) + ZYAN_NEEDS_BIT(n, 3) + \
526  ZYAN_NEEDS_BIT(n, 4) + ZYAN_NEEDS_BIT(n, 5) + \
527  ZYAN_NEEDS_BIT(n, 6) + ZYAN_NEEDS_BIT(n, 7) + \
528  ZYAN_NEEDS_BIT(n, 8) + ZYAN_NEEDS_BIT(n, 9) + \
529  ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \
530  ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \
531  ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \
532  ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \
533  ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \
534  ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \
535  ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \
536  ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \
537  ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \
538  ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \
539  ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31) \
540  )
541 
542 /* ---------------------------------------------------------------------------------------------- */
543 
544 /* ============================================================================================== */
545 
546 #endif /* ZYCORE_DEFINES_H */