duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

Defines.h (18963B)


      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(sun) || defined(__sun)
    101 #   define ZYAN_SOLARIS
    102 #   define ZYAN_POSIX
    103 #elif defined(__unix)
    104 #   define ZYAN_UNIX
    105 #   define ZYAN_POSIX
    106 #elif defined(__posix)
    107 #   define ZYAN_POSIX
    108 #else
    109 #   define ZYAN_UNKNOWN_PLATFORM
    110 #endif
    111 
    112 /* ============================================================================================== */
    113 /* Kernel mode detection                                                                          */
    114 /* ============================================================================================== */
    115 
    116 #if (defined(ZYAN_WINDOWS) && defined(_KERNEL_MODE)) || \
    117     (defined(ZYAN_APPLE) && defined(KERNEL)) || \
    118     (defined(ZYAN_LINUX) && defined(__KERNEL__)) || \
    119     (defined(__FreeBSD_kernel__))
    120 #   define ZYAN_KERNEL
    121 #else
    122 #   define ZYAN_USER
    123 #endif
    124 
    125 /* ============================================================================================== */
    126 /* Architecture detection                                                                         */
    127 /* ============================================================================================== */
    128 
    129 #if defined(_M_AMD64) || defined(__x86_64__)
    130 #   define ZYAN_X64
    131 #elif defined(_M_IX86) || defined(__i386__)
    132 #   define ZYAN_X86
    133 #elif defined(_M_ARM64) || defined(__aarch64__)
    134 #   define ZYAN_AARCH64
    135 #elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__)
    136 #   define ZYAN_ARM
    137 #elif defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__WASM__)
    138 #   define ZYAN_WASM
    139 #elif defined(__powerpc64__)
    140 #   define ZYAN_PPC64
    141 #elif defined(__powerpc__)
    142 #   define ZYAN_PPC
    143 #elif defined(__riscv) && __riscv_xlen == 64
    144 #   define ZYAN_RISCV64
    145 #else
    146 #   error "Unsupported architecture detected"
    147 #endif
    148 
    149 /* ============================================================================================== */
    150 /* Debug/Release detection                                                                        */
    151 /* ============================================================================================== */
    152 
    153 #if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
    154 #   ifdef _DEBUG
    155 #       define ZYAN_DEBUG
    156 #   else
    157 #       define ZYAN_RELEASE
    158 #   endif
    159 #elif defined(ZYAN_GNUC) || defined(ZYAN_ICC)
    160 #   ifdef NDEBUG
    161 #       define ZYAN_RELEASE
    162 #   else
    163 #       define ZYAN_DEBUG
    164 #   endif
    165 #else
    166 #   define ZYAN_RELEASE
    167 #endif
    168 
    169 /* ============================================================================================== */
    170 /* Deprecation hint                                                                               */
    171 /* ============================================================================================== */
    172 
    173 #if defined(ZYAN_GCC) || defined(ZYAN_CLANG)
    174 #   define ZYAN_DEPRECATED __attribute__((__deprecated__))
    175 #elif defined(ZYAN_MSVC)
    176 #   define ZYAN_DEPRECATED __declspec(deprecated)
    177 #else
    178 #   define ZYAN_DEPRECATED
    179 #endif
    180 
    181 /* ============================================================================================== */
    182 /* Generic DLL import/export helpers                                                              */
    183 /* ============================================================================================== */
    184 
    185 #if defined(ZYAN_MSVC)
    186 #   define ZYAN_DLLEXPORT __declspec(dllexport)
    187 #   define ZYAN_DLLIMPORT __declspec(dllimport)
    188 #else
    189 #   define ZYAN_DLLEXPORT
    190 #   define ZYAN_DLLIMPORT
    191 #endif
    192 
    193 /* ============================================================================================== */
    194 /* Zycore dll{export,import}                                                                      */
    195 /* ============================================================================================== */
    196 
    197 // This is a cut-down version of what CMake's `GenerateExportHeader` would usually generate. To
    198 // simplify builds without CMake, we define these things manually instead of relying on CMake
    199 // to generate the header.
    200 //
    201 // For static builds, our CMakeList will define `ZYCORE_STATIC_BUILD`. For shared library builds,
    202 // our CMake will define `ZYCORE_SHOULD_EXPORT` depending on whether the target is being imported or
    203 // exported. If CMake isn't used, users can manually define these to fit their use-case.
    204 
    205 // Backward compatibility: CMake would previously generate these variables names. However, because
    206 // they have pretty cryptic names, we renamed them when we got rid of `GenerateExportHeader`. For
    207 // backward compatibility for users that don't use CMake and previously manually defined these, we
    208 // translate the old defines here and print a warning.
    209 #if defined(ZYCORE_STATIC_DEFINE)
    210 #   pragma message("ZYCORE_STATIC_DEFINE was renamed to ZYCORE_STATIC_BUILD.")
    211 #   define ZYCORE_STATIC_BUILD
    212 #endif
    213 #if defined(Zycore_EXPORTS)
    214 #   pragma message("Zycore_EXPORTS was renamed to ZYCORE_SHOULD_EXPORT.")
    215 #   define ZYCORE_SHOULD_EXPORT
    216 #endif
    217 
    218 /**
    219  * Symbol is exported in shared library builds.
    220  */
    221 #if defined(ZYCORE_STATIC_BUILD)
    222 #   define ZYCORE_EXPORT
    223 #else
    224 #   if defined(ZYCORE_SHOULD_EXPORT)
    225 #       define ZYCORE_EXPORT ZYAN_DLLEXPORT
    226 #   else
    227 #       define ZYCORE_EXPORT ZYAN_DLLIMPORT
    228 #   endif
    229 #endif
    230 
    231 /**
    232  * Symbol is not exported and for internal use only.
    233  */
    234 #define ZYCORE_NO_EXPORT
    235 
    236 /* ============================================================================================== */
    237 /* Misc compatibility macros                                                                      */
    238 /* ============================================================================================== */
    239 
    240 #if defined(ZYAN_CLANG)
    241 #   define ZYAN_NO_SANITIZE(what) __attribute__((no_sanitize(what)))
    242 #else
    243 #   define ZYAN_NO_SANITIZE(what)
    244 #endif
    245 
    246 #if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
    247 #   define ZYAN_INLINE __inline
    248 #else
    249 #   define ZYAN_INLINE static inline
    250 #endif
    251 
    252 #if defined(ZYAN_MSVC)
    253 #   define ZYAN_NOINLINE __declspec(noinline)
    254 #elif defined(ZYAN_GCC) || defined(ZYAN_CLANG)
    255 #   define ZYAN_NOINLINE __attribute__((noinline))
    256 #else
    257 #   define ZYAN_NOINLINE
    258 #endif
    259 
    260 /* ============================================================================================== */
    261 /* Debugging and optimization macros                                                              */
    262 /* ============================================================================================== */
    263 
    264 /**
    265  * Runtime debug assertion.
    266  */
    267 #if defined(ZYAN_NO_LIBC)
    268 #   define ZYAN_ASSERT(condition) (void)(condition)
    269 #elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
    270 #   include <wdm.h>
    271 #   define ZYAN_ASSERT(condition) NT_ASSERT(condition)
    272 #else
    273 #   include <assert.h>
    274 #   define ZYAN_ASSERT(condition) assert(condition)
    275 #endif
    276 
    277 /**
    278  * Compiler-time assertion.
    279  */
    280 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
    281 #   define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x)
    282 #elif (defined(__cplusplus) && __cplusplus >= 201103L) || \
    283       (defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \
    284       (defined (_MSC_VER) && (_MSC_VER >= 1800))
    285 #   define ZYAN_STATIC_ASSERT(x) static_assert(x, #x)
    286 #else
    287 #   define ZYAN_STATIC_ASSERT(x) \
    288         typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1]
    289 #endif
    290 
    291 /**
    292  * Marks the current code path as unreachable.
    293  */
    294 #if defined(ZYAN_RELEASE)
    295 #   if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs.
    296 #       if __has_builtin(__builtin_unreachable)
    297 #           define ZYAN_UNREACHABLE __builtin_unreachable()
    298 #       else
    299 #           define ZYAN_UNREACHABLE for(;;)
    300 #       endif
    301 #   elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4)
    302 #       define ZYAN_UNREACHABLE __builtin_unreachable()
    303 #   elif defined(ZYAN_ICC)
    304 #       ifdef ZYAN_WINDOWS
    305 #           include <stdlib.h> // "missing return statement" workaround
    306 #           define ZYAN_UNREACHABLE __assume(0); (void)abort()
    307 #       else
    308 #           define ZYAN_UNREACHABLE __builtin_unreachable()
    309 #       endif
    310 #   elif defined(ZYAN_MSVC)
    311 #       define ZYAN_UNREACHABLE __assume(0)
    312 #   else
    313 #       define ZYAN_UNREACHABLE for(;;)
    314 #   endif
    315 #elif defined(ZYAN_NO_LIBC)
    316 #   define ZYAN_UNREACHABLE for(;;)
    317 #elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
    318 #   define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} }
    319 #else
    320 #   include <stdlib.h>
    321 #   define ZYAN_UNREACHABLE { assert(0); abort(); }
    322 #endif
    323 
    324 /* ============================================================================================== */
    325 /* Utils                                                                                          */
    326 /* ============================================================================================== */
    327 
    328 /* ---------------------------------------------------------------------------------------------- */
    329 /* General purpose                                                                                */
    330 /* ---------------------------------------------------------------------------------------------- */
    331 
    332 /**
    333  * Marks the specified parameter as unused.
    334  *
    335  * @param   x   The name of the unused parameter.
    336  */
    337 #define ZYAN_UNUSED(x) (void)(x)
    338 
    339 /**
    340  * Intentional fallthrough.
    341  */
    342 #if defined(ZYAN_GCC) && __GNUC__ >= 7
    343 #   define ZYAN_FALLTHROUGH ; __attribute__((__fallthrough__))
    344 #else
    345 #   define ZYAN_FALLTHROUGH
    346 #endif
    347 
    348 /**
    349  * Declares a bitfield.
    350  *
    351  * @param   x   The size (in bits) of the bitfield.
    352  */
    353 #define ZYAN_BITFIELD(x) : x
    354 
    355 /**
    356  * Marks functions that require libc (cannot be used with `ZYAN_NO_LIBC`).
    357  */
    358 #define ZYAN_REQUIRES_LIBC
    359 
    360 /**
    361  * Decorator for `printf`-style functions.
    362  *
    363  * @param   format_index    The 1-based index of the format string parameter.
    364  * @param   first_to_check  The 1-based index of the format arguments parameter.
    365  */
    366 #if defined(__RESHARPER__)
    367 #   define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
    368         [[gnu::format(printf, format_index, first_to_check)]]
    369 #elif defined(ZYAN_GCC)
    370 #   define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
    371         __attribute__((format(printf, format_index, first_to_check)))
    372 #else
    373 #   define ZYAN_PRINTF_ATTR(format_index, first_to_check)
    374 #endif
    375 
    376 /**
    377  * Decorator for `wprintf`-style functions.
    378  *
    379  * @param   format_index    The 1-based index of the format string parameter.
    380  * @param   first_to_check  The 1-based index of the format arguments parameter.
    381  */
    382 #if defined(__RESHARPER__)
    383 #   define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \
    384         [[rscpp::format(wprintf, format_index, first_to_check)]]
    385 #else
    386 #   define ZYAN_WPRINTF_ATTR(format_index, first_to_check)
    387 #endif
    388 
    389 /* ---------------------------------------------------------------------------------------------- */
    390 /* Arrays                                                                                         */
    391 /* ---------------------------------------------------------------------------------------------- */
    392 
    393 /**
    394  * Returns the length (number of elements) of an array.
    395  *
    396  * @param   a   The name of the array.
    397  *
    398  * @return  The number of elements of the given array.
    399  */
    400 #define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
    401 
    402 /* ---------------------------------------------------------------------------------------------- */
    403 /* Arithmetic                                                                                     */
    404 /* ---------------------------------------------------------------------------------------------- */
    405 
    406 /**
    407  * Returns the smaller value of `a` or `b`.
    408  *
    409  * @param   a   The first value.
    410  * @param   b   The second value.
    411  *
    412  * @return  The smaller value of `a` or `b`.
    413  */
    414 #define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b))
    415 
    416 /**
    417  * Returns the bigger value of `a` or `b`.
    418  *
    419  * @param   a   The first value.
    420  * @param   b   The second value.
    421  *
    422  * @return  The bigger value of `a` or `b`.
    423  */
    424 #define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b))
    425 
    426 /**
    427  * Returns the absolute value of `a`.
    428  *
    429  * @param   a   The value.
    430  *
    431  * @return  The absolute value of `a`.
    432  */
    433 #define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a))
    434 
    435 /**
    436  * Checks, if the given value is a power of 2.
    437  *
    438  * @param   x   The value.
    439  *
    440  * @return  `ZYAN_TRUE`, if the given value is a power of 2 or `ZYAN_FALSE`, if not.
    441  *
    442  * Note that this macro always returns `ZYAN_TRUE` for `x == 0`.
    443  */
    444 #define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
    445 
    446 /**
    447  * Checks, if the given value is properly aligned.
    448  *
    449  * Note that this macro only works for powers of 2.
    450  */
    451 #define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0)
    452 
    453 /**
    454  * Aligns the value to the nearest given alignment boundary (by rounding it up).
    455  *
    456  * @param   x       The value.
    457  * @param   align   The desired alignment.
    458  *
    459  * @return  The aligned value.
    460  *
    461  * Note that this macro only works for powers of 2.
    462  */
    463 #define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
    464 
    465 /**
    466  * Aligns the value to the nearest given alignment boundary (by rounding it down).
    467  *
    468  * @param   x       The value.
    469  * @param   align   The desired alignment.
    470  *
    471  * @return  The aligned value.
    472  *
    473  * Note that this macro only works for powers of 2.
    474  */
    475 #define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1))
    476 
    477 /* ---------------------------------------------------------------------------------------------- */
    478 /* Bit operations                                                                                 */
    479 /* ---------------------------------------------------------------------------------------------- */
    480 
    481 /*
    482  * Checks, if the bit at index `b` is required to present the ordinal value `n`.
    483  *
    484  * @param   n   The ordinal value.
    485  * @param   b   The bit index.
    486  *
    487  * @return  `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or
    488  *          `ZYAN_FALSE`, if not.
    489  *
    490  * Note that this macro always returns `ZYAN_FALSE` for `n == 0`.
    491  */
    492 #define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0)
    493 
    494 /*
    495  * Returns the number of bits required to represent the ordinal value `n`.
    496  *
    497  * @param   n   The ordinal value.
    498  *
    499  * @return  The number of bits required to represent the ordinal value `n`.
    500  *
    501  * Note that this macro returns `0` for `n == 0`.
    502  */
    503 #define ZYAN_BITS_TO_REPRESENT(n) \
    504     ( \
    505         ZYAN_NEEDS_BIT(n,  0) + ZYAN_NEEDS_BIT(n,  1) + \
    506         ZYAN_NEEDS_BIT(n,  2) + ZYAN_NEEDS_BIT(n,  3) + \
    507         ZYAN_NEEDS_BIT(n,  4) + ZYAN_NEEDS_BIT(n,  5) + \
    508         ZYAN_NEEDS_BIT(n,  6) + ZYAN_NEEDS_BIT(n,  7) + \
    509         ZYAN_NEEDS_BIT(n,  8) + ZYAN_NEEDS_BIT(n,  9) + \
    510         ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \
    511         ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \
    512         ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \
    513         ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \
    514         ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \
    515         ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \
    516         ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \
    517         ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \
    518         ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \
    519         ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \
    520         ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31)   \
    521     )
    522 
    523 /* ---------------------------------------------------------------------------------------------- */
    524 
    525 /* ============================================================================================== */
    526 
    527 #endif /* ZYCORE_DEFINES_H */