mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 23:28:48 +00:00
Make Map_Info store pointers to cell info rather than inline
This commit is contained in:
+2
-2
@@ -2085,8 +2085,8 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
|
|||||||
}
|
}
|
||||||
j += 1
|
j += 1
|
||||||
|
|
||||||
key := runtime.map_cell_index_dynamic(ks, &info.map_info.ks, bucket_index)
|
key := runtime.map_cell_index_dynamic(ks, info.map_info.ks, bucket_index)
|
||||||
value := runtime.map_cell_index_dynamic(vs, &info.map_info.vs, bucket_index)
|
value := runtime.map_cell_index_dynamic(vs, info.map_info.vs, bucket_index)
|
||||||
|
|
||||||
fmt_arg(&Info{writer = fi.writer}, any{rawptr(key), info.key.id}, 'v')
|
fmt_arg(&Info{writer = fi.writer}, any{rawptr(key), info.key.id}, 'v')
|
||||||
io.write_string(fi.writer, "=", &fi.n)
|
io.write_string(fi.writer, "=", &fi.n)
|
||||||
|
|||||||
@@ -272,13 +272,13 @@ clear_map :: proc "contextless" (m: ^$T/map[$K]$V) {
|
|||||||
if m == nil {
|
if m == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
map_clear_dynamic((^Raw_Map)(m), map_info(K, V))
|
map_clear_dynamic((^Raw_Map)(m), map_info(T))
|
||||||
}
|
}
|
||||||
|
|
||||||
@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 {
|
||||||
__dynamic_map_reserve((^Raw_Map)(m), map_info(K, V), uint(capacity), loc)
|
__dynamic_map_reserve((^Raw_Map)(m), map_info(T), uint(capacity), loc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,8 +306,7 @@ 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
|
||||||
info := map_info(K, V)
|
_ = map_erase_dynamic((^Raw_Map)(m), map_info(T), uintptr(&key))
|
||||||
_ = map_erase_dynamic((^Raw_Map)(m), info, uintptr(&key))
|
|
||||||
// TODO(bill) old key and value
|
// TODO(bill) old key and value
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -184,13 +184,15 @@ map_hash_is_empty :: #force_inline proc "contextless" (hash: Map_Hash) -> bool {
|
|||||||
return hash == 0
|
return hash == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
map_hash_is_deleted :: #force_inline proc "contextless" (hash: Map_Hash) -> bool {
|
map_hash_is_deleted :: #force_no_inline proc "contextless" (hash: Map_Hash) -> bool {
|
||||||
// The MSB indicates a tombstone
|
// The MSB indicates a tombstone
|
||||||
return (hash >> ((size_of(Map_Hash) * 8) - 1)) != 0
|
N :: size_of(Map_Hash)*8 - 1
|
||||||
|
return hash >> N != 0
|
||||||
}
|
}
|
||||||
map_hash_is_valid :: #force_inline proc "contextless" (hash: Map_Hash) -> bool {
|
map_hash_is_valid :: #force_inline proc "contextless" (hash: Map_Hash) -> bool {
|
||||||
// The MSB indicates a tombstone
|
// The MSB indicates a tombstone
|
||||||
return (hash != 0) & ((hash >> ((size_of(Map_Hash) * 8) - 1)) == 0)
|
N :: size_of(Map_Hash)*8 - 1
|
||||||
|
return (hash != 0) & (hash >> N == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -212,42 +214,19 @@ map_probe_distance :: #force_inline proc "contextless" (m: Raw_Map, hash: Map_Ha
|
|||||||
// about the map to make working with it possible. This info structure stores
|
// about the map to make working with it possible. This info structure stores
|
||||||
// that.
|
// that.
|
||||||
//
|
//
|
||||||
// The Odin compiler should generate this for __get_map_header.
|
// 32-bytes on 64-bit
|
||||||
//
|
// 16-bytes on 32-bit
|
||||||
// 80-bytes on 64-bit
|
|
||||||
// 40-bytes on 32-bit
|
|
||||||
Map_Info :: struct {
|
Map_Info :: struct {
|
||||||
ks: Map_Cell_Info, // 32-bytes on 64-bit, 16-bytes on 32-bit
|
ks: ^Map_Cell_Info, // 8-bytes on 64-bit, 4-bytes on 32-bit
|
||||||
vs: Map_Cell_Info, // 32-bytes on 64-bit, 16-bytes on 32-bit
|
vs: ^Map_Cell_Info, // 8-bytes on 64-bit, 4-bytes on 32-bit
|
||||||
key_hasher: proc "contextless" (key: rawptr, seed: Map_Hash) -> Map_Hash, // 8-bytes on 64-bit, 4-bytes on 32-bit
|
key_hasher: proc "contextless" (key: rawptr, seed: Map_Hash) -> Map_Hash, // 8-bytes on 64-bit, 4-bytes on 32-bit
|
||||||
key_equal: proc "contextless" (lhs, rhs: rawptr) -> bool, // 8-bytes on 64-bit, 4-bytes on 32-bit
|
key_equal: proc "contextless" (lhs, rhs: rawptr) -> bool, // 8-bytes on 64-bit, 4-bytes on 32-bit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The Map_Info structure is basically a pseudo-table of information for a given K and V pair.
|
// The Map_Info structure is basically a pseudo-table of information for a given K and V pair.
|
||||||
map_info :: #force_inline proc "contextless" ($K: typeid, $V: typeid) -> ^Map_Info where intrinsics.type_is_comparable(K) {
|
// map_info :: proc "contextless" ($T: typeid/map[$K]$V) -> ^Map_Info {...}
|
||||||
@static INFO := Map_Info {
|
map_info :: intrinsics.type_map_info
|
||||||
Map_Cell_Info {
|
|
||||||
size_of(K),
|
|
||||||
align_of(K),
|
|
||||||
size_of(Map_Cell(K)),
|
|
||||||
len(Map_Cell(K){}.data),
|
|
||||||
},
|
|
||||||
Map_Cell_Info {
|
|
||||||
size_of(V),
|
|
||||||
align_of(V),
|
|
||||||
size_of(Map_Cell(V)),
|
|
||||||
len(Map_Cell(V){}.data),
|
|
||||||
},
|
|
||||||
proc "contextless" (ptr: rawptr, seed: uintptr) -> Map_Hash {
|
|
||||||
return intrinsics.type_hasher_proc(K)(ptr, seed)
|
|
||||||
} ,
|
|
||||||
proc "contextless" (a, b: rawptr) -> bool {
|
|
||||||
return intrinsics.type_equal_proc(K)(a, b)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return &INFO
|
|
||||||
}
|
|
||||||
|
|
||||||
map_kvh_data_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info) -> (ks: uintptr, vs: uintptr, hs: [^]Map_Hash, sk: uintptr, sv: uintptr) {
|
map_kvh_data_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info) -> (ks: uintptr, vs: uintptr, hs: [^]Map_Hash, sk: uintptr, sv: uintptr) {
|
||||||
@static INFO_HS := Map_Cell_Info {
|
@static INFO_HS := Map_Cell_Info {
|
||||||
@@ -259,12 +238,12 @@ map_kvh_data_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Inf
|
|||||||
|
|
||||||
capacity := uintptr(1) << map_log2_cap(m)
|
capacity := uintptr(1) << map_log2_cap(m)
|
||||||
ks = map_data(m)
|
ks = map_data(m)
|
||||||
vs = map_cell_index_dynamic(ks, &info.ks, capacity) // Skip past ks to get start of vs
|
vs = map_cell_index_dynamic(ks, info.ks, capacity) // Skip past ks to get start of vs
|
||||||
hs_ := map_cell_index_dynamic(vs, &info.vs, capacity) // Skip past vs to get start of hs
|
hs_ := map_cell_index_dynamic(vs, info.vs, capacity) // Skip past vs to get start of hs
|
||||||
sk = map_cell_index_dynamic(hs_, &INFO_HS, capacity) // Skip past hs to get start of sk
|
sk = map_cell_index_dynamic(hs_, &INFO_HS, capacity) // Skip past hs to get start of sk
|
||||||
// Need to skip past two elements in the scratch key space to get to the start
|
// Need to skip past two elements in the scratch key space to get to the start
|
||||||
// of the scratch value space, of which there's only two elements as well.
|
// of the scratch value space, of which there's only two elements as well.
|
||||||
sv = map_cell_index_dynamic_const(sk, &info.ks, 2)
|
sv = map_cell_index_dynamic_const(sk, info.ks, 2)
|
||||||
|
|
||||||
hs = ([^]Map_Hash)(hs_)
|
hs = ([^]Map_Hash)(hs_)
|
||||||
return
|
return
|
||||||
@@ -272,7 +251,7 @@ map_kvh_data_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Inf
|
|||||||
|
|
||||||
map_kvh_data_values_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info) -> (vs: uintptr) {
|
map_kvh_data_values_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info) -> (vs: uintptr) {
|
||||||
capacity := uintptr(1) << map_log2_cap(m)
|
capacity := uintptr(1) << map_log2_cap(m)
|
||||||
return map_cell_index_dynamic(map_data(m), &info.ks, capacity) // Skip past ks to get start of vs
|
return map_cell_index_dynamic(map_data(m), info.ks, capacity) // Skip past ks to get start of vs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -303,11 +282,11 @@ map_alloc_dynamic :: proc(info: ^Map_Info, log2_capacity: uintptr, allocator :=
|
|||||||
}
|
}
|
||||||
|
|
||||||
size := uintptr(0)
|
size := uintptr(0)
|
||||||
size = round(map_cell_index_dynamic(size, &info.ks, capacity))
|
size = round(map_cell_index_dynamic(size, info.ks, capacity))
|
||||||
size = round(map_cell_index_dynamic(size, &info.vs, capacity))
|
size = round(map_cell_index_dynamic(size, info.vs, capacity))
|
||||||
size = round(map_cell_index_dynamic(size, &INFO_HS, capacity))
|
size = round(map_cell_index_dynamic(size, &INFO_HS, capacity))
|
||||||
size = round(map_cell_index_dynamic(size, &info.ks, 2)) // Two additional ks for scratch storage
|
size = round(map_cell_index_dynamic(size, info.ks, 2)) // Two additional ks for scratch storage
|
||||||
size = round(map_cell_index_dynamic(size, &info.vs, 2)) // Two additional vs for scratch storage
|
size = round(map_cell_index_dynamic(size, info.vs, 2)) // Two additional vs for scratch storage
|
||||||
|
|
||||||
data := mem_alloc(int(size), MAP_CACHE_LINE_SIZE, allocator) or_return
|
data := mem_alloc(int(size), MAP_CACHE_LINE_SIZE, allocator) or_return
|
||||||
data_ptr := uintptr(raw_data(data))
|
data_ptr := uintptr(raw_data(data))
|
||||||
@@ -334,8 +313,8 @@ map_alloc_dynamic :: proc(info: ^Map_Info, log2_capacity: uintptr, allocator :=
|
|||||||
// This procedure returns the address of the just inserted value.
|
// This procedure returns the address of the just inserted value.
|
||||||
@(optimization_mode="speed")
|
@(optimization_mode="speed")
|
||||||
map_insert_hash_dynamic :: proc(m: Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) -> (result: uintptr) {
|
map_insert_hash_dynamic :: proc(m: Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) -> (result: uintptr) {
|
||||||
info_ks := &info.ks
|
info_ks := info.ks
|
||||||
info_vs := &info.vs
|
info_vs := info.vs
|
||||||
|
|
||||||
p := map_desired_position(m, h)
|
p := map_desired_position(m, h)
|
||||||
d := uintptr(0)
|
d := uintptr(0)
|
||||||
@@ -416,8 +395,8 @@ map_insert_hash_dynamic :: proc(m: Raw_Map, #no_alias info: ^Map_Info, h: Map_Ha
|
|||||||
|
|
||||||
@(optimization_mode="speed")
|
@(optimization_mode="speed")
|
||||||
map_add_hash_dynamic :: proc(m: Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) {
|
map_add_hash_dynamic :: proc(m: Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) {
|
||||||
info_ks := &info.ks
|
info_ks := info.ks
|
||||||
info_vs := &info.vs
|
info_vs := info.vs
|
||||||
|
|
||||||
capacity := uintptr(1) << map_log2_cap(m)
|
capacity := uintptr(1) << map_log2_cap(m)
|
||||||
p := map_desired_position(m, h)
|
p := map_desired_position(m, h)
|
||||||
@@ -515,8 +494,8 @@ map_grow_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info) -> Al
|
|||||||
ks, vs, hs, _, _ := map_kvh_data_dynamic(m^, info)
|
ks, vs, hs, _, _ := map_kvh_data_dynamic(m^, info)
|
||||||
|
|
||||||
// Cache these loads to avoid hitting them in the for loop.
|
// Cache these loads to avoid hitting them in the for loop.
|
||||||
info_ks := &info.ks
|
info_ks := info.ks
|
||||||
info_vs := &info.vs
|
info_vs := info.vs
|
||||||
|
|
||||||
n := map_len(m^)
|
n := map_len(m^)
|
||||||
for i := uintptr(0); i < old_capacity; i += 1 {
|
for i := uintptr(0); i < old_capacity; i += 1 {
|
||||||
@@ -576,8 +555,8 @@ map_reserve_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, ne
|
|||||||
ks, vs, hs, _, _ := map_kvh_data_dynamic(m^, info)
|
ks, vs, hs, _, _ := map_kvh_data_dynamic(m^, info)
|
||||||
|
|
||||||
// Cache these loads to avoid hitting them in the for loop.
|
// Cache these loads to avoid hitting them in the for loop.
|
||||||
info_ks := &info.ks
|
info_ks := info.ks
|
||||||
info_vs := &info.vs
|
info_vs := info.vs
|
||||||
|
|
||||||
n := map_len(m^)
|
n := map_len(m^)
|
||||||
for i := uintptr(0); i < capacity; i += 1 {
|
for i := uintptr(0); i < capacity; i += 1 {
|
||||||
@@ -629,8 +608,8 @@ map_shrink_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info) ->
|
|||||||
|
|
||||||
ks, vs, hs, _, _ := map_kvh_data_dynamic(m^, info)
|
ks, vs, hs, _, _ := map_kvh_data_dynamic(m^, info)
|
||||||
|
|
||||||
info_ks := &info.ks
|
info_ks := info.ks
|
||||||
info_vs := &info.vs
|
info_vs := info.vs
|
||||||
|
|
||||||
n := map_len(m^)
|
n := map_len(m^)
|
||||||
for i := uintptr(0); i < capacity; i += 1 {
|
for i := uintptr(0); i < capacity; i += 1 {
|
||||||
@@ -678,7 +657,7 @@ map_lookup_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info,
|
|||||||
d := uintptr(0)
|
d := uintptr(0)
|
||||||
c := (uintptr(1) << map_log2_cap(m)) - 1
|
c := (uintptr(1) << map_log2_cap(m)) - 1
|
||||||
ks, _, hs, _, _ := map_kvh_data_dynamic(m, info)
|
ks, _, hs, _, _ := map_kvh_data_dynamic(m, info)
|
||||||
info_ks := &info.ks
|
info_ks := info.ks
|
||||||
for {
|
for {
|
||||||
element_hash := hs[p]
|
element_hash := hs[p]
|
||||||
if map_hash_is_empty(element_hash) {
|
if map_hash_is_empty(element_hash) {
|
||||||
@@ -702,7 +681,7 @@ map_exists_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info,
|
|||||||
d := uintptr(0)
|
d := uintptr(0)
|
||||||
c := (uintptr(1) << map_log2_cap(m)) - 1
|
c := (uintptr(1) << map_log2_cap(m)) - 1
|
||||||
ks, _, hs, _, _ := map_kvh_data_dynamic(m, info)
|
ks, _, hs, _, _ := map_kvh_data_dynamic(m, info)
|
||||||
info_ks := &info.ks
|
info_ks := info.ks
|
||||||
for {
|
for {
|
||||||
element_hash := hs[p]
|
element_hash := hs[p]
|
||||||
if map_hash_is_empty(element_hash) {
|
if map_hash_is_empty(element_hash) {
|
||||||
@@ -766,7 +745,7 @@ __dynamic_map_get :: proc "contextless" (m: rawptr, #no_alias info: ^Map_Info, k
|
|||||||
rm := (^Raw_Map)(m)^
|
rm := (^Raw_Map)(m)^
|
||||||
if index, ok := map_lookup_dynamic(rm, info, uintptr(key)); ok {
|
if index, ok := map_lookup_dynamic(rm, info, uintptr(key)); ok {
|
||||||
vs := map_kvh_data_values_dynamic(rm, info)
|
vs := map_kvh_data_values_dynamic(rm, info)
|
||||||
ptr = rawptr(map_cell_index_dynamic(vs, &info.vs, index))
|
ptr = rawptr(map_cell_index_dynamic(vs, info.vs, index))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5363,6 +5363,29 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case BuiltinProc_type_map_info:
|
||||||
|
{
|
||||||
|
Operand op = {};
|
||||||
|
Type *bt = check_type(c, ce->args[0]);
|
||||||
|
Type *type = base_type(bt);
|
||||||
|
if (type == nullptr || type == t_invalid) {
|
||||||
|
error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_type_map(type)) {
|
||||||
|
gbString t = type_to_string(type);
|
||||||
|
error(ce->args[0], "Expected a map type for '%.*s', got %s", LIT(builtin_name), t);
|
||||||
|
gb_string_free(t);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_map_key_type_dependencies(c, type);
|
||||||
|
|
||||||
|
operand->mode = Addressing_Value;
|
||||||
|
operand->type = t_map_info_ptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case BuiltinProc_constant_utf16_cstring:
|
case BuiltinProc_constant_utf16_cstring:
|
||||||
{
|
{
|
||||||
String value = {};
|
String value = {};
|
||||||
|
|||||||
@@ -2851,6 +2851,9 @@ void init_core_map_type(Checker *c) {
|
|||||||
t_map_info = find_core_type(c, str_lit("Map_Info"));
|
t_map_info = find_core_type(c, str_lit("Map_Info"));
|
||||||
t_map_cell_info = find_core_type(c, str_lit("Map_Cell_Info"));
|
t_map_cell_info = find_core_type(c, str_lit("Map_Cell_Info"));
|
||||||
t_raw_map = find_core_type(c, str_lit("Raw_Map"));
|
t_raw_map = find_core_type(c, str_lit("Raw_Map"));
|
||||||
|
|
||||||
|
t_map_info_ptr = alloc_type_pointer(t_map_info);
|
||||||
|
t_map_cell_info_ptr = alloc_type_pointer(t_map_cell_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_preload(Checker *c) {
|
void init_preload(Checker *c) {
|
||||||
|
|||||||
@@ -277,6 +277,7 @@ BuiltinProc__type_simple_boolean_end,
|
|||||||
|
|
||||||
BuiltinProc_type_equal_proc,
|
BuiltinProc_type_equal_proc,
|
||||||
BuiltinProc_type_hasher_proc,
|
BuiltinProc_type_hasher_proc,
|
||||||
|
BuiltinProc_type_map_info,
|
||||||
|
|
||||||
BuiltinProc__type_end,
|
BuiltinProc__type_end,
|
||||||
|
|
||||||
@@ -572,6 +573,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
|||||||
|
|
||||||
{STR_LIT("type_equal_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
{STR_LIT("type_equal_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||||
{STR_LIT("type_hasher_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
{STR_LIT("type_hasher_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||||
|
{STR_LIT("type_map_info"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||||
|
|
||||||
|
|
||||||
{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||||
|
|||||||
+13
-1
@@ -502,6 +502,11 @@ lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, A
|
|||||||
|
|
||||||
|
|
||||||
LLVMValueRef lb_gen_map_cell_info(lbModule *m, Type *type) {
|
LLVMValueRef lb_gen_map_cell_info(lbModule *m, Type *type) {
|
||||||
|
lbAddr *found = map_get(&m->map_cell_info_map, type);
|
||||||
|
if (found) {
|
||||||
|
return found->addr.value;
|
||||||
|
}
|
||||||
|
|
||||||
i64 size = 0, len = 0;
|
i64 size = 0, len = 0;
|
||||||
map_cell_size_and_len(type, &size, &len);
|
map_cell_size_and_len(type, &size, &len);
|
||||||
|
|
||||||
@@ -510,8 +515,15 @@ LLVMValueRef lb_gen_map_cell_info(lbModule *m, Type *type) {
|
|||||||
const_values[1] = lb_const_int(m, t_uintptr, type_align_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[2] = lb_const_int(m, t_uintptr, size).value;
|
||||||
const_values[3] = lb_const_int(m, t_uintptr, len).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));
|
LLVMValueRef llvm_res = llvm_const_named_struct(m, t_map_cell_info, const_values, gb_count_of(const_values));
|
||||||
|
lbValue res = {llvm_res, t_map_cell_info};
|
||||||
|
|
||||||
|
lbAddr addr = lb_add_global_generated(m, t_map_cell_info, res, nullptr);
|
||||||
|
lb_make_global_private_const(addr);
|
||||||
|
|
||||||
|
map_set(&m->map_cell_info_map, type, addr);
|
||||||
|
|
||||||
|
return addr.addr.value;
|
||||||
}
|
}
|
||||||
lbValue lb_gen_map_info_ptr(lbModule *m, Type *map_type) {
|
lbValue lb_gen_map_info_ptr(lbModule *m, Type *map_type) {
|
||||||
map_type = base_type(map_type);
|
map_type = base_type(map_type);
|
||||||
|
|||||||
@@ -160,7 +160,8 @@ struct lbModule {
|
|||||||
StringMap<lbAddr> objc_classes;
|
StringMap<lbAddr> objc_classes;
|
||||||
StringMap<lbAddr> objc_selectors;
|
StringMap<lbAddr> objc_selectors;
|
||||||
|
|
||||||
PtrMap<Type *, lbAddr> map_info_map;
|
PtrMap<Type *, lbAddr> map_cell_info_map; // address of runtime.Map_Info
|
||||||
|
PtrMap<Type *, lbAddr> map_info_map; // address of runtime.Map_Cell_Info
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lbGenerator {
|
struct lbGenerator {
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ void lb_init_module(lbModule *m, Checker *c) {
|
|||||||
string_map_init(&m->objc_selectors, a);
|
string_map_init(&m->objc_selectors, a);
|
||||||
|
|
||||||
map_init(&m->map_info_map, a, 0);
|
map_init(&m->map_info_map, a, 0);
|
||||||
|
map_init(&m->map_cell_info_map, a, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2324,6 +2324,9 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
|
|||||||
case BuiltinProc_type_hasher_proc:
|
case BuiltinProc_type_hasher_proc:
|
||||||
return lb_get_hasher_proc_for_type(p->module, ce->args[0]->tav.type);
|
return lb_get_hasher_proc_for_type(p->module, ce->args[0]->tav.type);
|
||||||
|
|
||||||
|
case BuiltinProc_type_map_info:
|
||||||
|
return lb_gen_map_info_ptr(p->module, ce->args[0]->tav.type);
|
||||||
|
|
||||||
case BuiltinProc_fixed_point_mul:
|
case BuiltinProc_fixed_point_mul:
|
||||||
case BuiltinProc_fixed_point_div:
|
case BuiltinProc_fixed_point_div:
|
||||||
case BuiltinProc_fixed_point_mul_sat:
|
case BuiltinProc_fixed_point_mul_sat:
|
||||||
|
|||||||
@@ -685,6 +685,8 @@ gb_global Type *t_source_code_location_ptr = nullptr;
|
|||||||
|
|
||||||
gb_global Type *t_map_info = nullptr;
|
gb_global Type *t_map_info = nullptr;
|
||||||
gb_global Type *t_map_cell_info = nullptr;
|
gb_global Type *t_map_cell_info = nullptr;
|
||||||
|
gb_global Type *t_map_info_ptr = nullptr;
|
||||||
|
gb_global Type *t_map_cell_info_ptr = nullptr;
|
||||||
gb_global Type *t_raw_map = nullptr;
|
gb_global Type *t_raw_map = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user