From f27f832ede52e322c6c53667619903c69776dd8b Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 4 Mar 2020 17:08:28 +0100 Subject: [PATCH] cgen: definitions + other fixes; calloc fix --- vlib/builtin/array.v | 12 +- vlib/builtin/builtin.v | 5 +- vlib/builtin/cfns.v | 1 + vlib/builtin/int.v | 2 +- vlib/builtin/map.v | 6 +- vlib/compiler/cheaders.v | 2 +- vlib/compiler/table.v | 4 +- vlib/os/os.v | 18 +-- vlib/v/ast/ast.v | 1 + vlib/v/builder/builder.v | 7 +- vlib/v/gen/cgen.v | 19 ++- vlib/v/gen/cheaders.v | 310 +++++++++++++++++++++++++++++++++++++++ vlib/v/parser/fn.v | 14 +- 13 files changed, 370 insertions(+), 31 deletions(-) create mode 100644 vlib/v/gen/cheaders.v diff --git a/vlib/builtin/array.v b/vlib/builtin/array.v index ab8d3d592b..2167ea08df 100644 --- a/vlib/builtin/array.v +++ b/vlib/builtin/array.v @@ -29,7 +29,7 @@ fn new_array(mylen int, cap int, elm_size int) array { len: mylen cap: cap_ element_size: elm_size - data: calloc(cap_ * elm_size) + data: vcalloc(cap_ * elm_size) } return arr } @@ -46,7 +46,7 @@ fn new_array_from_c_array(len, cap, elm_size int, c_array voidptr) array { len: len cap: cap element_size: elm_size - data: calloc(cap_ * elm_size) + data: vcalloc(cap_ * elm_size) } // TODO Write all memory functions (like memcpy) in V C.memcpy(arr.data, c_array, len * elm_size) @@ -74,7 +74,7 @@ fn (a mut array) ensure_cap(required int) { cap *= 2 } if a.cap == 0 { - a.data = calloc(cap * a.element_size) + a.data = vcalloc(cap * a.element_size) } else { a.data = C.realloc(a.data, cap * a.element_size) @@ -95,7 +95,7 @@ pub fn (a array) repeat(count int) array { len: count * a.len cap: count * a.len element_size: a.element_size - data: calloc(size) + data: vcalloc(size) } for i in 0..count { C.memcpy(arr.data + i * a.len * a.element_size, a.data, a.len * a.element_size) @@ -264,7 +264,7 @@ pub fn (a array) clone() array { len: a.len cap: a.cap element_size: a.element_size - data: calloc(size) + data: vcalloc(size) } C.memcpy(arr.data, a.data, a.cap * a.element_size) return arr @@ -335,7 +335,7 @@ pub fn (a array) reverse() array { len: a.len cap: a.cap element_size: a.element_size - data: calloc(a.cap * a.element_size) + data: vcalloc(a.cap * a.element_size) } for i in 0..a.len { C.memcpy(arr.data + i * arr.element_size, &a[a.len - 1 - i], arr.element_size) diff --git a/vlib/builtin/builtin.v b/vlib/builtin/builtin.v index 00567fb2a5..3a3caee268 100644 --- a/vlib/builtin/builtin.v +++ b/vlib/builtin/builtin.v @@ -160,8 +160,11 @@ TODO */ } +pub fn v_calloc(n int) byteptr { + return C.calloc(n, 1) + } -pub fn calloc(n int) byteptr { +pub fn vcalloc(n int) byteptr { if n <= 0 { panic('calloc(<=0)') } diff --git a/vlib/builtin/cfns.v b/vlib/builtin/cfns.v index 83334f36b5..ee9ca60a8d 100644 --- a/vlib/builtin/cfns.v +++ b/vlib/builtin/cfns.v @@ -4,6 +4,7 @@ fn C.memcpy(byteptr, byteptr, int) voidptr fn C.memmove(byteptr, byteptr, int) voidptr +fn C.calloc(int) byteptr // fn C.malloc(int) byteptr fn C.realloc(a byteptr, b int) byteptr diff --git a/vlib/builtin/int.v b/vlib/builtin/int.v index 93893ece0f..064243dac8 100644 --- a/vlib/builtin/int.v +++ b/vlib/builtin/int.v @@ -18,7 +18,7 @@ pub fn (nn int) str() string { return '0' } max := 16 - mut buf := calloc(max + 1) + mut buf := vcalloc(max + 1) mut len := 0 mut is_neg := false if n < 0 { diff --git a/vlib/builtin/map.v b/vlib/builtin/map.v index 1022b47ab8..b198735c83 100644 --- a/vlib/builtin/map.v +++ b/vlib/builtin/map.v @@ -62,7 +62,7 @@ mut: fn new_map(n, value_bytes int) map { probe_hash_bytes := sizeof(u32) * init_capicity key_value_bytes := sizeof(KeyValue) * init_capicity - memory := calloc(key_value_bytes + probe_hash_bytes) + memory := vcalloc(key_value_bytes + probe_hash_bytes) return map{ value_bytes: value_bytes range_cap: init_range_cap @@ -157,7 +157,7 @@ fn (m mut map) expand() { fn (m mut map) rehash(old_range_cap u32) { probe_hash_bytes := sizeof(u32) * (m.range_cap + 1) key_value_bytes := sizeof(KeyValue) * (m.range_cap + 1) - memory := calloc(probe_hash_bytes + key_value_bytes) + memory := vcalloc(probe_hash_bytes + key_value_bytes) mut new_key_values := &KeyValue(memory) mut new_probe_hash := &u32(memory + key_value_bytes) for i := u32(0); i < old_range_cap + 1; i++ { @@ -207,7 +207,7 @@ fn (m mut map) rehash(old_range_cap u32) { fn (m mut map) cached_rehash(old_range_cap u32) { probe_hash_bytes := sizeof(u32) * (m.range_cap + 1) key_value_bytes := sizeof(KeyValue) * (m.range_cap + 1) - memory := calloc(probe_hash_bytes + key_value_bytes) + memory := vcalloc(probe_hash_bytes + key_value_bytes) mut new_probe_hash := &u32(memory + key_value_bytes) mut new_key_values := &KeyValue(memory) for i := u32(0); i < old_range_cap + 1; i++ { diff --git a/vlib/compiler/cheaders.v b/vlib/compiler/cheaders.v index 1c72d28097..2a051e0f0f 100644 --- a/vlib/compiler/cheaders.v +++ b/vlib/compiler/cheaders.v @@ -289,7 +289,7 @@ var map_int = function() {} //#include // int64_t etc //#include // int64_t etc -//================================== TYPEDEFS ================================*/ +//================================== 1TYPEDEFS ================================*/ typedef int64_t i64; typedef int16_t i16; diff --git a/vlib/compiler/table.v b/vlib/compiler/table.v index 58cb29095c..e8fe7088ce 100644 --- a/vlib/compiler/table.v +++ b/vlib/compiler/table.v @@ -164,7 +164,9 @@ const ( c_reserved = ['delete', 'exit', 'unix', // 'print', // 'ok', - 'error', 'malloc', 'calloc', 'free', 'panic', + 'error', 'malloc', +//'calloc', +'free', 'panic', // Full list of C reserved words, from: https://en.cppreference.com/w/c/keyword 'auto', 'char', 'default', 'do', 'double', 'extern', 'float', 'inline', 'int', 'long', 'register', 'restrict', 'short', 'signed', 'sizeof', 'static', 'switch', 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while', ] ) diff --git a/vlib/os/os.v b/vlib/os/os.v index 0643c72eb8..464bbfeac9 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -840,7 +840,7 @@ fn C.readlink() int // process. pub fn executable() string { $if linux { - mut result := calloc(MAX_PATH) + mut result := vcalloc(MAX_PATH) count := C.readlink('/proc/self/exe', result, MAX_PATH) if count < 0 { eprintln('os.executable() failed at reading /proc/self/exe to get exe path') @@ -850,12 +850,12 @@ pub fn executable() string { } $if windows { max := 512 - mut result := &u16(calloc(max * 2)) // MAX_PATH * sizeof(wchar_t) + mut result := &u16(vcalloc(max * 2)) // MAX_PATH * sizeof(wchar_t) len := C.GetModuleFileName(0, result, max) return string_from_wide2(result, len) } $if macos { - mut result := calloc(MAX_PATH) + mut result := vcalloc(MAX_PATH) pid := C.getpid() ret := proc_pidpath(pid, result, MAX_PATH) if ret <= 0 { @@ -865,7 +865,7 @@ pub fn executable() string { return string(result) } $if freebsd { - mut result := calloc(MAX_PATH) + mut result := vcalloc(MAX_PATH) mib := [1/* CTL_KERN */, 14/* KERN_PROC */, 12/* KERN_PROC_PATHNAME */, -1] size := MAX_PATH C.sysctl(mib.data, 4, result, &size, 0, 0) @@ -879,7 +879,7 @@ pub fn executable() string { $if solaris {} $if haiku {} $if netbsd { - mut result := calloc(MAX_PATH) + mut result := vcalloc(MAX_PATH) count := C.readlink('/proc/curproc/exe', result, MAX_PATH) if count < 0 { eprintln('os.executable() failed at reading /proc/curproc/exe to get exe path') @@ -888,7 +888,7 @@ pub fn executable() string { return string(result,count) } $if dragonfly { - mut result := calloc(MAX_PATH) + mut result := vcalloc(MAX_PATH) count := C.readlink('/proc/curproc/file', result, MAX_PATH) if count < 0 { eprintln('os.executable() failed at reading /proc/curproc/file to get exe path') @@ -952,13 +952,13 @@ pub fn chdir(path string) { pub fn getwd() string { $if windows { max := 512 // MAX_PATH * sizeof(wchar_t) - buf := &u16(calloc(max * 2)) + buf := &u16(vcalloc(max * 2)) if C._wgetcwd(buf, max) == 0 { return '' } return string_from_wide(buf) } $else { - buf := calloc(512) + buf := vcalloc(512) if C.getcwd(buf, 512) == 0 { return '' } @@ -972,7 +972,7 @@ pub fn getwd() string { // and https://insanecoding.blogspot.com/2007/11/implementing-realpath-in-c.html // NB: this particular rabbit hole is *deep* ... pub fn realpath(fpath string) string { - mut fullpath := calloc(MAX_PATH) + mut fullpath := vcalloc(MAX_PATH) mut ret := charptr(0) $if windows { ret = C._fullpath(fullpath, fpath.str, MAX_PATH) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 67236ea3f2..347e85dad6 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -139,6 +139,7 @@ pub: receiver Field is_method bool rec_mut bool // is receiver mutable + is_c bool } pub struct BranchStmt { diff --git a/vlib/v/builder/builder.v b/vlib/v/builder/builder.v index 5029b045fc..974f5674b0 100644 --- a/vlib/v/builder/builder.v +++ b/vlib/v/builder/builder.v @@ -51,7 +51,12 @@ pub fn (b mut Builder) gen_c(v_files []string) string { pub fn (b mut Builder) build_c(v_files []string, out_file string) { println('build_c($out_file)') - os.write_file(out_file, b.gen_c(v_files)) + mut f := os.create(out_file) or { + panic(err) + } + f.writeln(b.gen_c(v_files)) + f.close() + // os.write_file(out_file, b.gen_c(v_files)) } pub fn (b mut Builder) build_x64(v_files []string, out_file string) { diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index c107389690..317513f060 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -9,6 +9,7 @@ import ( struct Gen { out strings.Builder + typedefs strings.Builder definitions strings.Builder // typedefs, defines etc (everything that goes to the top of the file) table &table.Table mut: @@ -17,17 +18,26 @@ mut: } pub fn cgen(files []ast.File, table &table.Table) string { - println('start cgen') + println('start cgen2') mut g := Gen{ out: strings.new_builder(100) + typedefs: strings.new_builder(100) definitions: strings.new_builder(100) table: table fn_decl: 0 } + g.init() for file in files { g.stmts(file.stmts) } - return g.definitions.str() + g.out.str() + return g.typedefs.str() + g.definitions.str() + g.out.str() +} + +pub fn (g mut Gen) init() { + g.definitions.writeln('// Generated by the V compiler') + g.definitions.writeln('#include ') // int64_t etc + g.definitions.writeln(c_builtin_types) + g.definitions.writeln(c_headers) } pub fn (g &Gen) save() {} @@ -126,6 +136,9 @@ fn (g mut Gen) stmt(node ast.Stmt) { } } ast.FnDecl { + if it.is_c { + return + } g.reset_tmp_count() g.fn_decl = it // &it is_main := it.name == 'main' @@ -232,6 +245,8 @@ fn (g mut Gen) stmt(node ast.Stmt) { g.writeln('\t$field_type_sym.name $field.name;') } g.writeln('} $it.name;') + name := it.name.replace('.', '__') + g.typedefs.writeln('typedef struct $name $name;') } ast.TypeDecl { g.writeln('// type') diff --git a/vlib/v/gen/cheaders.v b/vlib/v/gen/cheaders.v new file mode 100644 index 0000000000..6380af5f15 --- /dev/null +++ b/vlib/v/gen/cheaders.v @@ -0,0 +1,310 @@ +module gen + +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) + +#ifndef V64_PRINTFORMAT +#ifdef PRIx64 +#define V64_PRINTFORMAT "0x%"PRIx64 +#elif defined(__WIN32__) +#define V64_PRINTFORMAT "0x%I64x" +#elif defined(__LINUX__) && defined(__LP64__) +#define V64_PRINTFORMAT "0x%lx" +#else +#define V64_PRINTFORMAT "0x%llx" +#endif +#endif + +' + c_headers = ' + +// c_headers +#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; } +static inline uint64_t fastest_hash(const void *key, size_t len, uint64_t seed) { + const uint8_t *p = (const uint8_t *)key; + return _like_(len >= 4) ? (_wyr4(p) + _wyr4(p + len - 4)) * (_wyr4(p + (len >> 1) - 2) ^ seed) : (_like_(len) ? _wyr3(p, len) * (_wyp0 ^ seed) : seed); +} +#endif + +' + c_builtin_types = ' + +//================================== builtin types ================================*/ + +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 + +' +) diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 20f865c1f1..3783315468 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -11,9 +11,9 @@ import ( pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr { tok := p.tok name := p.check_name() - fn_name := if is_c {'C.$name' } else if mod.len > 0 { '${mod}.$name' } else { name } + fn_name := if is_c { 'C.$name' } else if mod.len > 0 { '${mod}.$name' } else { name } p.check(.lpar) - args, muts := p.call_args() + args,muts := p.call_args() mut or_stmts := []ast.Stmt if p.tok.kind == .key_orelse { p.next() @@ -24,7 +24,7 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr { args: args muts: muts // tok: tok - + pos: tok.position() is_c: is_c or_block: ast.OrExpr{ @@ -34,7 +34,7 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr { return node } -pub fn (p mut Parser) call_args() ([]ast.Expr, []bool) { +pub fn (p mut Parser) call_args() ([]ast.Expr,[]bool) { mut args := []ast.Expr mut muts := []bool for p.tok.kind != .rpar { @@ -52,7 +52,7 @@ pub fn (p mut Parser) call_args() ([]ast.Expr, []bool) { } } p.check(.rpar) - return args, muts + return args,muts } fn (p mut Parser) fn_decl() ast.FnDecl { @@ -158,7 +158,8 @@ fn (p mut Parser) fn_decl() ast.FnDecl { else { if is_c { name = 'C.$name' - } else { + } + else { name = p.prepend_mod(name) } p.table.register_fn(table.Fn{ @@ -187,6 +188,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { } is_method: is_method rec_mut: rec_mut + is_c: is_c } }