v2 / vlib / v / gen / c / cheaders.v
1196 lines · 1175 sloc · 40.76 KB · dc78362355deb62d094f8ad1e36b7de038701fbc
Raw
1module c
2
3import v.ast
4
5// Note: @@@ here serve as placeholders.
6// They will be replaced with correct strings
7// for each constant, during C code generation.
8
9// V_COMMIT_HASH is generated by cmd/tools/gen_vc.v .
10const c_commit_hash_default = '
11#ifndef V_COMMIT_HASH
12 #define V_COMMIT_HASH "@@@"
13#endif
14'
15
16const c_concurrency_helpers = '
17typedef struct __shared_map __shared_map;
18struct __shared_map {
19 sync__RwMutex mtx;
20 map val;
21};
22static inline voidptr __dup_shared_map(voidptr src, ${ast.int_type_name} sz) {
23 __shared_map* dest = builtin__memdup(src, sz);
24 sync__RwMutex_init(&dest->mtx);
25 return dest;
26}
27typedef struct __shared_array __shared_array;
28struct __shared_array {
29 sync__RwMutex mtx;
30 array val;
31};
32static inline voidptr __dup_shared_array(voidptr src, ${ast.int_type_name} sz) {
33 __shared_array* dest = builtin__memdup(src, sz);
34 sync__RwMutex_init(&dest->mtx);
35 return dest;
36}
37static inline void __sort_ptr(uintptr_t a[], bool b[], ${ast.int_type_name} l) {
38 for (${ast.int_type_name} i=1; i<l; i++) {
39 uintptr_t ins = a[i];
40 bool insb = b[i];
41 ${ast.int_type_name} j = i;
42 while(j>0 && a[j-1] > ins) {
43 a[j] = a[j-1];
44 b[j] = b[j-1];
45 j--;
46 }
47 a[j] = ins;
48 b[j] = insb;
49 }
50}
51'
52
53const c_common_macros = '
54#define E_STRUCT_DECL
55#define E_STRUCT
56#define __NOINLINE __attribute__((noinline))
57#define __IRQHANDLER __attribute__((interrupt))
58#define __V_architecture 0
59#if defined(__x86_64__) || defined(_M_AMD64)
60 #define __V_amd64 1
61 #undef __V_architecture
62 #define __V_architecture 1
63#endif
64#if defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64)
65 #define __V_arm64 1
66 #undef __V_architecture
67 #define __V_architecture 2
68#endif
69#if defined(__arm__) || defined(_M_ARM)
70 #define __V_arm32 1
71 #undef __V_architecture
72 #define __V_architecture 3
73#endif
74#if defined(__riscv) && __riscv_xlen == 64
75 #define __V_rv64 1
76 #undef __V_architecture
77 #define __V_architecture 4
78#endif
79#if defined(__riscv) && __riscv_xlen == 32
80 #define __V_rv32 1
81 #undef __V_architecture
82 #define __V_architecture 5
83#endif
84#if defined(__i386__) || defined(_M_IX86)
85 #define __V_x86 1
86 #undef __V_architecture
87 #define __V_architecture 6
88#endif
89#if defined(__s390x__)
90 #define __V_s390x 1
91 #undef __V_architecture
92 #define __V_architecture 7
93#endif
94#if defined(__powerpc64__) && defined(__LITTLE_ENDIAN__)
95 #define __V_ppc64le 1
96 #undef __V_architecture
97 #define __V_architecture 8
98#endif
99#if defined(__loongarch64)
100 #define __V_loongarch64 1
101 #undef __V_architecture
102 #define __V_architecture 9
103#endif
104#if defined(__sparc__)
105 #define __V_sparc64 1
106 #undef __V_architecture
107 #define __V_architecture 10
108#endif
109#if defined(__powerpc64__) && defined(__BIG_ENDIAN__)
110 #define __V_ppc64 1
111 #undef __V_architecture
112 #define __V_architecture 11
113#endif
114#if (defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) || defined(__ppc__) || defined(__ppc) || defined(__PPC__)) && !defined(__powerpc64__) && !defined(__ppc64__) && !defined(__PPC64__)
115 #define __V_ppc 1
116 #undef __V_architecture
117 #define __V_architecture 12
118#endif
119// Using just __GNUC__ for detecting gcc, is not reliable because other compilers define it too:
120#ifdef __GNUC__
121 #define __V_GCC__
122#endif
123#ifdef __TINYC__
124 #undef __V_GCC__
125#endif
126#ifdef __cplusplus
127 #undef __V_GCC__
128#endif
129#ifdef __clang__
130 #undef __V_GCC__
131#endif
132#ifdef _MSC_VER
133 #undef __V_GCC__
134 #undef E_STRUCT_DECL
135 #undef E_STRUCT
136 #define E_STRUCT_DECL unsigned char _dummy_pad
137 #define E_STRUCT 0
138#endif
139#if defined(__has_include) && !defined(__TINYC__)
140 #if __has_include(<execinfo.h>) && !defined(_WIN32)
141 #define __V_HAVE_EXECINFO_H 1
142 #include <execinfo.h>
143 #else
144 // On linux: int backtrace(void **__array, int __size);
145 // On BSD: size_t backtrace(void **, size_t);
146 #endif
147#elif (defined(__linux__) && (defined(__GLIBC__) || defined(__GNU_LIBRARY__))) || defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
148 #define __V_HAVE_EXECINFO_H 1
149 #include <execinfo.h>
150#else
151 // On linux: int backtrace(void **__array, int __size);
152 // On BSD: size_t backtrace(void **, size_t);
153#endif
154#ifndef __V_HAVE_EXECINFO_H
155 #ifdef __cplusplus
156 extern "C" {
157 #endif
158 int backtrace(void **__array, int __size);
159 char **backtrace_symbols(void *const *__array, int __size);
160 void backtrace_symbols_fd(void *const *__array, int __size, int __fd);
161 #ifdef __cplusplus
162 }
163 #endif
164#endif
165#ifdef __TINYC__
166 #define _Atomic volatile
167 #undef E_STRUCT_DECL
168 #undef E_STRUCT
169 #define E_STRUCT_DECL unsigned char _dummy_pad
170 #define E_STRUCT 0
171 #undef __NOINLINE
172 #undef __IRQHANDLER
173 // tcc does not support inlining at all
174 #define __NOINLINE
175 #define __IRQHANDLER
176 // #include <byteswap.h>
177 int tcc_backtrace(const char *fmt, ...);
178#endif
179// Use __offsetof_ptr instead of __offset_of, when you *do* have a valid pointer, to avoid UB:
180#ifndef __offsetof_ptr
181 #define __offsetof_ptr(ptr,PTYPE,FIELDNAME) ((size_t)((byte *)&((PTYPE *)ptr)->FIELDNAME - (byte *)ptr))
182#endif
183// for __offset_of
184#ifndef __offsetof
185#if defined(__TINYC__) || defined(_MSC_VER)
186 #define __offsetof(PTYPE,FIELDNAME) ((size_t)(&((PTYPE *)0)->FIELDNAME))
187#else
188 #define __offsetof(st, m) __builtin_offsetof(st, m)
189#endif
190#endif
191#if defined(_WIN32) || defined(__CYGWIN__)
192 #define VV_EXP extern __declspec(dllexport)
193 #ifdef _VPARALLELCC
194 #define VV_LOC
195 #else
196 #define VV_LOC static
197 #endif
198#else
199 // 4 < gcc < 5 is used by some older Ubuntu LTS and Centos versions,
200 // and does not support __has_attribute(visibility) ...
201 #ifndef __has_attribute
202 #define __has_attribute(x) 0 // Compatibility with non-clang compilers.
203 #endif
204 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || (defined(__clang__) && __has_attribute(visibility))
205 #ifdef ARM
206 #define VV_EXP extern __attribute__((externally_visible,visibility("default")))
207 #else
208 #define VV_EXP extern __attribute__((visibility("default")))
209 #endif
210 #if defined(_VOBJECTFILE) || (defined(__clang__) && (defined(_VUSECACHE) || defined(_VBUILDMODULE)))
211 #define VV_LOC static
212 #else
213 #define VV_LOC __attribute__ ((visibility ("hidden")))
214 #endif
215 #else
216 #define VV_EXP extern
217 #ifdef _VPARALLELCC
218 #define VV_LOC
219 #else
220 #define VV_LOC static
221 #endif
222 #endif
223#endif
224#ifdef __cplusplus
225 #include <utility>
226 #define _MOV std::move
227#else
228 #define _MOV
229#endif
230#if defined(__TINYC__) && defined(__has_include) // tcc does not support has_include properly yet, turn it off completely
231#undef __has_include
232#endif
233//likely and unlikely macros
234#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
235 #define _likely_(x) __builtin_expect(x,1)
236 #define _unlikely_(x) __builtin_expect(x,0)
237#else
238 #define _likely_(x) (x)
239 #define _unlikely_(x) (x)
240#endif
241'
242
243const c_common_weak_attr = '
244#if !defined(VWEAK)
245 #define VWEAK __attribute__((weak))
246 #ifdef _MSC_VER
247 #undef VWEAK
248 #define VWEAK
249 #endif
250 #if defined(__MINGW32__) || defined(__MINGW64__)
251 #undef VWEAK
252 #define VWEAK
253 #endif
254#endif
255'
256
257const c_common_hidden_attr = '
258#if !defined(VHIDDEN)
259 #define VHIDDEN __attribute__((visibility("hidden")))
260 #ifdef _MSC_VER
261 #undef VHIDDEN
262 #define VHIDDEN
263 #endif
264 #if defined(__MINGW32__) || defined(__MINGW64__)
265 #undef VHIDDEN
266 #define VHIDDEN
267 #endif
268#endif
269'
270
271const c_common_callconv_attr = '
272#if !defined(VCALLCONV)
273 #ifdef _MSC_VER
274 #define VCALLCONV(name) __##name
275 #else
276 #define VCALLCONV(name) __attribute__((name))
277 #endif
278#endif
279'
280
281const c_common_noreturn_attr = '
282#if !defined(VNORETURN)
283 #if defined(__TINYC__)
284 #define VNORETURN __attribute__((noreturn))
285 # elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
286 # define VNORETURN _Noreturn
287 # elif !defined(VNORETURN) && defined(__GNUC__) && __GNUC__ >= 2
288 # define VNORETURN __attribute__((noreturn))
289 # endif
290 #ifndef VNORETURN
291 #define VNORETURN
292 #endif
293#endif
294'
295
296const c_common_unreachable_attr = '
297#if !defined(VUNREACHABLE)
298 #if defined(__GNUC__) && !defined(__clang__)
299 #define V_GCC_VERSION (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__)
300 #if (V_GCC_VERSION >= 40500L) && !defined(__TINYC__)
301 #define VUNREACHABLE() do { __builtin_unreachable(); } while (0)
302 #endif
303 #endif
304 #if defined(__clang__) && defined(__has_builtin) && !defined(__TINYC__)
305 #if __has_builtin(__builtin_unreachable)
306 #define VUNREACHABLE() do { __builtin_unreachable(); } while (0)
307 #endif
308 #endif
309 #ifndef VUNREACHABLE
310 #define VUNREACHABLE() do { } while (0)
311 #endif
312#endif
313'
314
315const c_unsigned_comparison_functions = '
316// unsigned/signed comparisons
317static inline bool _us32_gt(uint32_t a, int32_t b) { return a > INT32_MAX || (int32_t)a > b; }
318static inline bool _us32_ge(uint32_t a, int32_t b) { return a >= INT32_MAX || (int32_t)a >= b; }
319static inline bool _us32_eq(uint32_t a, int32_t b) { return a <= INT32_MAX && (int32_t)a == b; }
320static inline bool _us32_ne(uint32_t a, int32_t b) { return a > INT32_MAX || (int32_t)a != b; }
321static inline bool _us32_le(uint32_t a, int32_t b) { return a <= INT32_MAX && (int32_t)a <= b; }
322static inline bool _us32_lt(uint32_t a, int32_t b) { return a < INT32_MAX && (int32_t)a < b; }
323static inline bool _us64_gt(uint64_t a, int64_t b) { return a > INT64_MAX || (int64_t)a > b; }
324static inline bool _us64_ge(uint64_t a, int64_t b) { return a >= INT64_MAX || (int64_t)a >= b; }
325static inline bool _us64_eq(uint64_t a, int64_t b) { return a <= INT64_MAX && (int64_t)a == b; }
326static inline bool _us64_ne(uint64_t a, int64_t b) { return a > INT64_MAX || (int64_t)a != b; }
327static inline bool _us64_le(uint64_t a, int64_t b) { return a <= INT64_MAX && (int64_t)a <= b; }
328static inline bool _us64_lt(uint64_t a, int64_t b) { return a < INT64_MAX && (int64_t)a < b; }
329'
330
331const c_float_to_unsigned_conversion_functions = '
332// deterministic float -> u64 conversions for explicit V casts
333// direct C casts are undefined for out-of-range values
334static inline uint64_t _v_f64_to_u64(double x) {
335 if (!(x >= 0.0)) {
336 return 0;
337 }
338 if (x >= 18446744073709551616.0) {
339 return UINT64_MAX;
340 }
341 return (uint64_t)x;
342}
343'
344
345const c_helper_macros = '//============================== HELPER C MACROS =============================*/
346// _SLIT0 is used as NULL string for literal arguments
347// `"" s` is used to enforce a string literal argument
348#define _SLIT0 (string){.str=(byteptr)(""), .len=0, .is_lit=1}
349#define _S(s) ((string){.str=(byteptr)("" s), .len=(sizeof(s)-1), .is_lit=1})
350#define _SLEN(s, n) ((string){.str=(byteptr)("" s), .len=n, .is_lit=1})
351// optimized way to compare literal strings
352#define _SLIT_EQ(sptr, slen, lit) (slen == sizeof("" lit)-1 && !builtin__vmemcmp(sptr, "" lit, slen))
353#define _SLIT_NE(sptr, slen, lit) (slen != sizeof("" lit)-1 || builtin__vmemcmp(sptr, "" lit, slen))
354// take the address of an rvalue
355#define ADDR(type, expr) (&((type[]){expr}[0]))
356// copy something to the heap
357#define HEAP(type, expr) ((type*)builtin__memdup((void*)&((type[]){expr}[0]), sizeof(type)))
358#define HEAP_noscan(type, expr) ((type*)builtin__memdup_noscan((void*)&((type[]){expr}[0]), sizeof(type)))
359#define HEAP_align(type, expr, align) ((type*)builtin__memdup_align((void*)&((type[]){expr}[0]), sizeof(type), align))
360#define HEAP_vgc(type, expr, ptrmap, nptrs) ((type*)builtin__vgc_memdup_typed((void*)&((type[]){expr}[0]), sizeof(type), (ptrmap), (nptrs)))
361#define _PUSH_MANY(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); builtin__array_push_many(arr, tmp.data, tmp.len);}
362#define _PUSH_MANY_noscan(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); builtin__array_push_many_noscan(arr, tmp.data, tmp.len);}
363'
364
365const c_windows_msvc_intsizeof_macro = '#ifndef _INTSIZEOF\n\t#define _INTSIZEOF(n) \\\n\t\t((sizeof(n) + \\\n\t\tsizeof(int) - 1) & \\\n\t\t~(sizeof(int) - 1))\n#endif\n'
366
367const c_windows_msvc_va_arg_macro = '#ifndef va_arg\n\t#define va_arg(ap, t) \\\n\t\t(*(t*)((ap += \\\n\t\t_INTSIZEOF(t)) - \\\n\t\t_INTSIZEOF(t)))\n#endif\n'
368
369const c_headers = c_helper_macros + c_common_macros + c_common_callconv_attr +
370 r'
371// c_headers
372typedef int (*qsort_callback_func)(const void*, const void*);
373#if defined(_MSC_VER) && !defined(__clang__)
374 #define V_CRT_LINKAGE __declspec(dllimport)
375 #define V_CRT_CALL VCALLCONV(cdecl)
376#else
377 #define V_CRT_LINKAGE
378 #define V_CRT_CALL
379#endif
380#if (defined(_MSC_VER) && !defined(__clang__)) || defined(__cplusplus)
381// Under C++ (g++/clang++), let libc declare FILE/stdio/string/stdlib to keep
382// noexcept specifiers consistent — the manual extern "C" prototypes below
383// would otherwise conflict with system headers under -std=c++NN.
384#include <stdarg.h>
385#include <stdio.h>
386#include <stdlib.h>
387#include <string.h>
388#ifndef va_copy
389 #define va_copy(dest, src) ((dest) = (src))
390#endif
391#ifndef _TRUNCATE
392 #define _TRUNCATE ((size_t)-1)
393#endif
394#elif defined(__MINGW32__) || defined(__MINGW64__) || (defined(__clang__) && (defined(_WIN32) || defined(_WIN64)))
395typedef struct _iobuf FILE;
396FILE* __cdecl __acrt_iob_func(unsigned index);
397#define stdin (__acrt_iob_func(0))
398#define stdout (__acrt_iob_func(1))
399#define stderr (__acrt_iob_func(2))
400#elif defined(__TINYC__) && (defined(_WIN32) || defined(_WIN64))
401#ifndef _FILE_DEFINED
402struct _iobuf {
403 char *_ptr;
404 int _cnt;
405 char *_base;
406 int _flag;
407 int _file;
408 int _charbuf;
409 int _bufsiz;
410 char *_tmpfname;
411};
412typedef struct _iobuf FILE;
413#define _FILE_DEFINED
414#endif
415 #if defined(_WIN64)
416FILE* __cdecl __iob_func(void);
417 #else
418 #ifdef _MSVCRT_
419extern FILE _iob[];
420 #define __iob_func() (_iob)
421 #else
422extern FILE (*_imp___iob)[];
423 #define __iob_func() (*_imp___iob)
424 #define _iob __iob_func()
425 #endif
426 #endif
427#define stdin (&__iob_func()[0])
428#define stdout (&__iob_func()[1])
429#define stderr (&__iob_func()[2])
430#elif defined(__vinix__)
431typedef struct __file FILE;
432extern FILE* stdin;
433extern FILE* stdout;
434extern FILE* stderr;
435struct __thread_data;
436struct __threadattr;
437// pthread_t handling for vinix builds:
438// - Vinix kernel (freestanding, __STDC_HOSTED__=0): no libc, define
439// pthread_t ourselves so V code that references it compiles.
440// - util-vinix cross-compiled on a libc-providing host (hosted, e.g.
441// glibc on Linux or macOS with -D__vinix__): pull pthread_t from
442// libc to avoid colliding with the libc typedef.
443#if defined(__STDC_HOSTED__) && __STDC_HOSTED__ && defined(__has_include) && __has_include(<pthread.h>)
444#include <pthread.h>
445#else
446typedef struct __thread_data *pthread_t;
447#endif
448typedef __builtin_va_list va_list;
449#ifndef va_start
450 #define va_start(ap, v) __builtin_va_start(ap, v)
451#endif
452#ifndef va_arg
453 #define va_arg(ap, t) __builtin_va_arg(ap, t)
454#endif
455#ifndef va_end
456 #define va_end(ap) __builtin_va_end(ap)
457#endif
458#ifndef va_copy
459 #define va_copy(dest, src) __builtin_va_copy(dest, src)
460#endif
461#else
462 #if defined(__APPLE__) || defined(__FreeBSD__)
463typedef struct __sFILE FILE;
464extern FILE* __stdinp;
465extern FILE* __stdoutp;
466extern FILE* __stderrp;
467#define stdin __stdinp
468#define stdout __stdoutp
469#define stderr __stderrp
470 #elif defined(__NetBSD__) || defined(__DragonFly__)
471typedef struct __sFILE FILE;
472extern FILE* __stdinp;
473extern FILE* __stdoutp;
474extern FILE* __stderrp;
475#define stdin __stdinp
476#define stdout __stdoutp
477#define stderr __stderrp
478 #elif defined(__OpenBSD__)
479typedef struct __sFILE FILE;
480#ifndef _STDFILES_DECLARED
481 #define _STDFILES_DECLARED
482struct __sFstub { long _stub; };
483extern struct __sFstub __stdin[];
484extern struct __sFstub __stdout[];
485extern struct __sFstub __stderr[];
486#endif
487#define stdin ((struct __sFILE *)__stdin)
488#define stdout ((struct __sFILE *)__stdout)
489#define stderr ((struct __sFILE *)__stderr)
490 #elif defined(__BIONIC__)
491struct __sFILE;
492typedef struct __sFILE FILE;
493extern FILE* stdin;
494extern FILE* stdout;
495extern FILE* stderr;
496 #elif defined(__linux__) && !defined(__GLIBC__) && !defined(__GNU_LIBRARY__) && !defined(__BIONIC__) && !defined(__UCLIBC__)
497typedef struct _IO_FILE FILE;
498// musl exposes the stdio streams as `FILE *const`, so match that to stay
499// compatible with later <stdio.h> includes from headers like miniz.h.
500extern FILE* const stdin;
501extern FILE* const stdout;
502extern FILE* const stderr;
503 #else
504typedef struct _IO_FILE FILE;
505extern FILE* stdin;
506extern FILE* stdout;
507extern FILE* stderr;
508 #endif
509typedef __builtin_va_list va_list;
510#ifndef va_start
511 #define va_start(ap, v) __builtin_va_start(ap, v)
512#endif
513#ifndef va_arg
514 #define va_arg(ap, t) __builtin_va_arg(ap, t)
515#endif
516#ifndef va_end
517 #define va_end(ap) __builtin_va_end(ap)
518#endif
519#ifndef va_copy
520 #define va_copy(dest, src) __builtin_va_copy(dest, src)
521#endif
522#endif
523#if (!defined(_MSC_VER) || defined(__clang__)) && !defined(__cplusplus)
524// mingw-w64 stdio.h declares these as static __mingw_ovr inline overrides
525// when __USE_MINGW_ANSI_STDIO is on. Skip them under gcc+mingw to avoid
526// static-after-extern conflicts; clang+mingw needs them because it builds
527// with -Werror=implicit-function-declaration and does not hit the conflict.
528#if !((defined(__MINGW32__) || defined(__MINGW64__)) && !defined(__clang__))
529V_CRT_LINKAGE int V_CRT_CALL vfprintf(FILE *stream, const char *format, va_list ap);
530V_CRT_LINKAGE int V_CRT_CALL vsnprintf(char *str, size_t size, const char *format, va_list ap);
531V_CRT_LINKAGE int V_CRT_CALL fprintf(FILE *stream, const char *format, ...);
532V_CRT_LINKAGE int V_CRT_CALL printf(const char *format, ...);
533V_CRT_LINKAGE int V_CRT_CALL snprintf(char *str, size_t size, const char *format, ...);
534V_CRT_LINKAGE int V_CRT_CALL sprintf(char *str, const char *format, ...);
535V_CRT_LINKAGE int V_CRT_CALL sscanf(const char *str, const char *format, ...);
536V_CRT_LINKAGE int V_CRT_CALL scanf(const char *format, ...);
537#endif
538V_CRT_LINKAGE int V_CRT_CALL puts(const char *str);
539V_CRT_LINKAGE void V_CRT_CALL perror(const char *str);
540V_CRT_LINKAGE int V_CRT_CALL fputs(const char *str, FILE *stream);
541V_CRT_LINKAGE int V_CRT_CALL getchar(void);
542V_CRT_LINKAGE int V_CRT_CALL putchar(int ch);
543V_CRT_LINKAGE int V_CRT_CALL getc(FILE *stream);
544V_CRT_LINKAGE int V_CRT_CALL fgetc(FILE *stream);
545V_CRT_LINKAGE int V_CRT_CALL ungetc(int ch, FILE *stream);
546V_CRT_LINKAGE int V_CRT_CALL fflush(FILE *stream);
547V_CRT_LINKAGE int V_CRT_CALL feof(FILE *stream);
548V_CRT_LINKAGE int V_CRT_CALL ferror(FILE *stream);
549V_CRT_LINKAGE void V_CRT_CALL clearerr(FILE *stream);
550V_CRT_LINKAGE int V_CRT_CALL setvbuf(FILE *stream, char *buf, int mode, size_t size);
551V_CRT_LINKAGE long V_CRT_CALL ftell(FILE *stream);
552V_CRT_LINKAGE void V_CRT_CALL rewind(FILE *stream);
553V_CRT_LINKAGE FILE * V_CRT_CALL fopen(const char *filename, const char *mode);
554V_CRT_LINKAGE FILE * V_CRT_CALL fdopen(int fd, const char *mode);
555V_CRT_LINKAGE FILE * V_CRT_CALL freopen(const char *filename, const char *mode, FILE *stream);
556V_CRT_LINKAGE int V_CRT_CALL fileno(FILE *stream);
557V_CRT_LINKAGE size_t V_CRT_CALL fread(void *ptr, size_t size, size_t items, FILE *stream);
558V_CRT_LINKAGE size_t V_CRT_CALL fwrite(const void *ptr, size_t size, size_t items, FILE *stream);
559#if defined(__vinix__)
560V_CRT_LINKAGE char * V_CRT_CALL fgets(char *str, size_t size, FILE *stream);
561#else
562V_CRT_LINKAGE char * V_CRT_CALL fgets(char *str, int size, FILE *stream);
563#endif
564V_CRT_LINKAGE int V_CRT_CALL fclose(FILE *stream);
565#if defined(__vinix__)
566V_CRT_LINKAGE FILE * V_CRT_CALL popen(char *command, char *mode);
567#else
568V_CRT_LINKAGE FILE * V_CRT_CALL popen(const char *command, const char *mode);
569#endif
570V_CRT_LINKAGE int V_CRT_CALL pclose(FILE *stream);
571V_CRT_LINKAGE void * V_CRT_CALL malloc(size_t size);
572V_CRT_LINKAGE void * V_CRT_CALL calloc(size_t nitems, size_t size);
573V_CRT_LINKAGE void * V_CRT_CALL realloc(void *ptr, size_t size);
574V_CRT_LINKAGE void * V_CRT_CALL aligned_alloc(size_t alignment, size_t size);
575V_CRT_LINKAGE void V_CRT_CALL free(void *ptr);
576V_CRT_LINKAGE int V_CRT_CALL rand(void);
577V_CRT_LINKAGE void V_CRT_CALL srand(unsigned int seed);
578V_CRT_LINKAGE int V_CRT_CALL atexit(void (*cb)(void));
579V_CRT_LINKAGE void V_CRT_CALL exit(int status);
580V_CRT_LINKAGE int V_CRT_CALL abs(int n);
581V_CRT_LINKAGE int V_CRT_CALL atoi(const char *str);
582V_CRT_LINKAGE double V_CRT_CALL atof(const char *str);
583V_CRT_LINKAGE char * V_CRT_CALL getenv(const char *name);
584V_CRT_LINKAGE int V_CRT_CALL setenv(const char *name, const char *value, int overwrite);
585V_CRT_LINKAGE int V_CRT_CALL unsetenv(const char *name);
586V_CRT_LINKAGE int V_CRT_CALL system(const char *command);
587V_CRT_LINKAGE int V_CRT_CALL remove(const char *path);
588V_CRT_LINKAGE int V_CRT_CALL rename(const char *old_path, const char *new_path);
589V_CRT_LINKAGE char * V_CRT_CALL realpath(const char *path, char *resolved_path);
590V_CRT_LINKAGE int V_CRT_CALL mkstemp(char *stemplate);
591V_CRT_LINKAGE void V_CRT_CALL qsort(void *base, size_t items, size_t item_size, qsort_callback_func cb);
592#if defined(__vinix__)
593V_CRT_LINKAGE int V_CRT_CALL strcmp(char *left, char *right);
594V_CRT_LINKAGE int V_CRT_CALL strncmp(char *left, char *right, size_t n);
595#else
596V_CRT_LINKAGE int V_CRT_CALL strcmp(const char *left, const char *right);
597V_CRT_LINKAGE int V_CRT_CALL strncmp(const char *left, const char *right, size_t n);
598#endif
599#if !defined(_WIN32) && !defined(_WIN64) && !defined(__BIONIC__)
600V_CRT_LINKAGE char * V_CRT_CALL strdup(const char *str);
601#endif
602#if !defined(_WIN32) && !defined(_WIN64)
603V_CRT_LINKAGE int V_CRT_CALL strcasecmp(const char *left, const char *right);
604V_CRT_LINKAGE int V_CRT_CALL strncasecmp(const char *left, const char *right, size_t n);
605#endif
606#if defined(__vinix__)
607V_CRT_LINKAGE size_t V_CRT_CALL strlen(char *str);
608#else
609V_CRT_LINKAGE size_t V_CRT_CALL strlen(const char *str);
610#endif
611V_CRT_LINKAGE char * V_CRT_CALL strerror(int errnum);
612V_CRT_LINKAGE void * V_CRT_CALL memcpy(void *dest, const void *src, size_t n);
613V_CRT_LINKAGE void * V_CRT_CALL memmove(void *dest, const void *src, size_t n);
614V_CRT_LINKAGE void * V_CRT_CALL memset(void *dest, int ch, size_t n);
615V_CRT_LINKAGE int V_CRT_CALL memcmp(const void *left, const void *right, size_t n);
616V_CRT_LINKAGE void * V_CRT_CALL memchr(const void *str, int c, size_t n);
617V_CRT_LINKAGE char * V_CRT_CALL strchr(const char *str, int c);
618V_CRT_LINKAGE char * V_CRT_CALL strrchr(const char *str, int c);
619V_CRT_LINKAGE char * V_CRT_CALL strstr(const char *haystack, const char *needle);
620V_CRT_LINKAGE int V_CRT_CALL fseek(FILE *stream, long offset, int whence);
621V_CRT_LINKAGE isize V_CRT_CALL getline(char **lineptr, size_t *n, FILE *stream);
622#if defined(_WIN32) || defined(_WIN64)
623V_CRT_LINKAGE int V_CRT_CALL _fileno(FILE *stream);
624V_CRT_LINKAGE FILE * V_CRT_CALL _wfopen(const unsigned short *filename, const unsigned short *mode);
625V_CRT_LINKAGE int V_CRT_CALL _wremove(const unsigned short *path);
626V_CRT_LINKAGE void * V_CRT_CALL _aligned_malloc(size_t size, size_t alignment);
627V_CRT_LINKAGE void * V_CRT_CALL _aligned_realloc(void *memory, size_t size, size_t alignment);
628V_CRT_LINKAGE void V_CRT_CALL _aligned_free(void *memory);
629V_CRT_LINKAGE unsigned short * V_CRT_CALL _wgetenv(const unsigned short *varname);
630V_CRT_LINKAGE int V_CRT_CALL _wputenv(const unsigned short *envstring);
631#endif
632#if defined(_MSC_VER) && !defined(__clang__)
633#ifndef _TRUNCATE
634 #define _TRUNCATE ((size_t)-1)
635#endif
636V_CRT_LINKAGE int V_CRT_CALL _vscprintf(const char *format, va_list ap);
637V_CRT_LINKAGE int V_CRT_CALL _vsnprintf_s(char *buffer, size_t size, size_t count, const char *format, va_list ap);
638#endif
639#endif
640#ifndef _IOFBF
641 #define _IOFBF 0
642#endif
643#ifndef _IOLBF
644 #define _IOLBF 1
645#endif
646#ifndef _IONBF
647 #define _IONBF 2
648#endif
649#ifndef EOF
650 #define EOF (-1)
651#endif
652#ifndef SEEK_SET
653 #define SEEK_SET 0
654#endif
655#ifndef SEEK_CUR
656 #define SEEK_CUR 1
657#endif
658#ifndef SEEK_END
659 #define SEEK_END 2
660#endif
661#ifndef RAND_MAX
662enum {
663 #if defined(_MSC_VER)
664 RAND_MAX = 0x7fff
665 #else
666 RAND_MAX = 2147483647
667 #endif
668};
669#endif
670#undef V_CRT_LINKAGE
671#undef V_CRT_CALL
672static void v_stable_sort(void *base, size_t items, size_t item_size, qsort_callback_func cb) {
673 if (items < 2 || item_size == 0) {
674 return;
675 }
676 if (items > ((size_t)-1) / item_size) {
677 qsort(base, items, item_size, cb);
678 return;
679 }
680 const size_t bytes = items * item_size;
681 char *base_bytes = (char*)base;
682 char *tmp = (char*)malloc(bytes);
683 if (tmp == 0) {
684 qsort(base, items, item_size, cb);
685 return;
686 }
687 char *src = base_bytes;
688 char *dst = tmp;
689 for (size_t width = 1; width < items;) {
690 for (size_t left = 0; left < items;) {
691 size_t mid = left;
692 mid += width;
693 if (mid > items) {
694 mid = items;
695 }
696 size_t right = mid;
697 right += width;
698 if (right > items || right < mid) {
699 right = items;
700 }
701 size_t i = left;
702 size_t j = mid;
703 size_t k = left;
704 while (i < mid && j < right) {
705 char *leftp = src;
706 leftp += i * item_size;
707 char *rightp = src;
708 rightp += j * item_size;
709 char *dstp = dst;
710 dstp += k * item_size;
711 if (cb(leftp, rightp) <= 0) {
712 memcpy(dstp, leftp, item_size);
713 i++;
714 } else {
715 memcpy(dstp, rightp, item_size);
716 j++;
717 }
718 k++;
719 }
720 while (i < mid) {
721 char *dstp = dst;
722 dstp += k * item_size;
723 char *srcp = src;
724 srcp += i * item_size;
725 memcpy(dstp, srcp, item_size);
726 i++;
727 k++;
728 }
729 while (j < right) {
730 char *dstp = dst;
731 dstp += k * item_size;
732 char *srcp = src;
733 srcp += j * item_size;
734 memcpy(dstp, srcp, item_size);
735 j++;
736 k++;
737 }
738 left = right;
739 }
740 char *next_src = dst;
741 dst = src;
742 src = next_src;
743 if (width > items / 2) {
744 width = items;
745 } else {
746 width *= 2;
747 }
748 }
749 if (src != base_bytes) {
750 memcpy(base_bytes, src, bytes);
751 }
752 free(tmp);
753}
754#if defined(__TINYC__)
755// https://lists.nongnu.org/archive/html/tinycc-devel/2025-10/msg00007.html
756// gnu headers use to #define __attribute__ to empty for non-gcc compilers
757#undef __attribute__
758#endif
759#if defined(_MSC_VER) && !defined(__clang__)
760// Ensure C99-like return semantics and NUL-termination for MSVC snprintf/vsnprintf.
761static int v__vsnprintf(char *s, size_t n, const char *fmt, va_list ap) {
762 va_list ap_copy;
763 va_copy(ap_copy, ap);
764 const int needed = _vscprintf(fmt, ap_copy);
765 va_end(ap_copy);
766 if (n > 0) {
767 const int written = _vsnprintf_s(s, n, _TRUNCATE, fmt, ap);
768 if (written < 0) {
769 s[n -
770 1] = 0;
771 }
772 }
773 return needed;
774}
775static int v__snprintf(char *s, size_t n, const char *fmt, ...) {
776 va_list ap;
777 va_start(ap, fmt);
778 const int needed = v__vsnprintf(s, n, fmt, ap);
779 va_end(ap);
780 return needed;
781}
782#define vsnprintf v__vsnprintf
783#define snprintf v__snprintf
784#endif
785//================================== GLOBALS =================================*/
786#ifdef _VOBJECTFILE
787static void _vinit(int ___argc, voidptr ___argv);
788static void _vcleanup(void);
789#else
790void _vinit(int ___argc, voidptr ___argv);
791void _vcleanup(void);
792#endif
793#ifdef _WIN32
794 // Export helpers so the autogenerated DllMain, or a user-defined one,
795 // can reuse the default V shared-library init/cleanup path.
796 #ifdef _VOBJECTFILE
797 static void _vinit_caller();
798 static void _vcleanup_caller();
799 #else
800 VV_EXP void _vinit_caller();
801 VV_EXP void _vcleanup_caller();
802 #endif
803#endif
804#if !defined(_WIN32)
805#define sigaction_size sizeof(sigaction);
806#endif
807#define _ARR_LEN(a) ( (sizeof(a)) / (sizeof(a[0])) )
808#if INTPTR_MAX == INT32_MAX
809 #define TARGET_IS_32BIT 1
810#elif INTPTR_MAX == INT64_MAX
811 #define TARGET_IS_64BIT 1
812#else
813 #error "The environment is not 32 or 64-bit."
814#endif
815#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__)
816 #define TARGET_ORDER_IS_BIG 1
817#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_ARM64) || defined(_M_X64) || defined(_M_IX86)
818 #define TARGET_ORDER_IS_LITTLE 1
819#else
820 #error "Unknown architecture endianness"
821#endif
822#if !defined(_WIN32) && !defined(__vinix__)
823 #include <ctype.h>
824 #include <locale.h> // tolower
825 #include <sys/time.h>
826 #include <unistd.h> // sleep
827 extern char **environ;
828 #include <pthread.h>
829 #ifndef PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP
830 // musl does not have that
831 #define pthread_rwlockattr_setkind_np(a, b)
832 #endif
833#endif
834#if (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__serenity__) || defined(__sun) || defined(__plan9__) || defined(__OpenBSD__)) && !defined(__vinix__)
835 #include <sys/types.h>
836 #include <sys/wait.h> // for os__wait
837#endif
838#ifdef __OpenBSD__
839 #include <sys/resource.h>
840#endif
841#ifdef __FreeBSD__
842 #include <signal.h>
843 #include <execinfo.h>
844#endif
845#ifdef __NetBSD__
846 #include <sys/wait.h> // for os__wait
847#endif
848#ifdef __TERMUX__
849#if !defined(__BIONIC_AVAILABILITY_GUARD)
850 #define __BIONIC_AVAILABILITY_GUARD(api_level) 0
851#endif
852#if __BIONIC_AVAILABILITY_GUARD(28)
853#else
854void * aligned_alloc(size_t alignment, size_t size) { return malloc(size); }
855#endif
856#endif
857#ifdef __APPLE__
858 // macOS only exports aligned_alloc starting with 10.15.
859 #if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500
860static void *v__aligned_alloc_fallback(size_t alignment, size_t size) {
861 void *res = 0;
862 if (alignment < sizeof(void *)) {
863 alignment = sizeof(void *);
864 }
865 if (posix_memalign(&res, alignment, size) != 0) {
866 return 0;
867 }
868 return res;
869}
870 #define aligned_alloc v__aligned_alloc_fallback
871 #endif
872#endif
873#ifdef _WIN32
874 #ifdef WINVER
875 #undef WINVER
876 #endif
877 #define WINVER 0x0600
878 #ifdef _WIN32_WINNT
879 #undef _WIN32_WINNT
880 #endif
881 #define _WIN32_WINNT 0x0600
882 #ifndef WIN32_FULL
883 #define WIN32_LEAN_AND_MEAN
884 #endif
885 #ifndef _UNICODE
886 #define _UNICODE
887 #endif
888 #ifndef UNICODE
889 #define UNICODE
890 #endif
891 #include <windows.h>
892 #include <io.h> // _waccess
893 #include <direct.h> // _wgetcwd
894 #ifdef V_USE_SIGNAL_H
895 #include <signal.h> // signal and SIGSEGV for segmentation fault handler
896 #endif
897 #ifdef _MSC_VER
898 // On MSVC these are the same (as long as /volatile:ms is passed)
899 #define _Atomic volatile
900 // MSVC cannot parse some things properly
901 #undef __NOINLINE
902 #undef __IRQHANDLER
903 #define __NOINLINE __declspec(noinline)
904 #define __IRQHANDLER __declspec(naked)
905 #include <dbghelp.h>
906 #pragma comment(lib, "Dbghelp")
907 #endif
908#endif
909#if defined(__CYGWIN__) && !defined(_WIN32)
910 #error Cygwin is not supported, please use MinGW or Visual Studio.
911#endif
912#if defined(__MINGW32__) || defined(__MINGW64__) || (defined(_WIN32) && defined(__TINYC__)) || defined(_MSC_VER)
913 #undef PRId64
914 #undef PRIi64
915 #undef PRIo64
916 #undef PRIu64
917 #undef PRIx64
918 #undef PRIX64
919 #define PRId64 "lld"
920 #define PRIi64 "lli"
921 #define PRIo64 "llo"
922 #define PRIu64 "llu"
923 #define PRIx64 "llx"
924 #define PRIX64 "llX"
925#endif
926#ifdef _VFREESTANDING
927#undef _VFREESTANDING
928#endif
929'
930
931const c_builtin_types = '
932//================================== builtin types ================================*/
933#if defined(__x86_64__) || defined(_M_AMD64) || defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || (defined(__riscv_xlen) && __riscv_xlen == 64) || defined(__s390x__) || (defined(__powerpc64__) && defined(__LITTLE_ENDIAN__)) || defined(__loongarch64) || defined(__sparc__) || (defined(__powerpc64__) && defined(__BIG_ENDIAN__))
934typedef int64_t vint_t;
935#else
936typedef int32_t vint_t;
937#endif
938typedef int64_t i64;
939typedef int16_t i16;
940typedef int8_t i8;
941typedef uint64_t u64;
942typedef uint32_t u32;
943typedef uint8_t u8;
944typedef uint16_t u16;
945typedef u8 byte;
946typedef int32_t i32;
947typedef uint32_t rune;
948typedef size_t usize;
949typedef ptrdiff_t isize;
950#ifndef VNOFLOAT
951typedef float f32;
952typedef double f64;
953#else
954typedef int32_t f32;
955typedef int64_t f64;
956#endif
957typedef int64_t int_literal;
958#ifndef VNOFLOAT
959typedef double float_literal;
960#else
961typedef int64_t float_literal;
962#endif
963typedef unsigned char* byteptr;
964typedef void* voidptr;
965typedef char* charptr;
966typedef u8 array_fixed_byte_300 [300];
967typedef struct sync__Channel* chan;
968#ifndef CUSTOM_DEFINE_no_bool
969 #ifndef __cplusplus
970 #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 202311L
971 #ifndef bool
972 #ifdef CUSTOM_DEFINE_4bytebool
973 typedef int bool;
974 #else
975 typedef u8 bool;
976 #endif
977 #define true 1
978 #define false 0
979 #endif
980 #endif
981 #endif
982#endif
983'
984
985const c_shift_helpers = '
986#define V_SAFE_SHIFT_BITS(type) ((u64)(sizeof(type) * 8))
987#define V_SAFE_LSHIFT_UNSIGNED(name, type) static inline type name(type x, u64 y) { return y >= V_SAFE_SHIFT_BITS(type) ? (type)0 : (type)(x << y); }
988#define V_SAFE_LSHIFT_SIGNED(name, type, unsigned_type) static inline type name(type x, u64 y) { return y >= V_SAFE_SHIFT_BITS(type) ? (type)0 : (type)(((unsigned_type)x) << y); }
989#define V_SAFE_RSHIFT_UNSIGNED(name, type) static inline type name(type x, u64 y) { return y >= V_SAFE_SHIFT_BITS(type) ? (type)0 : (type)(x >> y); }
990#define V_SAFE_RSHIFT_SIGNED(name, type) static inline type name(type x, u64 y) { return y >= V_SAFE_SHIFT_BITS(type) ? (type)(x < 0 ? -1 : 0) : (type)(x >> y); }
991V_SAFE_LSHIFT_SIGNED(v__lshift_char, char, u8)
992V_SAFE_RSHIFT_SIGNED(v__rshift_char, char)
993V_SAFE_LSHIFT_SIGNED(v__lshift_i8, i8, u8)
994V_SAFE_RSHIFT_SIGNED(v__rshift_i8, i8)
995V_SAFE_LSHIFT_SIGNED(v__lshift_i16, i16, u16)
996V_SAFE_RSHIFT_SIGNED(v__rshift_i16, i16)
997V_SAFE_LSHIFT_SIGNED(v__lshift_i32, i32, u32)
998V_SAFE_RSHIFT_SIGNED(v__rshift_i32, i32)
999V_SAFE_LSHIFT_SIGNED(v__lshift_int, int, unsigned int)
1000V_SAFE_RSHIFT_SIGNED(v__rshift_int, int)
1001V_SAFE_LSHIFT_SIGNED(v__lshift_vint_t, vint_t, u64)
1002V_SAFE_RSHIFT_SIGNED(v__rshift_vint_t, vint_t)
1003V_SAFE_LSHIFT_SIGNED(v__lshift_i64, i64, u64)
1004V_SAFE_RSHIFT_SIGNED(v__rshift_i64, i64)
1005V_SAFE_LSHIFT_SIGNED(v__lshift_isize, isize, usize)
1006V_SAFE_RSHIFT_SIGNED(v__rshift_isize, isize)
1007V_SAFE_LSHIFT_UNSIGNED(v__lshift_u8, u8)
1008V_SAFE_RSHIFT_UNSIGNED(v__rshift_u8, u8)
1009V_SAFE_LSHIFT_UNSIGNED(v__lshift_u16, u16)
1010V_SAFE_RSHIFT_UNSIGNED(v__rshift_u16, u16)
1011V_SAFE_LSHIFT_UNSIGNED(v__lshift_u32, u32)
1012V_SAFE_RSHIFT_UNSIGNED(v__rshift_u32, u32)
1013V_SAFE_LSHIFT_UNSIGNED(v__lshift_u64, u64)
1014V_SAFE_RSHIFT_UNSIGNED(v__rshift_u64, u64)
1015V_SAFE_LSHIFT_UNSIGNED(v__lshift_usize, usize)
1016V_SAFE_RSHIFT_UNSIGNED(v__rshift_usize, usize)
1017V_SAFE_LSHIFT_UNSIGNED(v__lshift_rune, rune)
1018V_SAFE_RSHIFT_UNSIGNED(v__rshift_rune, rune)
1019V_SAFE_LSHIFT_SIGNED(v__lshift_int_literal, int_literal, u64)
1020V_SAFE_RSHIFT_SIGNED(v__rshift_int_literal, int_literal)
1021#undef V_SAFE_RSHIFT_SIGNED
1022#undef V_SAFE_RSHIFT_UNSIGNED
1023#undef V_SAFE_LSHIFT_SIGNED
1024#undef V_SAFE_LSHIFT_UNSIGNED
1025#undef V_SAFE_SHIFT_BITS
1026'
1027
1028const c_mapfn_callback_types = '
1029typedef u64 (*MapHashFn)(voidptr);
1030typedef bool (*MapEqFn)(voidptr, voidptr);
1031typedef void (*MapCloneFn)(voidptr, voidptr);
1032typedef void (*MapFreeFn)(voidptr);
1033'
1034
1035const c_bare_headers = c_helper_macros + c_common_macros + c_common_callconv_attr +
1036 '
1037#define _VFREESTANDING
1038// Memory allocation related headers
1039void *malloc(size_t size);
1040void *calloc(size_t nitems, size_t size);
1041void *realloc(void *ptr, size_t size);
1042void *memcpy(void *dest, const void *src, size_t n);
1043void *memset(void *s, int c, size_t n);
1044void *memmove(void *dest, const void *src, size_t n);
1045// varargs implementation, TODO: works on tcc and gcc, but is very unportable and hacky
1046typedef __builtin_va_list va_list;
1047#define va_start(a, b) __builtin_va_start(a, b)
1048#define va_end(a) __builtin_va_end(a)
1049#define va_arg(a, b) __builtin_va_arg(a, b)
1050#define va_copy(a, b) __builtin_va_copy(a, b)
1051//================================== GLOBALS =================================*/
1052#ifdef _VOBJECTFILE
1053static void _vinit(int ___argc, voidptr ___argv);
1054static void _vcleanup(void);
1055#else
1056void _vinit(int ___argc, voidptr ___argv);
1057void _vcleanup();
1058#endif
1059#if !defined(_WIN32)
1060#define sigaction_size sizeof(sigaction);
1061#endif
1062#define _ARR_LEN(a) ( (sizeof(a)) / (sizeof(a[0])) )
1063VV_LOC voidptr builtin__memdup(voidptr src, isize size);
1064'
1065
1066const c_wyhash_headers = '
1067#ifndef wyhash_final_version_4_2
1068#define wyhash_final_version_4_2
1069#ifndef WYHASH_CONDOM
1070// protections that produce different results:
1071// 1: normal valid behavior
1072// 2: extra protection against entropy loss (probability=2^-63), aka. "blind multiplication"
1073#define WYHASH_CONDOM 1
1074#endif
1075#ifndef WYHASH_32BIT_MUM
1076// 0: normal version, slow on 32 bit systems
1077// 1: faster on 32 bit systems but produces different results, incompatible with wy2u0k function
1078#define WYHASH_32BIT_MUM 0
1079#endif
1080// includes
1081#include <stdint.h>
1082#if defined(_MSC_VER) && defined(_M_X64)
1083 #include <intrin.h>
1084 #pragma intrinsic(_umul128)
1085#endif
1086// 128bit multiply function
1087static inline uint64_t _wyrot(uint64_t x) { return (x>>32)|(x<<32); }
1088static inline void _wymum(uint64_t *A, uint64_t *B){
1089#if(WYHASH_32BIT_MUM)
1090 uint64_t hh=(*A>>32)*(*B>>32), hl=(*A>>32)*(uint32_t)*B, lh=(uint32_t)*A*(*B>>32), ll=(uint64_t)(uint32_t)*A*(uint32_t)*B;
1091 #if(WYHASH_CONDOM>1)
1092 *A^=_wyrot(hl)^hh; *B^=_wyrot(lh)^ll;
1093 #else
1094 *A=_wyrot(hl)^hh; *B=_wyrot(lh)^ll;
1095 #endif
1096#elif defined(__SIZEOF_INT128__) && !defined(VWASM)
1097 __uint128_t r=*A; r*=*B;
1098 #if(WYHASH_CONDOM>1)
1099 *A^=(uint64_t)r; *B^=(uint64_t)(r>>64);
1100 #else
1101 *A=(uint64_t)r; *B=(uint64_t)(r>>64);
1102 #endif
1103#elif defined(_MSC_VER) && defined(_M_X64)
1104 #if(WYHASH_CONDOM>1)
1105 uint64_t a, b;
1106 a=_umul128(*A,*B,&b);
1107 *A^=a; *B^=b;
1108 #else
1109 *A=_umul128(*A,*B,B);
1110 #endif
1111#else
1112 uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B, hi, lo;
1113 uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t<rl;
1114 lo=t+(rm1<<32); c+=lo<t; hi=rh+(rm0>>32)+(rm1>>32)+c;
1115 #if(WYHASH_CONDOM>1)
1116 *A^=lo; *B^=hi;
1117 #else
1118 *A=lo; *B=hi;
1119 #endif
1120#endif
1121}
1122// multiply and xor mix function, aka MUM
1123static inline uint64_t _wymix(uint64_t A, uint64_t B){ _wymum(&A,&B); return A^B; }
1124// endian macros
1125#ifndef WYHASH_LITTLE_ENDIAN
1126 #ifdef TARGET_ORDER_IS_LITTLE
1127 #define WYHASH_LITTLE_ENDIAN 1
1128 #else
1129 #define WYHASH_LITTLE_ENDIAN 0
1130 #endif
1131#endif
1132// read functions
1133#if (WYHASH_LITTLE_ENDIAN)
1134 static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return v;}
1135 static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return v;}
1136#elif !defined(__TINYC__) && (defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__))
1137 static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return __builtin_bswap64(v);}
1138 static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return __builtin_bswap32(v);}
1139#elif defined(_MSC_VER)
1140 static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return _byteswap_uint64(v);}
1141 static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return _byteswap_ulong(v);}
1142#else
1143 static inline uint64_t _wyr8(const uint8_t *p) {
1144 uint64_t v; memcpy(&v, p, 8);
1145 return (((v >> 56) & 0xff)| ((v >> 40) & 0xff00)| ((v >> 24) & 0xff0000)| ((v >> 8) & 0xff000000)| ((v << 8) & 0xff00000000)| ((v << 24) & 0xff0000000000)| ((v << 40) & 0xff000000000000)| ((v << 56) & 0xff00000000000000));
1146 }
1147 static inline uint64_t _wyr4(const uint8_t *p) {
1148 uint32_t v; memcpy(&v, p, 4);
1149 return (((v >> 24) & 0xff)| ((v >> 8) & 0xff00)| ((v << 8) & 0xff0000)| ((v << 24) & 0xff000000));
1150 }
1151#endif
1152static inline uint64_t _wyr3(const uint8_t *p, size_t k) { return (((uint64_t)p[0])<<16)|(((uint64_t)p[k>>1])<<8)|p[k-1];}
1153// wyhash main function
1154static inline uint64_t wyhash(const void *key, size_t len, uint64_t seed, const uint64_t *secret){
1155 const uint8_t *p=(const uint8_t *)key; seed^=_wymix(seed^secret[0]^len,secret[1]); uint64_t a, b;
1156 if (_likely_(len<=16)) {
1157 if (_likely_(len>=4)) { a=(_wyr4(p)<<32)|_wyr4(p+((len>>3)<<2)); b=(_wyr4(p+len-4)<<32)|_wyr4(p+len-4-((len>>3)<<2)); }
1158 else if (_likely_(len>0)) { a=_wyr3(p,len); b=0; }
1159 else a=b=0;
1160 } else {
1161 size_t i=len;
1162 if (_unlikely_(i>=48)) {
1163 uint64_t see1=seed, see2=seed;
1164 do {
1165 seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed);
1166 see1=_wymix(_wyr8(p+16)^secret[2],_wyr8(p+24)^see1);
1167 see2=_wymix(_wyr8(p+32)^secret[3],_wyr8(p+40)^see2);
1168 p+=48; i-=48;
1169 } while(_likely_(i>=48));
1170 seed^=see1^see2;
1171 }
1172 while(_unlikely_(i>16)) { seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed); i-=16; p+=16; }
1173 a=_wyr8(p+i-16); b=_wyr8(p+i-8);
1174 }
1175 a^=secret[1]; b^=seed; _wymum(&a,&b);
1176 return _wymix(a^secret[0]^len,b^secret[1]);
1177}
1178// the default secret parameters
1179static const uint64_t _wyp[4] = {0x2d358dccaa6c78a5ull, 0x8bb84b93962eacc9ull, 0x4b33a62ed433d4a3ull, 0x4d5a2da51de1aa47ull};
1180// a useful 64bit-64bit mix function to produce deterministic pseudo random numbers that can pass BigCrush and PractRand
1181static inline uint64_t wyhash64(uint64_t A, uint64_t B){ A^=0x2d358dccaa6c78a5ull; B^=0x8bb84b93962eacc9ull; _wymum(&A,&B); return _wymix(A^0x2d358dccaa6c78a5ull,B^0x8bb84b93962eacc9ull);}
1182// the wyrand PRNG that pass BigCrush and PractRand
1183static inline uint64_t wyrand(uint64_t *seed){ *seed+=0x2d358dccaa6c78a5ull; return _wymix(*seed,*seed^0x8bb84b93962eacc9ull);}
1184#ifndef __vinix__
1185// convert any 64 bit pseudo random numbers to uniform distribution [0,1). It can be combined with wyrand, wyhash64 or wyhash.
1186static inline double wy2u01(uint64_t r){ const double _wynorm=1.0/(1ull<<52); return (r>>12)*_wynorm;}
1187// convert any 64 bit pseudo random numbers to APPROXIMATE Gaussian distribution. It can be combined with wyrand, wyhash64 or wyhash.
1188static 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;}
1189#endif
1190#if(!WYHASH_32BIT_MUM)
1191// fast range integer random number generation on [0,k) credit to Daniel Lemire. May not work when WYHASH_32BIT_MUM=1. It can be combined with wyrand, wyhash64 or wyhash.
1192static inline uint64_t wy2u0k(uint64_t r, uint64_t k){ _wymum(&r,&k); return k; }
1193#endif
1194#endif
1195#define _IN_MAP(val, m) builtin__map_exists(m, val)
1196'
1197