summary refs log tree commit diff stats
path: root/lib/nimbase.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/nimbase.h')
-rw-r--r--[-rwxr-xr-x]lib/nimbase.h668
1 files changed, 425 insertions, 243 deletions
diff --git a/lib/nimbase.h b/lib/nimbase.h
index c7b3e551d..cf0c8002b 100755..100644
--- a/lib/nimbase.h
+++ b/lib/nimbase.h
@@ -1,7 +1,7 @@
 /*
 
-            Nimrod's Runtime Library
-        (c) Copyright 2010 Andreas Rumpf
+            Nim's Runtime Library
+        (c) Copyright 2015 Andreas Rumpf
 
     See the file "copying.txt", included in this
     distribution, for details about the copyright.
@@ -10,28 +10,85 @@
 /* compiler symbols:
 __BORLANDC__
 _MSC_VER
-__WATCOMC__
-__LCC__
 __GNUC__
-__DMC__
-__POCC__
 __TINYC__
+__clang__
+__AVR__
+__arm__
+__EMSCRIPTEN__
 */
 
 
 #ifndef NIMBASE_H
 #define NIMBASE_H
 
-#if !defined(__TINYC__)
-#  include  <math.h>
+/*------------ declaring a custom attribute to support using LLVM's Address Sanitizer ------------ */
+
+/*
+   This definition exists to provide support for using the LLVM ASAN (Address SANitizer) tooling with Nim. This
+   should only be used to mark implementations of the GC system that raise false flags with the ASAN tooling, or
+   for functions that are hot and need to be disabled for performance reasons. Based on the official ASAN
+   documentation, both the clang and gcc compilers are supported. In addition to that, a check is performed to
+   verify that the necessary attribute is supported by the compiler.
+
+   To flag a proc as ignored, append the following code pragma to the proc declaration:
+      {.codegenDecl: "CLANG_NO_SANITIZE_ADDRESS $# $#$#".}
+
+   For further information, please refer to the official documentation:
+     https://github.com/google/sanitizers/wiki/AddressSanitizer
+ */
+#define CLANG_NO_SANITIZE_ADDRESS
+#if defined(__clang__)
+#  if __has_attribute(no_sanitize_address)
+#    undef CLANG_NO_SANITIZE_ADDRESS
+#    define CLANG_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
+#  endif
+#endif
+
+
+/* ------------ ignore typical warnings in Nim-generated files ------------- */
+#if defined(__GNUC__) || defined(__clang__)
+#  pragma GCC diagnostic ignored "-Wpragmas"
+#  pragma GCC diagnostic ignored "-Wwritable-strings"
+#  pragma GCC diagnostic ignored "-Winvalid-noreturn"
+#  pragma GCC diagnostic ignored "-Wformat"
+#  pragma GCC diagnostic ignored "-Wlogical-not-parentheses"
+#  pragma GCC diagnostic ignored "-Wlogical-op-parentheses"
+#  pragma GCC diagnostic ignored "-Wshadow"
+#  pragma GCC diagnostic ignored "-Wunused-function"
+#  pragma GCC diagnostic ignored "-Wunused-variable"
+#  pragma GCC diagnostic ignored "-Winvalid-offsetof"
+#  pragma GCC diagnostic ignored "-Wtautological-compare"
+#  pragma GCC diagnostic ignored "-Wswitch-bool"
+#  pragma GCC diagnostic ignored "-Wmacro-redefined"
+#  pragma GCC diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
+#  pragma GCC diagnostic ignored "-Wpointer-bool-conversion"
+#  pragma GCC diagnostic ignored "-Wconstant-conversion"
+#endif
+
+#if defined(_MSC_VER)
+#  pragma warning(disable: 4005 4100 4101 4189 4191 4200 4244 4293 4296 4309)
+#  pragma warning(disable: 4310 4365 4456 4477 4514 4574 4611 4668 4702 4706)
+#  pragma warning(disable: 4710 4711 4774 4800 4809 4820 4996 4090 4297)
+#endif
+/* ------------------------------------------------------------------------- */
+
+#if defined(__GNUC__) && !defined(__ZEPHYR__)
+/* Zephyr does some magic in it's headers that override the GCC stdlib. This breaks that. */
+#  define _GNU_SOURCE 1
+#endif
+
+#if defined(__TINYC__)
+/*#  define __GNUC__ 3
+#  define GCC_MAJOR 4
+#  define __GNUC_MINOR__ 4
+#  define __GNUC_PATCHLEVEL__ 5 */
+#  define __DECLSPEC_SUPPORTED 1
 #endif
 
 /* calling convention mess ----------------------------------------------- */
-#if defined(__GNUC__) || defined(__LCC__) || defined(__POCC__) \
-                      || defined(__TINYC__)
+#if defined(__GNUC__) || defined(__TINYC__)
   /* these should support C99's inline */
-  /* the test for __POCC__ has to come before the test for _MSC_VER,
-     because PellesC defines _MSC_VER too. This is brain-dead. */
 #  define N_INLINE(rettype, name) inline rettype name
 #elif defined(__BORLANDC__) || defined(_MSC_VER)
 /* Borland's compiler is really STRANGE here; note that the __fastcall
@@ -39,77 +96,131 @@ __TINYC__
    the return type, so we do not handle this mess in the code generator
    but rather here. */
 #  define N_INLINE(rettype, name) __inline rettype name
-#elif defined(__DMC__)
-#  define N_INLINE(rettype, name) inline rettype name
-#elif defined(__WATCOMC__)
-#  define N_INLINE(rettype, name) __inline rettype name
 #else /* others are less picky: */
 #  define N_INLINE(rettype, name) rettype __inline name
 #endif
 
-#if defined(__POCC__) || defined(_MSC_VER)
-#  define HAVE_LRINT 1
-#endif
+#define N_INLINE_PTR(rettype, name) rettype (*name)
 
-#if defined(__POCC__)
-#  define NIM_CONST /* PCC is really picky with const modifiers */
-#  undef _MSC_VER /* Yeah, right PCC defines _MSC_VER even if it is
-                     not that compatible. Well done. */
-#elif defined(__cplusplus)
+#if defined(__cplusplus)
 #  define NIM_CONST /* C++ is picky with const modifiers */
 #else
 #  define NIM_CONST  const
 #endif
 
-#define NIM_THREADVAR __thread
+/*
+  NIM_THREADVAR declaration based on
+  http://stackoverflow.com/questions/18298280/how-to-declare-a-variable-as-thread-local-portably
+*/
+#if defined _WIN32
+#  if defined _MSC_VER || defined __BORLANDC__
+#    define NIM_THREADVAR __declspec(thread)
+#  else
+#    define NIM_THREADVAR __thread
+#  endif
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__
+#  define NIM_THREADVAR _Thread_local
+#elif defined _WIN32 && ( \
+       defined _MSC_VER || \
+       defined __ICL || \
+       defined __BORLANDC__ )
+#  define NIM_THREADVAR __declspec(thread)
+#elif defined(__TINYC__) || defined(__GENODE__)
+#  define NIM_THREADVAR
+/* note that ICC (linux) and Clang are covered by __GNUC__ */
+#elif defined __GNUC__ || \
+       defined __SUNPRO_C || \
+       defined __xlC__
+#  define NIM_THREADVAR __thread
+#else
+#  error "Cannot define NIM_THREADVAR"
+#endif
+
+#if defined(__cplusplus)
+  #define NIM_THREAD_LOCAL thread_local
+#endif
 
 /* --------------- how int64 constants should be declared: ----------- */
-#if defined(__GNUC__) || defined(__LCC__) || \
-    defined(__POCC__) || defined(__DMC__)
+#if defined(__GNUC__) || defined(_MSC_VER)
 #  define IL64(x) x##LL
 #else /* works only without LL */
-#  define IL64(x) x
+#  define IL64(x) ((NI64)x)
 #endif
 
 /* ---------------- casting without correct aliasing rules ----------- */
 
-#if defined(__GNUCC__)
+#if defined(__GNUC__)
 #  define NIM_CAST(type, ptr) (((union{type __x__;}*)(ptr))->__x__)
 #else
 #  define NIM_CAST(type, ptr) ((type)(ptr))
 #endif
 
+
 /* ------------------------------------------------------------------- */
+#ifdef  __cplusplus
+#  define NIM_EXTERNC extern "C"
+#else
+#  define NIM_EXTERNC
+#endif
 
 #if defined(WIN32) || defined(_WIN32) /* only Windows has this mess... */
+#  define N_LIB_PRIVATE
 #  define N_CDECL(rettype, name) rettype __cdecl name
 #  define N_STDCALL(rettype, name) rettype __stdcall name
 #  define N_SYSCALL(rettype, name) rettype __syscall name
 #  define N_FASTCALL(rettype, name) rettype __fastcall name
-#  define N_SAFECALL(rettype, name) rettype __safecall name
+#  define N_THISCALL(rettype, name) rettype __thiscall name
+#  define N_SAFECALL(rettype, name) rettype __stdcall name
 /* function pointers with calling convention: */
 #  define N_CDECL_PTR(rettype, name) rettype (__cdecl *name)
 #  define N_STDCALL_PTR(rettype, name) rettype (__stdcall *name)
 #  define N_SYSCALL_PTR(rettype, name) rettype (__syscall *name)
 #  define N_FASTCALL_PTR(rettype, name) rettype (__fastcall *name)
-#  define N_SAFECALL_PTR(rettype, name) rettype (__safecall *name)
+#  define N_THISCALL_PTR(rettype, name) rettype (__thiscall *name)
+#  define N_SAFECALL_PTR(rettype, name) rettype (__stdcall *name)
 
-#  define N_LIB_EXPORT  extern __declspec(dllexport)
+#  ifdef __EMSCRIPTEN__
+#    define N_LIB_EXPORT  NIM_EXTERNC __declspec(dllexport) __attribute__((used))
+#    define N_LIB_EXPORT_VAR  __declspec(dllexport) __attribute__((used))
+#  else
+#    define N_LIB_EXPORT  NIM_EXTERNC __declspec(dllexport)
+#    define N_LIB_EXPORT_VAR  __declspec(dllexport)
+#  endif
 #  define N_LIB_IMPORT  extern __declspec(dllimport)
 #else
-#  define N_CDECL(rettype, name) rettype name
-#  define N_STDCALL(rettype, name) rettype name
-#  define N_SYSCALL(rettype, name) rettype name
-#  define N_FASTCALL(rettype, name) rettype name
-#  define N_SAFECALL(rettype, name) rettype name
-/* function pointers with calling convention: */
-#  define N_CDECL_PTR(rettype, name) rettype (*name)
-#  define N_STDCALL_PTR(rettype, name) rettype (*name)
-#  define N_SYSCALL_PTR(rettype, name) rettype (*name)
-#  define N_FASTCALL_PTR(rettype, name) rettype (*name)
-#  define N_SAFECALL_PTR(rettype, name) rettype (*name)
-
-#  define N_LIB_EXPORT  extern
+#  define N_LIB_PRIVATE __attribute__((visibility("hidden")))
+#  if defined(__GNUC__)
+#    define N_CDECL(rettype, name) rettype name
+#    define N_STDCALL(rettype, name) rettype name
+#    define N_SYSCALL(rettype, name) rettype name
+#    define N_FASTCALL(rettype, name) __attribute__((fastcall)) rettype name
+#    define N_SAFECALL(rettype, name) rettype name
+/*   function pointers with calling convention: */
+#    define N_CDECL_PTR(rettype, name) rettype (*name)
+#    define N_STDCALL_PTR(rettype, name) rettype (*name)
+#    define N_SYSCALL_PTR(rettype, name) rettype (*name)
+#    define N_FASTCALL_PTR(rettype, name) __attribute__((fastcall)) rettype (*name)
+#    define N_SAFECALL_PTR(rettype, name) rettype (*name)
+#  else
+#    define N_CDECL(rettype, name) rettype name
+#    define N_STDCALL(rettype, name) rettype name
+#    define N_SYSCALL(rettype, name) rettype name
+#    define N_FASTCALL(rettype, name) rettype name
+#    define N_SAFECALL(rettype, name) rettype name
+/*   function pointers with calling convention: */
+#    define N_CDECL_PTR(rettype, name) rettype (*name)
+#    define N_STDCALL_PTR(rettype, name) rettype (*name)
+#    define N_SYSCALL_PTR(rettype, name) rettype (*name)
+#    define N_FASTCALL_PTR(rettype, name) rettype (*name)
+#    define N_SAFECALL_PTR(rettype, name) rettype (*name)
+#  endif
+#  ifdef __EMSCRIPTEN__
+#    define N_LIB_EXPORT NIM_EXTERNC __attribute__((visibility("default"), used))
+#    define N_LIB_EXPORT_VAR  __attribute__((visibility("default"), used))
+#  else
+#    define N_LIB_EXPORT NIM_EXTERNC __attribute__((visibility("default")))
+#    define N_LIB_EXPORT_VAR  __attribute__((visibility("default")))
+#  endif
 #  define N_LIB_IMPORT  extern
 #endif
 
@@ -117,13 +228,8 @@ __TINYC__
 /* specify no calling convention */
 #define N_NOCONV_PTR(rettype, name) rettype (*name)
 
-#define N_CLOSURE(rettype, name) rettype name
-/* specify no calling convention */
-#define N_CLOSURE_PTR(rettype, name) rettype (*name)
-
-
 #if defined(__GNUC__) || defined(__ICC__)
-#  define N_NOINLINE(rettype, name) rettype __attribute__((noinline)) name
+#  define N_NOINLINE(rettype, name) rettype __attribute__((__noinline__)) name
 #elif defined(_MSC_VER)
 #  define N_NOINLINE(rettype, name) __declspec(noinline) rettype name
 #else
@@ -132,194 +238,221 @@ __TINYC__
 
 #define N_NOINLINE_PTR(rettype, name) rettype (*name)
 
-#if defined(__BORLANDC__) || defined(__WATCOMC__) || \
-    defined(__POCC__) || defined(_MSC_VER)
+#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(WIN32) || defined(_WIN32)
 /* these compilers have a fastcall so use it: */
-#  define N_NIMCALL(rettype, name) rettype __fastcall name
-#  define N_NIMCALL_PTR(rettype, name) rettype (__fastcall *name)
+#  ifdef __TINYC__
+#    define N_NIMCALL(rettype, name) rettype __attribute((__fastcall)) name
+#    define N_NIMCALL_PTR(rettype, name) rettype (__attribute((__fastcall)) *name)
+#    define N_RAW_NIMCALL __attribute((__fastcall))
+#  else
+#    define N_NIMCALL(rettype, name) rettype __fastcall name
+#    define N_NIMCALL_PTR(rettype, name) rettype (__fastcall *name)
+#    define N_RAW_NIMCALL __fastcall
+#  endif
 #else
 #  define N_NIMCALL(rettype, name) rettype name /* no modifier */
 #  define N_NIMCALL_PTR(rettype, name) rettype (*name)
+#  define N_RAW_NIMCALL
 #endif
 
-/* ----------------------------------------------------------------------- */
-
-/* from float_cast.h: */
+#define N_CLOSURE(rettype, name) N_NIMCALL(rettype, name)
+#define N_CLOSURE_PTR(rettype, name) N_NIMCALL_PTR(rettype, name)
 
-/*
-** Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
-**
-** Permission to use, copy, modify, distribute, and sell this file for any
-** purpose is hereby granted without fee, provided that the above copyright
-** and this permission notice appear in all copies.  No representations are
-** made about the suitability of this software for any purpose.  It is
-** provided "as is" without express or implied warranty.
-*/
+/* ----------------------------------------------------------------------- */
 
-/* Version 1.1 */
-
-
-/*============================================================================
-**  On Intel Pentium processors (especially PIII and probably P4), converting
-**  from float to int is very slow. To meet the C specs, the code produced by
-**  most C compilers targeting Pentium needs to change the FPU rounding mode
-**  before the float to int conversion is performed.
-**
-**  Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
-**  is this flushing of the pipeline which is so slow.
-**
-**  Fortunately the ISO C99 specifications define the functions lrint, lrintf,
-**  llrint and llrintf which fix this problem as a side effect.
-**
-**  On Unix-like systems, the configure process should have detected the
-**  presence of these functions. If they weren't found we have to replace them
-**  here with a standard C cast.
-*/
+#define COMMA ,
 
-/*
-**	The C99 prototypes for lrint and lrintf are as follows:
-**
-**		long int lrintf (float x);
-**		long int lrint  (double x);
-*/
+#include <limits.h>
+#include <stddef.h>
 
-#if defined(__LCC__) || (defined(__GNUC__) && defined(WIN32))
-/* Linux' GCC does not seem to have these. Why? */
-#  define HAVE_LRINT
-#  define HAVE_LRINTF
+// define NIM_STATIC_ASSERT
+// example use case: CT sizeof for importc types verification
+// where we have {.completeStruct.} (or lack of {.incompleteStruct.})
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
+#define NIM_STATIC_ASSERT(x, msg) _Static_assert((x), msg)
+#elif defined(__cplusplus)
+#define NIM_STATIC_ASSERT(x, msg) static_assert((x), msg)
+#else
+#define _NIM_STATIC_ASSERT_FINAL(x, append_name) typedef int NIM_STATIC_ASSERT_AUX ## append_name[(x) ? 1 : -1];
+#define _NIM_STATIC_ASSERT_STAGE_3(x, line)      _NIM_STATIC_ASSERT_FINAL(x, _AT_LINE_##line)
+#define _NIM_STATIC_ASSERT_STAGE_2(x, line)      _NIM_STATIC_ASSERT_STAGE_3(x, line)
+#define NIM_STATIC_ASSERT(x, msg)                _NIM_STATIC_ASSERT_STAGE_2(x,__LINE__)
+// On failure, your C compiler will say something like:
+//   "error: 'NIM_STATIC_ASSERT_AUX_AT_LINE_XXX' declared as an array with a negative size"
+// Adding the line number helps to avoid redefinitions which are not allowed in
+// old GCC versions, however the order of evaluation for __LINE__ is a little tricky,
+// hence all the helper macros. See https://stackoverflow.com/a/3385694 for more info.
 #endif
 
-#if defined(HAVE_LRINT) && defined(HAVE_LRINTF)
-
-/*  These defines enable functionality introduced with the 1999 ISO C
-**  standard. They must be defined before the inclusion of math.h to
-**  engage them. If optimisation is enabled, these functions will be
-**  inlined. With optimisation switched off, you have to link in the
-**  maths library using -lm.
-*/
-
-#  define  _ISOC9X_SOURCE  1
-#  define  _ISOC99_SOURCE  1
-#  define  __USE_ISOC9X  1
-#  define  __USE_ISOC99  1
+/* C99 compiler? */
+#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901))
+#  define HAVE_STDINT_H
+#endif
 
-#elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
-   && !defined(__BORLANDC__) && !defined(__POCC__)
+/* Known compiler with stdint.h that doesn't fit the general pattern? */
+#if defined(__AVR__) || (defined(__cplusplus) && (__cplusplus < 201103))
+#  define HAVE_STDINT_H
+#endif
 
-/*  Win32 doesn't seem to have these functions.
-**  Therefore implement inline versions of these functions here.
-*/
-static N_INLINE(long int, lrint)(double flt) {
-  long int intgr;
-  _asm {
-    fld flt
-    fistp intgr
-  };
-  return intgr;
-}
+#if (!defined(HAVE_STDINT_H) && defined(__cplusplus) && (__cplusplus >= 201103))
+#  define HAVE_CSTDINT
+#endif
 
-static N_INLINE(long int, lrintf)(float flt) {
-  long int intgr;
-  _asm {
-    fld flt
-    fistp intgr
-  };
-  return intgr;
-}
 
+/* wrap all Nim typedefs into namespace Nim */
+#ifdef USE_NIM_NAMESPACE
+#ifdef HAVE_CSTDINT
+#include <cstdint>
 #else
-
-#  ifndef lrint
-#    define  lrint(dbl)   ((long int)(dbl))
-#  endif
-#  ifndef lrintf
-#    define  lrintf(flt)  ((long int)(flt))
-#  endif
-
-#endif /* defined(HAVE_LRINT) && defined(HAVE_LRINTF) */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <limits.h>
-#include <stddef.h>
-#include <signal.h>
-#include <setjmp.h>
-
-/*
-#ifndef INF
-static unsigned long nimInf[2]={0xffffffff, 0x7fffffff};
-#  define INF (*(double*) nimInf)
-#endif */
-
-/* C99 compiler? */
-#if (defined(__STD_VERSION__) && (__STD_VERSION__ >= 199901))
-#  define HAVE_STDINT_H
+#include <stdint.h>
+#endif
+namespace USE_NIM_NAMESPACE {
 #endif
 
-#if defined(__LCC__) || defined(__DMC__) || defined(__POCC__)
-#  define HAVE_STDINT_H
+// preexisting check, seems paranoid, maybe remove
+#if defined(NIM_TRUE) || defined(NIM_FALSE) || defined(NIM_BOOL)
+#error "nim reserved preprocessor macros clash"
 #endif
 
 /* bool types (C++ has it): */
 #ifdef __cplusplus
-#  ifndef NIM_TRUE
-#    define NIM_TRUE true
-#  endif
-#  ifndef NIM_FALSE
-#    define NIM_FALSE false
-#  endif
-#  define NIM_BOOL bool
+#define NIM_BOOL bool
+#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901)
+// see #13798: to avoid conflicts for code emitting `#include <stdbool.h>`
+#define NIM_BOOL _Bool
 #else
-#  ifdef bool
-#    define NIM_BOOL bool
-#  else
-  typedef unsigned char NIM_BOOL;
-#  endif
-#  ifndef NIM_TRUE
-#    define NIM_TRUE ((NIM_BOOL) 1)
-#  endif
-#  ifndef NIM_FALSE
-#    define NIM_FALSE ((NIM_BOOL) 0)
-#  endif
+typedef unsigned char NIM_BOOL; // best effort
 #endif
 
-#define NIM_NIL ((void*)0) /* C's NULL is fucked up in some C compilers, so
+NIM_STATIC_ASSERT(sizeof(NIM_BOOL) == 1, ""); // check whether really needed
+NIM_STATIC_ASSERT(CHAR_BIT == 8, "");
+  // fail fast for (rare) environments where this doesn't hold, as some implicit
+  // assumptions would need revisiting (e.g. `uint8` or https://github.com/nim-lang/Nim/pull/18505)
+
+#define NIM_TRUE true
+#define NIM_FALSE false
+
+#ifdef __cplusplus
+#  if __cplusplus >= 201103L
+#    /* nullptr is more type safe (less implicit conversions than 0) */
+#    define NIM_NIL nullptr
+#  else
+#    // both `((void*)0)` and `NULL` would cause codegen to emit
+#    // error: assigning to 'Foo *' from incompatible type 'void *'
+#    // but codegen could be fixed if need. See also potential caveat regarding
+#    // NULL.
+#    // However, `0` causes other issues, see #13798
+#    define NIM_NIL 0
+#  endif
+#else
+#  include <stdbool.h>
+#  define NIM_NIL ((void*)0) /* C's NULL is fucked up in some C compilers, so
                               the generated code does not rely on it anymore */
+#endif
 
-#if defined(__BORLANDC__) || defined(__DMC__) \
-   || defined(__WATCOMC__) || defined(_MSC_VER)
+#if defined(__BORLANDC__) || defined(_MSC_VER)
 typedef signed char NI8;
 typedef signed short int NI16;
 typedef signed int NI32;
+typedef __int64 NI64;
 /* XXX: Float128? */
 typedef unsigned char NU8;
 typedef unsigned short int NU16;
-typedef unsigned __int64 NU64;
-typedef __int64 NI64;
 typedef unsigned int NU32;
+typedef unsigned __int64 NU64;
 #elif defined(HAVE_STDINT_H)
+#ifndef USE_NIM_NAMESPACE
 #  include <stdint.h>
+#endif
 typedef int8_t NI8;
 typedef int16_t NI16;
 typedef int32_t NI32;
 typedef int64_t NI64;
-typedef uint64_t NU64;
 typedef uint8_t NU8;
 typedef uint16_t NU16;
 typedef uint32_t NU32;
+typedef uint64_t NU64;
+#elif defined(HAVE_CSTDINT)
+#ifndef USE_NIM_NAMESPACE
+#  include <cstdint>
+#endif
+typedef std::int8_t NI8;
+typedef std::int16_t NI16;
+typedef std::int32_t NI32;
+typedef std::int64_t NI64;
+typedef std::uint8_t NU8;
+typedef std::uint16_t NU16;
+typedef std::uint32_t NU32;
+typedef std::uint64_t NU64;
+#else
+/* Unknown compiler/version, do our best */
+#ifdef __INT8_TYPE__
+typedef __INT8_TYPE__ NI8;
 #else
 typedef signed char NI8;
+#endif
+#ifdef __INT16_TYPE__
+typedef __INT16_TYPE__ NI16;
+#else
 typedef signed short int NI16;
+#endif
+#ifdef __INT32_TYPE__
+typedef __INT32_TYPE__ NI32;
+#else
 typedef signed int NI32;
+#endif
+#ifdef __INT64_TYPE__
+typedef __INT64_TYPE__ NI64;
+#else
+typedef long long int NI64;
+#endif
 /* XXX: Float128? */
+#ifdef __UINT8_TYPE__
+typedef __UINT8_TYPE__ NU8;
+#else
 typedef unsigned char NU8;
+#endif
+#ifdef __UINT16_TYPE__
+typedef __UINT16_TYPE__ NU16;
+#else
 typedef unsigned short int NU16;
-typedef unsigned long long int NU64;
-typedef long long int NI64;
+#endif
+#ifdef __UINT32_TYPE__
+typedef __UINT32_TYPE__ NU32;
+#else
 typedef unsigned int NU32;
 #endif
+#ifdef __UINT64_TYPE__
+typedef __UINT64_TYPE__ NU64;
+#else
+typedef unsigned long long int NU64;
+#endif
+#endif
+
+#ifdef NIM_INTBITS
+#  if NIM_INTBITS == 64
+typedef NI64 NI;
+typedef NU64 NU;
+#  elif NIM_INTBITS == 32
+typedef NI32 NI;
+typedef NU32 NU;
+#  elif NIM_INTBITS == 16
+typedef NI16 NI;
+typedef NU16 NU;
+#  elif NIM_INTBITS == 8
+typedef NI8 NI;
+typedef NU8 NU;
+#  else
+#    error "invalid bit width for int"
+#  endif
+#endif
+
+// for now there isn't an easy way for C code to reach the program result
+// when hot code reloading is ON - users will have to:
+// load the nimhcr.dll, get the hcrGetGlobal proc from there and use it
+#ifndef NIM_HOT_CODE_RELOADING
+extern NI nim_program_result;
+#endif
 
 typedef float NF32;
 typedef double NF64;
@@ -334,31 +467,18 @@ typedef char* NCSTRING;
 #  define NIM_IMAN 0
 #endif
 
-static N_INLINE(NI32, float64ToInt32)(double val) {
-  val = val + 68719476736.0*1.5;
-  /* 2^36 * 1.5,  (52-_shiftamt=36) uses limited precisicion to floor */
-  return ((NI32*)&val)[NIM_IMAN] >> 16; /* 16.16 fixed point representation */
-}
-
-static N_INLINE(NI32, float32ToInt32)(float val) {
-  return float64ToInt32((double)val);
-}
-
-#define float64ToInt64(x) ((NI64) (x))
-
-#define zeroMem(a, size) memset(a, 0, size)
-#define equalMem(a, b, size) (memcmp(a, b, size) == 0)
+#define NIM_STRLIT_FLAG ((NU)(1) << ((NIM_INTBITS) - 2)) /* This has to be the same as system.strlitFlag! */
 
 #define STRING_LITERAL(name, str, length) \
-  static const struct {                   \
-    TGenericSeq Sup;                      \
-    NIM_CHAR data[length + 1];            \
-  } name = {{length, length}, str}
-
-typedef struct TStringDesc* string;
-
-/* declared size of a sequence: */
-#if defined(__GNUC__)
+   static const struct {                   \
+     TGenericSeq Sup;                      \
+     NIM_CHAR data[(length) + 1];          \
+  } name = {{length, (NI) ((NU)length | NIM_STRLIT_FLAG)}, str}
+
+/* declared size of a sequence/variable length array: */
+#if defined(__cplusplus) && defined(__clang__)
+#  define SEQ_DECL_SIZE 1
+#elif defined(__GNUC__) || defined(_MSC_VER)
 #  define SEQ_DECL_SIZE /* empty is correct! */
 #else
 #  define SEQ_DECL_SIZE 1000000
@@ -367,18 +487,15 @@ typedef struct TStringDesc* string;
 #define ALLOC_0(size)  calloc(1, size)
 #define DL_ALLOC_0(size) dlcalloc(1, size)
 
-#define GenericSeqSize sizeof(TGenericSeq)
 #define paramCount() cmdCount
 
-#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__i386__)
-#  ifndef NAN
-static unsigned long nimNaN[2]={0xffffffff, 0x7fffffff};
-#    define NAN (*(double*) nimNaN)
-#  endif
-#endif
-
+// NAN definition copied from math.h included in the Windows SDK version 10.0.14393.0
 #ifndef NAN
-#  define NAN (0.0 / 0.0)
+#  ifndef _HUGE_ENUF
+#    define _HUGE_ENUF  1e+300  // _HUGE_ENUF*_HUGE_ENUF must overflow
+#  endif
+#  define NAN_INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
+#  define NAN ((float)(NAN_INFINITY * 0.0F))
 #endif
 
 #ifndef INF
@@ -386,42 +503,107 @@ static unsigned long nimNaN[2]={0xffffffff, 0x7fffffff};
 #    define INF INFINITY
 #  elif defined(HUGE_VAL)
 #    define INF  HUGE_VAL
+#  elif defined(_MSC_VER)
+#    include <float.h>
+#    define INF (DBL_MAX+DBL_MAX)
 #  else
 #    define INF (1.0 / 0.0)
 #  endif
 #endif
-/*
-typedef struct TSafePoint TSafePoint;
-struct TSafePoint {
-  NI exc;
-  NCSTRING excname;
-  NCSTRING msg;
-  TSafePoint* prev;
-  jmp_buf context;
-}; */
-
-typedef struct TFrame TFrame;
-struct TFrame {
+
+typedef struct TFrame_ TFrame;
+struct TFrame_ {
   TFrame* prev;
   NCSTRING procname;
   NI line;
   NCSTRING filename;
-  NI len;
+  NI16 len;
+  NI16 calldepth;
+  NI frameMsgLen;
 };
 
-extern TFrame* framePtr;
-/*extern TSafePoint* excHandler; */
+#define NIM_POSIX_INIT  __attribute__((constructor))
 
-#if defined(__cplusplus)
-struct NimException {
-  TSafePoint sp;
-
-  NimException(NI aExc, NCSTRING aExcname, NCSTRING aMsg) {
-    sp.exc = aExc; sp.excname = aExcname; sp.msg = aMsg;
-    sp.prev = excHandler;
-    excHandler = &sp;
-  }
-};
+#ifdef __GNUC__
+#  define NIM_LIKELY(x) __builtin_expect(x, 1)
+#  define NIM_UNLIKELY(x) __builtin_expect(x, 0)
+/* We need the following for the posix wrapper. In particular it will give us
+   POSIX_SPAWN_USEVFORK: */
+#  ifndef _GNU_SOURCE
+#    define _GNU_SOURCE
+#  endif
+#else
+#  define NIM_LIKELY(x) (x)
+#  define NIM_UNLIKELY(x) (x)
+#endif
+
+#if 0 // defined(__GNUC__) || defined(__clang__)
+// not needed anymore because the stack marking cares about
+// interior pointers now
+static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); }
+#  define GC_GUARD __attribute__ ((cleanup(GCGuard)))
+#else
+#  define GC_GUARD
+#endif
+
+// Test to see if Nim and the C compiler agree on the size of a pointer.
+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.");
+
+#ifdef USE_NIM_NAMESPACE
+}
+#endif
+
+#if defined(_MSC_VER)
+#  define NIM_ALIGN(x)  __declspec(align(x))
+#  define NIM_ALIGNOF(x) __alignof(x)
+#else
+#  define NIM_ALIGN(x)  __attribute__((aligned(x)))
+#  define NIM_ALIGNOF(x) __alignof__(x)
 #endif
 
+/* ---------------- platform specific includes ----------------------- */
+
+/* VxWorks related includes */
+#if defined(__VXWORKS__)
+#  include <sys/types.h>
+#  include <types/vxWind.h>
+#  include <tool/gnu/toolMacros.h>
+#elif defined(__FreeBSD__)
+#  include <sys/types.h>
+#endif
+
+/* these exist to make the codegen logic simpler */
+#define nimModInt(a, b, res) (((*res) = (a) % (b)), 0)
+#define nimModInt64(a, b, res) (((*res) = (a) % (b)), 0)
+
+#if (!defined(_MSC_VER) || defined(__clang__)) && !defined(NIM_EmulateOverflowChecks)
+  /* these exist because we cannot have .compilerProcs that are importc'ed
+    by a different name */
+
+  #define nimAddInt64(a, b, res) __builtin_saddll_overflow(a, b, (long long int*)res)
+  #define nimSubInt64(a, b, res) __builtin_ssubll_overflow(a, b, (long long int*)res)
+  #define nimMulInt64(a, b, res) __builtin_smulll_overflow(a, b, (long long int*)res)
+
+  #if NIM_INTBITS == 32
+    #if defined(__arm__) && defined(__GNUC__)
+      /* arm-none-eabi-gcc targets defines int32_t as long int */
+      #define nimAddInt(a, b, res) __builtin_saddl_overflow(a, b, res)
+      #define nimSubInt(a, b, res) __builtin_ssubl_overflow(a, b, res)
+      #define nimMulInt(a, b, res) __builtin_smull_overflow(a, b, res)
+    #else
+      #define nimAddInt(a, b, res) __builtin_sadd_overflow(a, b, res)
+      #define nimSubInt(a, b, res) __builtin_ssub_overflow(a, b, res)
+      #define nimMulInt(a, b, res) __builtin_smul_overflow(a, b, res)
+    #endif
+  #else
+    /* map it to the 'long long' variant */
+    #define nimAddInt(a, b, res) __builtin_saddll_overflow(a, b, (long long int*)res)
+    #define nimSubInt(a, b, res) __builtin_ssubll_overflow(a, b, (long long int*)res)
+    #define nimMulInt(a, b, res) __builtin_smulll_overflow(a, b, (long long int*)res)
+  #endif
 #endif
+
+#define NIM_NOALIAS __restrict
+/* __restrict is said to work for all the C(++) compilers out there that we support */
+
+#endif /* NIMBASE_H */