diff options
Diffstat (limited to 'src/llvm_backend.cpp')
| -rw-r--r-- | src/llvm_backend.cpp | 184 |
1 files changed, 131 insertions, 53 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 39b4030af..bc024ab8b 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -8559,6 +8559,9 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, case BuiltinProc_type_equal_proc: return lb_get_equal_proc_for_type(p->module, ce->args[0]->tav.type); + + case BuiltinProc_type_hasher_proc: + return lb_get_hasher_proc_for_type(p->module, ce->args[0]->tav.type); } GB_PANIC("Unhandled built-in procedure %.*s", LIT(builtin_procs[id].name)); @@ -9169,84 +9172,156 @@ lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type) { LLVMTypeRef ptr_type = lb_type(m, pt); auto key = hash_type(type); - lbProcedure **found = map_get(&m->compare_procs, key); + lbProcedure **found = map_get(&m->equal_procs, key); lbProcedure *compare_proc = nullptr; if (found) { compare_proc = *found; - } else { - static u32 proc_index = 0; + GB_ASSERT(compare_proc != nullptr); + return {compare_proc->value, compare_proc->type}; + } - char buf[16] = {}; - isize n = gb_snprintf(buf, 16, "__$cmp%u", ++proc_index); - char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); - String proc_name = make_string_c(str); + static u32 proc_index = 0; - lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_equal_proc); - lb_begin_procedure_body(p); + char buf[16] = {}; + isize n = gb_snprintf(buf, 16, "__$equal%u", ++proc_index); + char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); + String proc_name = make_string_c(str); + + lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_equal_proc); + map_set(&m->equal_procs, key, p); + lb_begin_procedure_body(p); + + LLVMValueRef x = LLVMGetParam(p->value, 0); + LLVMValueRef y = LLVMGetParam(p->value, 1); + x = LLVMBuildPointerCast(p->builder, x, ptr_type, ""); + y = LLVMBuildPointerCast(p->builder, y, ptr_type, ""); + lbValue lhs = {x, pt}; + lbValue rhs = {y, pt}; + + + lbBlock *block_same_ptr = lb_create_block(p, "same_ptr"); + lbBlock *block_diff_ptr = lb_create_block(p, "diff_ptr"); + + lbValue same_ptr = lb_emit_comp(p, Token_CmpEq, lhs, rhs); + lb_emit_if(p, same_ptr, block_same_ptr, block_diff_ptr); + lb_start_block(p, block_same_ptr); + LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_bool), 1, false)); + + lb_start_block(p, block_diff_ptr); + + if (type->kind == Type_Struct) { + type_set_offsets(type); - LLVMValueRef x = LLVMGetParam(p->value, 0); - LLVMValueRef y = LLVMGetParam(p->value, 1); - x = LLVMBuildPointerCast(p->builder, x, ptr_type, ""); - y = LLVMBuildPointerCast(p->builder, y, ptr_type, ""); - lbValue lhs = {x, pt}; - lbValue rhs = {y, pt}; + lbBlock *block_false = lb_create_block(p, "bfalse"); + lbValue res = lb_const_bool(m, t_bool, true); + for_array(i, type->Struct.fields) { + lbBlock *next_block = lb_create_block(p, "btrue"); - lbBlock *block_same_ptr = lb_create_block(p, "same_ptr"); - lbBlock *block_diff_ptr = lb_create_block(p, "diff_ptr"); + lbValue pleft = lb_emit_struct_ep(p, lhs, cast(i32)i); + lbValue pright = lb_emit_struct_ep(p, rhs, cast(i32)i); + lbValue left = lb_emit_load(p, pleft); + lbValue right = lb_emit_load(p, pright); + lbValue ok = lb_emit_comp(p, Token_CmpEq, left, right); + + lb_emit_if(p, ok, next_block, block_false); + + lb_emit_jump(p, next_block); + lb_start_block(p, next_block); + } - lbValue same_ptr = lb_emit_comp(p, Token_CmpEq, lhs, rhs); - lb_emit_if(p, same_ptr, block_same_ptr, block_diff_ptr); - lb_start_block(p, block_same_ptr); LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_bool), 1, false)); - lb_start_block(p, block_diff_ptr); + lb_start_block(p, block_false); - if (type->kind == Type_Struct) { - type_set_offsets(type); + LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_bool), 0, false)); + } else { + lbValue left = lb_emit_load(p, lhs); + lbValue right = lb_emit_load(p, rhs); + lbValue ok = lb_emit_comp(p, Token_CmpEq, left, right); + ok = lb_emit_conv(p, ok, t_bool); + LLVMBuildRet(p->builder, ok.value); + } - lbBlock *block_false = lb_create_block(p, "bfalse"); - lbValue res = lb_const_bool(m, t_bool, true); + lb_end_procedure_body(p); - for_array(i, type->Struct.fields) { - lbBlock *next_block = lb_create_block(p, "btrue"); + compare_proc = p; + return {compare_proc->value, compare_proc->type}; +} + +lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) { + Type *original_type = type; + type = base_type(type); + GB_ASSERT(is_type_valid_for_keys(type)); - lbValue pleft = lb_emit_struct_ep(p, lhs, cast(i32)i); - lbValue pright = lb_emit_struct_ep(p, rhs, cast(i32)i); - lbValue left = lb_emit_load(p, pleft); - lbValue right = lb_emit_load(p, pright); - lbValue ok = lb_emit_comp(p, Token_CmpEq, left, right); + Type *pt = alloc_type_pointer(type); + LLVMTypeRef ptr_type = lb_type(m, pt); - lb_emit_if(p, ok, next_block, block_false); + auto key = hash_type(type); + lbProcedure **found = map_get(&m->hasher_procs, key); + lbProcedure *hasher_proc = nullptr; + if (found) { + hasher_proc = *found; + GB_ASSERT(hasher_proc != nullptr); + return {hasher_proc->value, hasher_proc->type}; + } - lb_emit_jump(p, next_block); - lb_start_block(p, next_block); - } + static u32 proc_index = 0; - LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_bool), 1, false)); + char buf[16] = {}; + isize n = gb_snprintf(buf, 16, "__$hasher%u", ++proc_index); + char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); + String proc_name = make_string_c(str); - lb_start_block(p, block_false); + lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_hasher_proc); + map_set(&m->hasher_procs, key, p); + lb_begin_procedure_body(p); - LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_bool), 0, false)); - } else { - lbValue left = lb_emit_load(p, lhs); - lbValue right = lb_emit_load(p, rhs); - lbValue ok = lb_emit_comp(p, Token_CmpEq, left, right); - ok = lb_emit_conv(p, ok, t_bool); - LLVMBuildRet(p->builder, ok.value); - } + LLVMValueRef x = LLVMGetParam(p->value, 0); + LLVMValueRef y = LLVMGetParam(p->value, 1); + lbValue data = {x, t_rawptr}; + lbValue seed = {y, t_uintptr}; - lb_end_procedure_body(p); + if (type->kind == Type_Struct) { + type_set_offsets(type); - map_set(&m->compare_procs, key, p); + GB_PANIC("Type_Struct"); + } else if (is_type_string(type)) { + auto args = array_make<lbValue>(permanent_allocator(), 2); + args[0] = data; + args[1] = seed; + lbValue res = lb_emit_runtime_call(p, "default_hasher_string", args); + LLVMBuildRet(p->builder, res.value); + } else { + GB_ASSERT_MSG(is_type_simple_compare(type), "%s", type_to_string(type)); + + i64 sz = type_size_of(type); + char const *name = nullptr; + switch (sz) { + case 1: name = "default_hasher1"; break; + case 2: name = "default_hasher2"; break; + case 4: name = "default_hasher4"; break; + case 8: name = "default_hasher8"; break; + case 16: name = "default_hasher16"; break; + default: GB_PANIC("unhandled hasher for key type: %s", type_to_string(type)); + } + GB_ASSERT(name != nullptr); - compare_proc = p; + auto args = array_make<lbValue>(permanent_allocator(), 2); + args[0] = data; + args[1] = seed; + lbValue res = lb_emit_runtime_call(p, name, args); + LLVMBuildRet(p->builder, res.value); } - GB_ASSERT(compare_proc != nullptr); - return {compare_proc->value, compare_proc->type}; + lb_end_procedure_body(p); + + hasher_proc = p; + return {hasher_proc->value, hasher_proc->type}; } + + lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue right) { Type *a = core_type(left.type); Type *b = core_type(right.type); @@ -11571,7 +11646,8 @@ void lb_init_module(lbModule *m, Checker *c) { string_map_init(&m->const_strings, a); map_init(&m->anonymous_proc_lits, a); map_init(&m->function_type_map, a); - map_init(&m->compare_procs, a); + map_init(&m->equal_procs, a); + map_init(&m->hasher_procs, a); array_init(&m->procedures_to_generate, a); array_init(&m->foreign_library_paths, a); @@ -12307,10 +12383,12 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_map_ptr); init_map_internal_types(t); - LLVMValueRef vals[3] = { + LLVMValueRef vals[5] = { lb_get_type_info_ptr(m, t->Map.key).value, lb_get_type_info_ptr(m, t->Map.value).value, lb_get_type_info_ptr(m, t->Map.generated_struct_type).value, + lb_get_equal_proc_for_type(m, t->Map.key).value, + lb_get_hasher_proc_for_type(m, t->Map.key).value }; lbValue res = {}; |