module compiler const ( c_common_macros = ' #define EMPTY_STRUCT_DECLARATION #define EMPTY_STRUCT_INITIALIZATION 0 // Due to a tcc bug, the length of an array needs to be specified, but GCC crashes if it is... #define EMPTY_ARRAY_OF_ELEMS(x,n) (x[]) #define TCCSKIP(x) x #ifdef __TINYC__ #undef EMPTY_STRUCT_DECLARATION #undef EMPTY_STRUCT_INITIALIZATION #define EMPTY_STRUCT_DECLARATION char _dummy #define EMPTY_STRUCT_INITIALIZATION 0 #undef EMPTY_ARRAY_OF_ELEMS #define EMPTY_ARRAY_OF_ELEMS(x,n) (x[n]) #undef TCCSKIP #define TCCSKIP(x) #endif // for __offset_of #ifndef __offsetof #define __offsetof(s,memb) \\ ((size_t)((char *)&((s *)0)->memb - (char *)0)) #endif #define OPTION_CAST(x) (x) ' c_headers = ' //#include // int64_t etc #include // TODO remove all these includes, define all function signatures and types manually #include //#include "fns.h" #include #include // for va_list #include // memcpy #if INTPTR_MAX == INT32_MAX #define TARGET_IS_32BIT 1 #elif INTPTR_MAX == INT64_MAX #define TARGET_IS_64BIT 1 #else #error "The environment is not 32 or 64-bit." #endif #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || defined(__BIG_ENDIAN__) || defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__) #define TARGET_ORDER_IS_BIG #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) #define TARGET_ORDER_IS_LITTLE #else #error "Unknown architecture endianness" #endif #ifndef _WIN32 #include #include // tolower #include #include // sleep #endif #if defined(__CYGWIN__) && !defined(_WIN32) #error Cygwin is not supported, please use MinGW or Visual Studio. #endif #ifdef __linux__ #include #include // os__wait uses wait on nix #endif #ifdef __FreeBSD__ #include #include // os__wait uses wait on nix #endif #ifdef __DragonFly__ #include #include // os__wait uses wait on nix #endif #ifdef __OpenBSD__ #include #include #include // os__wait uses wait on nix #endif #ifdef __NetBSD__ #include // os__wait uses wait on nix #endif $c_common_macros #ifdef _WIN32 #define WINVER 0x0600 #ifdef _WIN32_WINNT #undef _WIN32_WINNT #endif #define _WIN32_WINNT 0x0600 #define WIN32_LEAN_AND_MEAN #define _UNICODE #define UNICODE #include #include // _waccess #include // _wgetcwd //#include #ifdef _MSC_VER // On MSVC these are the same (as long as /volatile:ms is passed) #define _Atomic volatile // MSVC cannot parse some things properly #undef EMPTY_STRUCT_DECLARATION #undef OPTION_CAST #define EMPTY_STRUCT_DECLARATION int ____dummy_variable #define OPTION_CAST(x) #include #pragma comment(lib, "Dbghelp.lib") #endif #else #include #endif //============================== HELPER C MACROS =============================*/ #define _PUSH(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); array_push(arr, &tmp);} #define _PUSH_MANY(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); array_push_many(arr, tmp.data, tmp.len);} #define _IN(typ, val, arr) array_##typ##_contains(arr, val) #define _IN_MAP(val, m) map_exists(m, val) #define DEFAULT_EQUAL(a, b) (a == b) #define DEFAULT_NOT_EQUAL(a, b) (a != b) #define DEFAULT_LT(a, b) (a < b) #define DEFAULT_LE(a, b) (a <= b) #define DEFAULT_GT(a, b) (a > b) #define DEFAULT_GE(a, b) (a >= b) // NB: macro_fXX_eq and macro_fXX_ne are NOT used // in the generated C code. They are here just for // completeness/testing. #define macro_f64_eq(a, b) (a == b) #define macro_f64_ne(a, b) (a != b) #define macro_f64_lt(a, b) (a < b) #define macro_f64_le(a, b) (a <= b) #define macro_f64_gt(a, b) (a > b) #define macro_f64_ge(a, b) (a >= b) #define macro_f32_eq(a, b) (a == b) #define macro_f32_ne(a, b) (a != b) #define macro_f32_lt(a, b) (a < b) #define macro_f32_le(a, b) (a <= b) #define macro_f32_gt(a, b) (a > b) #define macro_f32_ge(a, b) (a >= b) //================================== GLOBALS =================================*/ byte g_str_buf[1024]; int load_so(byteptr); void reload_so(); // ============== wyhash ============== // Author: Wang Yi #ifndef wyhash_version_4 #define wyhash_version_4 #include #include #if defined(_MSC_VER) && defined(_M_X64) #include #pragma intrinsic(_umul128) #endif const uint64_t _wyp0=0xa0761d6478bd642full, _wyp1=0xe7037ed1a0b428dbull, _wyp2=0x8ebc6af09c88c6e3ull, _wyp3=0x589965cc75374cc3ull, _wyp4=0x1d8e4e27c47d124full; static inline uint64_t _wyrotr(uint64_t v, unsigned k) { return (v>>k)|(v<<(64-k)); } static inline uint64_t _wymum(uint64_t A, uint64_t B) { #ifdef WYHASH32 uint64_t hh=(A>>32)*(B>>32), hl=(A>>32)*(unsigned)B, lh=(unsigned)A*(B>>32), ll=(uint64_t)(unsigned)A*(unsigned)B; return _wyrotr(hl,32)^_wyrotr(lh,32)^hh^ll; #else #ifdef __SIZEOF_INT128__ __uint128_t r=A; r*=B; return (r>>64)^r; #elif defined(_MSC_VER) && defined(_M_X64) A=_umul128(A, B, &B); return A^B; #else uint64_t ha=A>>32, hb=B>>32, la=(uint32_t)A, lb=(uint32_t)B, hi, lo; uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t>32)+(rm1>>32)+c; return hi^lo; #endif #endif } #ifndef WYHASH_LITTLE_ENDIAN #if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) #define WYHASH_LITTLE_ENDIAN 1 #elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) #define WYHASH_LITTLE_ENDIAN 0 #endif #endif #if(WYHASH_LITTLE_ENDIAN) || defined(__TINYC__) static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return v; } static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return v; } #else #if defined(__GNUC__) || defined(__INTEL_COMPILER) static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return __builtin_bswap64(v); } static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return __builtin_bswap32(v); } #elif defined(_MSC_VER) static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return _byteswap_uint64(v);} static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return _byteswap_ulong(v); } #endif #endif static inline uint64_t _wyr3(const uint8_t *p, unsigned k) { return (((uint64_t)p[0])<<16)|(((uint64_t)p[k>>1])<<8)|p[k-1]; } static inline uint64_t wyhash(const void* key, uint64_t len, uint64_t seed) { const uint8_t *p=(const uint8_t*)key; uint64_t i=len&63; #if defined(__GNUC__) || defined(__INTEL_COMPILER) #define _like_(x) __builtin_expect(x,1) #define _unlike_(x) __builtin_expect(x,0) #else #define _like_(x) (x) #define _unlike_(x) (x) #endif if(_unlike_(!i)) { } else if(_unlike_(i<4)) seed=_wymum(_wyr3(p,i)^seed^_wyp0,seed^_wyp1); else if(_like_(i<=8)) seed=_wymum(_wyr4(p)^seed^_wyp0,_wyr4(p+i-4)^seed^_wyp1); else if(_like_(i<=16)) seed=_wymum(_wyr8(p)^seed^_wyp0,_wyr8(p+i-8)^seed^_wyp1); else if(_like_(i<=24)) seed=_wymum(_wyr8(p)^seed^_wyp0,_wyr8(p+8)^seed^_wyp1)^_wymum(_wyr8(p+i-8)^seed^_wyp2,seed^_wyp3); else if(_like_(i<=32)) seed=_wymum(_wyr8(p)^seed^_wyp0,_wyr8(p+8)^seed^_wyp1)^_wymum(_wyr8(p+16)^seed^_wyp2,_wyr8(p+i-8)^seed^_wyp3); else{ seed=_wymum(_wyr8(p)^seed^_wyp0,_wyr8(p+8)^seed^_wyp1)^_wymum(_wyr8(p+16)^seed^_wyp2,_wyr8(p+24)^seed^_wyp3)^_wymum(_wyr8(p+i-32)^seed^_wyp1,_wyr8(p+i-24)^seed^_wyp2)^_wymum(_wyr8(p+i-16)^seed^_wyp3,_wyr8(p+i-8)^seed^_wyp0); } if(_like_(i==len)) return _wymum(seed,len^_wyp4); uint64_t see1=seed, see2=seed, see3=seed; for(p+=i,i=len-i; _like_(i>=64); i-=64,p+=64) { seed=_wymum(_wyr8(p)^seed^_wyp0,_wyr8(p+8)^seed^_wyp1); see1=_wymum(_wyr8(p+16)^see1^_wyp2,_wyr8(p+24)^see1^_wyp3); see2=_wymum(_wyr8(p+32)^see2^_wyp1,_wyr8(p+40)^see2^_wyp2); see3=_wymum(_wyr8(p+48)^see3^_wyp3,_wyr8(p+56)^see3^_wyp0); } return _wymum(seed^see1^see2,see3^len^_wyp4); } static inline uint64_t wyhash64(uint64_t A, uint64_t B) { return _wymum(_wymum(A^_wyp0, B^_wyp1), _wyp2); } static inline uint64_t wyrand(uint64_t *seed) { *seed+=_wyp0; return _wymum(*seed^_wyp1,*seed); } static inline double wy2u01(uint64_t r) { const double _wynorm=1.0/(1ull<<52); return (r>>11)*_wynorm; } static inline double wy2gau(uint64_t r) { const double _wynorm=1.0/(1ull<<20); return ((r&0x1fffff)+((r>>21)&0x1fffff)+((r>>42)&0x1fffff))*_wynorm-3.0; } #endif ' js_headers = ' var array_string = function() {} var array_byte = function() {} var array_int = function() {} var byte = function() {} var double = function() {} var int = function() {} var f64 = function() {} var f32 = function() {} var i64 = function() {} var i32 = function() {} var i16 = function() {} var u64 = function() {} var u32 = function() {} var u16 = function() {} var i8 = function() {} var bool = function() {} var rune = function() {} var map_string = function() {} var map_int = function() {} ' c_builtin_types = ' //#include // int64_t etc //#include // int64_t etc //================================== TYPEDEFS ================================*/ typedef int64_t i64; typedef int16_t i16; typedef int8_t i8; typedef uint64_t u64; typedef uint32_t u32; typedef uint16_t u16; typedef uint8_t byte; typedef uint32_t rune; typedef float f32; typedef double f64; typedef unsigned char* byteptr; typedef int* intptr; typedef void* voidptr; typedef char* charptr; typedef struct array array; typedef struct map map; typedef array array_string; typedef array array_int; typedef array array_byte; typedef array array_f32; typedef array array_f64; typedef array array_u16; typedef array array_u32; typedef array array_u64; typedef map map_int; typedef map map_string; #ifndef bool typedef int bool; #define true 1 #define false 0 #endif ' bare_c_headers = ' $c_common_macros #ifndef exit #define exit(rc) sys_exit(rc) void sys_exit (int); #endif ' )