mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-15 15:41:26 -07:00
Begin work on implementing the new map internals
This commit is contained in:
@@ -2072,6 +2072,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
|
||||
if info.generated_struct == nil {
|
||||
return
|
||||
}
|
||||
/*
|
||||
entries := &m.entries
|
||||
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)
|
||||
@@ -2106,6 +2107,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
|
||||
value := data + entry_type.offsets[3] // value: Value
|
||||
fmt_arg(fi, any{rawptr(value), info.value.id}, 'v')
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
case runtime.Type_Info_Struct:
|
||||
|
||||
+10
-11
@@ -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) {
|
||||
free(raw_data(str), allocator, loc)
|
||||
delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
||||
return free(raw_data(str), allocator, loc)
|
||||
}
|
||||
delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) {
|
||||
free((^byte)(str), allocator, loc)
|
||||
delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
||||
return free((^byte)(str), allocator, loc)
|
||||
}
|
||||
delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) {
|
||||
free(raw_data(array), array.allocator, loc)
|
||||
delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) -> Allocator_Error {
|
||||
return free(raw_data(array), array.allocator, loc)
|
||||
}
|
||||
delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) {
|
||||
free(raw_data(array), allocator, loc)
|
||||
delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
||||
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
|
||||
delete_slice(raw.hashes, raw.entries.allocator, loc)
|
||||
free(raw.entries.data, raw.entries.allocator, loc)
|
||||
return runtime.map_free(raw, loc)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ length :: proc(val: any) -> int {
|
||||
return (^runtime.Raw_Dynamic_Array)(val.data).len
|
||||
|
||||
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:
|
||||
if a.is_cstring {
|
||||
@@ -305,7 +305,7 @@ capacity :: proc(val: any) -> int {
|
||||
return (^runtime.Raw_Dynamic_Array)(val.data).cap
|
||||
|
||||
case Type_Info_Map:
|
||||
return (^runtime.Raw_Map)(val.data).entries.cap
|
||||
return runtime.map_cap((^runtime.Raw_Map)(val.data)^)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
+25
-2
@@ -394,9 +394,32 @@ Raw_Dynamic_Array :: struct {
|
||||
allocator: Allocator,
|
||||
}
|
||||
|
||||
// The raw, type-erased representation of a map.
|
||||
//
|
||||
// 32-bytes on 64-bit
|
||||
// 16-bytes on 32-bit
|
||||
Raw_Map :: struct {
|
||||
hashes: []Map_Index,
|
||||
entries: Raw_Dynamic_Array,
|
||||
// A single allocation spanning all keys, values, and hashes.
|
||||
// {
|
||||
// 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 {
|
||||
|
||||
@@ -159,20 +159,7 @@ delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #cal
|
||||
}
|
||||
@builtin
|
||||
delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error {
|
||||
Entry :: struct {
|
||||
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
|
||||
return map_free(transmute(Raw_Map)m, loc)
|
||||
}
|
||||
|
||||
|
||||
@@ -285,19 +272,13 @@ clear_map :: proc "contextless" (m: ^$T/map[$K]$V) {
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
raw_map := (^Raw_Map)(m)
|
||||
entries := (^Raw_Dynamic_Array)(&raw_map.entries)
|
||||
entries.len = 0
|
||||
for _, i in raw_map.hashes {
|
||||
raw_map.hashes[i] = MAP_SENTINEL
|
||||
}
|
||||
map_clear_dynamic((^Raw_Map)(m), map_info(K, V))
|
||||
}
|
||||
|
||||
@builtin
|
||||
reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int, loc := #caller_location) {
|
||||
if m != nil {
|
||||
h := __get_map_header_table(T)
|
||||
__dynamic_map_reserve(m, h, uint(capacity), loc)
|
||||
__dynamic_map_reserve((^Raw_Map)(m), map_info(K, V), 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) {
|
||||
if m != nil {
|
||||
key := key
|
||||
h := __get_map_header(m)
|
||||
fr := __map_find(h, &key)
|
||||
if fr.entry_index != MAP_SENTINEL {
|
||||
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)
|
||||
}
|
||||
info := map_info(K, V)
|
||||
_ = map_erase_dynamic((^Raw_Map)(m), info, uintptr(&key))
|
||||
// TODO(bill) old key and value
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 value = is_polymorphic_type_assignable(c, poly->Map.value, source->Map.value, true, modify_type);
|
||||
if (key || value) {
|
||||
poly->Map.entry_type = nullptr;
|
||||
poly->Map.internal_type = nullptr;
|
||||
poly->Map.lookup_result_type = nullptr;
|
||||
init_map_internal_types(poly);
|
||||
|
||||
+8
-41
@@ -2176,40 +2176,9 @@ Type *make_optional_ok_type(Type *value, bool typed) {
|
||||
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) {
|
||||
GB_ASSERT(type->kind == Type_Map);
|
||||
init_map_entry_type(type);
|
||||
GB_ASSERT(t_allocator != nullptr);
|
||||
if (type->Map.internal_type != nullptr) return;
|
||||
|
||||
Type *key = type->Map.key;
|
||||
@@ -2221,19 +2190,17 @@ void init_map_internal_types(Type *type) {
|
||||
|
||||
/*
|
||||
struct {
|
||||
hashes: []int;
|
||||
entries: [dynamic]EntryType;
|
||||
data: uintptr,
|
||||
size: uintptr,
|
||||
allocator: runtime.Allocator,
|
||||
}
|
||||
*/
|
||||
Scope *s = create_scope(nullptr, builtin_pkg->scope);
|
||||
|
||||
Type *hashes_type = alloc_type_slice(t_int);
|
||||
Type *entries_type = alloc_type_dynamic_array(type->Map.entry_type);
|
||||
|
||||
|
||||
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);
|
||||
auto fields = slice_make<Entity *>(permanent_allocator(), 3);
|
||||
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);
|
||||
|
||||
generated_struct_type->Struct.fields = fields;
|
||||
type_set_offsets(generated_struct_type);
|
||||
|
||||
+4
-4
@@ -2842,12 +2842,12 @@ void init_core_source_code_location(Checker *c) {
|
||||
}
|
||||
|
||||
void init_core_map_type(Checker *c) {
|
||||
if (t_map_hash != nullptr) {
|
||||
if (t_map_info != nullptr) {
|
||||
return;
|
||||
}
|
||||
t_map_hash = find_core_type(c, str_lit("Map_Hash"));
|
||||
t_map_header = find_core_type(c, str_lit("Map_Header"));
|
||||
t_map_header_table = find_core_type(c, str_lit("Map_Header_Table"));
|
||||
t_map_info = find_core_type(c, str_lit("Map_Info"));
|
||||
t_map_cell_info = find_core_type(c, str_lit("Map_Cell_Info"));
|
||||
init_mem_allocator(c);
|
||||
}
|
||||
|
||||
void init_preload(Checker *c) {
|
||||
|
||||
+63
-47
@@ -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) {
|
||||
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);
|
||||
|
||||
@@ -500,51 +500,67 @@ lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, A
|
||||
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;
|
||||
|
||||
map_type = base_type(map_type);
|
||||
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) {
|
||||
return lb_addr_load(p, *found);
|
||||
return lb_addr_get_ptr(p, *found);
|
||||
}
|
||||
|
||||
GB_ASSERT(map_type->Map.entry_type->kind == Type_Struct);
|
||||
i64 entry_size = type_size_of (map_type->Map.entry_type);
|
||||
i64 entry_align = type_align_of (map_type->Map.entry_type);
|
||||
GB_ASSERT(t_map_info != nullptr);
|
||||
GB_ASSERT(t_map_cell_info != nullptr);
|
||||
|
||||
i64 key_offset = type_offset_of(map_type->Map.entry_type, 2);
|
||||
i64 key_size = type_size_of (map_type->Map.key);
|
||||
LLVMValueRef key_cell_info = lb_gen_map_cell_info(m, 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);
|
||||
i64 value_size = type_size_of (map_type->Map.value);
|
||||
LLVMValueRef const_values[4] = {};
|
||||
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;
|
||||
Type *val_type = map_type->Map.value;
|
||||
gb_unused(val_type);
|
||||
LLVMValueRef llvm_res = llvm_const_named_struct(m, t_map_info, const_values, gb_count_of(const_values));
|
||||
lbValue res = {llvm_res, t_map_info};
|
||||
|
||||
Type *st = base_type(t_map_header_table);
|
||||
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);
|
||||
lbAddr addr = lb_add_global_generated(m, t_map_info, res, nullptr);
|
||||
lb_make_global_private_const(addr);
|
||||
|
||||
map_set(&m->map_header_table_map, map_type, addr);
|
||||
return lb_addr_load(p, addr);
|
||||
map_set(&m->map_info_map, map_type, addr);
|
||||
return lb_addr_get_ptr(p, addr);
|
||||
}
|
||||
|
||||
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) {
|
||||
Type *map_type = base_type(type_deref(map_ptr.type));
|
||||
|
||||
lbValue key_ptr = {};
|
||||
auto args = array_make<lbValue>(permanent_allocator(), 4);
|
||||
lbValue key_ptr = lb_address_from_load_or_generate_local(p, key);
|
||||
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[1] = lb_gen_map_header_table_internal(p, map_type);
|
||||
args[2] = lb_gen_map_key_hash(p, key, map_type->Map.key, &key_ptr);
|
||||
args[3] = key_ptr;
|
||||
args[1] = lb_gen_map_info_ptr(p, map_type);
|
||||
args[2] = key_ptr;
|
||||
|
||||
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);
|
||||
GB_ASSERT(map_type->kind == Type_Map);
|
||||
|
||||
lbValue key_ptr = {};
|
||||
lbValue key_hash = lb_gen_map_key_hash(p, map_key, map_type->Map.key, &key_ptr);
|
||||
lbValue key_ptr = lb_address_from_load_or_generate_local(p, map_key);
|
||||
key_ptr = lb_emit_conv(p, key_ptr, t_rawptr);
|
||||
lbValue v = lb_emit_conv(p, map_value, map_type->Map.value);
|
||||
|
||||
lbAddr value_addr = lb_add_local_generated(p, v.type, false);
|
||||
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[1] = lb_gen_map_header_table_internal(p, map_type);
|
||||
args[2] = key_hash;
|
||||
args[3] = key_ptr;
|
||||
args[4] = lb_emit_conv(p, value_addr.addr, t_rawptr);
|
||||
args[5] = lb_emit_source_code_location_as_global(p, node);
|
||||
args[1] = lb_gen_map_info_ptr(p, map_type);
|
||||
args[2] = key_ptr;
|
||||
args[3] = lb_emit_conv(p, value_addr.addr, t_rawptr);
|
||||
args[4] = lb_emit_source_code_location_as_global(p, node);
|
||||
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);
|
||||
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[2] = lb_const_int(p->module, t_int, capacity);
|
||||
args[1] = lb_gen_map_info_ptr(p, type_deref(map_ptr.type));
|
||||
args[2] = lb_const_int(p->module, t_uint, capacity);
|
||||
args[3] = lb_emit_source_code_location_as_global(p, proc_name, pos);
|
||||
lb_emit_runtime_call(p, "__dynamic_map_reserve", args);
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ struct lbModule {
|
||||
StringMap<lbAddr> objc_classes;
|
||||
StringMap<lbAddr> objc_selectors;
|
||||
|
||||
PtrMap<Type *, lbAddr> map_header_table_map;
|
||||
PtrMap<Type *, lbAddr> map_info_map;
|
||||
};
|
||||
|
||||
struct lbGenerator {
|
||||
|
||||
@@ -75,7 +75,7 @@ void lb_init_module(lbModule *m, Checker *c) {
|
||||
string_map_init(&m->objc_classes, 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,27 +1939,13 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
defer (m->internal_type_level += 1);
|
||||
|
||||
unsigned field_count = cast(unsigned)(internal_type->Struct.fields.count);
|
||||
GB_ASSERT(field_count == 2);
|
||||
LLVMTypeRef *fields = gb_alloc_array(temporary_allocator(), LLVMTypeRef, field_count);
|
||||
GB_ASSERT(field_count == 3);
|
||||
|
||||
LLVMTypeRef entries_fields[] = {
|
||||
lb_type(m, t_rawptr), // data
|
||||
lb_type(m, t_int), // len
|
||||
lb_type(m, t_int), // cap
|
||||
LLVMTypeRef fields[3] = {
|
||||
lb_type(m, t_uintptr), // data
|
||||
lb_type(m, t_uintptr), // len
|
||||
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);
|
||||
}
|
||||
|
||||
+8
-14
@@ -226,7 +226,6 @@ struct TypeProc {
|
||||
TYPE_KIND(Map, struct { \
|
||||
Type *key; \
|
||||
Type *value; \
|
||||
Type *entry_type; \
|
||||
Type *internal_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_ptr = nullptr;
|
||||
|
||||
gb_global Type *t_map_hash = nullptr;
|
||||
gb_global Type *t_map_header = nullptr;
|
||||
gb_global Type *t_map_header_table = nullptr;
|
||||
gb_global Type *t_map_info = nullptr;
|
||||
gb_global Type *t_map_cell_info = 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) {
|
||||
// IMPORTANT TODO(bill): Should these members be available to should I only allow them with
|
||||
// `Raw_Dynamic_Array` type?
|
||||
GB_ASSERT(t_allocator != nullptr);
|
||||
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);
|
||||
@@ -3342,15 +3338,12 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
|
||||
return sel;
|
||||
}
|
||||
} 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);
|
||||
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) {
|
||||
selection_add_index(&sel, 1);
|
||||
selection_add_index(&sel, 3);
|
||||
selection_add_index(&sel, 2);
|
||||
sel.entity = entity__allocator;
|
||||
return sel;
|
||||
}
|
||||
@@ -3795,11 +3788,12 @@ i64 type_size_of_internal(Type *t, TypePath *path) {
|
||||
case Type_Map:
|
||||
/*
|
||||
struct {
|
||||
hashes: []int, // 2 words
|
||||
entries: [dynamic]Entry_Type, // 5 words
|
||||
data: uintptr, // 1 word
|
||||
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: {
|
||||
i64 count, align, size;
|
||||
|
||||
Reference in New Issue
Block a user