Begin work on implementing the new map internals

This commit is contained in:
gingerBill
2022-11-07 23:02:21 +00:00
parent f1c24f434b
commit c96e0afbf1
13 changed files with 832 additions and 492 deletions
+2
View File
@@ -2072,6 +2072,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
if info.generated_struct == nil { if info.generated_struct == nil {
return return
} }
/*
entries := &m.entries entries := &m.entries
gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct) gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct)
ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array) ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array)
@@ -2106,6 +2107,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
value := data + entry_type.offsets[3] // value: Value value := data + entry_type.offsets[3] // value: Value
fmt_arg(fi, any{rawptr(value), info.value.id}, 'v') fmt_arg(fi, any{rawptr(value), info.value.id}, 'v')
} }
*/
} }
case runtime.Type_Info_Struct: case runtime.Type_Info_Struct:
+10 -11
View File
@@ -112,22 +112,21 @@ query_info :: proc(pointer: rawptr, allocator: Allocator, loc := #caller_locatio
delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) { delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
free(raw_data(str), allocator, loc) return free(raw_data(str), allocator, loc)
} }
delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) { delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
free((^byte)(str), allocator, loc) return free((^byte)(str), allocator, loc)
} }
delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) { delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) -> Allocator_Error {
free(raw_data(array), array.allocator, loc) return free(raw_data(array), array.allocator, loc)
} }
delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) { delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
free(raw_data(array), allocator, loc) return free(raw_data(array), allocator, loc)
} }
delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) { delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error {
raw := transmute(Raw_Map)m raw := transmute(Raw_Map)m
delete_slice(raw.hashes, raw.entries.allocator, loc) return runtime.map_free(raw, loc)
free(raw.entries.data, raw.entries.allocator, loc)
} }
+2 -2
View File
@@ -273,7 +273,7 @@ length :: proc(val: any) -> int {
return (^runtime.Raw_Dynamic_Array)(val.data).len return (^runtime.Raw_Dynamic_Array)(val.data).len
case Type_Info_Map: case Type_Info_Map:
return (^runtime.Raw_Map)(val.data).entries.len return runtime.map_len((^runtime.Raw_Map)(val.data)^)
case Type_Info_String: case Type_Info_String:
if a.is_cstring { if a.is_cstring {
@@ -305,7 +305,7 @@ capacity :: proc(val: any) -> int {
return (^runtime.Raw_Dynamic_Array)(val.data).cap return (^runtime.Raw_Dynamic_Array)(val.data).cap
case Type_Info_Map: case Type_Info_Map:
return (^runtime.Raw_Map)(val.data).entries.cap return runtime.map_cap((^runtime.Raw_Map)(val.data)^)
} }
return 0 return 0
} }
+25 -2
View File
@@ -394,9 +394,32 @@ Raw_Dynamic_Array :: struct {
allocator: Allocator, allocator: Allocator,
} }
// The raw, type-erased representation of a map.
//
// 32-bytes on 64-bit
// 16-bytes on 32-bit
Raw_Map :: struct { Raw_Map :: struct {
hashes: []Map_Index, // A single allocation spanning all keys, values, and hashes.
entries: Raw_Dynamic_Array, // {
// k: Map_Cell(K) * (capacity / ks_per_cell)
// v: Map_Cell(V) * (capacity / vs_per_cell)
// h: Map_Cell(H) * (capacity / hs_per_cell)
// }
//
// The data is allocated assuming 64-byte alignment, meaning the address is
// always a multiple of 64. This means we have 6 bits of zeros in the pointer
// to store the capacity. We can store a value as large as 2^6-1 or 63 in
// there. This conveniently is the maximum log2 capacity we can have for a map
// as Odin uses signed integers to represent capacity.
//
// Since the hashes are backed by Map_Hash, which is just a 64-bit unsigned
// integer, the cell structure for hashes is unnecessary because 64/8 is 8 and
// requires no padding, meaning it can be indexed as a regular array of
// Map_Hash directly, though for consistency sake it's written as if it were
// an array of Map_Cell(Map_Hash).
data: uintptr, // 8-bytes on 64-bits, 4-bytes on 32-bits
len: uintptr, // 8-bytes on 64-bits, 4-bytes on 32-bits
allocator: Allocator, // 16-bytes on 64-bits, 8-bytes on 32-bits
} }
Raw_Any :: struct { Raw_Any :: struct {
+6 -31
View File
@@ -159,20 +159,7 @@ delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #cal
} }
@builtin @builtin
delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error { delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error {
Entry :: struct { return map_free(transmute(Raw_Map)m, loc)
hash: uintptr,
next: int,
key: K,
value: V,
}
raw := transmute(Raw_Map)m
err := delete_slice(raw.hashes, raw.entries.allocator, loc)
err1 := mem_free_with_size(raw.entries.data, raw.entries.cap*size_of(Entry), raw.entries.allocator, loc)
if err == nil {
err = err1
}
return err
} }
@@ -285,19 +272,13 @@ clear_map :: proc "contextless" (m: ^$T/map[$K]$V) {
if m == nil { if m == nil {
return return
} }
raw_map := (^Raw_Map)(m) map_clear_dynamic((^Raw_Map)(m), map_info(K, V))
entries := (^Raw_Dynamic_Array)(&raw_map.entries)
entries.len = 0
for _, i in raw_map.hashes {
raw_map.hashes[i] = MAP_SENTINEL
}
} }
@builtin @builtin
reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int, loc := #caller_location) { reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int, loc := #caller_location) {
if m != nil { if m != nil {
h := __get_map_header_table(T) __dynamic_map_reserve((^Raw_Map)(m), map_info(K, V), uint(capacity), loc)
__dynamic_map_reserve(m, h, uint(capacity), loc)
} }
} }
@@ -325,15 +306,9 @@ shrink_map :: proc(m: ^$T/map[$K]$V, new_cap := -1, loc := #caller_location) ->
delete_key :: proc(m: ^$T/map[$K]$V, key: K) -> (deleted_key: K, deleted_value: V) { delete_key :: proc(m: ^$T/map[$K]$V, key: K) -> (deleted_key: K, deleted_value: V) {
if m != nil { if m != nil {
key := key key := key
h := __get_map_header(m) info := map_info(K, V)
fr := __map_find(h, &key) _ = map_erase_dynamic((^Raw_Map)(m), info, uintptr(&key))
if fr.entry_index != MAP_SENTINEL { // TODO(bill) old key and value
entry := __dynamic_map_get_entry(h, fr.entry_index)
deleted_key = (^K)(uintptr(entry)+h.key_offset)^
deleted_value = (^V)(uintptr(entry)+h.value_offset)^
__dynamic_map_erase(h, fr)
}
} }
return return
} }
File diff suppressed because it is too large Load Diff
-1
View File
@@ -1364,7 +1364,6 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source,
bool key = is_polymorphic_type_assignable(c, poly->Map.key, source->Map.key, true, modify_type); bool key = is_polymorphic_type_assignable(c, poly->Map.key, source->Map.key, true, modify_type);
bool value = is_polymorphic_type_assignable(c, poly->Map.value, source->Map.value, true, modify_type); bool value = is_polymorphic_type_assignable(c, poly->Map.value, source->Map.value, true, modify_type);
if (key || value) { if (key || value) {
poly->Map.entry_type = nullptr;
poly->Map.internal_type = nullptr; poly->Map.internal_type = nullptr;
poly->Map.lookup_result_type = nullptr; poly->Map.lookup_result_type = nullptr;
init_map_internal_types(poly); init_map_internal_types(poly);
+8 -41
View File
@@ -2176,40 +2176,9 @@ Type *make_optional_ok_type(Type *value, bool typed) {
return t; return t;
} }
void init_map_entry_type(Type *type) {
GB_ASSERT(type->kind == Type_Map);
if (type->Map.entry_type != nullptr) return;
// NOTE(bill): The preload types may have not been set yet
GB_ASSERT(t_map_hash != nullptr);
/*
struct {
hash: uintptr,
next: int,
key: Key,
value: Value,
}
*/
Scope *s = create_scope(nullptr, builtin_pkg->scope);
auto fields = slice_make<Entity *>(permanent_allocator(), 4);
fields[0] = alloc_entity_field(s, make_token_ident(str_lit("hash")), t_uintptr, false, 0, EntityState_Resolved);
fields[1] = alloc_entity_field(s, make_token_ident(str_lit("next")), t_int, false, 1, EntityState_Resolved);
fields[2] = alloc_entity_field(s, make_token_ident(str_lit("key")), type->Map.key, false, 2, EntityState_Resolved);
fields[3] = alloc_entity_field(s, make_token_ident(str_lit("value")), type->Map.value, false, 3, EntityState_Resolved);
Type *entry_type = alloc_type_struct();
entry_type->Struct.fields = fields;
entry_type->Struct.tags = gb_alloc_array(permanent_allocator(), String, fields.count);
type_set_offsets(entry_type);
type->Map.entry_type = entry_type;
}
void init_map_internal_types(Type *type) { void init_map_internal_types(Type *type) {
GB_ASSERT(type->kind == Type_Map); GB_ASSERT(type->kind == Type_Map);
init_map_entry_type(type); GB_ASSERT(t_allocator != nullptr);
if (type->Map.internal_type != nullptr) return; if (type->Map.internal_type != nullptr) return;
Type *key = type->Map.key; Type *key = type->Map.key;
@@ -2221,19 +2190,17 @@ void init_map_internal_types(Type *type) {
/* /*
struct { struct {
hashes: []int; data: uintptr,
entries: [dynamic]EntryType; size: uintptr,
allocator: runtime.Allocator,
} }
*/ */
Scope *s = create_scope(nullptr, builtin_pkg->scope); Scope *s = create_scope(nullptr, builtin_pkg->scope);
Type *hashes_type = alloc_type_slice(t_int); auto fields = slice_make<Entity *>(permanent_allocator(), 3);
Type *entries_type = alloc_type_dynamic_array(type->Map.entry_type); fields[0] = alloc_entity_field(s, make_token_ident(str_lit("data")), t_uintptr, false, 0, EntityState_Resolved);
fields[1] = alloc_entity_field(s, make_token_ident(str_lit("size")), t_uintptr, false, 1, EntityState_Resolved);
fields[2] = alloc_entity_field(s, make_token_ident(str_lit("allocator")), t_allocator, false, 2, EntityState_Resolved);
auto fields = slice_make<Entity *>(permanent_allocator(), 2);
fields[0] = alloc_entity_field(s, make_token_ident(str_lit("hashes")), hashes_type, false, 0, EntityState_Resolved);
fields[1] = alloc_entity_field(s, make_token_ident(str_lit("entries")), entries_type, false, 1, EntityState_Resolved);
generated_struct_type->Struct.fields = fields; generated_struct_type->Struct.fields = fields;
type_set_offsets(generated_struct_type); type_set_offsets(generated_struct_type);
+4 -4
View File
@@ -2842,12 +2842,12 @@ void init_core_source_code_location(Checker *c) {
} }
void init_core_map_type(Checker *c) { void init_core_map_type(Checker *c) {
if (t_map_hash != nullptr) { if (t_map_info != nullptr) {
return; return;
} }
t_map_hash = find_core_type(c, str_lit("Map_Hash")); t_map_info = find_core_type(c, str_lit("Map_Info"));
t_map_header = find_core_type(c, str_lit("Map_Header")); t_map_cell_info = find_core_type(c, str_lit("Map_Cell_Info"));
t_map_header_table = find_core_type(c, str_lit("Map_Header_Table")); init_mem_allocator(c);
} }
void init_preload(Checker *c) { void init_preload(Checker *c) {
+63 -47
View File
@@ -298,7 +298,7 @@ lbValue lb_simple_compare_hash(lbProcedure *p, Type *type, lbValue data, lbValue
lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) { lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
type = core_type(type); type = core_type(type);
GB_ASSERT(is_type_valid_for_keys(type)); GB_ASSERT_MSG(is_type_valid_for_keys(type), "%s", type_to_string(type));
Type *pt = alloc_type_pointer(type); Type *pt = alloc_type_pointer(type);
@@ -500,51 +500,67 @@ lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, A
return value; return value;
} }
lbValue lb_gen_map_header_table_internal(lbProcedure *p, Type *map_type) { // IMPORTANT NOTE(bill): This must match the definition in dynamic_map_internal.odin
enum : i64 {
MAP_CACHE_LINE_LOG2 = 6,
MAP_CACHE_LINE_SIZE = 1 << MAP_CACHE_LINE_LOG2
};
GB_STATIC_ASSERT(MAP_CACHE_LINE_SIZE >= 64);
void lb_map_cell_size_and_len(Type *type, i64 *size_, i64 *len_) {
i64 elem_sz = type_size_of(type);
i64 len = 1;
if (0 < elem_sz && elem_sz < MAP_CACHE_LINE_SIZE) {
len = MAP_CACHE_LINE_SIZE / elem_sz;
}
i64 size = align_formula(elem_sz * len, MAP_CACHE_LINE_SIZE);
if (size_) *size_ = size;
if (len_) *len_ = len;
}
LLVMValueRef lb_gen_map_cell_info(lbModule *m, Type *type) {
i64 size = 0, len = 0;
lb_map_cell_size_and_len(type, &size, &len);
LLVMValueRef const_values[4] = {};
const_values[0] = lb_const_int(m, t_uintptr, type_size_of(type)).value;
const_values[1] = lb_const_int(m, t_uintptr, type_align_of(type)).value;
const_values[2] = lb_const_int(m, t_uintptr, size).value;
const_values[3] = lb_const_int(m, t_uintptr, len).value;
return llvm_const_named_struct(m, t_map_cell_info, const_values, gb_count_of(const_values));
}
lbValue lb_gen_map_info_ptr(lbProcedure *p, Type *map_type) {
lbModule *m = p->module; lbModule *m = p->module;
map_type = base_type(map_type); map_type = base_type(map_type);
GB_ASSERT(map_type->kind == Type_Map); GB_ASSERT(map_type->kind == Type_Map);
lbAddr *found = map_get(&m->map_header_table_map, map_type); lbAddr *found = map_get(&m->map_info_map, map_type);
if (found) { if (found) {
return lb_addr_load(p, *found); return lb_addr_get_ptr(p, *found);
} }
GB_ASSERT(map_type->Map.entry_type->kind == Type_Struct); GB_ASSERT(t_map_info != nullptr);
i64 entry_size = type_size_of (map_type->Map.entry_type); GB_ASSERT(t_map_cell_info != nullptr);
i64 entry_align = type_align_of (map_type->Map.entry_type);
i64 key_offset = type_offset_of(map_type->Map.entry_type, 2); LLVMValueRef key_cell_info = lb_gen_map_cell_info(m, map_type->Map.key);
i64 key_size = type_size_of (map_type->Map.key); LLVMValueRef value_cell_info = lb_gen_map_cell_info(m, map_type->Map.value);
i64 value_offset = type_offset_of(map_type->Map.entry_type, 3); LLVMValueRef const_values[4] = {};
i64 value_size = type_size_of (map_type->Map.value); const_values[0] = key_cell_info;
const_values[1] = value_cell_info;
const_values[2] = lb_get_hasher_proc_for_type(m, map_type->Map.key).value;
const_values[3] = lb_get_equal_proc_for_type(m, map_type->Map.key).value;
Type *key_type = map_type->Map.key; LLVMValueRef llvm_res = llvm_const_named_struct(m, t_map_info, const_values, gb_count_of(const_values));
Type *val_type = map_type->Map.value; lbValue res = {llvm_res, t_map_info};
gb_unused(val_type);
Type *st = base_type(t_map_header_table); lbAddr addr = lb_add_global_generated(m, t_map_info, res, nullptr);
GB_ASSERT(st->Struct.fields.count == 7);
LLVMValueRef const_values[7] = {};
const_values[0] = lb_get_equal_proc_for_type(m, key_type) .value;
const_values[1] = lb_const_int(m, t_int, entry_size) .value;
const_values[2] = lb_const_int(m, t_int, entry_align) .value;
const_values[3] = lb_const_int(m, t_uintptr, key_offset) .value;
const_values[4] = lb_const_int(m, t_int, key_size) .value;
const_values[5] = lb_const_int(m, t_uintptr, value_offset).value;
const_values[6] = lb_const_int(m, t_int, value_size) .value;
LLVMValueRef llvm_res = llvm_const_named_struct(m, t_map_header_table, const_values, gb_count_of(const_values));
lbValue res = {llvm_res, t_map_header_table};
lbAddr addr = lb_add_global_generated(m, t_map_header_table, res, nullptr);
lb_make_global_private_const(addr); lb_make_global_private_const(addr);
map_set(&m->map_header_table_map, map_type, addr); map_set(&m->map_info_map, map_type, addr);
return lb_addr_load(p, addr); return lb_addr_get_ptr(p, addr);
} }
lbValue lb_const_hash(lbModule *m, lbValue key, Type *key_type) { lbValue lb_const_hash(lbModule *m, lbValue key, Type *key_type) {
@@ -616,12 +632,13 @@ lbValue lb_gen_map_key_hash(lbProcedure *p, lbValue key, Type *key_type, lbValue
lbValue lb_internal_dynamic_map_get_ptr(lbProcedure *p, lbValue const &map_ptr, lbValue const &key) { lbValue lb_internal_dynamic_map_get_ptr(lbProcedure *p, lbValue const &map_ptr, lbValue const &key) {
Type *map_type = base_type(type_deref(map_ptr.type)); Type *map_type = base_type(type_deref(map_ptr.type));
lbValue key_ptr = {}; lbValue key_ptr = lb_address_from_load_or_generate_local(p, key);
auto args = array_make<lbValue>(permanent_allocator(), 4); key_ptr = lb_emit_conv(p, key_ptr, t_rawptr);
auto args = array_make<lbValue>(permanent_allocator(), 3);
args[0] = lb_emit_conv(p, map_ptr, t_rawptr); args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = lb_gen_map_header_table_internal(p, map_type); args[1] = lb_gen_map_info_ptr(p, map_type);
args[2] = lb_gen_map_key_hash(p, key, map_type->Map.key, &key_ptr); args[2] = key_ptr;
args[3] = key_ptr;
lbValue ptr = lb_emit_runtime_call(p, "__dynamic_map_get", args); lbValue ptr = lb_emit_runtime_call(p, "__dynamic_map_get", args);
@@ -633,20 +650,19 @@ void lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbValue const &map_ptr,
map_type = base_type(map_type); map_type = base_type(map_type);
GB_ASSERT(map_type->kind == Type_Map); GB_ASSERT(map_type->kind == Type_Map);
lbValue key_ptr = {}; lbValue key_ptr = lb_address_from_load_or_generate_local(p, map_key);
lbValue key_hash = lb_gen_map_key_hash(p, map_key, map_type->Map.key, &key_ptr); key_ptr = lb_emit_conv(p, key_ptr, t_rawptr);
lbValue v = lb_emit_conv(p, map_value, map_type->Map.value); lbValue v = lb_emit_conv(p, map_value, map_type->Map.value);
lbAddr value_addr = lb_add_local_generated(p, v.type, false); lbAddr value_addr = lb_add_local_generated(p, v.type, false);
lb_addr_store(p, value_addr, v); lb_addr_store(p, value_addr, v);
auto args = array_make<lbValue>(permanent_allocator(), 6); auto args = array_make<lbValue>(permanent_allocator(), 5);
args[0] = lb_emit_conv(p, map_ptr, t_rawptr); args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = lb_gen_map_header_table_internal(p, map_type); args[1] = lb_gen_map_info_ptr(p, map_type);
args[2] = key_hash; args[2] = key_ptr;
args[3] = key_ptr; args[3] = lb_emit_conv(p, value_addr.addr, t_rawptr);
args[4] = lb_emit_conv(p, value_addr.addr, t_rawptr); args[4] = lb_emit_source_code_location_as_global(p, node);
args[5] = lb_emit_source_code_location_as_global(p, node);
lb_emit_runtime_call(p, "__dynamic_map_set", args); lb_emit_runtime_call(p, "__dynamic_map_set", args);
} }
@@ -660,8 +676,8 @@ void lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const
auto args = array_make<lbValue>(permanent_allocator(), 4); auto args = array_make<lbValue>(permanent_allocator(), 4);
args[0] = lb_emit_conv(p, map_ptr, t_rawptr); args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = lb_gen_map_header_table_internal(p, type_deref(map_ptr.type)); args[1] = lb_gen_map_info_ptr(p, type_deref(map_ptr.type));
args[2] = lb_const_int(p->module, t_int, capacity); args[2] = lb_const_int(p->module, t_uint, capacity);
args[3] = lb_emit_source_code_location_as_global(p, proc_name, pos); args[3] = lb_emit_source_code_location_as_global(p, proc_name, pos);
lb_emit_runtime_call(p, "__dynamic_map_reserve", args); lb_emit_runtime_call(p, "__dynamic_map_reserve", args);
} }
+1 -1
View File
@@ -160,7 +160,7 @@ struct lbModule {
StringMap<lbAddr> objc_classes; StringMap<lbAddr> objc_classes;
StringMap<lbAddr> objc_selectors; StringMap<lbAddr> objc_selectors;
PtrMap<Type *, lbAddr> map_header_table_map; PtrMap<Type *, lbAddr> map_info_map;
}; };
struct lbGenerator { struct lbGenerator {
+5 -19
View File
@@ -75,7 +75,7 @@ void lb_init_module(lbModule *m, Checker *c) {
string_map_init(&m->objc_classes, a); string_map_init(&m->objc_classes, a);
string_map_init(&m->objc_selectors, a); string_map_init(&m->objc_selectors, a);
map_init(&m->map_header_table_map, a, 0); map_init(&m->map_info_map, a, 0);
} }
@@ -1939,28 +1939,14 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
defer (m->internal_type_level += 1); defer (m->internal_type_level += 1);
unsigned field_count = cast(unsigned)(internal_type->Struct.fields.count); unsigned field_count = cast(unsigned)(internal_type->Struct.fields.count);
GB_ASSERT(field_count == 2); GB_ASSERT(field_count == 3);
LLVMTypeRef *fields = gb_alloc_array(temporary_allocator(), LLVMTypeRef, field_count);
LLVMTypeRef entries_fields[] = { LLVMTypeRef fields[3] = {
lb_type(m, t_rawptr), // data lb_type(m, t_uintptr), // data
lb_type(m, t_int), // len lb_type(m, t_uintptr), // len
lb_type(m, t_int), // cap
lb_type(m, t_allocator), // allocator lb_type(m, t_allocator), // allocator
}; };
fields[0] = lb_type(m, internal_type->Struct.fields[0]->type);
fields[1] = LLVMStructTypeInContext(ctx, entries_fields, gb_count_of(entries_fields), false);
{ // Add this to simplify things
lbStructFieldRemapping entries_field_remapping = {};
slice_init(&entries_field_remapping, permanent_allocator(), gb_count_of(entries_fields));
for_array(i, entries_field_remapping) {
entries_field_remapping[i] = cast(i32)i;
}
map_set(&m->struct_field_remapping, cast(void *)fields[1], entries_field_remapping);
}
return LLVMStructTypeInContext(ctx, fields, field_count, false); return LLVMStructTypeInContext(ctx, fields, field_count, false);
} }
+8 -14
View File
@@ -226,7 +226,6 @@ struct TypeProc {
TYPE_KIND(Map, struct { \ TYPE_KIND(Map, struct { \
Type *key; \ Type *key; \
Type *value; \ Type *value; \
Type *entry_type; \
Type *internal_type; \ Type *internal_type; \
Type *lookup_result_type; \ Type *lookup_result_type; \
}) \ }) \
@@ -685,9 +684,8 @@ gb_global Type *t_allocator_error = nullptr;
gb_global Type *t_source_code_location = nullptr; gb_global Type *t_source_code_location = nullptr;
gb_global Type *t_source_code_location_ptr = nullptr; gb_global Type *t_source_code_location_ptr = nullptr;
gb_global Type *t_map_hash = nullptr; gb_global Type *t_map_info = nullptr;
gb_global Type *t_map_header = nullptr; gb_global Type *t_map_cell_info = nullptr;
gb_global Type *t_map_header_table = nullptr;
gb_global Type *t_equal_proc = nullptr; gb_global Type *t_equal_proc = nullptr;
@@ -3330,8 +3328,6 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
} }
} }
} else if (type->kind == Type_DynamicArray) { } else if (type->kind == Type_DynamicArray) {
// IMPORTANT TODO(bill): Should these members be available to should I only allow them with
// `Raw_Dynamic_Array` type?
GB_ASSERT(t_allocator != nullptr); GB_ASSERT(t_allocator != nullptr);
String allocator_str = str_lit("allocator"); String allocator_str = str_lit("allocator");
gb_local_persist Entity *entity__allocator = alloc_entity_field(nullptr, make_token_ident(allocator_str), t_allocator, false, 3); gb_local_persist Entity *entity__allocator = alloc_entity_field(nullptr, make_token_ident(allocator_str), t_allocator, false, 3);
@@ -3342,15 +3338,12 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
return sel; return sel;
} }
} else if (type->kind == Type_Map) { } else if (type->kind == Type_Map) {
// IMPORTANT TODO(bill): Should these members be available to should I only allow them with
// `Raw_Map` type?
GB_ASSERT(t_allocator != nullptr); GB_ASSERT(t_allocator != nullptr);
String allocator_str = str_lit("allocator"); String allocator_str = str_lit("allocator");
gb_local_persist Entity *entity__allocator = alloc_entity_field(nullptr, make_token_ident(allocator_str), t_allocator, false, 3); gb_local_persist Entity *entity__allocator = alloc_entity_field(nullptr, make_token_ident(allocator_str), t_allocator, false, 2);
if (field_name == allocator_str) { if (field_name == allocator_str) {
selection_add_index(&sel, 1); selection_add_index(&sel, 2);
selection_add_index(&sel, 3);
sel.entity = entity__allocator; sel.entity = entity__allocator;
return sel; return sel;
} }
@@ -3795,11 +3788,12 @@ i64 type_size_of_internal(Type *t, TypePath *path) {
case Type_Map: case Type_Map:
/* /*
struct { struct {
hashes: []int, // 2 words data: uintptr, // 1 word
entries: [dynamic]Entry_Type, // 5 words size: uintptr, // 1 word
allocator: runtime.Allocator, // 2 words
} }
*/ */
return (2 + (3 + 2))*build_context.word_size; return (1 + 1 + 2)*build_context.word_size;
case Type_Tuple: { case Type_Tuple: {
i64 count, align, size; i64 count, align, size;