mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Allow 128 bit map keys
This commit is contained in:
+9
-9
@@ -26,7 +26,7 @@
|
|||||||
// The compiler relies upon this _exact_ order
|
// The compiler relies upon this _exact_ order
|
||||||
TypeInfoEnumValue :: raw_union {
|
TypeInfoEnumValue :: raw_union {
|
||||||
f: f64,
|
f: f64,
|
||||||
i: i64,
|
i: i128,
|
||||||
}
|
}
|
||||||
// NOTE(bill): This must match the compiler's
|
// NOTE(bill): This must match the compiler's
|
||||||
CallingConvention :: enum {
|
CallingConvention :: enum {
|
||||||
@@ -537,24 +537,24 @@ __slice_append :: proc(slice_: rawptr, elem_size, elem_align: int,
|
|||||||
|
|
||||||
// Map stuff
|
// Map stuff
|
||||||
|
|
||||||
__default_hash :: proc(data: []byte) -> u64 {
|
__default_hash :: proc(data: []byte) -> u128 {
|
||||||
fnv64a :: proc(data: []byte) -> u64 {
|
fnv128a :: proc(data: []byte) -> u128 {
|
||||||
h: u64 = 0xcbf29ce484222325;
|
h: u128 = 0x6c62272e07bb014262b821756295c58d;
|
||||||
for b in data {
|
for b in data {
|
||||||
h = (h ~ u64(b)) * 0x100000001b3;
|
h = (h ~ u128(b)) * 0x1000000000000000000013b;
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
return fnv64a(data);
|
return fnv128a(data);
|
||||||
}
|
}
|
||||||
__default_hash_string :: proc(s: string) -> u64 {
|
__default_hash_string :: proc(s: string) -> u128 {
|
||||||
return __default_hash([]byte(s));
|
return __default_hash([]byte(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
__INITIAL_MAP_CAP :: 16;
|
__INITIAL_MAP_CAP :: 16;
|
||||||
|
|
||||||
__MapKey :: struct #ordered {
|
__MapKey :: struct #ordered {
|
||||||
hash: u64,
|
hash: u128,
|
||||||
str: string,
|
str: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -699,7 +699,7 @@ __dynamic_map_hash_equal :: proc(h: __MapHeader, a, b: __MapKey) -> bool {
|
|||||||
__dynamic_map_find :: proc(using h: __MapHeader, key: __MapKey) -> __MapFindResult {
|
__dynamic_map_find :: proc(using h: __MapHeader, key: __MapKey) -> __MapFindResult {
|
||||||
fr := __MapFindResult{-1, -1, -1};
|
fr := __MapFindResult{-1, -1, -1};
|
||||||
if len(m.hashes) > 0 {
|
if len(m.hashes) > 0 {
|
||||||
fr.hash_index = int(key.hash % u64(len(m.hashes)));
|
fr.hash_index = int(key.hash % u128(len(m.hashes)));
|
||||||
fr.entry_index = m.hashes[fr.hash_index];
|
fr.entry_index = m.hashes[fr.hash_index];
|
||||||
for fr.entry_index >= 0 {
|
for fr.entry_index >= 0 {
|
||||||
entry := __dynamic_map_get_entry(h, fr.entry_index);
|
entry := __dynamic_map_get_entry(h, fr.entry_index);
|
||||||
|
|||||||
+60
-54
@@ -13,6 +13,26 @@ StringBuffer :: union {
|
|||||||
Dynamic{buf: [dynamic]byte},
|
Dynamic{buf: [dynamic]byte},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FmtInfo :: struct {
|
||||||
|
minus: bool,
|
||||||
|
plus: bool,
|
||||||
|
space: bool,
|
||||||
|
zero: bool,
|
||||||
|
hash: bool,
|
||||||
|
width_set: bool,
|
||||||
|
prec_set: bool,
|
||||||
|
|
||||||
|
width: int,
|
||||||
|
prec: int,
|
||||||
|
|
||||||
|
reordered: bool,
|
||||||
|
good_arg_index: bool,
|
||||||
|
|
||||||
|
buf: ^StringBuffer,
|
||||||
|
arg: any, // Temporary
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
make_string_buffer_from_slice :: proc(b: []byte) -> StringBuffer {
|
make_string_buffer_from_slice :: proc(b: []byte) -> StringBuffer {
|
||||||
return StringBuffer.Static{b};
|
return StringBuffer.Static{b};
|
||||||
}
|
}
|
||||||
@@ -21,7 +41,13 @@ make_string_dynamic_buffer :: proc() -> StringBuffer {
|
|||||||
return StringBuffer.Dynamic{make([dynamic]byte)};
|
return StringBuffer.Dynamic{make([dynamic]byte)};
|
||||||
}
|
}
|
||||||
string_buffer_data :: proc(buf: ^StringBuffer) -> []byte {
|
string_buffer_data :: proc(buf: ^StringBuffer) -> []byte {
|
||||||
return string_buffer_data(buf^);
|
match b in buf {
|
||||||
|
case StringBuffer.Static:
|
||||||
|
return b.buf[..];
|
||||||
|
case StringBuffer.Dynamic:
|
||||||
|
return b.buf[..];
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
}
|
}
|
||||||
string_buffer_data :: proc(buf: StringBuffer) -> []byte {
|
string_buffer_data :: proc(buf: StringBuffer) -> []byte {
|
||||||
match b in buf {
|
match b in buf {
|
||||||
@@ -66,23 +92,15 @@ write_rune :: proc(buf: ^StringBuffer, r: rune) {
|
|||||||
write_bytes(buf, b[0..<n]);
|
write_bytes(buf, b[0..<n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
FmtInfo :: struct {
|
write_int :: proc(buf: ^StringBuffer, i: i128, base: int) {
|
||||||
minus: bool,
|
b: [129]byte;
|
||||||
plus: bool,
|
s := strconv.append_bits(b[0..<0], u128(i), base, true, 128, strconv.digits, 0);
|
||||||
space: bool,
|
write_string(buf, s);
|
||||||
zero: bool,
|
}
|
||||||
hash: bool,
|
write_int :: proc(buf: ^StringBuffer, i: i64, base: int) {
|
||||||
width_set: bool,
|
b: [129]byte;
|
||||||
prec_set: bool,
|
s := strconv.append_bits(b[0..<0], u128(i), base, true, 64, strconv.digits, 0);
|
||||||
|
write_string(buf, s);
|
||||||
width: int,
|
|
||||||
prec: int,
|
|
||||||
|
|
||||||
reordered: bool,
|
|
||||||
good_arg_index: bool,
|
|
||||||
|
|
||||||
buf: ^StringBuffer,
|
|
||||||
arg: any, // Temporary
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -114,15 +132,13 @@ fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
print :: proc(args: ..any) -> int {
|
// print* procedures return the number of bytes written
|
||||||
return fprint(os.stdout, ..args);
|
print :: proc(args: ..any) -> int { return fprint(os.stdout, ..args); }
|
||||||
}
|
print_err :: proc(args: ..any) -> int { return fprint(os.stderr, ..args); }
|
||||||
println :: proc(args: ..any) -> int {
|
println :: proc(args: ..any) -> int { return fprintln(os.stdout, ..args); }
|
||||||
return fprintln(os.stdout, ..args);
|
println_err :: proc(args: ..any) -> int { return fprintln(os.stderr, ..args); }
|
||||||
}
|
printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args); }
|
||||||
printf :: proc(fmt: string, args: ..any) -> int {
|
printf_err :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args); }
|
||||||
return fprintf(os.stdout, fmt, ..args);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// aprint* procedures return a string that was allocated with the current context
|
// aprint* procedures return a string that was allocated with the current context
|
||||||
@@ -144,10 +160,7 @@ aprintf :: proc(fmt: string, args: ..any) -> string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// bprint* procedures
|
// bprint* procedures return a string that was allocated with the current context
|
||||||
|
|
||||||
|
|
||||||
// aprint* procedure return a string that was allocated with the current context
|
|
||||||
// They must be freed accordingly
|
// They must be freed accordingly
|
||||||
bprint :: proc(buf: []byte, args: ..any) -> string {
|
bprint :: proc(buf: []byte, args: ..any) -> string {
|
||||||
sb := make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
|
sb := make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
|
||||||
@@ -376,16 +389,6 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write_int :: proc(buf: ^StringBuffer, i: i128, base: int) {
|
|
||||||
b: [129]byte;
|
|
||||||
s := strconv.append_bits(b[0..<0], u128(i), base, true, 128, strconv.digits, 0);
|
|
||||||
write_string(buf, s);
|
|
||||||
}
|
|
||||||
write_int :: proc(buf: ^StringBuffer, i: i64, base: int) {
|
|
||||||
b: [129]byte;
|
|
||||||
s := strconv.append_bits(b[0..<0], u128(i), base, true, 64, strconv.digits, 0);
|
|
||||||
write_string(buf, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
_parse_int :: proc(s: string, offset: int) -> (result: int, offset: int, ok: bool) {
|
_parse_int :: proc(s: string, offset: int) -> (result: int, offset: int, ok: bool) {
|
||||||
is_digit :: proc(r: rune) -> bool #inline {
|
is_digit :: proc(r: rune) -> bool #inline {
|
||||||
@@ -703,23 +706,26 @@ fmt_enum :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
|||||||
case 'd', 'f':
|
case 'd', 'f':
|
||||||
fmt_arg(fi, any{v.data, type_info_base(e.base)}, verb);
|
fmt_arg(fi, any{v.data, type_info_base(e.base)}, verb);
|
||||||
case 's', 'v':
|
case 's', 'v':
|
||||||
i: i64;
|
i: i128;
|
||||||
f: f64;
|
f: f64;
|
||||||
ok := false;
|
ok := false;
|
||||||
a := any{v.data, type_info_base(e.base)};
|
a := any{v.data, type_info_base(e.base)};
|
||||||
match v in a {
|
match v in a {
|
||||||
case i8: i = i64(v);
|
case i8: i = i128(v);
|
||||||
case i16: i = i64(v);
|
case i16: i = i128(v);
|
||||||
case i32: i = i64(v);
|
case i32: i = i128(v);
|
||||||
case i64: i = i64(v);
|
case i64: i = i128(v);
|
||||||
case int: i = i64(v);
|
case i128: i = i128(v);
|
||||||
case u8: i = i64(v);
|
case int: i = i128(v);
|
||||||
case u16: i = i64(v);
|
case u8: i = i128(v);
|
||||||
case u32: i = i64(v);
|
case u16: i = i128(v);
|
||||||
case u64: i = i64(v);
|
case u32: i = i128(v);
|
||||||
case uint: i = i64(v);
|
case u64: i = i128(v);
|
||||||
case f32: f = f64(v); i = transmute(i64, f);
|
case u128: i = i128(v);
|
||||||
case f64: f = f64(v); i = transmute(i64, f);
|
case uint: i = i128(v);
|
||||||
|
|
||||||
|
case f32: f = f64(v); i = i128(transmute(i64, f));
|
||||||
|
case f64: f = f64(v); i = i128(transmute(i64, f));
|
||||||
}
|
}
|
||||||
|
|
||||||
if types.is_string(e.base) {
|
if types.is_string(e.base) {
|
||||||
|
|||||||
+18
-5
@@ -2250,6 +2250,23 @@ bool check_is_vector_elem(Checker *c, AstNode *expr) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool check_is_not_addressable(Checker *c, Operand *o) {
|
||||||
|
if (o->mode != Addressing_Variable) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (is_type_bit_field_value(o->type)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (check_is_expr_vector_index(c, o->expr)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (check_is_vector_elem(c, o->expr)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
|
void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
|
||||||
switch (op.kind) {
|
switch (op.kind) {
|
||||||
case Token_And: { // Pointer address
|
case Token_And: { // Pointer address
|
||||||
@@ -2257,11 +2274,7 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
|
|||||||
o->type = make_type_pointer(c->allocator, o->type);
|
o->type = make_type_pointer(c->allocator, o->type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (check_is_not_addressable(c, o)) {
|
||||||
if (o->mode != Addressing_Variable ||
|
|
||||||
check_is_expr_vector_index(c, o->expr) ||
|
|
||||||
check_is_vector_elem(c, o->expr) ||
|
|
||||||
is_type_bit_field_value(o->type)) {
|
|
||||||
if (ast_node_expect(node, AstNode_UnaryExpr)) {
|
if (ast_node_expect(node, AstNode_UnaryExpr)) {
|
||||||
ast_node(ue, UnaryExpr, node);
|
ast_node(ue, UnaryExpr, node);
|
||||||
gbString str = expr_to_string(ue->expr);
|
gbString str = expr_to_string(ue->expr);
|
||||||
|
|||||||
+2
-1
@@ -310,8 +310,8 @@ typedef struct CheckerInfo {
|
|||||||
MapEntity uses; // Key: AstNode * | Identifier -> Entity
|
MapEntity uses; // Key: AstNode * | Identifier -> Entity
|
||||||
MapScope scopes; // Key: AstNode * | Node -> Scope
|
MapScope scopes; // Key: AstNode * | Node -> Scope
|
||||||
MapExprInfo untyped; // Key: AstNode * | Expression -> ExprInfo
|
MapExprInfo untyped; // Key: AstNode * | Expression -> ExprInfo
|
||||||
MapDeclInfo entities; // Key: Entity *
|
|
||||||
MapEntity implicits; // Key: AstNode *
|
MapEntity implicits; // Key: AstNode *
|
||||||
|
MapDeclInfo entities; // Key: Entity *
|
||||||
MapEntity foreigns; // Key: String
|
MapEntity foreigns; // Key: String
|
||||||
MapAstFile files; // Key: String (full path)
|
MapAstFile files; // Key: String (full path)
|
||||||
MapIsize type_info_map; // Key: Type *
|
MapIsize type_info_map; // Key: Type *
|
||||||
@@ -698,6 +698,7 @@ void init_universal_scope(void) {
|
|||||||
t_u8_ptr = make_type_pointer(a, t_u8);
|
t_u8_ptr = make_type_pointer(a, t_u8);
|
||||||
t_int_ptr = make_type_pointer(a, t_int);
|
t_int_ptr = make_type_pointer(a, t_int);
|
||||||
t_i64_ptr = make_type_pointer(a, t_i64);
|
t_i64_ptr = make_type_pointer(a, t_i64);
|
||||||
|
t_i128_ptr = make_type_pointer(a, t_i128);
|
||||||
t_f64_ptr = make_type_pointer(a, t_f64);
|
t_f64_ptr = make_type_pointer(a, t_f64);
|
||||||
t_byte_slice = make_type_slice(a, t_byte);
|
t_byte_slice = make_type_slice(a, t_byte);
|
||||||
t_string_slice = make_type_slice(a, t_string);
|
t_string_slice = make_type_slice(a, t_string);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ gbAllocator heap_allocator(void) {
|
|||||||
#include "string.c"
|
#include "string.c"
|
||||||
#include "array.c"
|
#include "array.c"
|
||||||
#include "integer128.c"
|
#include "integer128.c"
|
||||||
|
#include "murmurhash3.c"
|
||||||
|
|
||||||
gb_global String global_module_path = {0};
|
gb_global String global_module_path = {0};
|
||||||
gb_global bool global_module_path_set = false;
|
gb_global bool global_module_path_set = false;
|
||||||
|
|||||||
@@ -1656,14 +1656,15 @@ irValue *ir_gen_map_header(irProcedure *proc, irValue *map_val, Type *map_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_gen_map_key(irProcedure *proc, irValue *key, Type *key_type) {
|
irValue *ir_gen_map_key(irProcedure *proc, irValue *key, Type *key_type) {
|
||||||
|
Type *hash_type = t_u128;
|
||||||
irValue *v = ir_add_local_generated(proc, t_map_key);
|
irValue *v = ir_add_local_generated(proc, t_map_key);
|
||||||
Type *t = base_type(ir_type(key));
|
Type *t = base_type(ir_type(key));
|
||||||
key = ir_emit_conv(proc, key, key_type);
|
key = ir_emit_conv(proc, key, key_type);
|
||||||
if (is_type_integer(t)) {
|
if (is_type_integer(t)) {
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, key, t_u64));
|
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, key, hash_type));
|
||||||
} else if (is_type_pointer(t)) {
|
} else if (is_type_pointer(t)) {
|
||||||
irValue *p = ir_emit_conv(proc, key, t_uint);
|
irValue *p = ir_emit_conv(proc, key, t_uint);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, p, t_u64));
|
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, p, hash_type));
|
||||||
} else if (is_type_float(t)) {
|
} else if (is_type_float(t)) {
|
||||||
irValue *bits = NULL;
|
irValue *bits = NULL;
|
||||||
i64 size = type_size_of(proc->module->allocator, t);
|
i64 size = type_size_of(proc->module->allocator, t);
|
||||||
@@ -1673,7 +1674,7 @@ irValue *ir_gen_map_key(irProcedure *proc, irValue *key, Type *key_type) {
|
|||||||
default: GB_PANIC("Unhandled float size: %lld bits", size); break;
|
default: GB_PANIC("Unhandled float size: %lld bits", size); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, bits, t_u64));
|
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, bits, hash_type));
|
||||||
} else if (is_type_string(t)) {
|
} else if (is_type_string(t)) {
|
||||||
irValue *str = ir_emit_conv(proc, key, t_string);
|
irValue *str = ir_emit_conv(proc, key, t_string);
|
||||||
irValue *hashed_str = NULL;
|
irValue *hashed_str = NULL;
|
||||||
@@ -7823,9 +7824,8 @@ void ir_gen_tree(irGen *s) {
|
|||||||
ExactValue value = fields[i]->Constant.value;
|
ExactValue value = fields[i]->Constant.value;
|
||||||
|
|
||||||
if (is_value_int) {
|
if (is_value_int) {
|
||||||
i64 i = i128_to_i64(value.value_integer);
|
value_ep = ir_emit_conv(proc, value_ep, t_i128_ptr);
|
||||||
value_ep = ir_emit_conv(proc, value_ep, t_i64_ptr);
|
ir_emit_store(proc, value_ep, ir_value_constant(a, t_i128, value));
|
||||||
ir_emit_store(proc, value_ep, ir_const_i64(a, i));
|
|
||||||
} else {
|
} else {
|
||||||
GB_ASSERT(is_type_float(t->Record.enum_base_type));
|
GB_ASSERT(is_type_float(t->Record.enum_base_type));
|
||||||
f64 f = value.value_float;
|
f64 f = value.value_float;
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ gb_inline HashKey hashing_proc(void const *data, isize len) {
|
|||||||
h.kind = HashKey_Default;
|
h.kind = HashKey_Default;
|
||||||
// h.key = gb_murmur64(data, len);
|
// h.key = gb_murmur64(data, len);
|
||||||
h.key = gb_fnv64a(data, len);
|
h.key = gb_fnv64a(data, len);
|
||||||
|
// h.key = MurmurHash3_128(data, len, 0x3803cb8e);
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +53,7 @@ gb_inline HashKey hash_string(String s) {
|
|||||||
|
|
||||||
gb_inline HashKey hash_pointer(void *ptr) {
|
gb_inline HashKey hash_pointer(void *ptr) {
|
||||||
HashKey h = {HashKey_Default};
|
HashKey h = {HashKey_Default};
|
||||||
|
// h.key = u128_from_u64(cast(u64)cast(uintptr)ptr);
|
||||||
h.key = cast(u64)cast(uintptr)ptr;
|
h.key = cast(u64)cast(uintptr)ptr;
|
||||||
h.ptr = ptr;
|
h.ptr = ptr;
|
||||||
h.kind = HashKey_Default;
|
h.kind = HashKey_Default;
|
||||||
|
|||||||
+2
-2
@@ -307,6 +307,7 @@ gb_global Type *t_rune = &basic_type_aliases[1];
|
|||||||
gb_global Type *t_u8_ptr = NULL;
|
gb_global Type *t_u8_ptr = NULL;
|
||||||
gb_global Type *t_int_ptr = NULL;
|
gb_global Type *t_int_ptr = NULL;
|
||||||
gb_global Type *t_i64_ptr = NULL;
|
gb_global Type *t_i64_ptr = NULL;
|
||||||
|
gb_global Type *t_i128_ptr = NULL;
|
||||||
gb_global Type *t_f64_ptr = NULL;
|
gb_global Type *t_f64_ptr = NULL;
|
||||||
gb_global Type *t_byte_slice = NULL;
|
gb_global Type *t_byte_slice = NULL;
|
||||||
gb_global Type *t_string_slice = NULL;
|
gb_global Type *t_string_slice = NULL;
|
||||||
@@ -874,8 +875,7 @@ bool is_type_valid_for_keys(Type *t) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (is_type_integer(t)) {
|
if (is_type_integer(t)) {
|
||||||
// NOTE(bill): Not (u|i)128
|
return true;
|
||||||
return t->Basic.size <= 8;
|
|
||||||
}
|
}
|
||||||
if (is_type_float(t)) {
|
if (is_type_float(t)) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user