diff options
Diffstat (limited to 'lib/nimbase.h')
-rw-r--r-- | lib/nimbase.h | 102 |
1 files changed, 60 insertions, 42 deletions
diff --git a/lib/nimbase.h b/lib/nimbase.h index e43492b76..cf0c8002b 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -10,14 +10,12 @@ /* compiler symbols: __BORLANDC__ _MSC_VER -__WATCOMC__ -__LCC__ __GNUC__ -__DMC__ -__POCC__ __TINYC__ __clang__ __AVR__ +__arm__ +__EMSCRIPTEN__ */ @@ -75,7 +73,8 @@ __AVR__ #endif /* ------------------------------------------------------------------------- */ -#if defined(__GNUC__) +#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 @@ -88,11 +87,8 @@ __AVR__ #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 @@ -100,21 +96,13 @@ __AVR__ 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 #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 @@ -124,12 +112,17 @@ __AVR__ NIM_THREADVAR declaration based on http://stackoverflow.com/questions/18298280/how-to-declare-a-variable-as-thread-local-portably */ -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__ +#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 __DMC__ || \ defined __BORLANDC__ ) # define NIM_THREADVAR __declspec(thread) #elif defined(__TINYC__) || defined(__GENODE__) @@ -143,9 +136,12 @@ __AVR__ # 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__) || defined(_MSC_VER) +#if defined(__GNUC__) || defined(_MSC_VER) # define IL64(x) x##LL #else /* works only without LL */ # define IL64(x) ((NI64)x) @@ -183,12 +179,13 @@ __AVR__ # define N_THISCALL_PTR(rettype, name) rettype (__thiscall *name) # define N_SAFECALL_PTR(rettype, name) rettype (__stdcall *name) -# ifdef __cplusplus -# define N_LIB_EXPORT NIM_EXTERNC __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_EXPORT_VAR __declspec(dllexport) # define N_LIB_IMPORT extern __declspec(dllimport) #else # define N_LIB_PRIVATE __attribute__((visibility("hidden"))) @@ -217,8 +214,13 @@ __AVR__ # define N_FASTCALL_PTR(rettype, name) rettype (*name) # define N_SAFECALL_PTR(rettype, name) rettype (*name) # endif -# define N_LIB_EXPORT NIM_EXTERNC __attribute__((visibility("default"))) -# define N_LIB_EXPORT_VAR __attribute__((visibility("default"))) +# 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 @@ -236,8 +238,7 @@ __AVR__ #define N_NOINLINE_PTR(rettype, name) rettype (*name) -#if defined(__BORLANDC__) || defined(__WATCOMC__) || \ - defined(__POCC__) || defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) +#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) /* these compilers have a fastcall so use it: */ # ifdef __TINYC__ # define N_NIMCALL(rettype, name) rettype __attribute((__fastcall)) name @@ -272,11 +273,15 @@ __AVR__ #elif defined(__cplusplus) #define NIM_STATIC_ASSERT(x, msg) static_assert((x), msg) #else -#define NIM_STATIC_ASSERT(x, msg) typedef int NIM_STATIC_ASSERT_AUX[(x) ? 1 : -1]; +#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' declared as an array with a negative size" -// we could use a better fallback to also show line number, using: -// http://www.pixelbeat.org/programming/gcc/static_assert.html +// "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 /* C99 compiler? */ @@ -285,8 +290,7 @@ __AVR__ #endif /* Known compiler with stdint.h that doesn't fit the general pattern? */ -#if defined(__LCC__) || defined(__DMC__) || defined(__POCC__) || \ - defined(__AVR__) || (defined(__cplusplus) && (__cplusplus < 201103)) +#if defined(__AVR__) || (defined(__cplusplus) && (__cplusplus < 201103)) # define HAVE_STDINT_H #endif @@ -321,6 +325,9 @@ typedef unsigned char NIM_BOOL; // best effort #endif 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 @@ -343,8 +350,7 @@ NIM_STATIC_ASSERT(sizeof(NIM_BOOL) == 1, ""); // check whether really needed 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; @@ -470,7 +476,9 @@ typedef char* NCSTRING; } name = {{length, (NI) ((NU)length | NIM_STRLIT_FLAG)}, str} /* declared size of a sequence/variable length array: */ -#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) +#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 @@ -539,7 +547,7 @@ static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); } #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, ""); +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 } @@ -577,9 +585,16 @@ NIM_STATIC_ASSERT(sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8, "" #define nimMulInt64(a, b, res) __builtin_smulll_overflow(a, b, (long long int*)res) #if NIM_INTBITS == 32 - #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) + #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) @@ -588,4 +603,7 @@ NIM_STATIC_ASSERT(sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8, "" #endif #endif +#define NIM_NOALIAS __restrict +/* __restrict is said to work for all the C(++) compilers out there that we support */ + #endif /* NIMBASE_H */ |