xref: /haiku/headers/libs/zydis/Zycore/Defines.h (revision 909af08f4328301fbdef1ffb41f566c3b5bec0c7)
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 
27 /**
28  * @file
29  * General helper and platform detection macros.
30  */
31 
32 #ifndef ZYCORE_DEFINES_H
33 #define ZYCORE_DEFINES_H
34 
35 /* ============================================================================================== */
36 /* Meta macros                                                                                    */
37 /* ============================================================================================== */
38 
39 /**
40  * Concatenates two values using the stringify operator (`##`).
41  *
42  * @param   x   The first value.
43  * @param   y   The second value.
44  *
45  * @return  The combined string of the given values.
46  */
47 #define ZYAN_MACRO_CONCAT(x, y) x ## y
48 
49 /**
50  * Concatenates two values using the stringify operator (`##`) and expands the value to
51  *          be used in another macro.
52  *
53  * @param   x   The first value.
54  * @param   y   The second value.
55  *
56  * @return  The combined string of the given values.
57  */
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 
223 /**
224  * Symbol is exported in shared library builds.
225  */
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 
236 /**
237  * Symbol is not exported and for internal use only.
238  */
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 
269 /**
270  * Runtime debug assertion.
271  */
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 
282 /**
283  * Compiler-time assertion.
284  */
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 
296 /**
297  * Marks the current code path as unreachable.
298  */
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 
337 /**
338  * Marks the specified parameter as unused.
339  *
340  * @param   x   The name of the unused parameter.
341  */
342 #define ZYAN_UNUSED(x) (void)(x)
343 
344 /**
345  * Intentional fallthrough.
346  */
347 #if defined(ZYAN_GCC) && __GNUC__ >= 7
348 #   define ZYAN_FALLTHROUGH ; __attribute__((__fallthrough__))
349 #else
350 #   define ZYAN_FALLTHROUGH
351 #endif
352 
353 /**
354  * Declares a bitfield.
355  *
356  * @param   x   The size (in bits) of the bitfield.
357  */
358 #define ZYAN_BITFIELD(x) : x
359 
360 /**
361  * Marks functions that require libc (cannot be used with `ZYAN_NO_LIBC`).
362  */
363 #define ZYAN_REQUIRES_LIBC
364 
365 /**
366  * Decorator for `printf`-style functions.
367  *
368  * @param   format_index    The 1-based index of the format string parameter.
369  * @param   first_to_check  The 1-based index of the format arguments parameter.
370  */
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 
381 /**
382  * Decorator for `wprintf`-style functions.
383  *
384  * @param   format_index    The 1-based index of the format string parameter.
385  * @param   first_to_check  The 1-based index of the format arguments parameter.
386  */
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 
398 /**
399  * Returns the length (number of elements) of an array.
400  *
401  * @param   a   The name of the array.
402  *
403  * @return  The number of elements of the given array.
404  */
405 #define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
406 
407 /* ---------------------------------------------------------------------------------------------- */
408 /* Arithmetic                                                                                     */
409 /* ---------------------------------------------------------------------------------------------- */
410 
411 /**
412  * Returns the smaller value of `a` or `b`.
413  *
414  * @param   a   The first value.
415  * @param   b   The second value.
416  *
417  * @return  The smaller value of `a` or `b`.
418  */
419 #define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b))
420 
421 /**
422  * Returns the bigger value of `a` or `b`.
423  *
424  * @param   a   The first value.
425  * @param   b   The second value.
426  *
427  * @return  The bigger value of `a` or `b`.
428  */
429 #define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b))
430 
431 /**
432  * Returns the absolute value of `a`.
433  *
434  * @param   a   The value.
435  *
436  * @return  The absolute value of `a`.
437  */
438 #define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a))
439 
440 /**
441  * Checks, if the given value is a power of 2.
442  *
443  * @param   x   The value.
444  *
445  * @return  `ZYAN_TRUE`, if the given value is a power of 2 or `ZYAN_FALSE`, if not.
446  *
447  * Note that this macro always returns `ZYAN_TRUE` for `x == 0`.
448  */
449 #define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
450 
451 /**
452  * Checks, if the given value is properly aligned.
453  *
454  * Note that this macro only works for powers of 2.
455  */
456 #define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0)
457 
458 /**
459  * Aligns the value to the nearest given alignment boundary (by rounding it up).
460  *
461  * @param   x       The value.
462  * @param   align   The desired alignment.
463  *
464  * @return  The aligned value.
465  *
466  * Note that this macro only works for powers of 2.
467  */
468 #define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
469 
470 /**
471  * Aligns the value to the nearest given alignment boundary (by rounding it down).
472  *
473  * @param   x       The value.
474  * @param   align   The desired alignment.
475  *
476  * @return  The aligned value.
477  *
478  * Note that this macro only works for powers of 2.
479  */
480 #define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1))
481 
482 /**
483  * Divide the 64bit integer value by the given divisor.
484  *
485  * @param   n       Variable containing the dividend that will be updated with the result of the
486  *                  division.
487  * @param   divisor The divisor.
488  */
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 */
547