mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: definitions + other fixes; calloc fix
This commit is contained in:
parent
37453945d0
commit
f27f832ede
@ -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)
|
||||
|
@ -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)')
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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++ {
|
||||
|
@ -289,7 +289,7 @@ var map_int = function() {}
|
||||
//#include <inttypes.h> // int64_t etc
|
||||
//#include <stdint.h> // int64_t etc
|
||||
|
||||
//================================== TYPEDEFS ================================*/
|
||||
//================================== 1TYPEDEFS ================================*/
|
||||
|
||||
typedef int64_t i64;
|
||||
typedef int16_t i16;
|
||||
|
@ -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', ]
|
||||
)
|
||||
|
18
vlib/os/os.v
18
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)
|
||||
|
@ -139,6 +139,7 @@ pub:
|
||||
receiver Field
|
||||
is_method bool
|
||||
rec_mut bool // is receiver mutable
|
||||
is_c bool
|
||||
}
|
||||
|
||||
pub struct BranchStmt {
|
||||
|
@ -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) {
|
||||
|
@ -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 <inttypes.h>') // 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')
|
||||
|
310
vlib/v/gen/cheaders.v
Normal file
310
vlib/v/gen/cheaders.v
Normal file
@ -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 <stdio.h> // TODO remove all these includes, define all function signatures and types manually
|
||||
#include <stdlib.h>
|
||||
|
||||
//#include "fns.h"
|
||||
#include <signal.h>
|
||||
#include <stdarg.h> // for va_list
|
||||
#include <string.h> // 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 <ctype.h>
|
||||
#include <locale.h> // tolower
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h> // sleep
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__) && !defined(_WIN32)
|
||||
#error Cygwin is not supported, please use MinGW or Visual Studio.
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h> // os__wait uses wait on nix
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h> // os__wait uses wait on nix
|
||||
#endif
|
||||
|
||||
#ifdef __DragonFly__
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h> // os__wait uses wait on nix
|
||||
#endif
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/wait.h> // os__wait uses wait on nix
|
||||
#endif
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#include <sys/wait.h> // 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 <windows.h>
|
||||
|
||||
#include <io.h> // _waccess
|
||||
#include <direct.h> // _wgetcwd
|
||||
//#include <WinSock2.h>
|
||||
#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 <dbghelp.h>
|
||||
#pragma comment(lib, "Dbghelp.lib")
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#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 <godspeed_china@yeah.net>
|
||||
#ifndef wyhash_version_4
|
||||
#define wyhash_version_4
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#if defined(_MSC_VER) && defined(_M_X64)
|
||||
#include <intrin.h>
|
||||
#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<rl;
|
||||
lo=t+(rm1<<32); c+=lo<t;hi=rh+(rm0>>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
|
||||
|
||||
'
|
||||
)
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user