Mock out map get/set functionality

This commit is contained in:
gingerBill
2023-08-07 14:40:42 +01:00
parent 67ffae7e32
commit 0c1b39d881
8 changed files with 300 additions and 22 deletions
+17 -1
View File
@@ -189,6 +189,19 @@ gb_internal cgAddr cg_addr(cgValue const &value) {
return addr;
}
gb_internal cgAddr cg_addr_map(cgValue addr, cgValue map_key, Type *map_type, Type *map_result) {
GB_ASSERT(is_type_pointer(addr.type));
Type *mt = type_deref(addr.type);
GB_ASSERT(is_type_map(mt));
cgAddr v = {cgAddr_Map, addr};
v.map.key = map_key;
v.map.type = map_type;
v.map.result = map_result;
return v;
}
gb_internal void cg_set_debug_pos_from_node(cgProcedure *p, Ast *node) {
if (node) {
TokenPos pos = ast_token(node).pos;
@@ -435,6 +448,8 @@ gb_internal cgModule *cg_module_create(Checker *c) {
map_init(&m->hasher_procs);
map_init(&m->map_get_procs);
map_init(&m->map_set_procs);
map_init(&m->map_info_map);
map_init(&m->map_cell_info_map);
array_init(&m->single_threaded_procedure_queue, heap_allocator());
@@ -461,6 +476,8 @@ gb_internal void cg_module_destroy(cgModule *m) {
map_destroy(&m->hasher_procs);
map_destroy(&m->map_get_procs);
map_destroy(&m->map_set_procs);
map_destroy(&m->map_info_map);
map_destroy(&m->map_cell_info_map);
array_free(&m->single_threaded_procedure_queue);
@@ -784,7 +801,6 @@ gb_internal bool cg_generate_code(Checker *c, LinkerData *linker_data) {
}
TB_DebugFormat debug_format = TB_DEBUGFMT_NONE;
if (build_context.ODIN_DEBUG) {
switch (build_context.metrics.os) {
+8 -1
View File
@@ -237,6 +237,9 @@ struct cgModule {
PtrMap<Type *, cgProcedure *> map_get_procs;
PtrMap<Type *, cgProcedure *> map_set_procs;
RecursiveMutex map_info_mutex;
PtrMap<Type *, TB_Symbol *> map_info_map;
PtrMap<Type *, TB_Symbol *> map_cell_info_map;
// NOTE(bill): no need to protect this with a mutex
PtrMap<uintptr, TB_FileID> file_id_map; // Key: AstFile.id (i32 cast to uintptr)
@@ -289,6 +292,7 @@ gb_internal cgValue cg_value(TB_Symbol * s, Type *type);
gb_internal cgValue cg_value(TB_Node * node, Type *type);
gb_internal cgAddr cg_addr(cgValue const &value);
gb_internal cgAddr cg_addr_map(cgValue addr, cgValue map_key, Type *map_type, Type *map_result);
gb_internal u64 cg_typeid_as_u64(cgModule *m, Type *type);
gb_internal cgValue cg_type_info(cgProcedure *p, Type *type);
@@ -370,4 +374,7 @@ gb_internal cgValue cg_handle_param_value(cgProcedure *p, Type *parameter_type,
gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value);
gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &x);
gb_internal cgValue cg_builtin_map_info(cgProcedure *p, Type *map_type);
gb_internal cgValue cg_builtin_map_cell_info(cgProcedure *p, Type *type);
gb_internal cgValue cg_emit_source_code_location_as_global(cgProcedure *p, String const &proc_name, TokenPos pos);
gb_internal cgValue cg_emit_source_code_location_as_global(cgProcedure *p, Ast *node);
+129
View File
@@ -231,6 +231,76 @@ gb_internal cgValue cg_builtin_mem_copy_non_overlapping(cgProcedure *p, cgValue
return dst;
}
gb_internal TB_Symbol *cg_builtin_map_cell_info_symbol(cgModule *m, Type *type) {
MUTEX_GUARD(&m->map_info_mutex);
TB_Symbol **found = map_get(&m->map_cell_info_map, type);
if (found) {
return *found;
}
i64 size = 0, len = 0;
map_cell_size_and_len(type, &size, &len);
TB_Global *global = tb_global_create(m->mod, 0, "", cg_debug_type(m, t_map_cell_info), TB_LINKAGE_PRIVATE);
tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), global, type_size_of(t_map_cell_info), type_align_of(t_map_cell_info), 4);
i64 ptr_size = build_context.ptr_size;
void *size_of_type = tb_global_add_region(m->mod, global, 0*ptr_size, ptr_size);
void *align_of_type = tb_global_add_region(m->mod, global, 1*ptr_size, ptr_size);
void *size_of_cell = tb_global_add_region(m->mod, global, 2*ptr_size, ptr_size);
void *elements_per_cell = tb_global_add_region(m->mod, global, 3*ptr_size, ptr_size);
cg_write_uint_at_ptr(size_of_type, type_size_of(type), t_uintptr);
cg_write_uint_at_ptr(align_of_type, type_align_of(type), t_uintptr);
cg_write_uint_at_ptr(size_of_cell, size, t_uintptr);
cg_write_uint_at_ptr(elements_per_cell, len, t_uintptr);
map_set(&m->map_cell_info_map, type, cast(TB_Symbol *)global);
return cast(TB_Symbol *)global;
}
gb_internal cgValue cg_builtin_map_cell_info(cgProcedure *p, Type *type) {
type = core_type(type);
TB_Symbol *symbol = cg_builtin_map_cell_info_symbol(p->module, type);
TB_Node *node = tb_inst_get_symbol_address(p->func, symbol);
return cg_value(node, t_map_cell_info_ptr);
}
gb_internal cgValue cg_builtin_map_info(cgProcedure *p, Type *map_type) {
map_type = base_type(map_type);
GB_ASSERT(map_type->kind == Type_Map);
cgModule *m = p->module;
MUTEX_GUARD(&m->map_info_mutex);
TB_Global *global = nullptr;
TB_Symbol **found = map_get(&m->map_info_map, map_type);
if (found) {
global = cast(TB_Global *)*found;
} else {
global = tb_global_create(m->mod, 0, "", cg_debug_type(m, t_map_info), TB_LINKAGE_PRIVATE);
tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), global, type_size_of(t_map_info), type_align_of(t_map_info), 4);
TB_Symbol *key_cell_info = cg_builtin_map_cell_info_symbol(m, map_type->Map.key);
TB_Symbol *value_cell_info = cg_builtin_map_cell_info_symbol(m, map_type->Map.value);
cgProcedure *key_hasher = cg_hasher_proc_for_type(p->module, map_type->Map.key);
cgProcedure *key_equal = cg_equal_proc_for_type (p->module, map_type->Map.key);
tb_global_add_symbol_reloc(p->module->mod, global, 0*build_context.ptr_size, key_cell_info);
tb_global_add_symbol_reloc(p->module->mod, global, 1*build_context.ptr_size, value_cell_info);
tb_global_add_symbol_reloc(p->module->mod, global, 2*build_context.ptr_size, key_hasher->symbol);
tb_global_add_symbol_reloc(p->module->mod, global, 3*build_context.ptr_size, key_equal->symbol);
map_set(&m->map_info_map, map_type, cast(TB_Symbol *)global);
}
GB_ASSERT(global != nullptr);
TB_Node *node = tb_inst_get_symbol_address(p->func, cast(TB_Symbol *)global);
return cg_value(node, t_map_info_ptr);
}
gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr) {
ast_node(ce, CallExpr, expr);
@@ -434,6 +504,65 @@ gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr
case BuiltinProc_type_hasher_proc:
return cg_hasher_proc_value_for_type(p, ce->args[0]->tav.type);
case BuiltinProc_type_map_cell_info:
return cg_builtin_map_cell_info(p, ce->args[0]->tav.type);
case BuiltinProc_type_map_info:
return cg_builtin_map_info(p, ce->args[0]->tav.type);
case BuiltinProc_expect:
{
Type *t = default_type(expr->tav.type);
cgValue x = cg_emit_conv(p, cg_build_expr(p, ce->args[0]), t);
cgValue y = cg_emit_conv(p, cg_build_expr(p, ce->args[1]), t);
gb_unused(y);
return x;
}
case BuiltinProc_count_leading_zeros:
{
cgValue n = cg_build_expr(p, ce->args[0]);
n = cg_emit_conv(p, n, default_type(expr->tav.type));
GB_ASSERT(n.kind == cgValue_Value);
TB_Node *val = tb_inst_clz(p->func, n.node);
val = tb_inst_zxt(p->func, val, cg_data_type(n.type));
return cg_value(val, n.type);
}
case BuiltinProc_count_trailing_zeros:
{
cgValue n = cg_build_expr(p, ce->args[0]);
n = cg_emit_conv(p, n, default_type(expr->tav.type));
GB_ASSERT(n.kind == cgValue_Value);
TB_Node *val = tb_inst_ctz(p->func, n.node);
val = tb_inst_zxt(p->func, val, cg_data_type(n.type));
return cg_value(val, n.type);
}
case BuiltinProc_count_ones:
{
cgValue n = cg_build_expr(p, ce->args[0]);
n = cg_emit_conv(p, n, default_type(expr->tav.type));
GB_ASSERT(n.kind == cgValue_Value);
TB_Node *val = tb_inst_popcount(p->func, n.node);
val = tb_inst_zxt(p->func, val, cg_data_type(n.type));
return cg_value(val, n.type);
}
case BuiltinProc_count_zeros:
{
cgValue n = cg_build_expr(p, ce->args[0]);
n = cg_emit_conv(p, n, default_type(expr->tav.type));
GB_ASSERT(n.kind == cgValue_Value);
TB_DataType dt = cg_data_type(n.type);
TB_Node *ones = tb_inst_popcount(p->func, n.node);
ones = tb_inst_zxt(p->func, ones, dt);
cgValue size = cg_const_int(p, n.type, 8*type_size_of(n.type));
return cg_emit_arith(p, Token_Sub, size, cg_value(ones, n.type), n.type);
}
}
+11 -2
View File
@@ -96,7 +96,11 @@ gb_internal cgValue cg_emit_source_code_location_as_global(cgProcedure *p, Strin
return cg_lvalue_addr(ptr, t_source_code_location);
}
gb_internal cgValue cg_emit_source_code_location_as_global(cgProcedure *p, Ast *node) {
String proc_name = p->name;
TokenPos pos = ast_token(node).pos;
return cg_emit_source_code_location_as_global(p, proc_name, pos);
}
gb_internal void cg_write_big_int_at_ptr(void *dst, BigInt const *a, Type *original_type) {
GB_ASSERT(build_context.endian_kind == TargetEndian_Little);
@@ -949,7 +953,12 @@ gb_internal cgValue cg_const_value(cgProcedure *p, Type *type, ExactValue const
GB_ASSERT(!TB_IS_VOID_TYPE(dt));
// GB_ASSERT(dt.raw != TB_TYPE_I128.raw);
if (is_type_unsigned(type)) {
u64 i = exact_value_to_u64(value);
u64 i = 0;
if (value.kind == ExactValue_Integer && value.value_integer.sign) {
i = exact_value_to_i64(value);
} else {
i = exact_value_to_u64(value);
}
return cg_value(tb_inst_uint(p->func, dt, i), type);
} else {
i64 i = exact_value_to_i64(value);
+94 -11
View File
@@ -3416,9 +3416,93 @@ gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) {
token_pos_to_string(token_pos));
return {};
}
gb_internal cgValue cg_map_data_uintptr(cgProcedure *p, cgValue value) {
GB_ASSERT(is_type_map(value.type) || are_types_identical(value.type, t_raw_map));
cgValue data = cg_emit_struct_ev(p, value, 0);
u64 mask_value = 0;
if (build_context.ptr_size == 4) {
mask_value = 0xfffffffful & ~(MAP_CACHE_LINE_SIZE-1);
} else {
mask_value = 0xffffffffffffffffull & ~(MAP_CACHE_LINE_SIZE-1);
}
cgValue mask = cg_const_int(p, t_uintptr, mask_value);
return cg_emit_arith(p, Token_And, data, mask, t_uintptr);
}
gb_internal cgValue cg_gen_map_key_hash(cgProcedure *p, cgValue const &map_ptr, cgValue key, cgValue *key_ptr_) {
TEMPORARY_ALLOCATOR_GUARD();
cgValue key_ptr = cg_address_from_load_or_generate_local(p, key);
key_ptr = cg_emit_conv(p, key_ptr, t_rawptr);
if (key_ptr_) *key_ptr_ = key_ptr;
Type* key_type = base_type(type_deref(map_ptr.type))->Map.key;
cgValue hasher = cg_hasher_proc_value_for_type(p, key_type);
Slice<cgValue> args = {};
args = slice_make<cgValue>(temporary_allocator(), 1);
args[0] = cg_map_data_uintptr(p, cg_emit_load(p, map_ptr));
cgValue seed = cg_emit_runtime_call(p, "map_seed_from_map_data", args);
args = slice_make<cgValue>(temporary_allocator(), 2);
args[0] = key_ptr;
args[1] = seed;
return cg_emit_call(p, hasher, args);
}
gb_internal cgValue cg_internal_dynamic_map_get_ptr(cgProcedure *p, cgValue const &map_ptr, cgValue const &key) {
TEMPORARY_ALLOCATOR_GUARD();
Type *map_type = base_type(type_deref(map_ptr.type));
GB_ASSERT(map_type->kind == Type_Map);
cgValue ptr = {};
cgValue key_ptr = {};
cgValue hash = cg_gen_map_key_hash(p, map_ptr, key, &key_ptr);
auto args = slice_make<cgValue>(temporary_allocator(), 4);
args[0] = cg_emit_transmute(p, map_ptr, t_raw_map_ptr);
args[1] = cg_builtin_map_info(p, map_type);
args[2] = hash;
args[3] = key_ptr;
ptr = cg_emit_runtime_call(p, "__dynamic_map_get", args);
return cg_emit_conv(p, ptr, alloc_type_pointer(map_type->Map.value));
}
gb_internal void cg_internal_dynamic_map_set(cgProcedure *p, cgValue const &map_ptr, Type *map_type,
cgValue const &map_key, cgValue const &map_value, Ast *node) {
TEMPORARY_ALLOCATOR_GUARD();
map_type = base_type(map_type);
GB_ASSERT(map_type->kind == Type_Map);
cgValue key_ptr = {};
cgValue hash = cg_gen_map_key_hash(p, map_ptr, map_key, &key_ptr);
cgValue v = cg_emit_conv(p, map_value, map_type->Map.value);
cgValue value_ptr = cg_address_from_load_or_generate_local(p, v);
auto args = slice_make<cgValue>(temporary_allocator(), 6);
args[0] = cg_emit_conv(p, map_ptr, t_raw_map_ptr);
args[1] = cg_builtin_map_info(p, map_type);
args[2] = hash;
args[3] = cg_emit_conv(p, key_ptr, t_rawptr);
args[4] = cg_emit_conv(p, value_ptr, t_rawptr);
args[5] = cg_emit_source_code_location_as_global(p, node);
cg_emit_runtime_call(p, "__dynamic_map_set", args);
}
gb_internal cgValue cg_build_addr_ptr(cgProcedure *p, Ast *expr) {
cgAddr addr = cg_build_addr(p, expr);
return cg_addr_get_ptr(p, addr);
@@ -3501,17 +3585,16 @@ gb_internal cgAddr cg_build_addr_index_expr(cgProcedure *p, Ast *expr) {
GB_ASSERT_MSG(is_type_indexable(t), "%s %s", type_to_string(t), expr_to_string(expr));
if (is_type_map(t)) {
GB_PANIC("TODO(bill): map indexing");
// lbAddr map_addr = lb_build_addr(p, ie->expr);
// lbValue key = lb_build_expr(p, ie->index);
// key = lb_emit_conv(p, key, t->Map.key);
cgAddr map_addr = cg_build_addr(p, ie->expr);
cgValue key = cg_build_expr(p, ie->index);
key = cg_emit_conv(p, key, t->Map.key);
// Type *result_type = type_of_expr(expr);
// lbValue map_ptr = lb_addr_get_ptr(p, map_addr);
// if (is_type_pointer(type_deref(map_ptr.type))) {
// map_ptr = lb_emit_load(p, map_ptr);
// }
// return lb_addr_map(map_ptr, key, t, result_type);
Type *result_type = type_of_expr(expr);
cgValue map_ptr = cg_addr_get_ptr(p, map_addr);
if (is_type_pointer(type_deref(map_ptr.type))) {
map_ptr = cg_emit_load(p, map_ptr);
}
return cg_addr_map(map_ptr, key, t, result_type);
}
switch (t->kind) {
+5 -1
View File
@@ -388,7 +388,7 @@ gb_internal WORKER_TASK_PROC(cg_procedure_compile_worker_proc) {
// emit ir
if (
// string_starts_with(p->name, str_lit("bug@main")) ||
string_starts_with(p->name, str_lit("main@")) ||
// p->name == str_lit("runtime@_windows_default_alloc_or_resize") ||
false
) { // IR Printing
@@ -398,6 +398,7 @@ gb_internal WORKER_TASK_PROC(cg_procedure_compile_worker_proc) {
tb_pass_print(passes);
fprintf(stdout, "\n");
fflush(stdout);
}
if (false) { // GraphViz printing
tb_function_print(p->func, tb_default_print_callback, stdout);
@@ -408,6 +409,7 @@ gb_internal WORKER_TASK_PROC(cg_procedure_compile_worker_proc) {
if (emit_asm) {
tb_output_print_asm(output, stdout);
fprintf(stdout, "\n");
fflush(stdout);
}
return 0;
@@ -1018,6 +1020,7 @@ gb_internal cgProcedure *cg_equal_proc_for_type(cgModule *m, Type *type) {
cgProcedure *p = cg_procedure_create_dummy(m, proc_name, t_equal_proc);
map_set(&m->equal_procs, type, p);
p->split_returns_index = 2;
cg_procedure_begin(p);
@@ -1168,6 +1171,7 @@ gb_internal cgProcedure *cg_hasher_proc_for_type(cgModule *m, Type *type) {
cgProcedure *p = cg_procedure_create_dummy(m, proc_name, t_hasher_proc);
map_set(&m->hasher_procs, type, p);
p->split_returns_index = 2;
cg_procedure_begin(p);
defer (cg_procedure_end(p));
+33 -3
View File
@@ -77,7 +77,7 @@ gb_internal void cg_emit_store(cgProcedure *p, cgValue dst, cgValue src, bool is
GB_ASSERT(is_type_pointer(dst.type));
Type *dst_type = type_deref(dst.type);
GB_ASSERT_MSG(are_types_identical(dst_type, src.type), "%s vs %s", type_to_string(dst_type), type_to_string(src.type));
GB_ASSERT_MSG(are_types_identical(core_type(dst_type), core_type(src.type)), "%s vs %s", type_to_string(dst_type), type_to_string(src.type));
TB_DataType dt = cg_data_type(dst_type);
TB_DataType st = cg_data_type(src.type);
@@ -225,6 +225,35 @@ gb_internal cgValue cg_addr_load(cgProcedure *p, cgAddr addr) {
switch (addr.kind) {
case cgAddr_Default:
return cg_emit_load(p, addr.addr);
case cgAddr_Map:
{
Type *map_type = base_type(type_deref(addr.addr.type));
GB_ASSERT(map_type->kind == Type_Map);
cgAddr v_addr = cg_add_local(p, map_type->Map.value, nullptr, true);
cgValue ptr = cg_internal_dynamic_map_get_ptr(p, addr.addr, addr.map.key);
cgValue ok = cg_emit_conv(p, cg_emit_comp_against_nil(p, Token_NotEq, ptr), t_bool);
TB_Node *then = cg_control_region(p, "map.get.then");
TB_Node *done = cg_control_region(p, "map.get.done");
cg_emit_if(p, ok, then, done);
tb_inst_set_control(p->func, then);
{
cgValue value = cg_emit_conv(p, ptr, alloc_type_pointer(map_type->Map.value));
value = cg_emit_load(p, value);
cg_addr_store(p, v_addr, value);
}
cg_emit_goto(p, done);
tb_inst_set_control(p->func, done);
cgValue v = cg_addr_load(p, v_addr);
if (is_type_tuple(addr.map.result)) {
return cg_value_multi2(v, ok, addr.map.result);
} else {
return v;
}
}
}
GB_PANIC("TODO(bill): cg_addr_load %p", addr.addr.node);
return {};
@@ -254,7 +283,8 @@ gb_internal void cg_addr_store(cgProcedure *p, cgAddr addr, cgValue value) {
} else if (addr.kind == cgAddr_RelativeSlice) {
GB_PANIC("TODO(bill): cgAddr_RelativeSlice");
} else if (addr.kind == cgAddr_Map) {
GB_PANIC("TODO(bill): cgAddr_Map");
cg_internal_dynamic_map_set(p, addr.addr, addr.map.type, addr.map.key, value, p->curr_stmt);
return;
} else if (addr.kind == cgAddr_Context) {
cgAddr old_addr = cg_find_or_generate_context_ptr(p);
@@ -1096,7 +1126,7 @@ gb_internal void cg_build_return_stmt_internal(cgProcedure *p, Slice<cgValue> co
}
} else {
GB_ASSERT(!is_calling_convention_odin(p->type->Proc.calling_convention));
GB_ASSERT_MSG(!is_calling_convention_odin(p->type->Proc.calling_convention), "missing %s", proc_calling_convention_strings[p->type->Proc.calling_convention]);
if (p->return_by_ptr) {
Entity *e = tuple->variables[return_count-1];
+3 -3
View File
@@ -332,14 +332,14 @@ gb_internal void cg_setup_type_info_data(cgModule *m) {
char const *name = CG_TYPE_INFO_TYPES_NAME;
Type *t = alloc_type_array(t_type_info_ptr, count);
TB_Global *g = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE);
tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count*2);
tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count*3);
cg_global_type_info_member_types = GlobalTypeInfoData{g, t, t_type_info_ptr, 0};
}
{
char const *name = CG_TYPE_INFO_NAMES_NAME;
Type *t = alloc_type_array(t_string, count);
TB_Global *g = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE);
tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count*2);
tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count*3);
cg_global_type_info_member_names = GlobalTypeInfoData{g, t, t_string, 0};
}
{
@@ -362,7 +362,7 @@ gb_internal void cg_setup_type_info_data(cgModule *m) {
char const *name = CG_TYPE_INFO_TAGS_NAME;
Type *t = alloc_type_array(t_string, count);
TB_Global *g = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE);
tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count*2);
tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count*3);
cg_global_type_info_member_tags = GlobalTypeInfoData{g, t, t_string, 0};
}
}