xref: /haiku/headers/libs/zydis/Zycore/Defines.h (revision 1003e004e6c97eb60657a98928dd334e141c59ee)
1*1003e004SJérôme Duval /***************************************************************************************************
2*1003e004SJérôme Duval 
3*1003e004SJérôme Duval   Zyan Core Library (Zycore-C)
4*1003e004SJérôme Duval 
5*1003e004SJérôme Duval   Original Author : Florian Bernd, Joel Hoener
6*1003e004SJérôme Duval 
7*1003e004SJérôme Duval  * Permission is hereby granted, free of charge, to any person obtaining a copy
8*1003e004SJérôme Duval  * of this software and associated documentation files (the "Software"), to deal
9*1003e004SJérôme Duval  * in the Software without restriction, including without limitation the rights
10*1003e004SJérôme Duval  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11*1003e004SJérôme Duval  * copies of the Software, and to permit persons to whom the Software is
12*1003e004SJérôme Duval  * furnished to do so, subject to the following conditions:
13*1003e004SJérôme Duval  *
14*1003e004SJérôme Duval  * The above copyright notice and this permission notice shall be included in all
15*1003e004SJérôme Duval  * copies or substantial portions of the Software.
16*1003e004SJérôme Duval  *
17*1003e004SJérôme Duval  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*1003e004SJérôme Duval  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*1003e004SJérôme Duval  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20*1003e004SJérôme Duval  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21*1003e004SJérôme Duval  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22*1003e004SJérôme Duval  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23*1003e004SJérôme Duval  * SOFTWARE.
24*1003e004SJérôme Duval 
25*1003e004SJérôme Duval ***************************************************************************************************/
26*1003e004SJérôme Duval 
27*1003e004SJérôme Duval /**
28*1003e004SJérôme Duval  * @file
29*1003e004SJérôme Duval  * General helper and platform detection macros.
30*1003e004SJérôme Duval  */
31*1003e004SJérôme Duval 
32*1003e004SJérôme Duval #ifndef ZYCORE_DEFINES_H
33*1003e004SJérôme Duval #define ZYCORE_DEFINES_H
34*1003e004SJérôme Duval 
35*1003e004SJérôme Duval /* ============================================================================================== */
36*1003e004SJérôme Duval /* Meta macros                                                                                    */
37*1003e004SJérôme Duval /* ============================================================================================== */
38*1003e004SJérôme Duval 
39*1003e004SJérôme Duval /**
40*1003e004SJérôme Duval  * Concatenates two values using the stringify operator (`##`).
41*1003e004SJérôme Duval  *
42*1003e004SJérôme Duval  * @param   x   The first value.
43*1003e004SJérôme Duval  * @param   y   The second value.
44*1003e004SJérôme Duval  *
45*1003e004SJérôme Duval  * @return  The combined string of the given values.
46*1003e004SJérôme Duval  */
47*1003e004SJérôme Duval #define ZYAN_MACRO_CONCAT(x, y) x ## y
48*1003e004SJérôme Duval 
49*1003e004SJérôme Duval /**
50*1003e004SJérôme Duval  * Concatenates two values using the stringify operator (`##`) and expands the value to
51*1003e004SJérôme Duval  *          be used in another macro.
52*1003e004SJérôme Duval  *
53*1003e004SJérôme Duval  * @param   x   The first value.
54*1003e004SJérôme Duval  * @param   y   The second value.
55*1003e004SJérôme Duval  *
56*1003e004SJérôme Duval  * @return  The combined string of the given values.
57*1003e004SJérôme Duval  */
58*1003e004SJérôme Duval #define ZYAN_MACRO_CONCAT_EXPAND(x, y) ZYAN_MACRO_CONCAT(x, y)
59*1003e004SJérôme Duval 
60*1003e004SJérôme Duval /* ============================================================================================== */
61*1003e004SJérôme Duval /* Compiler detection                                                                             */
62*1003e004SJérôme Duval /* ============================================================================================== */
63*1003e004SJérôme Duval 
64*1003e004SJérôme Duval #if defined(__clang__)
65*1003e004SJérôme Duval #   define ZYAN_CLANG
66*1003e004SJérôme Duval #   define ZYAN_GNUC
67*1003e004SJérôme Duval #elif defined(__ICC) || defined(__INTEL_COMPILER)
68*1003e004SJérôme Duval #   define ZYAN_ICC
69*1003e004SJérôme Duval #elif defined(__GNUC__) || defined(__GNUG__)
70*1003e004SJérôme Duval #   define ZYAN_GCC
71*1003e004SJérôme Duval #   define ZYAN_GNUC
72*1003e004SJérôme Duval #elif defined(_MSC_VER)
73*1003e004SJérôme Duval #   define ZYAN_MSVC
74*1003e004SJérôme Duval #elif defined(__BORLANDC__)
75*1003e004SJérôme Duval #   define ZYAN_BORLAND
76*1003e004SJérôme Duval #else
77*1003e004SJérôme Duval #   define ZYAN_UNKNOWN_COMPILER
78*1003e004SJérôme Duval #endif
79*1003e004SJérôme Duval 
80*1003e004SJérôme Duval /* ============================================================================================== */
81*1003e004SJérôme Duval /* Platform detection                                                                             */
82*1003e004SJérôme Duval /* ============================================================================================== */
83*1003e004SJérôme Duval 
84*1003e004SJérôme Duval #if defined(_WIN32)
85*1003e004SJérôme Duval #   define ZYAN_WINDOWS
86*1003e004SJérôme Duval #elif defined(__EMSCRIPTEN__)
87*1003e004SJérôme Duval #   define ZYAN_EMSCRIPTEN
88*1003e004SJérôme Duval #elif defined(__wasi__) || defined(__WASI__)
89*1003e004SJérôme Duval // via: https://reviews.llvm.org/D57155
90*1003e004SJérôme Duval #   define ZYAN_WASI
91*1003e004SJérôme Duval #elif defined(__APPLE__)
92*1003e004SJérôme Duval #   define ZYAN_APPLE
93*1003e004SJérôme Duval #   define ZYAN_POSIX
94*1003e004SJérôme Duval #elif defined(__linux)
95*1003e004SJérôme Duval #   define ZYAN_LINUX
96*1003e004SJérôme Duval #   define ZYAN_POSIX
97*1003e004SJérôme Duval #elif defined(__FreeBSD__)
98*1003e004SJérôme Duval #   define ZYAN_FREEBSD
99*1003e004SJérôme Duval #   define ZYAN_POSIX
100*1003e004SJérôme Duval #elif defined(__NetBSD__)
101*1003e004SJérôme Duval #   define ZYAN_NETBSD
102*1003e004SJérôme Duval #   define ZYAN_POSIX
103*1003e004SJérôme Duval #elif defined(sun) || defined(__sun)
104*1003e004SJérôme Duval #   define ZYAN_SOLARIS
105*1003e004SJérôme Duval #   define ZYAN_POSIX
106*1003e004SJérôme Duval #elif defined(__unix) || defined(__unix__)
107*1003e004SJérôme Duval #   define ZYAN_UNIX
108*1003e004SJérôme Duval #   define ZYAN_POSIX
109*1003e004SJérôme Duval #elif defined(__posix)
110*1003e004SJérôme Duval #   define ZYAN_POSIX
111*1003e004SJérôme Duval #else
112*1003e004SJérôme Duval #   define ZYAN_UNKNOWN_PLATFORM
113*1003e004SJérôme Duval #endif
114*1003e004SJérôme Duval 
115*1003e004SJérôme Duval /* ============================================================================================== */
116*1003e004SJérôme Duval /* Kernel mode detection                                                                          */
117*1003e004SJérôme Duval /* ============================================================================================== */
118*1003e004SJérôme Duval 
119*1003e004SJérôme Duval #if (defined(ZYAN_WINDOWS) && defined(_KERNEL_MODE)) || \
120*1003e004SJérôme Duval     (defined(ZYAN_APPLE) && defined(KERNEL)) || \
121*1003e004SJérôme Duval     (defined(ZYAN_LINUX) && defined(__KERNEL__)) || \
122*1003e004SJérôme Duval     (defined(__FreeBSD_kernel__))
123*1003e004SJérôme Duval #   define ZYAN_KERNEL
124*1003e004SJérôme Duval #else
125*1003e004SJérôme Duval #   define ZYAN_USER
126*1003e004SJérôme Duval #endif
127*1003e004SJérôme Duval 
128*1003e004SJérôme Duval /* ============================================================================================== */
129*1003e004SJérôme Duval /* Architecture detection                                                                         */
130*1003e004SJérôme Duval /* ============================================================================================== */
131*1003e004SJérôme Duval 
132*1003e004SJérôme Duval #if defined(_M_AMD64) || defined(__x86_64__)
133*1003e004SJérôme Duval #   define ZYAN_X64
134*1003e004SJérôme Duval #elif defined(_M_IX86) || defined(__i386__)
135*1003e004SJérôme Duval #   define ZYAN_X86
136*1003e004SJérôme Duval #elif defined(_M_ARM64) || defined(__aarch64__)
137*1003e004SJérôme Duval #   define ZYAN_AARCH64
138*1003e004SJérôme Duval #elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__)
139*1003e004SJérôme Duval #   define ZYAN_ARM
140*1003e004SJérôme Duval #elif defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__WASM__)
141*1003e004SJérôme Duval #   define ZYAN_WASM
142*1003e004SJérôme Duval #elif defined(__loongarch__)
143*1003e004SJérôme Duval #   define ZYAN_LOONGARCH
144*1003e004SJérôme Duval #elif defined(__powerpc64__)
145*1003e004SJérôme Duval #   define ZYAN_PPC64
146*1003e004SJérôme Duval #elif defined(__powerpc__)
147*1003e004SJérôme Duval #   define ZYAN_PPC
148*1003e004SJérôme Duval #elif defined(__riscv) && __riscv_xlen == 64
149*1003e004SJérôme Duval #   define ZYAN_RISCV64
150*1003e004SJérôme Duval #else
151*1003e004SJérôme Duval #   error "Unsupported architecture detected"
152*1003e004SJérôme Duval #endif
153*1003e004SJérôme Duval 
154*1003e004SJérôme Duval /* ============================================================================================== */
155*1003e004SJérôme Duval /* Debug/Release detection                                                                        */
156*1003e004SJérôme Duval /* ============================================================================================== */
157*1003e004SJérôme Duval 
158*1003e004SJérôme Duval #if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
159*1003e004SJérôme Duval #   ifdef _DEBUG
160*1003e004SJérôme Duval #       define ZYAN_DEBUG
161*1003e004SJérôme Duval #   else
162*1003e004SJérôme Duval #       define ZYAN_RELEASE
163*1003e004SJérôme Duval #   endif
164*1003e004SJérôme Duval #elif defined(ZYAN_GNUC) || defined(ZYAN_ICC)
165*1003e004SJérôme Duval #   ifdef NDEBUG
166*1003e004SJérôme Duval #       define ZYAN_RELEASE
167*1003e004SJérôme Duval #   else
168*1003e004SJérôme Duval #       define ZYAN_DEBUG
169*1003e004SJérôme Duval #   endif
170*1003e004SJérôme Duval #else
171*1003e004SJérôme Duval #   define ZYAN_RELEASE
172*1003e004SJérôme Duval #endif
173*1003e004SJérôme Duval 
174*1003e004SJérôme Duval /* ============================================================================================== */
175*1003e004SJérôme Duval /* Deprecation hint                                                                               */
176*1003e004SJérôme Duval /* ============================================================================================== */
177*1003e004SJérôme Duval 
178*1003e004SJérôme Duval #if defined(ZYAN_GCC) || defined(ZYAN_CLANG)
179*1003e004SJérôme Duval #   define ZYAN_DEPRECATED __attribute__((__deprecated__))
180*1003e004SJérôme Duval #elif defined(ZYAN_MSVC)
181*1003e004SJérôme Duval #   define ZYAN_DEPRECATED __declspec(deprecated)
182*1003e004SJérôme Duval #else
183*1003e004SJérôme Duval #   define ZYAN_DEPRECATED
184*1003e004SJérôme Duval #endif
185*1003e004SJérôme Duval 
186*1003e004SJérôme Duval /* ============================================================================================== */
187*1003e004SJérôme Duval /* Generic DLL import/export helpers                                                              */
188*1003e004SJérôme Duval /* ============================================================================================== */
189*1003e004SJérôme Duval 
190*1003e004SJérôme Duval #if defined(ZYAN_MSVC)
191*1003e004SJérôme Duval #   define ZYAN_DLLEXPORT __declspec(dllexport)
192*1003e004SJérôme Duval #   define ZYAN_DLLIMPORT __declspec(dllimport)
193*1003e004SJérôme Duval #else
194*1003e004SJérôme Duval #   define ZYAN_DLLEXPORT
195*1003e004SJérôme Duval #   define ZYAN_DLLIMPORT
196*1003e004SJérôme Duval #endif
197*1003e004SJérôme Duval 
198*1003e004SJérôme Duval /* ============================================================================================== */
199*1003e004SJérôme Duval /* Zycore dll{export,import}                                                                      */
200*1003e004SJérôme Duval /* ============================================================================================== */
201*1003e004SJérôme Duval 
202*1003e004SJérôme Duval // This is a cut-down version of what CMake's `GenerateExportHeader` would usually generate. To
203*1003e004SJérôme Duval // simplify builds without CMake, we define these things manually instead of relying on CMake
204*1003e004SJérôme Duval // to generate the header.
205*1003e004SJérôme Duval //
206*1003e004SJérôme Duval // For static builds, our CMakeList will define `ZYCORE_STATIC_BUILD`. For shared library builds,
207*1003e004SJérôme Duval // our CMake will define `ZYCORE_SHOULD_EXPORT` depending on whether the target is being imported or
208*1003e004SJérôme Duval // exported. If CMake isn't used, users can manually define these to fit their use-case.
209*1003e004SJérôme Duval 
210*1003e004SJérôme Duval // Backward compatibility: CMake would previously generate these variables names. However, because
211*1003e004SJérôme Duval // they have pretty cryptic names, we renamed them when we got rid of `GenerateExportHeader`. For
212*1003e004SJérôme Duval // backward compatibility for users that don't use CMake and previously manually defined these, we
213*1003e004SJérôme Duval // translate the old defines here and print a warning.
214*1003e004SJérôme Duval #if defined(ZYCORE_STATIC_DEFINE)
215*1003e004SJérôme Duval #   pragma message("ZYCORE_STATIC_DEFINE was renamed to ZYCORE_STATIC_BUILD.")
216*1003e004SJérôme Duval #   define ZYCORE_STATIC_BUILD
217*1003e004SJérôme Duval #endif
218*1003e004SJérôme Duval #if defined(Zycore_EXPORTS)
219*1003e004SJérôme Duval #   pragma message("Zycore_EXPORTS was renamed to ZYCORE_SHOULD_EXPORT.")
220*1003e004SJérôme Duval #   define ZYCORE_SHOULD_EXPORT
221*1003e004SJérôme Duval #endif
222*1003e004SJérôme Duval 
223*1003e004SJérôme Duval /**
224*1003e004SJérôme Duval  * Symbol is exported in shared library builds.
225*1003e004SJérôme Duval  */
226*1003e004SJérôme Duval #if defined(ZYCORE_STATIC_BUILD)
227*1003e004SJérôme Duval #   define ZYCORE_EXPORT
228*1003e004SJérôme Duval #else
229*1003e004SJérôme Duval #   if defined(ZYCORE_SHOULD_EXPORT)
230*1003e004SJérôme Duval #       define ZYCORE_EXPORT ZYAN_DLLEXPORT
231*1003e004SJérôme Duval #   else
232*1003e004SJérôme Duval #       define ZYCORE_EXPORT ZYAN_DLLIMPORT
233*1003e004SJérôme Duval #   endif
234*1003e004SJérôme Duval #endif
235*1003e004SJérôme Duval 
236*1003e004SJérôme Duval /**
237*1003e004SJérôme Duval  * Symbol is not exported and for internal use only.
238*1003e004SJérôme Duval  */
239*1003e004SJérôme Duval #define ZYCORE_NO_EXPORT
240*1003e004SJérôme Duval 
241*1003e004SJérôme Duval /* ============================================================================================== */
242*1003e004SJérôme Duval /* Misc compatibility macros                                                                      */
243*1003e004SJérôme Duval /* ============================================================================================== */
244*1003e004SJérôme Duval 
245*1003e004SJérôme Duval #if defined(ZYAN_CLANG)
246*1003e004SJérôme Duval #   define ZYAN_NO_SANITIZE(what) __attribute__((no_sanitize(what)))
247*1003e004SJérôme Duval #else
248*1003e004SJérôme Duval #   define ZYAN_NO_SANITIZE(what)
249*1003e004SJérôme Duval #endif
250*1003e004SJérôme Duval 
251*1003e004SJérôme Duval #if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
252*1003e004SJérôme Duval #   define ZYAN_INLINE __inline
253*1003e004SJérôme Duval #else
254*1003e004SJérôme Duval #   define ZYAN_INLINE static inline
255*1003e004SJérôme Duval #endif
256*1003e004SJérôme Duval 
257*1003e004SJérôme Duval #if defined(ZYAN_MSVC)
258*1003e004SJérôme Duval #   define ZYAN_NOINLINE __declspec(noinline)
259*1003e004SJérôme Duval #elif defined(ZYAN_GCC) || defined(ZYAN_CLANG)
260*1003e004SJérôme Duval #   define ZYAN_NOINLINE __attribute__((noinline))
261*1003e004SJérôme Duval #else
262*1003e004SJérôme Duval #   define ZYAN_NOINLINE
263*1003e004SJérôme Duval #endif
264*1003e004SJérôme Duval 
265*1003e004SJérôme Duval /* ============================================================================================== */
266*1003e004SJérôme Duval /* Debugging and optimization macros                                                              */
267*1003e004SJérôme Duval /* ============================================================================================== */
268*1003e004SJérôme Duval 
269*1003e004SJérôme Duval /**
270*1003e004SJérôme Duval  * Runtime debug assertion.
271*1003e004SJérôme Duval  */
272*1003e004SJérôme Duval #if defined(ZYAN_NO_LIBC)
273*1003e004SJérôme Duval #   define ZYAN_ASSERT(condition) (void)(condition)
274*1003e004SJérôme Duval #elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
275*1003e004SJérôme Duval #   include <wdm.h>
276*1003e004SJérôme Duval #   define ZYAN_ASSERT(condition) NT_ASSERT(condition)
277*1003e004SJérôme Duval #else
278*1003e004SJérôme Duval #   include <assert.h>
279*1003e004SJérôme Duval #   define ZYAN_ASSERT(condition) assert(condition)
280*1003e004SJérôme Duval #endif
281*1003e004SJérôme Duval 
282*1003e004SJérôme Duval /**
283*1003e004SJérôme Duval  * Compiler-time assertion.
284*1003e004SJérôme Duval  */
285*1003e004SJérôme Duval #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
286*1003e004SJérôme Duval #   define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x)
287*1003e004SJérôme Duval #elif (defined(__cplusplus) && __cplusplus >= 201103L) || \
288*1003e004SJérôme Duval       (defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \
289*1003e004SJérôme Duval       (defined (_MSC_VER) && (_MSC_VER >= 1800))
290*1003e004SJérôme Duval #   define ZYAN_STATIC_ASSERT(x) static_assert(x, #x)
291*1003e004SJérôme Duval #else
292*1003e004SJérôme Duval #   define ZYAN_STATIC_ASSERT(x) \
293*1003e004SJérôme Duval         typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1]
294*1003e004SJérôme Duval #endif
295*1003e004SJérôme Duval 
296*1003e004SJérôme Duval /**
297*1003e004SJérôme Duval  * Marks the current code path as unreachable.
298*1003e004SJérôme Duval  */
299*1003e004SJérôme Duval #if defined(ZYAN_RELEASE)
300*1003e004SJérôme Duval #   if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs.
301*1003e004SJérôme Duval #       if __has_builtin(__builtin_unreachable)
302*1003e004SJérôme Duval #           define ZYAN_UNREACHABLE __builtin_unreachable()
303*1003e004SJérôme Duval #       else
304*1003e004SJérôme Duval #           define ZYAN_UNREACHABLE for(;;)
305*1003e004SJérôme Duval #       endif
306*1003e004SJérôme Duval #   elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4)
307*1003e004SJérôme Duval #       define ZYAN_UNREACHABLE __builtin_unreachable()
308*1003e004SJérôme Duval #   elif defined(ZYAN_ICC)
309*1003e004SJérôme Duval #       ifdef ZYAN_WINDOWS
310*1003e004SJérôme Duval #           include <stdlib.h> // "missing return statement" workaround
311*1003e004SJérôme Duval #           define ZYAN_UNREACHABLE __assume(0); (void)abort()
312*1003e004SJérôme Duval #       else
313*1003e004SJérôme Duval #           define ZYAN_UNREACHABLE __builtin_unreachable()
314*1003e004SJérôme Duval #       endif
315*1003e004SJérôme Duval #   elif defined(ZYAN_MSVC)
316*1003e004SJérôme Duval #       define ZYAN_UNREACHABLE __assume(0)
317*1003e004SJérôme Duval #   else
318*1003e004SJérôme Duval #       define ZYAN_UNREACHABLE for(;;)
319*1003e004SJérôme Duval #   endif
320*1003e004SJérôme Duval #elif defined(ZYAN_NO_LIBC)
321*1003e004SJérôme Duval #   define ZYAN_UNREACHABLE for(;;)
322*1003e004SJérôme Duval #elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
323*1003e004SJérôme Duval #   define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} }
324*1003e004SJérôme Duval #else
325*1003e004SJérôme Duval #   include <stdlib.h>
326*1003e004SJérôme Duval #   define ZYAN_UNREACHABLE { assert(0); abort(); }
327*1003e004SJérôme Duval #endif
328*1003e004SJérôme Duval 
329*1003e004SJérôme Duval /* ============================================================================================== */
330*1003e004SJérôme Duval /* Utils                                                                                          */
331*1003e004SJérôme Duval /* ============================================================================================== */
332*1003e004SJérôme Duval 
333*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
334*1003e004SJérôme Duval /* General purpose                                                                                */
335*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
336*1003e004SJérôme Duval 
337*1003e004SJérôme Duval /**
338*1003e004SJérôme Duval  * Marks the specified parameter as unused.
339*1003e004SJérôme Duval  *
340*1003e004SJérôme Duval  * @param   x   The name of the unused parameter.
341*1003e004SJérôme Duval  */
342*1003e004SJérôme Duval #define ZYAN_UNUSED(x) (void)(x)
343*1003e004SJérôme Duval 
344*1003e004SJérôme Duval /**
345*1003e004SJérôme Duval  * Intentional fallthrough.
346*1003e004SJérôme Duval  */
347*1003e004SJérôme Duval #if defined(ZYAN_GCC) && __GNUC__ >= 7
348*1003e004SJérôme Duval #   define ZYAN_FALLTHROUGH ; __attribute__((__fallthrough__))
349*1003e004SJérôme Duval #else
350*1003e004SJérôme Duval #   define ZYAN_FALLTHROUGH
351*1003e004SJérôme Duval #endif
352*1003e004SJérôme Duval 
353*1003e004SJérôme Duval /**
354*1003e004SJérôme Duval  * Declares a bitfield.
355*1003e004SJérôme Duval  *
356*1003e004SJérôme Duval  * @param   x   The size (in bits) of the bitfield.
357*1003e004SJérôme Duval  */
358*1003e004SJérôme Duval #define ZYAN_BITFIELD(x) : x
359*1003e004SJérôme Duval 
360*1003e004SJérôme Duval /**
361*1003e004SJérôme Duval  * Marks functions that require libc (cannot be used with `ZYAN_NO_LIBC`).
362*1003e004SJérôme Duval  */
363*1003e004SJérôme Duval #define ZYAN_REQUIRES_LIBC
364*1003e004SJérôme Duval 
365*1003e004SJérôme Duval /**
366*1003e004SJérôme Duval  * Decorator for `printf`-style functions.
367*1003e004SJérôme Duval  *
368*1003e004SJérôme Duval  * @param   format_index    The 1-based index of the format string parameter.
369*1003e004SJérôme Duval  * @param   first_to_check  The 1-based index of the format arguments parameter.
370*1003e004SJérôme Duval  */
371*1003e004SJérôme Duval #if defined(__RESHARPER__)
372*1003e004SJérôme Duval #   define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
373*1003e004SJérôme Duval         [[gnu::format(printf, format_index, first_to_check)]]
374*1003e004SJérôme Duval #elif defined(ZYAN_GCC)
375*1003e004SJérôme Duval #   define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
376*1003e004SJérôme Duval         __attribute__((format(printf, format_index, first_to_check)))
377*1003e004SJérôme Duval #else
378*1003e004SJérôme Duval #   define ZYAN_PRINTF_ATTR(format_index, first_to_check)
379*1003e004SJérôme Duval #endif
380*1003e004SJérôme Duval 
381*1003e004SJérôme Duval /**
382*1003e004SJérôme Duval  * Decorator for `wprintf`-style functions.
383*1003e004SJérôme Duval  *
384*1003e004SJérôme Duval  * @param   format_index    The 1-based index of the format string parameter.
385*1003e004SJérôme Duval  * @param   first_to_check  The 1-based index of the format arguments parameter.
386*1003e004SJérôme Duval  */
387*1003e004SJérôme Duval #if defined(__RESHARPER__)
388*1003e004SJérôme Duval #   define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \
389*1003e004SJérôme Duval         [[rscpp::format(wprintf, format_index, first_to_check)]]
390*1003e004SJérôme Duval #else
391*1003e004SJérôme Duval #   define ZYAN_WPRINTF_ATTR(format_index, first_to_check)
392*1003e004SJérôme Duval #endif
393*1003e004SJérôme Duval 
394*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
395*1003e004SJérôme Duval /* Arrays                                                                                         */
396*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
397*1003e004SJérôme Duval 
398*1003e004SJérôme Duval /**
399*1003e004SJérôme Duval  * Returns the length (number of elements) of an array.
400*1003e004SJérôme Duval  *
401*1003e004SJérôme Duval  * @param   a   The name of the array.
402*1003e004SJérôme Duval  *
403*1003e004SJérôme Duval  * @return  The number of elements of the given array.
404*1003e004SJérôme Duval  */
405*1003e004SJérôme Duval #define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
406*1003e004SJérôme Duval 
407*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
408*1003e004SJérôme Duval /* Arithmetic                                                                                     */
409*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
410*1003e004SJérôme Duval 
411*1003e004SJérôme Duval /**
412*1003e004SJérôme Duval  * Returns the smaller value of `a` or `b`.
413*1003e004SJérôme Duval  *
414*1003e004SJérôme Duval  * @param   a   The first value.
415*1003e004SJérôme Duval  * @param   b   The second value.
416*1003e004SJérôme Duval  *
417*1003e004SJérôme Duval  * @return  The smaller value of `a` or `b`.
418*1003e004SJérôme Duval  */
419*1003e004SJérôme Duval #define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b))
420*1003e004SJérôme Duval 
421*1003e004SJérôme Duval /**
422*1003e004SJérôme Duval  * Returns the bigger value of `a` or `b`.
423*1003e004SJérôme Duval  *
424*1003e004SJérôme Duval  * @param   a   The first value.
425*1003e004SJérôme Duval  * @param   b   The second value.
426*1003e004SJérôme Duval  *
427*1003e004SJérôme Duval  * @return  The bigger value of `a` or `b`.
428*1003e004SJérôme Duval  */
429*1003e004SJérôme Duval #define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b))
430*1003e004SJérôme Duval 
431*1003e004SJérôme Duval /**
432*1003e004SJérôme Duval  * Returns the absolute value of `a`.
433*1003e004SJérôme Duval  *
434*1003e004SJérôme Duval  * @param   a   The value.
435*1003e004SJérôme Duval  *
436*1003e004SJérôme Duval  * @return  The absolute value of `a`.
437*1003e004SJérôme Duval  */
438*1003e004SJérôme Duval #define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a))
439*1003e004SJérôme Duval 
440*1003e004SJérôme Duval /**
441*1003e004SJérôme Duval  * Checks, if the given value is a power of 2.
442*1003e004SJérôme Duval  *
443*1003e004SJérôme Duval  * @param   x   The value.
444*1003e004SJérôme Duval  *
445*1003e004SJérôme Duval  * @return  `ZYAN_TRUE`, if the given value is a power of 2 or `ZYAN_FALSE`, if not.
446*1003e004SJérôme Duval  *
447*1003e004SJérôme Duval  * Note that this macro always returns `ZYAN_TRUE` for `x == 0`.
448*1003e004SJérôme Duval  */
449*1003e004SJérôme Duval #define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
450*1003e004SJérôme Duval 
451*1003e004SJérôme Duval /**
452*1003e004SJérôme Duval  * Checks, if the given value is properly aligned.
453*1003e004SJérôme Duval  *
454*1003e004SJérôme Duval  * Note that this macro only works for powers of 2.
455*1003e004SJérôme Duval  */
456*1003e004SJérôme Duval #define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0)
457*1003e004SJérôme Duval 
458*1003e004SJérôme Duval /**
459*1003e004SJérôme Duval  * Aligns the value to the nearest given alignment boundary (by rounding it up).
460*1003e004SJérôme Duval  *
461*1003e004SJérôme Duval  * @param   x       The value.
462*1003e004SJérôme Duval  * @param   align   The desired alignment.
463*1003e004SJérôme Duval  *
464*1003e004SJérôme Duval  * @return  The aligned value.
465*1003e004SJérôme Duval  *
466*1003e004SJérôme Duval  * Note that this macro only works for powers of 2.
467*1003e004SJérôme Duval  */
468*1003e004SJérôme Duval #define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
469*1003e004SJérôme Duval 
470*1003e004SJérôme Duval /**
471*1003e004SJérôme Duval  * Aligns the value to the nearest given alignment boundary (by rounding it down).
472*1003e004SJérôme Duval  *
473*1003e004SJérôme Duval  * @param   x       The value.
474*1003e004SJérôme Duval  * @param   align   The desired alignment.
475*1003e004SJérôme Duval  *
476*1003e004SJérôme Duval  * @return  The aligned value.
477*1003e004SJérôme Duval  *
478*1003e004SJérôme Duval  * Note that this macro only works for powers of 2.
479*1003e004SJérôme Duval  */
480*1003e004SJérôme Duval #define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1))
481*1003e004SJérôme Duval 
482*1003e004SJérôme Duval /**
483*1003e004SJérôme Duval  * Divide the 64bit integer value by the given divisor.
484*1003e004SJérôme Duval  *
485*1003e004SJérôme Duval  * @param   n       Variable containing the dividend that will be updated with the result of the
486*1003e004SJérôme Duval  *                  division.
487*1003e004SJérôme Duval  * @param   divisor The divisor.
488*1003e004SJérôme Duval  */
489*1003e004SJérôme Duval #if defined(ZYAN_LINUX) && defined(ZYAN_KERNEL)
490*1003e004SJérôme Duval #   include <asm/div64.h> /* do_div */
491*1003e004SJérôme Duval #   define ZYAN_DIV64(n, divisor) do_div(n, divisor)
492*1003e004SJérôme Duval #else
493*1003e004SJérôme Duval #   define ZYAN_DIV64(n, divisor) (n /= divisor)
494*1003e004SJérôme Duval #endif
495*1003e004SJérôme Duval 
496*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
497*1003e004SJérôme Duval /* Bit operations                                                                                 */
498*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
499*1003e004SJérôme Duval 
500*1003e004SJérôme Duval /*
501*1003e004SJérôme Duval  * Checks, if the bit at index `b` is required to present the ordinal value `n`.
502*1003e004SJérôme Duval  *
503*1003e004SJérôme Duval  * @param   n   The ordinal value.
504*1003e004SJérôme Duval  * @param   b   The bit index.
505*1003e004SJérôme Duval  *
506*1003e004SJérôme Duval  * @return  `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or
507*1003e004SJérôme Duval  *          `ZYAN_FALSE`, if not.
508*1003e004SJérôme Duval  *
509*1003e004SJérôme Duval  * Note that this macro always returns `ZYAN_FALSE` for `n == 0`.
510*1003e004SJérôme Duval  */
511*1003e004SJérôme Duval #define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0)
512*1003e004SJérôme Duval 
513*1003e004SJérôme Duval /*
514*1003e004SJérôme Duval  * Returns the number of bits required to represent the ordinal value `n`.
515*1003e004SJérôme Duval  *
516*1003e004SJérôme Duval  * @param   n   The ordinal value.
517*1003e004SJérôme Duval  *
518*1003e004SJérôme Duval  * @return  The number of bits required to represent the ordinal value `n`.
519*1003e004SJérôme Duval  *
520*1003e004SJérôme Duval  * Note that this macro returns `0` for `n == 0`.
521*1003e004SJérôme Duval  */
522*1003e004SJérôme Duval #define ZYAN_BITS_TO_REPRESENT(n) \
523*1003e004SJérôme Duval     ( \
524*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n,  0) + ZYAN_NEEDS_BIT(n,  1) + \
525*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n,  2) + ZYAN_NEEDS_BIT(n,  3) + \
526*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n,  4) + ZYAN_NEEDS_BIT(n,  5) + \
527*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n,  6) + ZYAN_NEEDS_BIT(n,  7) + \
528*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n,  8) + ZYAN_NEEDS_BIT(n,  9) + \
529*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \
530*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \
531*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \
532*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \
533*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \
534*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \
535*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \
536*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \
537*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \
538*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \
539*1003e004SJérôme Duval         ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31)   \
540*1003e004SJérôme Duval     )
541*1003e004SJérôme Duval 
542*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
543*1003e004SJérôme Duval 
544*1003e004SJérôme Duval /* ============================================================================================== */
545*1003e004SJérôme Duval 
546*1003e004SJérôme Duval #endif /* ZYCORE_DEFINES_H */
547