| Replace V with Nim 472eb49 nandithebull 14h ago | 1 | /* |
| 2 | |
| 3 | Nim's Runtime Library |
| 4 | (c) Copyright 2015 Andreas Rumpf |
| 5 | |
| 6 | See the file "copying.txt", included in this |
| 7 | distribution, for details about the copyright. |
| 8 | */ |
| 9 | |
| 10 | /* compiler symbols: |
| 11 | __BORLANDC__ |
| 12 | _MSC_VER |
| 13 | __GNUC__ |
| 14 | __TINYC__ |
| 15 | __clang__ |
| 16 | __AVR__ |
| 17 | __arm__ |
| 18 | __EMSCRIPTEN__ |
| 19 | */ |
| 20 | |
| 21 | |
| 22 | #ifndef NIMBASE_H |
| 23 | #define NIMBASE_H |
| 24 | |
| 25 | /*------------ declaring a custom attribute to support using LLVM's Address Sanitizer ------------ */ |
| 26 | |
| 27 | /* |
| 28 | This definition exists to provide support for using the LLVM ASAN (Address SANitizer) tooling with Nim. This |
| 29 | should only be used to mark implementations of the GC system that raise false flags with the ASAN tooling, or |
| 30 | for functions that are hot and need to be disabled for performance reasons. Based on the official ASAN |
| 31 | documentation, both the clang and gcc compilers are supported. In addition to that, a check is performed to |
| 32 | verify that the necessary attribute is supported by the compiler. |
| 33 | |
| 34 | To flag a proc as ignored, append the following code pragma to the proc declaration: |
| 35 | {.codegenDecl: "CLANG_NO_SANITIZE_ADDRESS $# $#$#".} |
| 36 | |
| 37 | For further information, please refer to the official documentation: |
| 38 | https://github.com/google/sanitizers/wiki/AddressSanitizer |
| 39 | */ |
| 40 | #define CLANG_NO_SANITIZE_ADDRESS |
| 41 | #if defined(__clang__) |
| 42 | # if __has_attribute(no_sanitize_address) |
| 43 | # undef CLANG_NO_SANITIZE_ADDRESS |
| 44 | # define CLANG_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) |
| 45 | # endif |
| 46 | #endif |
| 47 | |
| 48 | |
| 49 | /* ------------ ignore typical warnings in Nim-generated files ------------- */ |
| 50 | #if defined(__GNUC__) || defined(__clang__) |
| 51 | # pragma GCC diagnostic ignored "-Wpragmas" |
| 52 | # pragma GCC diagnostic ignored "-Wwritable-strings" |
| 53 | # pragma GCC diagnostic ignored "-Winvalid-noreturn" |
| 54 | # pragma GCC diagnostic ignored "-Wformat" |
| 55 | # pragma GCC diagnostic ignored "-Wlogical-not-parentheses" |
| 56 | # pragma GCC diagnostic ignored "-Wlogical-op-parentheses" |
| 57 | # pragma GCC diagnostic ignored "-Wshadow" |
| 58 | # pragma GCC diagnostic ignored "-Wunused-function" |
| 59 | # pragma GCC diagnostic ignored "-Wunused-variable" |
| 60 | # pragma GCC diagnostic ignored "-Winvalid-offsetof" |
| 61 | # pragma GCC diagnostic ignored "-Wtautological-compare" |
| 62 | # pragma GCC diagnostic ignored "-Wswitch-bool" |
| 63 | # pragma GCC diagnostic ignored "-Wmacro-redefined" |
| 64 | # pragma GCC diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers" |
| 65 | # pragma GCC diagnostic ignored "-Wpointer-bool-conversion" |
| 66 | # pragma GCC diagnostic ignored "-Wconstant-conversion" |
| 67 | #endif |
| 68 | |
| 69 | #if defined(_MSC_VER) |
| 70 | # pragma warning(disable: 4005 4100 4101 4189 4191 4200 4244 4293 4296 4309) |
| 71 | # pragma warning(disable: 4310 4365 4456 4477 4514 4574 4611 4668 4702 4706) |
| 72 | # pragma warning(disable: 4710 4711 4774 4800 4809 4820 4996 4090 4297) |
| 73 | #endif |
| 74 | /* ------------------------------------------------------------------------- */ |
| 75 | |
| 76 | #if defined(__GNUC__) && !defined(__ZEPHYR__) |
| 77 | /* Zephyr does some magic in it's headers that override the GCC stdlib. This breaks that. */ |
| 78 | # define _GNU_SOURCE 1 |
| 79 | #endif |
| 80 | |
| 81 | #if defined(__TINYC__) |
| 82 | /*# define __GNUC__ 3 |
| 83 | # define GCC_MAJOR 4 |
| 84 | # define __GNUC_MINOR__ 4 |
| 85 | # define __GNUC_PATCHLEVEL__ 5 */ |
| 86 | # define __DECLSPEC_SUPPORTED 1 |
| 87 | #endif |
| 88 | |
| 89 | /* calling convention mess ----------------------------------------------- */ |
| 90 | #if defined(__GNUC__) || defined(__TINYC__) |
| 91 | /* these should support C99's inline */ |
| 92 | # define N_INLINE(rettype, name) inline rettype name |
| 93 | #elif defined(__BORLANDC__) || defined(_MSC_VER) |
| 94 | /* Borland's compiler is really STRANGE here; note that the __fastcall |
| 95 | keyword cannot be before the return type, but __inline cannot be after |
| 96 | the return type, so we do not handle this mess in the code generator |
| 97 | but rather here. */ |
| 98 | # define N_INLINE(rettype, name) __inline rettype name |
| 99 | #else /* others are less picky: */ |
| 100 | # define N_INLINE(rettype, name) rettype __inline name |
| 101 | #endif |
| 102 | |
| 103 | #define N_INLINE_PTR(rettype, name) rettype (*name) |
| 104 | |
| 105 | #if defined(__cplusplus) |
| 106 | # define NIM_CONST /* C++ is picky with const modifiers */ |
| 107 | #else |
| 108 | # define NIM_CONST const |
| 109 | #endif |
| 110 | |
| 111 | /* |
| 112 | NIM_THREADVAR declaration based on |
| 113 | http://stackoverflow.com/questions/18298280/how-to-declare-a-variable-as-thread-local-portably |
| 114 | */ |
| 115 | #if defined _WIN32 |
| 116 | # if defined _MSC_VER || defined __BORLANDC__ |
| 117 | # define NIM_THREADVAR __declspec(thread) |
| 118 | # else |
| 119 | # define NIM_THREADVAR __thread |
| 120 | # endif |
| 121 | #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__ |
| 122 | # define NIM_THREADVAR _Thread_local |
| 123 | #elif defined _WIN32 && ( \ |
| 124 | defined _MSC_VER || \ |
| 125 | defined __ICL || \ |
| 126 | defined __BORLANDC__ ) |
| 127 | # define NIM_THREADVAR __declspec(thread) |
| 128 | #elif defined(__TINYC__) || defined(__GENODE__) |
| 129 | # define NIM_THREADVAR |
| 130 | /* note that ICC (linux) and Clang are covered by __GNUC__ */ |
| 131 | #elif defined __GNUC__ || \ |
| 132 | defined __SUNPRO_C || \ |
| 133 | defined __xlC__ |
| 134 | # define NIM_THREADVAR __thread |
| 135 | #else |
| 136 | # error "Cannot define NIM_THREADVAR" |
| 137 | #endif |
| 138 | |
| 139 | #if defined(__cplusplus) |
| 140 | #define NIM_THREAD_LOCAL thread_local |
| 141 | #endif |
| 142 | |
| 143 | /* --------------- how int64 constants should be declared: ----------- */ |
| 144 | #if defined(__GNUC__) || defined(_MSC_VER) |
| 145 | # define IL64(x) x##LL |
| 146 | #else /* works only without LL */ |
| 147 | # define IL64(x) ((NI64)x) |
| 148 | #endif |
| 149 | |
| 150 | /* ---------------- casting without correct aliasing rules ----------- */ |
| 151 | |
| 152 | #if defined(__GNUC__) |
| 153 | # define NIM_CAST(type, ptr) (((union{type __x__;}*)(ptr))->__x__) |
| 154 | #else |
| 155 | # define NIM_CAST(type, ptr) ((type)(ptr)) |
| 156 | #endif |
| 157 | |
| 158 | |
| 159 | /* ------------------------------------------------------------------- */ |
| 160 | #ifdef __cplusplus |
| 161 | # define NIM_EXTERNC extern "C" |
| 162 | #else |
| 163 | # define NIM_EXTERNC |
| 164 | #endif |
| 165 | |
| 166 | #if defined(WIN32) || defined(_WIN32) /* only Windows has this mess... */ |
| 167 | # define N_LIB_PRIVATE |
| 168 | # define N_CDECL(rettype, name) rettype __cdecl name |
| 169 | # define N_STDCALL(rettype, name) rettype __stdcall name |
| 170 | # define N_SYSCALL(rettype, name) rettype __syscall name |
| 171 | # define N_FASTCALL(rettype, name) rettype __fastcall name |
| 172 | # define N_THISCALL(rettype, name) rettype __thiscall name |
| 173 | # define N_SAFECALL(rettype, name) rettype __stdcall name |
| 174 | /* function pointers with calling convention: */ |
| 175 | # define N_CDECL_PTR(rettype, name) rettype (__cdecl *name) |
| 176 | # define N_STDCALL_PTR(rettype, name) rettype (__stdcall *name) |
| 177 | # define N_SYSCALL_PTR(rettype, name) rettype (__syscall *name) |
| 178 | # define N_FASTCALL_PTR(rettype, name) rettype (__fastcall *name) |
| 179 | # define N_THISCALL_PTR(rettype, name) rettype (__thiscall *name) |
| 180 | # define N_SAFECALL_PTR(rettype, name) rettype (__stdcall *name) |
| 181 | |
| 182 | # ifdef __EMSCRIPTEN__ |
| 183 | # define N_LIB_EXPORT NIM_EXTERNC __declspec(dllexport) __attribute__((used)) |
| 184 | # define N_LIB_EXPORT_VAR __declspec(dllexport) __attribute__((used)) |
| 185 | # else |
| 186 | # define N_LIB_EXPORT NIM_EXTERNC __declspec(dllexport) |
| 187 | # define N_LIB_EXPORT_VAR __declspec(dllexport) |
| 188 | # endif |
| 189 | # define N_LIB_IMPORT extern __declspec(dllimport) |
| 190 | #else |
| 191 | # define N_LIB_PRIVATE __attribute__((visibility("hidden"))) |
| 192 | # if defined(__GNUC__) |
| 193 | # define N_CDECL(rettype, name) rettype name |
| 194 | # define N_STDCALL(rettype, name) rettype name |
| 195 | # define N_SYSCALL(rettype, name) rettype name |
| 196 | # define N_FASTCALL(rettype, name) __attribute__((fastcall)) rettype name |
| 197 | # define N_SAFECALL(rettype, name) rettype name |
| 198 | /* function pointers with calling convention: */ |
| 199 | # define N_CDECL_PTR(rettype, name) rettype (*name) |
| 200 | # define N_STDCALL_PTR(rettype, name) rettype (*name) |
| 201 | # define N_SYSCALL_PTR(rettype, name) rettype (*name) |
| 202 | # define N_FASTCALL_PTR(rettype, name) __attribute__((fastcall)) rettype (*name) |
| 203 | # define N_SAFECALL_PTR(rettype, name) rettype (*name) |
| 204 | # else |
| 205 | # define N_CDECL(rettype, name) rettype name |
| 206 | # define N_STDCALL(rettype, name) rettype name |
| 207 | # define N_SYSCALL(rettype, name) rettype name |
| 208 | # define N_FASTCALL(rettype, name) rettype name |
| 209 | # define N_SAFECALL(rettype, name) rettype name |
| 210 | /* function pointers with calling convention: */ |
| 211 | # define N_CDECL_PTR(rettype, name) rettype (*name) |
| 212 | # define N_STDCALL_PTR(rettype, name) rettype (*name) |
| 213 | # define N_SYSCALL_PTR(rettype, name) rettype (*name) |
| 214 | # define N_FASTCALL_PTR(rettype, name) rettype (*name) |
| 215 | # define N_SAFECALL_PTR(rettype, name) rettype (*name) |
| 216 | # endif |
| 217 | # ifdef __EMSCRIPTEN__ |
| 218 | # define N_LIB_EXPORT NIM_EXTERNC __attribute__((visibility("default"), used)) |
| 219 | # define N_LIB_EXPORT_VAR __attribute__((visibility("default"), used)) |
| 220 | # else |
| 221 | # define N_LIB_EXPORT NIM_EXTERNC __attribute__((visibility("default"))) |
| 222 | # define N_LIB_EXPORT_VAR __attribute__((visibility("default"))) |
| 223 | # endif |
| 224 | # define N_LIB_IMPORT extern |
| 225 | #endif |
| 226 | |
| 227 | #define N_NOCONV(rettype, name) rettype name |
| 228 | /* specify no calling convention */ |
| 229 | #define N_NOCONV_PTR(rettype, name) rettype (*name) |
| 230 | |
| 231 | #if defined(__GNUC__) || defined(__ICC__) |
| 232 | # define N_NOINLINE(rettype, name) rettype __attribute__((__noinline__)) name |
| 233 | #elif defined(_MSC_VER) |
| 234 | # define N_NOINLINE(rettype, name) __declspec(noinline) rettype name |
| 235 | #else |
| 236 | # define N_NOINLINE(rettype, name) rettype name |
| 237 | #endif |
| 238 | |
| 239 | #define N_NOINLINE_PTR(rettype, name) rettype (*name) |
| 240 | |
| 241 | #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) |
| 242 | /* these compilers have a fastcall so use it: */ |
| 243 | # ifdef __TINYC__ |
| 244 | # define N_NIMCALL(rettype, name) rettype __attribute((__fastcall)) name |
| 245 | # define N_NIMCALL_PTR(rettype, name) rettype (__attribute((__fastcall)) *name) |
| 246 | # define N_RAW_NIMCALL __attribute((__fastcall)) |
| 247 | # else |
| 248 | # define N_NIMCALL(rettype, name) rettype __fastcall name |
| 249 | # define N_NIMCALL_PTR(rettype, name) rettype (__fastcall *name) |
| 250 | # define N_RAW_NIMCALL __fastcall |
| 251 | # endif |
| 252 | #else |
| 253 | # define N_NIMCALL(rettype, name) rettype name /* no modifier */ |
| 254 | # define N_NIMCALL_PTR(rettype, name) rettype (*name) |
| 255 | # define N_RAW_NIMCALL |
| 256 | #endif |
| 257 | |
| 258 | #define N_CLOSURE(rettype, name) N_NIMCALL(rettype, name) |
| 259 | #define N_CLOSURE_PTR(rettype, name) N_NIMCALL_PTR(rettype, name) |
| 260 | |
| 261 | /* ----------------------------------------------------------------------- */ |
| 262 | |
| 263 | #define COMMA , |
| 264 | |
| 265 | #include <limits.h> |
| 266 | #include <stddef.h> |
| 267 | |
| 268 | // define NIM_STATIC_ASSERT |
| 269 | // example use case: CT sizeof for importc types verification |
| 270 | // where we have {.completeStruct.} (or lack of {.incompleteStruct.}) |
| 271 | #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) |
| 272 | #define NIM_STATIC_ASSERT(x, msg) _Static_assert((x), msg) |
| 273 | #elif defined(__cplusplus) |
| 274 | #define NIM_STATIC_ASSERT(x, msg) static_assert((x), msg) |
| 275 | #else |
| 276 | #define _NIM_STATIC_ASSERT_FINAL(x, append_name) typedef int NIM_STATIC_ASSERT_AUX ## append_name[(x) ? 1 : -1]; |
| 277 | #define _NIM_STATIC_ASSERT_STAGE_3(x, line) _NIM_STATIC_ASSERT_FINAL(x, _AT_LINE_##line) |
| 278 | #define _NIM_STATIC_ASSERT_STAGE_2(x, line) _NIM_STATIC_ASSERT_STAGE_3(x, line) |
| 279 | #define NIM_STATIC_ASSERT(x, msg) _NIM_STATIC_ASSERT_STAGE_2(x,__LINE__) |
| 280 | // On failure, your C compiler will say something like: |
| 281 | // "error: 'NIM_STATIC_ASSERT_AUX_AT_LINE_XXX' declared as an array with a negative size" |
| 282 | // Adding the line number helps to avoid redefinitions which are not allowed in |
| 283 | // old GCC versions, however the order of evaluation for __LINE__ is a little tricky, |
| 284 | // hence all the helper macros. See https://stackoverflow.com/a/3385694 for more info. |
| 285 | #endif |
| 286 | |
| 287 | /* C99 compiler? */ |
| 288 | #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)) |
| 289 | # define HAVE_STDINT_H |
| 290 | #endif |
| 291 | |
| 292 | /* Known compiler with stdint.h that doesn't fit the general pattern? */ |
| 293 | #if defined(__AVR__) || (defined(__cplusplus) && (__cplusplus < 201103)) |
| 294 | # define HAVE_STDINT_H |
| 295 | #endif |
| 296 | |
| 297 | #if (!defined(HAVE_STDINT_H) && defined(__cplusplus) && (__cplusplus >= 201103)) |
| 298 | # define HAVE_CSTDINT |
| 299 | #endif |
| 300 | |
| 301 | |
| 302 | /* wrap all Nim typedefs into namespace Nim */ |
| 303 | #ifdef USE_NIM_NAMESPACE |
| 304 | #ifdef HAVE_CSTDINT |
| 305 | #include <cstdint> |
| 306 | #else |
| 307 | #include <stdint.h> |
| 308 | #endif |
| 309 | namespace USE_NIM_NAMESPACE { |
| 310 | #endif |
| 311 | |
| 312 | // preexisting check, seems paranoid, maybe remove |
| 313 | #if defined(NIM_TRUE) || defined(NIM_FALSE) || defined(NIM_BOOL) |
| 314 | #error "nim reserved preprocessor macros clash" |
| 315 | #endif |
| 316 | |
| 317 | /* bool types (C++ has it): */ |
| 318 | #ifdef __cplusplus |
| 319 | #define NIM_BOOL bool |
| 320 | #elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901) |
| 321 | // see #13798: to avoid conflicts for code emitting `#include <stdbool.h>` |
| 322 | #define NIM_BOOL _Bool |
| 323 | #else |
| 324 | typedef unsigned char NIM_BOOL; // best effort |
| 325 | #endif |
| 326 | |
| 327 | NIM_STATIC_ASSERT(sizeof(NIM_BOOL) == 1, ""); // check whether really needed |
| 328 | NIM_STATIC_ASSERT(CHAR_BIT == 8, ""); |
| 329 | // fail fast for (rare) environments where this doesn't hold, as some implicit |
| 330 | // assumptions would need revisiting (e.g. `uint8` or https://github.com/nim-lang/Nim/pull/18505) |
| 331 | |
| 332 | #define NIM_TRUE true |
| 333 | #define NIM_FALSE false |
| 334 | |
| 335 | #ifdef __cplusplus |
| 336 | # if __cplusplus >= 201103L |
| 337 | # /* nullptr is more type safe (less implicit conversions than 0) */ |
| 338 | # define NIM_NIL nullptr |
| 339 | # else |
| 340 | # // both `((void*)0)` and `NULL` would cause codegen to emit |
| 341 | # // error: assigning to 'Foo *' from incompatible type 'void *' |
| 342 | # // but codegen could be fixed if need. See also potential caveat regarding |
| 343 | # // NULL. |
| 344 | # // However, `0` causes other issues, see #13798 |
| 345 | # define NIM_NIL 0 |
| 346 | # endif |
| 347 | #else |
| 348 | # include <stdbool.h> |
| 349 | # define NIM_NIL ((void*)0) /* C's NULL is fucked up in some C compilers, so |
| 350 | the generated code does not rely on it anymore */ |
| 351 | #endif |
| 352 | |
| 353 | #if defined(__BORLANDC__) || defined(_MSC_VER) |
| 354 | typedef signed char NI8; |
| 355 | typedef signed short int NI16; |
| 356 | typedef signed int NI32; |
| 357 | typedef __int64 NI64; |
| 358 | /* XXX: Float128? */ |
| 359 | typedef unsigned char NU8; |
| 360 | typedef unsigned short int NU16; |
| 361 | typedef unsigned int NU32; |
| 362 | typedef unsigned __int64 NU64; |
| 363 | #elif defined(HAVE_STDINT_H) |
| 364 | #ifndef USE_NIM_NAMESPACE |
| 365 | # include <stdint.h> |
| 366 | #endif |
| 367 | typedef int8_t NI8; |
| 368 | typedef int16_t NI16; |
| 369 | typedef int32_t NI32; |
| 370 | typedef int64_t NI64; |
| 371 | typedef uint8_t NU8; |
| 372 | typedef uint16_t NU16; |
| 373 | typedef uint32_t NU32; |
| 374 | typedef uint64_t NU64; |
| 375 | #elif defined(HAVE_CSTDINT) |
| 376 | #ifndef USE_NIM_NAMESPACE |
| 377 | # include <cstdint> |
| 378 | #endif |
| 379 | typedef std::int8_t NI8; |
| 380 | typedef std::int16_t NI16; |
| 381 | typedef std::int32_t NI32; |
| 382 | typedef std::int64_t NI64; |
| 383 | typedef std::uint8_t NU8; |
| 384 | typedef std::uint16_t NU16; |
| 385 | typedef std::uint32_t NU32; |
| 386 | typedef std::uint64_t NU64; |
| 387 | #else |
| 388 | /* Unknown compiler/version, do our best */ |
| 389 | #ifdef __INT8_TYPE__ |
| 390 | typedef __INT8_TYPE__ NI8; |
| 391 | #else |
| 392 | typedef signed char NI8; |
| 393 | #endif |
| 394 | #ifdef __INT16_TYPE__ |
| 395 | typedef __INT16_TYPE__ NI16; |
| 396 | #else |
| 397 | typedef signed short int NI16; |
| 398 | #endif |
| 399 | #ifdef __INT32_TYPE__ |
| 400 | typedef __INT32_TYPE__ NI32; |
| 401 | #else |
| 402 | typedef signed int NI32; |
| 403 | #endif |
| 404 | #ifdef __INT64_TYPE__ |
| 405 | typedef __INT64_TYPE__ NI64; |
| 406 | #else |
| 407 | typedef long long int NI64; |
| 408 | #endif |
| 409 | /* XXX: Float128? */ |
| 410 | #ifdef __UINT8_TYPE__ |
| 411 | typedef __UINT8_TYPE__ NU8; |
| 412 | #else |
| 413 | typedef unsigned char NU8; |
| 414 | #endif |
| 415 | #ifdef __UINT16_TYPE__ |
| 416 | typedef __UINT16_TYPE__ NU16; |
| 417 | #else |
| 418 | typedef unsigned short int NU16; |
| 419 | #endif |
| 420 | #ifdef __UINT32_TYPE__ |
| 421 | typedef __UINT32_TYPE__ NU32; |
| 422 | #else |
| 423 | typedef unsigned int NU32; |
| 424 | #endif |
| 425 | #ifdef __UINT64_TYPE__ |
| 426 | typedef __UINT64_TYPE__ NU64; |
| 427 | #else |
| 428 | typedef unsigned long long int NU64; |
| 429 | #endif |
| 430 | #endif |
| 431 | |
| 432 | #ifdef NIM_INTBITS |
| 433 | # if NIM_INTBITS == 64 |
| 434 | typedef NI64 NI; |
| 435 | typedef NU64 NU; |
| 436 | # elif NIM_INTBITS == 32 |
| 437 | typedef NI32 NI; |
| 438 | typedef NU32 NU; |
| 439 | # elif NIM_INTBITS == 16 |
| 440 | typedef NI16 NI; |
| 441 | typedef NU16 NU; |
| 442 | # elif NIM_INTBITS == 8 |
| 443 | typedef NI8 NI; |
| 444 | typedef NU8 NU; |
| 445 | # else |
| 446 | # error "invalid bit width for int" |
| 447 | # endif |
| 448 | #endif |
| 449 | |
| 450 | // for now there isn't an easy way for C code to reach the program result |
| 451 | // when hot code reloading is ON - users will have to: |
| 452 | // load the nimhcr.dll, get the hcrGetGlobal proc from there and use it |
| 453 | #ifndef NIM_HOT_CODE_RELOADING |
| 454 | extern NI nim_program_result; |
| 455 | #endif |
| 456 | |
| 457 | typedef float NF32; |
| 458 | typedef double NF64; |
| 459 | typedef double NF; |
| 460 | |
| 461 | typedef char NIM_CHAR; |
| 462 | typedef char* NCSTRING; |
| 463 | |
| 464 | #ifdef NIM_BIG_ENDIAN |
| 465 | # define NIM_IMAN 1 |
| 466 | #else |
| 467 | # define NIM_IMAN 0 |
| 468 | #endif |
| 469 | |
| 470 | #define NIM_STRLIT_FLAG ((NU)(1) << ((NIM_INTBITS) - 2)) /* This has to be the same as system.strlitFlag! */ |
| 471 | |
| 472 | #define STRING_LITERAL(name, str, length) \ |
| 473 | static const struct { \ |
| 474 | TGenericSeq Sup; \ |
| 475 | NIM_CHAR data[(length) + 1]; \ |
| 476 | } name = {{length, (NI) ((NU)length | NIM_STRLIT_FLAG)}, str} |
| 477 | |
| 478 | /* declared size of a sequence/variable length array: */ |
| 479 | #if defined(__cplusplus) && defined(__clang__) |
| 480 | # define SEQ_DECL_SIZE 1 |
| 481 | #elif defined(__GNUC__) || defined(_MSC_VER) |
| 482 | # define SEQ_DECL_SIZE /* empty is correct! */ |
| 483 | #else |
| 484 | # define SEQ_DECL_SIZE 1000000 |
| 485 | #endif |
| 486 | |
| 487 | #define ALLOC_0(size) calloc(1, size) |
| 488 | #define DL_ALLOC_0(size) dlcalloc(1, size) |
| 489 | |
| 490 | #define paramCount() cmdCount |
| 491 | |
| 492 | // NAN definition copied from math.h included in the Windows SDK version 10.0.14393.0 |
| 493 | #ifndef NAN |
| 494 | # ifndef _HUGE_ENUF |
| 495 | # define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow |
| 496 | # endif |
| 497 | # define NAN_INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) |
| 498 | # define NAN ((float)(NAN_INFINITY * 0.0F)) |
| 499 | #endif |
| 500 | |
| 501 | #ifndef INF |
| 502 | # ifdef INFINITY |
| 503 | # define INF INFINITY |
| 504 | # elif defined(HUGE_VAL) |
| 505 | # define INF HUGE_VAL |
| 506 | # elif defined(_MSC_VER) |
| 507 | # include <float.h> |
| 508 | # define INF (DBL_MAX+DBL_MAX) |
| 509 | # else |
| 510 | # define INF (1.0 / 0.0) |
| 511 | # endif |
| 512 | #endif |
| 513 | |
| 514 | typedef struct TFrame_ TFrame; |
| 515 | struct TFrame_ { |
| 516 | TFrame* prev; |
| 517 | NCSTRING procname; |
| 518 | NI line; |
| 519 | NCSTRING filename; |
| 520 | NI16 len; |
| 521 | NI16 calldepth; |
| 522 | NI frameMsgLen; |
| 523 | }; |
| 524 | |
| 525 | #define NIM_POSIX_INIT __attribute__((constructor)) |
| 526 | |
| 527 | #ifdef __GNUC__ |
| 528 | # define NIM_LIKELY(x) __builtin_expect(x, 1) |
| 529 | # define NIM_UNLIKELY(x) __builtin_expect(x, 0) |
| 530 | /* We need the following for the posix wrapper. In particular it will give us |
| 531 | POSIX_SPAWN_USEVFORK: */ |
| 532 | # ifndef _GNU_SOURCE |
| 533 | # define _GNU_SOURCE |
| 534 | # endif |
| 535 | #else |
| 536 | # define NIM_LIKELY(x) (x) |
| 537 | # define NIM_UNLIKELY(x) (x) |
| 538 | #endif |
| 539 | |
| 540 | #if 0 // defined(__GNUC__) || defined(__clang__) |
| 541 | // not needed anymore because the stack marking cares about |
| 542 | // interior pointers now |
| 543 | static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); } |
| 544 | # define GC_GUARD __attribute__ ((cleanup(GCGuard))) |
| 545 | #else |
| 546 | # define GC_GUARD |
| 547 | #endif |
| 548 | |
| 549 | // Test to see if Nim and the C compiler agree on the size of a pointer. |
| 550 | NIM_STATIC_ASSERT(sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8, "Pointer size mismatch between Nim and C/C++ backend. You probably need to setup the backend compiler for target CPU."); |
| 551 | |
| 552 | #ifdef USE_NIM_NAMESPACE |
| 553 | } |
| 554 | #endif |
| 555 | |
| 556 | #if defined(_MSC_VER) |
| 557 | # define NIM_ALIGN(x) __declspec(align(x)) |
| 558 | # define NIM_ALIGNOF(x) __alignof(x) |
| 559 | #else |
| 560 | # define NIM_ALIGN(x) __attribute__((aligned(x))) |
| 561 | # define NIM_ALIGNOF(x) __alignof__(x) |
| 562 | #endif |
| 563 | |
| 564 | /* ---------------- platform specific includes ----------------------- */ |
| 565 | |
| 566 | /* VxWorks related includes */ |
| 567 | #if defined(__VXWORKS__) |
| 568 | # include <sys/types.h> |
| 569 | # include <types/vxWind.h> |
| 570 | # include <tool/gnu/toolMacros.h> |
| 571 | #elif defined(__FreeBSD__) |
| 572 | # include <sys/types.h> |
| 573 | #endif |
| 574 | |
| 575 | /* these exist to make the codegen logic simpler */ |
| 576 | #define nimModInt(a, b, res) (((*res) = (a) % (b)), 0) |
| 577 | #define nimModInt64(a, b, res) (((*res) = (a) % (b)), 0) |
| 578 | |
| 579 | #if (!defined(_MSC_VER) || defined(__clang__)) && !defined(NIM_EmulateOverflowChecks) |
| 580 | /* these exist because we cannot have .compilerProcs that are importc'ed |
| 581 | by a different name */ |
| 582 | |
| 583 | #define nimAddInt64(a, b, res) __builtin_saddll_overflow(a, b, (long long int*)res) |
| 584 | #define nimSubInt64(a, b, res) __builtin_ssubll_overflow(a, b, (long long int*)res) |
| 585 | #define nimMulInt64(a, b, res) __builtin_smulll_overflow(a, b, (long long int*)res) |
| 586 | |
| 587 | #if NIM_INTBITS == 32 |
| 588 | #if defined(__arm__) && defined(__GNUC__) |
| 589 | /* arm-none-eabi-gcc targets defines int32_t as long int */ |
| 590 | #define nimAddInt(a, b, res) __builtin_saddl_overflow(a, b, res) |
| 591 | #define nimSubInt(a, b, res) __builtin_ssubl_overflow(a, b, res) |
| 592 | #define nimMulInt(a, b, res) __builtin_smull_overflow(a, b, res) |
| 593 | #else |
| 594 | #define nimAddInt(a, b, res) __builtin_sadd_overflow(a, b, res) |
| 595 | #define nimSubInt(a, b, res) __builtin_ssub_overflow(a, b, res) |
| 596 | #define nimMulInt(a, b, res) __builtin_smul_overflow(a, b, res) |
| 597 | #endif |
| 598 | #else |
| 599 | /* map it to the 'long long' variant */ |
| 600 | #define nimAddInt(a, b, res) __builtin_saddll_overflow(a, b, (long long int*)res) |
| 601 | #define nimSubInt(a, b, res) __builtin_ssubll_overflow(a, b, (long long int*)res) |
| 602 | #define nimMulInt(a, b, res) __builtin_smulll_overflow(a, b, (long long int*)res) |
| 603 | #endif |
| 604 | #endif |
| 605 | |
| 606 | #define NIM_NOALIAS __restrict |
| 607 | /* __restrict is said to work for all the C(++) compilers out there that we support */ |
| 608 | |
| 609 | #endif /* NIMBASE_H */ |