From 046dd5503211c617a88d7de7d089dd5b74e63500 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 8 Nov 2022 13:02:32 +0000 Subject: Change `__dynamic_map_get` signature --- src/llvm_backend_expr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/llvm_backend_expr.cpp') diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 05a9fdfbf..7e9aa3a78 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1423,9 +1423,9 @@ lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) { switch (rt->kind) { case Type_Map: { - lbValue map_ptr = lb_address_from_load_or_generate_local(p, right); + lbValue map = right; lbValue key = left; - lbValue ptr = lb_internal_dynamic_map_get_ptr(p, map_ptr, key); + lbValue ptr = lb_internal_dynamic_map_get_ptr(p, map, key); if (be->op.kind == Token_in) { return lb_emit_conv(p, lb_emit_comp_against_nil(p, Token_NotEq, ptr), t_bool); } else { -- cgit v1.2.3 From 1bcec3f7696243664d8bfefa24b4262d4f412755 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 9 Nov 2022 22:21:36 +0000 Subject: Change map internal calls to use a pointer --- src/llvm_backend.cpp | 8 ++++---- src/llvm_backend_expr.cpp | 4 ++-- src/llvm_backend_general.cpp | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/llvm_backend_expr.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 2b95c5b2f..e12a4c016 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -757,8 +757,8 @@ lbValue lb_gen_map_key_hash(lbProcedure *p, lbValue key, Type *key_type, lbValue return hashed_key; } -lbValue lb_internal_dynamic_map_get_ptr(lbProcedure *p, lbValue const &map, lbValue const &key) { - Type *map_type = base_type(map.type); +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)); GB_ASSERT(map_type->kind == Type_Map); lbValue ptr = {}; @@ -770,13 +770,13 @@ lbValue lb_internal_dynamic_map_get_ptr(lbProcedure *p, lbValue const &map, lbVa lbValue map_get_proc = lb_get_map_get_proc_for_type(p->module, map_type); auto args = array_make(permanent_allocator(), 2); - args[0] = lb_address_from_load_or_generate_local(p, map); + args[0] = map_ptr; args[1] = key_ptr; ptr = lb_emit_call(p, map_get_proc, args); } else { auto args = array_make(permanent_allocator(), 3); - args[0] = lb_emit_transmute(p, map, t_raw_map); + args[0] = lb_emit_transmute(p, lb_emit_load(p, map_ptr), t_raw_map); args[1] = lb_gen_map_info_ptr(p->module, map_type); args[2] = key_ptr; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 7e9aa3a78..05a9fdfbf 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1423,9 +1423,9 @@ lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) { switch (rt->kind) { case Type_Map: { - lbValue map = right; + lbValue map_ptr = lb_address_from_load_or_generate_local(p, right); lbValue key = left; - lbValue ptr = lb_internal_dynamic_map_get_ptr(p, map, key); + lbValue ptr = lb_internal_dynamic_map_get_ptr(p, map_ptr, key); if (be->op.kind == Token_in) { return lb_emit_conv(p, lb_emit_comp_against_nil(p, Token_NotEq, ptr), t_bool); } else { diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 859542fb5..a0e4d80ba 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -418,7 +418,7 @@ lbValue lb_addr_get_ptr(lbProcedure *p, lbAddr const &addr) { switch (addr.kind) { case lbAddr_Map: - return lb_internal_dynamic_map_get_ptr(p, lb_emit_load(p, addr.addr), addr.map.key); + return lb_internal_dynamic_map_get_ptr(p, addr.addr, addr.map.key); case lbAddr_RelativePointer: { Type *rel_ptr = base_type(lb_addr_type(addr)); @@ -1075,7 +1075,7 @@ lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) { GB_ASSERT(map_type->kind == Type_Map); lbAddr v = lb_add_local_generated(p, map_type->Map.lookup_result_type, true); - lbValue ptr = lb_internal_dynamic_map_get_ptr(p, lb_emit_load(p, addr.addr), addr.map.key); + lbValue ptr = lb_internal_dynamic_map_get_ptr(p, addr.addr, addr.map.key); lbValue ok = lb_emit_conv(p, lb_emit_comp_against_nil(p, Token_NotEq, ptr), t_bool); lb_emit_store(p, lb_emit_struct_ep(p, v.addr, 1), ok); -- cgit v1.2.3 From 8852d090b61fab27f97787b37b7cbd5b63a52083 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 10 Nov 2022 12:46:53 +0000 Subject: Correct static map get; make get take a pointer to simplify compiler internals --- core/runtime/dynamic_map_internal.odin | 21 ++++++------ src/llvm_backend.cpp | 58 +++++++++++++++++++--------------- src/llvm_backend.hpp | 4 +-- src/llvm_backend_expr.cpp | 2 +- src/llvm_backend_proc.cpp | 4 +-- src/llvm_backend_type.cpp | 4 +-- src/llvm_backend_utility.cpp | 2 +- 7 files changed, 50 insertions(+), 45 deletions(-) (limited to 'src/llvm_backend_expr.cpp') diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin index f57dce885..aedd3f260 100644 --- a/core/runtime/dynamic_map_internal.odin +++ b/core/runtime/dynamic_map_internal.odin @@ -107,7 +107,7 @@ Map_Cell_Info :: struct { map_cell_info :: intrinsics.type_map_cell_info // Same as the above procedure but at runtime with the cell Map_Cell_Info value. -map_cell_index_dynamic :: #force_inline proc "contextless" (base: uintptr, info: ^Map_Cell_Info, index: uintptr) -> uintptr { +map_cell_index_dynamic :: #force_inline proc "contextless" (base: uintptr, #no_alias info: ^Map_Cell_Info, index: uintptr) -> uintptr { // Micro-optimize the common cases to save on integer division. elements_per_cell := uintptr(info.elements_per_cell) size_of_cell := uintptr(info.size_of_cell) @@ -355,13 +355,13 @@ map_alloc_dynamic :: proc "odin" (info: ^Map_Info, log2_capacity: uintptr, alloc // there is no type information. // // This procedure returns the address of the just inserted value. -map_insert_hash_dynamic :: proc "odin" (m: ^Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) -> (result: uintptr) { +map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) -> (result: uintptr) { + h := h pos := map_desired_position(m^, h) distance := uintptr(0) mask := (uintptr(1) << map_log2_cap(m^)) - 1 ks, vs, hs, sk, sv := map_kvh_data_dynamic(m^, info) - _, _ = sk, sv // Avoid redundant loads of these values size_of_k := info.ks.size_of_type @@ -376,7 +376,6 @@ map_insert_hash_dynamic :: proc "odin" (m: ^Raw_Map, #no_alias info: ^Map_Info, tk := map_cell_index_dynamic(sk, info.ks, 1) tv := map_cell_index_dynamic(sv, info.vs, 1) - h := h for { hp := &hs[pos] @@ -660,19 +659,19 @@ map_get :: proc "contextless" (m: $T/map[$K]$V, key: K) -> (stored_key: K, store } } -__dynamic_map_get_with_hash :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, key: rawptr) -> (ptr: rawptr) { +__dynamic_map_get_with_hash :: proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, key: rawptr) -> (ptr: rawptr) { if m.len == 0 { return nil } - pos := map_desired_position(m, h) + pos := map_desired_position(m^, h) distance := uintptr(0) - mask := (uintptr(1) << map_log2_cap(m)) - 1 - ks, vs, hs, _, _ := map_kvh_data_dynamic(m, info) + mask := (uintptr(1) << map_log2_cap(m^)) - 1 + ks, vs, hs, _, _ := map_kvh_data_dynamic(m^, info) for { element_hash := hs[pos] if map_hash_is_empty(element_hash) { return nil - } else if distance > map_probe_distance(m, element_hash, pos) { + } else if distance > map_probe_distance(m^, element_hash, pos) { return nil } else if element_hash == h && info.key_equal(key, rawptr(map_cell_index_dynamic(ks, info.ks, pos))) { return rawptr(map_cell_index_dynamic(vs, info.vs, pos)) @@ -682,7 +681,7 @@ __dynamic_map_get_with_hash :: proc "contextless" (m: Raw_Map, #no_alias info: ^ } } -__dynamic_map_get :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info, key: rawptr) -> (ptr: rawptr) { +__dynamic_map_get :: proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key: rawptr) -> (ptr: rawptr) { if m.len == 0 { return nil } @@ -693,7 +692,7 @@ __dynamic_map_get :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info, __dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> rawptr { hash := info.key_hasher(key, 0) - if found := __dynamic_map_get_with_hash(m^, info, hash, key); found != nil { + if found := __dynamic_map_get_with_hash(m, info, hash, key); found != nil { intrinsics.mem_copy_non_overlapping(found, value, info.vs.size_of_type) return found } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index e12a4c016..c313bc825 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -140,7 +140,7 @@ lbContextData *lb_push_context_onto_stack(lbProcedure *p, lbAddr ctx) { } -lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type) { +lbValue lb_equal_proc_for_type(lbModule *m, Type *type) { type = base_type(type); GB_ASSERT(is_type_comparable(type)); @@ -296,7 +296,7 @@ lbValue lb_simple_compare_hash(lbProcedure *p, Type *type, lbValue data, lbValue return lb_emit_runtime_call(p, "default_hasher_n", args); } -lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) { +lbValue lb_hasher_proc_for_type(lbModule *m, Type *type) { type = core_type(type); GB_ASSERT_MSG(is_type_valid_for_keys(type), "%s", type_to_string(type)); @@ -343,7 +343,7 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) { GB_ASSERT(type->Struct.offsets != nullptr); i64 offset = type->Struct.offsets[i]; Entity *field = type->Struct.fields[i]; - lbValue field_hasher = lb_get_hasher_proc_for_type(m, field->type); + lbValue field_hasher = lb_hasher_proc_for_type(m, field->type); lbValue ptr = lb_emit_ptr_offset(p, data, lb_const_int(m, t_uintptr, offset)); args[0] = ptr; @@ -356,7 +356,7 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) { if (is_type_union_maybe_pointer(type)) { Type *v = type->Union.variants[0]; - lbValue variant_hasher = lb_get_hasher_proc_for_type(m, v); + lbValue variant_hasher = lb_hasher_proc_for_type(m, v); args[0] = data; args[1] = seed; @@ -379,7 +379,7 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) { Type *v = type->Union.variants[i]; lbValue case_tag = lb_const_union_tag(p->module, type, v); - lbValue variant_hasher = lb_get_hasher_proc_for_type(m, v); + lbValue variant_hasher = lb_hasher_proc_for_type(m, v); args[0] = data; args[1] = seed; @@ -397,7 +397,7 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) { lb_addr_store(p, pres, seed); auto args = array_make(permanent_allocator(), 2); - lbValue elem_hasher = lb_get_hasher_proc_for_type(m, type->Array.elem); + lbValue elem_hasher = lb_hasher_proc_for_type(m, type->Array.elem); auto loop_data = lb_loop_start(p, cast(isize)type->Array.count, t_i32); @@ -418,7 +418,7 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) { lb_addr_store(p, res, seed); auto args = array_make(permanent_allocator(), 2); - lbValue elem_hasher = lb_get_hasher_proc_for_type(m, type->EnumeratedArray.elem); + lbValue elem_hasher = lb_hasher_proc_for_type(m, type->EnumeratedArray.elem); auto loop_data = lb_loop_start(p, cast(isize)type->EnumeratedArray.count, t_i32); @@ -454,7 +454,7 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) { } -lbValue lb_get_map_get_proc_for_type(lbModule *m, Type *type) { +lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) { GB_ASSERT(build_context.use_static_map_calls); type = base_type(type); GB_ASSERT(type->kind == Type_Map); @@ -468,7 +468,7 @@ lbValue lb_get_map_get_proc_for_type(lbModule *m, Type *type) { static u32 proc_index = 0; char buf[32] = {}; - isize n = gb_snprintf(buf, 32, "__$map_get%u", ++proc_index); + isize n = gb_snprintf(buf, 32, "__$map_get_%u", ++proc_index); char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); String proc_name = make_string_c(str); @@ -489,9 +489,23 @@ lbValue lb_get_map_get_proc_for_type(lbModule *m, Type *type) { LLVMAddAttributeAtIndex(p->value, 1+1, nonnull_attr); LLVMAddAttributeAtIndex(p->value, 1+1, noalias_attr); + lbBlock *loop_block = lb_create_block(p, "loop"); + lbBlock *hash_block = lb_create_block(p, "hash"); + lbBlock *probe_block = lb_create_block(p, "probe"); + lbBlock *increment_block = lb_create_block(p, "increment"); + lbBlock *hash_compare_block = lb_create_block(p, "hash_compare"); + lbBlock *key_compare_block = lb_create_block(p, "key_compare"); + lbBlock *value_block = lb_create_block(p, "value"); + lbBlock *nil_block = lb_create_block(p, "nil"); + map_ptr = lb_emit_conv(p, map_ptr, t_raw_map_ptr); lbValue map = lb_emit_load(p, map_ptr); + lbValue length = lb_map_len(p, map); + + lb_emit_if(p, lb_emit_comp(p, Token_CmpEq, length, lb_const_nil(m, t_int)), nil_block, hash_block); + lb_start_block(p, hash_block); + key_ptr = lb_emit_conv(p, key_ptr, alloc_type_pointer(type->Map.key)); lbValue key = lb_emit_load(p, key_ptr); @@ -521,16 +535,8 @@ lbValue lb_get_map_get_proc_for_type(lbModule *m, Type *type) { // lbValue res = // LLVMBuildRet(p->builder, res.value); - lbBlock *loop = lb_create_block(p, "loop"); - lbBlock *probe_block = lb_create_block(p, "probe"); - lbBlock *increment_block = lb_create_block(p, "increment"); - lbBlock *hash_compare_block = lb_create_block(p, "hash_compare"); - lbBlock *key_compare_block = lb_create_block(p, "key_compare"); - lbBlock *value_block = lb_create_block(p, "value"); - lbBlock *nil_block = lb_create_block(p, "nil"); - - lb_emit_jump(p, loop); - lb_start_block(p, loop); + lb_emit_jump(p, loop_block); + lb_start_block(p, loop_block); lbValue element_hash = lb_emit_load(p, lb_emit_ptr_offset(p, hs, lb_addr_load(p, pos))); { @@ -577,7 +583,7 @@ lbValue lb_get_map_get_proc_for_type(lbModule *m, Type *type) { lb_addr_store(p, pos, pp); lb_emit_increment(p, distance.addr); } - lb_emit_jump(p, loop); + lb_emit_jump(p, loop_block); lb_start_block(p, nil_block); { @@ -678,8 +684,8 @@ lbValue lb_gen_map_info_ptr(lbModule *m, Type *map_type) { 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; + const_values[2] = lb_hasher_proc_for_type(m, map_type->Map.key).value; + const_values[3] = lb_equal_proc_for_type(m, map_type->Map.key).value; 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}; @@ -746,7 +752,7 @@ lbValue lb_gen_map_key_hash(lbProcedure *p, lbValue key, Type *key_type, lbValue lbValue hashed_key = lb_const_hash(p->module, key, key_type); if (hashed_key.value == nullptr) { - lbValue hasher = lb_get_hasher_proc_for_type(p->module, key_type); + lbValue hasher = lb_hasher_proc_for_type(p->module, key_type); auto args = array_make(permanent_allocator(), 2); args[0] = key_ptr; @@ -767,16 +773,16 @@ lbValue lb_internal_dynamic_map_get_ptr(lbProcedure *p, lbValue const &map_ptr, key_ptr = lb_emit_conv(p, key_ptr, t_rawptr); if (build_context.use_static_map_calls) { - lbValue map_get_proc = lb_get_map_get_proc_for_type(p->module, map_type); + lbValue map_get_proc = lb_map_get_proc_for_type(p->module, map_type); auto args = array_make(permanent_allocator(), 2); - args[0] = map_ptr; + args[0] = lb_emit_conv(p, map_ptr, t_rawptr); args[1] = key_ptr; ptr = lb_emit_call(p, map_get_proc, args); } else { auto args = array_make(permanent_allocator(), 3); - args[0] = lb_emit_transmute(p, lb_emit_load(p, map_ptr), t_raw_map); + args[0] = lb_emit_transmute(p, map_ptr, t_raw_map_ptr); args[1] = lb_gen_map_info_ptr(p->module, map_type); args[2] = key_ptr; diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index f9fe6cff0..c4333e949 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -463,8 +463,8 @@ lbValue lb_emit_source_code_location_const(lbProcedure *p, String const &procedu lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type, ParameterValue const ¶m_value, TokenPos const &pos); -lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type); -lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type); +lbValue lb_equal_proc_for_type(lbModule *m, Type *type); +lbValue lb_hasher_proc_for_type(lbModule *m, Type *type); lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t); LLVMMetadataRef lb_debug_type(lbModule *m, Type *type); diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 05a9fdfbf..aee87242c 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -2215,7 +2215,7 @@ lbValue lb_compare_records(lbProcedure *p, TokenKind op_kind, lbValue left, lbVa args[2] = lb_const_int(p->module, t_int, type_size_of(type)); res = lb_emit_runtime_call(p, "memory_equal", args); } else { - lbValue value = lb_get_equal_proc_for_type(p->module, type); + lbValue value = lb_equal_proc_for_type(p->module, type); auto args = array_make(permanent_allocator(), 2); args[0] = lb_emit_conv(p, left_ptr, t_rawptr); args[1] = lb_emit_conv(p, right_ptr, t_rawptr); diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 6d7d7eecb..4b0323855 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -2319,10 +2319,10 @@ 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); + return lb_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); + return lb_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); diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index 26f89f985..307d9304b 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -666,7 +666,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da } if (is_type_comparable(t) && !is_type_simple_compare(t)) { - vals[3] = lb_get_equal_proc_for_type(m, t).value; + vals[3] = lb_equal_proc_for_type(m, t).value; } vals[4] = lb_const_bool(m, t_bool, t->Union.custom_align != 0).value; @@ -702,7 +702,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da vals[6] = is_raw_union.value; vals[7] = is_custom_align.value; if (is_type_comparable(t) && !is_type_simple_compare(t)) { - vals[8] = lb_get_equal_proc_for_type(m, t).value; + vals[8] = lb_equal_proc_for_type(m, t).value; } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 6d69021ce..30c531d71 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -1434,7 +1434,7 @@ lbValue lb_dynamic_array_allocator(lbProcedure *p, lbValue da) { } lbValue lb_map_len(lbProcedure *p, lbValue value) { - GB_ASSERT(is_type_map(value.type)); + GB_ASSERT_MSG(is_type_map(value.type) || are_types_identical(value.type, t_raw_map), "%s", type_to_string(value.type)); lbValue len = lb_emit_struct_ev(p, value, 1); return lb_emit_conv(p, len, t_int); } -- cgit v1.2.3 From 16fc96101049ef884401ab6182ea860390abd6a9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 11 Nov 2022 14:45:22 +0000 Subject: Begin work on map static set --- core/runtime/dynamic_map_internal.odin | 4 +- src/check_expr.cpp | 52 +++++++---- src/checker.cpp | 9 +- src/llvm_backend.cpp | 162 ++++++++++++++++++++++++++++++--- src/llvm_backend.hpp | 3 +- src/llvm_backend_const.cpp | 17 +++- src/llvm_backend_expr.cpp | 2 +- src/llvm_backend_general.cpp | 3 +- src/llvm_backend_utility.cpp | 7 ++ src/types.cpp | 1 + 10 files changed, 218 insertions(+), 42 deletions(-) (limited to 'src/llvm_backend_expr.cpp') diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin index 65f883c7c..9721340f6 100644 --- a/core/runtime/dynamic_map_internal.odin +++ b/core/runtime/dynamic_map_internal.odin @@ -696,9 +696,7 @@ __dynamic_map_check_grow :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: } // IMPORTANT: USED WITHIN THE COMPILER -__dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> rawptr { - hash := info.key_hasher(key, 0) - +__dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, hash: Map_Hash, key, value: rawptr, loc := #caller_location) -> rawptr { if found := __dynamic_map_get(m, info, hash, key); found != nil { intrinsics.mem_copy_non_overlapping(found, value, info.vs.size_of_type) return found diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 045b22ca2..c58aac609 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -285,6 +285,37 @@ void error_operand_no_value(Operand *o) { } } +void add_map_get_dependencies(CheckerContext *c) { + if (build_context.use_static_map_calls) { + add_package_dependency(c, "runtime", "map_desired_position"); + add_package_dependency(c, "runtime", "map_probe_distance"); + } else { + add_package_dependency(c, "runtime", "__dynamic_map_get"); + } +} + +void add_map_set_dependencies(CheckerContext *c) { + init_core_source_code_location(c->checker); + + if (t_map_set_proc == nullptr) { + Type *map_set_args[5] = {/*map*/t_rawptr, /*hash*/t_uintptr, /*key*/t_rawptr, /*value*/t_rawptr, /*#caller_location*/t_source_code_location}; + t_map_set_proc = alloc_type_proc_from_types(map_set_args, gb_count_of(map_set_args), t_rawptr, false, ProcCC_Odin); + } + + if (build_context.use_static_map_calls) { + add_package_dependency(c, "runtime", "__dynamic_map_check_grow"); + add_package_dependency(c, "runtime", "map_insert_hash_dynamic"); + } else { + add_package_dependency(c, "runtime", "__dynamic_map_set"); + } +} + +void add_map_reserve_dependencies(CheckerContext *c) { + init_core_source_code_location(c->checker); + add_package_dependency(c, "runtime", "__dynamic_map_reserve"); +} + + void check_scope_decls(CheckerContext *c, Slice const &nodes, isize reserve_size) { Scope *s = c->scope; @@ -3244,12 +3275,7 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint check_assignment(c, x, yt->Map.key, str_lit("map 'not_in'")); } - if (build_context.use_static_map_calls) { - add_package_dependency(c, "runtime", "map_desired_position"); - add_package_dependency(c, "runtime", "map_probe_distance"); - } else { - add_package_dependency(c, "runtime", "__dynamic_map_get"); - } + add_map_get_dependencies(c); } else if (is_type_bit_set(rhs_type)) { Type *yt = base_type(rhs_type); @@ -8560,8 +8586,8 @@ ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type * if (build_context.no_dynamic_literals && cl->elems.count) { error(node, "Compound literals of dynamic types have been disabled"); } else { - add_package_dependency(c, "runtime", "__dynamic_map_reserve"); - add_package_dependency(c, "runtime", "__dynamic_map_set"); + add_map_reserve_dependencies(c); + add_map_set_dependencies(c); } break; } @@ -8997,14 +9023,8 @@ ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_h o->type = t->Map.value; o->expr = node; - - add_package_dependency(c, "runtime", "__dynamic_map_set"); - if (build_context.use_static_map_calls) { - add_package_dependency(c, "runtime", "map_desired_position"); - add_package_dependency(c, "runtime", "map_probe_distance"); - } else { - add_package_dependency(c, "runtime", "__dynamic_map_get"); - } + add_map_get_dependencies(c); + add_map_set_dependencies(c); return Expr_Expr; } diff --git a/src/checker.cpp b/src/checker.cpp index 0c23f2627..4d1ef4614 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -922,14 +922,13 @@ void init_universal(void) { { Type *equal_args[2] = {t_rawptr, t_rawptr}; - t_equal_proc = alloc_type_proc_from_types(equal_args, 2, t_bool, false, ProcCC_Contextless); + t_equal_proc = alloc_type_proc_from_types(equal_args, gb_count_of(equal_args), t_bool, false, ProcCC_Contextless); Type *hasher_args[2] = {t_rawptr, t_uintptr}; - t_hasher_proc = alloc_type_proc_from_types(hasher_args, 2, t_uintptr, false, ProcCC_Contextless); + t_hasher_proc = alloc_type_proc_from_types(hasher_args, gb_count_of(hasher_args), t_uintptr, false, ProcCC_Contextless); Type *map_get_args[3] = {/*map*/t_rawptr, /*hash*/t_uintptr, /*key*/t_rawptr}; - t_map_get_proc = alloc_type_proc_from_types(map_get_args, 3, t_rawptr, false, ProcCC_Contextless); - + t_map_get_proc = alloc_type_proc_from_types(map_get_args, gb_count_of(map_get_args), t_rawptr, false, ProcCC_Contextless); } // Constants @@ -2844,7 +2843,7 @@ void init_core_source_code_location(Checker *c) { return; } t_source_code_location = find_core_type(c, str_lit("Source_Code_Location")); - t_source_code_location_ptr = alloc_type_pointer(t_allocator); + t_source_code_location_ptr = alloc_type_pointer(t_source_code_location); } void init_core_map_type(Checker *c) { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 5306ed35e..4c34a56e9 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -484,7 +484,7 @@ lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) { static u32 proc_index = 0; char buf[32] = {}; - isize n = gb_snprintf(buf, 32, "__$map_get_%u", ++proc_index); + isize n = gb_snprintf(buf, 32, "__$map_get-%u", ++proc_index); char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); String proc_name = make_string_c(str); @@ -613,6 +613,129 @@ lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) { return {p->value, p->type}; } +void lb_debug_print(lbProcedure *p, String const &str) { + auto args = array_make(heap_allocator(), 1); + args[0] = lb_const_string(p->module, str); + lb_emit_runtime_call(p, "print_string", args); +} + +lbValue lb_map_set_proc_for_type(lbModule *m, Type *type) { + GB_ASSERT(build_context.use_static_map_calls); + type = base_type(type); + GB_ASSERT(type->kind == Type_Map); + + + lbProcedure **found = map_get(&m->map_set_procs, type); + if (found) { + GB_ASSERT(*found != nullptr); + return {(*found)->value, (*found)->type}; + } + static u32 proc_index = 0; + + char buf[32] = {}; + isize n = gb_snprintf(buf, 32, "__$map_set-%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_map_set_proc); + map_set(&m->map_set_procs, type, p); + lb_begin_procedure_body(p); + defer (lb_end_procedure_body(p)); + + lb_add_attribute_to_proc(m, p->value, "nounwind"); + lb_add_attribute_to_proc(m, p->value, "noinline"); + + lbValue map_ptr = {LLVMGetParam(p->value, 0), t_rawptr}; + lbValue hash = {LLVMGetParam(p->value, 1), t_uintptr}; + lbValue key_ptr = {LLVMGetParam(p->value, 2), t_rawptr}; + lbValue value_ptr = {LLVMGetParam(p->value, 3), t_rawptr}; + lbValue location_ptr = {LLVMGetParam(p->value, 4), t_source_code_location_ptr}; + + map_ptr = lb_emit_conv(p, map_ptr, alloc_type_pointer(type)); + key_ptr = lb_emit_conv(p, key_ptr, alloc_type_pointer(type->Map.key)); + + lb_add_proc_attribute_at_index(p, 1+0, "nonnull"); + lb_add_proc_attribute_at_index(p, 1+0, "noalias"); + + lb_add_proc_attribute_at_index(p, 1+2, "nonnull"); + if (!are_types_identical(type->Map.key, type->Map.value)) { + lb_add_proc_attribute_at_index(p, 1+2, "noalias"); + } + lb_add_proc_attribute_at_index(p, 1+2, "readonly"); + + lb_add_proc_attribute_at_index(p, 1+3, "nonnull"); + if (!are_types_identical(type->Map.key, type->Map.value)) { + lb_add_proc_attribute_at_index(p, 1+3, "noalias"); + } + lb_add_proc_attribute_at_index(p, 1+3, "readonly"); + + lb_add_proc_attribute_at_index(p, 1+4, "nonnull"); + lb_add_proc_attribute_at_index(p, 1+4, "noalias"); + lb_add_proc_attribute_at_index(p, 1+4, "readonly"); + + //// + lbValue found_ptr = {}; + { + lbValue map_get_proc = lb_map_get_proc_for_type(m, type); + + auto args = array_make(permanent_allocator(), 3); + args[0] = lb_emit_conv(p, map_ptr, t_rawptr); + args[1] = hash; + args[2] = key_ptr; + + found_ptr = lb_emit_call(p, map_get_proc, args); + } + + + lbBlock *found_block = lb_create_block(p, "found"); + lbBlock *check_grow_block = lb_create_block(p, "check-grow"); + lbBlock *grow_fail_block = lb_create_block(p, "grow-fail"); + lbBlock *insert_block = lb_create_block(p, "insert"); + + lb_emit_if(p, lb_emit_comp_against_nil(p, Token_NotEq, found_ptr), found_block, check_grow_block); + lb_start_block(p, found_block); + { + lb_mem_copy_non_overlapping(p, found_ptr, value_ptr, lb_const_int(m, t_int, type_size_of(type->Map.value))); + LLVMBuildRet(p->builder, lb_emit_conv(p, found_ptr, t_rawptr).value); + } + lb_start_block(p, check_grow_block); + + + lbValue map_info = lb_gen_map_info_ptr(p->module, type); + + { + auto args = array_make(permanent_allocator(), 3); + args[0] = lb_emit_conv(p, map_ptr, t_rawptr); + args[1] = map_info; + args[2] = lb_emit_load(p, location_ptr); + lbValue grow_err = lb_emit_runtime_call(p, "__dynamic_map_check_grow", args); + + lb_emit_if(p, lb_emit_comp_against_nil(p, Token_NotEq, grow_err), grow_fail_block, insert_block); + + lb_start_block(p, grow_fail_block); + LLVMBuildRet(p->builder, LLVMConstNull(lb_type(m, t_rawptr))); + } + + lb_start_block(p, insert_block); + { + auto args = array_make(permanent_allocator(), 5); + args[0] = lb_emit_conv(p, map_ptr, t_rawptr); + args[1] = map_info; + args[2] = hash; + args[3] = lb_emit_conv(p, key_ptr, t_uintptr); + args[4] = lb_emit_conv(p, value_ptr, t_uintptr); + + lbValue result = lb_emit_runtime_call(p, "map_insert_hash_dynamic", args); + + lb_emit_increment(p, lb_map_len_ptr(p, map_ptr)); + + LLVMBuildRet(p->builder, lb_emit_conv(p, result, t_rawptr).value); + } + + return {p->value, p->type}; +} + + lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, Ast *expr, lbProcedure *parent) { lbProcedure **found = map_get(&m->gen->anonymous_proc_lits, expr); if (found) { @@ -810,8 +933,8 @@ lbValue lb_internal_dynamic_map_get_ptr(lbProcedure *p, lbValue const &map_ptr, return lb_emit_conv(p, ptr, alloc_type_pointer(map_type->Map.value)); } -void lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbValue const &map_ptr, Type *map_type, - lbValue const &map_key, lbValue const &map_value, Ast *node) { +void lb_internal_dynamic_map_set(lbProcedure *p, lbValue const &map_ptr, Type *map_type, + lbValue const &map_key, lbValue const &map_value, Ast *node) { map_type = base_type(map_type); GB_ASSERT(map_type->kind == Type_Map); @@ -821,14 +944,27 @@ void lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbValue const &map_ptr, lbValue v = lb_emit_conv(p, map_value, map_type->Map.value); lbValue value_ptr = lb_address_from_load_or_generate_local(p, v); - auto args = array_make(permanent_allocator(), 6); - args[0] = lb_emit_conv(p, map_ptr, t_raw_map_ptr); - args[1] = lb_gen_map_info_ptr(p->module, map_type); - args[2] = hash; - args[3] = lb_emit_conv(p, key_ptr, t_rawptr); - args[4] = lb_emit_conv(p, value_ptr, t_rawptr); - args[5] = lb_emit_source_code_location_as_global(p, node); - lb_emit_runtime_call(p, "__dynamic_map_set", args); + if (build_context.use_static_map_calls) { + lbValue map_set_proc = lb_map_set_proc_for_type(p->module, map_type); + + auto args = array_make(permanent_allocator(), 5); + args[0] = lb_emit_conv(p, map_ptr, t_rawptr); + args[1] = hash; + args[2] = lb_emit_conv(p, key_ptr, t_rawptr); + args[3] = lb_emit_conv(p, value_ptr, t_rawptr); + args[4] = lb_emit_source_code_location_as_global(p, node); + + lb_emit_call(p, map_set_proc, args); + } else { + auto args = array_make(permanent_allocator(), 6); + args[0] = lb_emit_conv(p, map_ptr, t_raw_map_ptr); + args[1] = lb_gen_map_info_ptr(p->module, map_type); + args[2] = hash; + args[3] = lb_emit_conv(p, key_ptr, t_rawptr); + args[4] = lb_emit_conv(p, value_ptr, t_rawptr); + args[5] = lb_emit_source_code_location_as_global(p, node); + lb_emit_runtime_call(p, "__dynamic_map_set", args); + } } void lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const capacity, TokenPos const &pos) { @@ -1386,6 +1522,10 @@ WORKER_TASK_PROC(lb_llvm_function_pass_worker_proc) { lbProcedure *p = m->map_get_procs.entries[i].value; lb_run_function_pass_manager(default_function_pass_manager, p); } + for_array(i, m->map_set_procs.entries) { + lbProcedure *p = m->map_set_procs.entries[i].value; + lb_run_function_pass_manager(default_function_pass_manager, p); + } return 0; } diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index c4333e949..9074de42a 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -145,6 +145,7 @@ struct lbModule { PtrMap equal_procs; PtrMap hasher_procs; PtrMap map_get_procs; + PtrMap map_set_procs; u32 nested_type_name_guid; @@ -451,7 +452,7 @@ lbValue lb_gen_map_cell_info_ptr(lbModule *m, Type *type); lbValue lb_gen_map_info_ptr(lbModule *m, Type *map_type); lbValue lb_internal_dynamic_map_get_ptr(lbProcedure *p, lbValue const &map_ptr, lbValue const &key); -void lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbValue const &map_ptr, Type *map_type, lbValue const &map_key, lbValue const &map_value, Ast *node); +void lb_internal_dynamic_map_set(lbProcedure *p, lbValue const &map_ptr, Type *map_type, lbValue const &map_key, lbValue const &map_value, Ast *node); void lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const capacity, TokenPos const &pos); lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e); diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index a8b66a0ea..dff5298c5 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -283,19 +283,28 @@ lbValue lb_emit_source_code_location_const(lbProcedure *p, Ast *node) { return lb_emit_source_code_location_const(p, proc_name, pos); } -lbValue lb_emit_source_code_location_as_global(lbProcedure *p, String const &procedure, TokenPos const &pos) { + +lbValue lb_emit_source_code_location_as_global_ptr(lbProcedure *p, String const &procedure, TokenPos const &pos) { lbValue loc = lb_emit_source_code_location_const(p, procedure, pos); lbAddr addr = lb_add_global_generated(p->module, loc.type, loc, nullptr); lb_make_global_private_const(addr); - return lb_addr_load(p, addr); + return addr.addr; } -lbValue lb_emit_source_code_location_as_global(lbProcedure *p, Ast *node) { +lbValue lb_emit_source_code_location_as_global_ptr(lbProcedure *p, Ast *node) { lbValue loc = lb_emit_source_code_location_const(p, node); lbAddr addr = lb_add_global_generated(p->module, loc.type, loc, nullptr); lb_make_global_private_const(addr); - return lb_addr_load(p, addr); + return addr.addr; +} + +lbValue lb_emit_source_code_location_as_global(lbProcedure *p, String const &procedure, TokenPos const &pos) { + return lb_emit_load(p, lb_emit_source_code_location_as_global_ptr(p, procedure, pos)); +} + +lbValue lb_emit_source_code_location_as_global(lbProcedure *p, Ast *node) { + return lb_emit_load(p, lb_emit_source_code_location_as_global_ptr(p, node)); } diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index aee87242c..e58c84c9c 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -4139,7 +4139,7 @@ lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { lbValue key = lb_build_expr(p, fv->field); lbValue value = lb_build_expr(p, fv->value); - lb_insert_dynamic_map_key_and_value(p, v.addr, type, key, value, elem); + lb_internal_dynamic_map_set(p, v.addr, type, key, value, elem); } break; } diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index a0e4d80ba..f36dc1842 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -68,6 +68,7 @@ void lb_init_module(lbModule *m, Checker *c) { map_init(&m->equal_procs, a); map_init(&m->hasher_procs, a); map_init(&m->map_get_procs, a); + map_init(&m->map_set_procs, a); array_init(&m->procedures_to_generate, a, 0, 1024); array_init(&m->missing_procedures_to_check, a, 0, 16); map_init(&m->debug_values, a); @@ -727,7 +728,7 @@ void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) { return; } else if (addr.kind == lbAddr_Map) { - lb_insert_dynamic_map_key_and_value(p, addr.addr, addr.map.type, addr.map.key, value, p->curr_stmt); + lb_internal_dynamic_map_set(p, addr.addr, addr.map.type, addr.map.key, value, p->curr_stmt); return; } else if (addr.kind == lbAddr_Context) { lbAddr old_addr = lb_find_or_generate_context_ptr(p); diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 30c531d71..101b9dbfb 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -1438,6 +1438,13 @@ lbValue lb_map_len(lbProcedure *p, lbValue value) { lbValue len = lb_emit_struct_ev(p, value, 1); return lb_emit_conv(p, len, t_int); } +lbValue lb_map_len_ptr(lbProcedure *p, lbValue map_ptr) { + Type *type = map_ptr.type; + GB_ASSERT(is_type_pointer(type)); + type = type_deref(type); + GB_ASSERT_MSG(is_type_map(type) || are_types_identical(type, t_raw_map), "%s", type_to_string(type)); + return lb_emit_struct_ep(p, map_ptr, 1); +} lbValue lb_map_cap(lbProcedure *p, lbValue value) { GB_ASSERT_MSG(is_type_map(value.type) || are_types_identical(value.type, t_raw_map), "%s", type_to_string(value.type)); diff --git a/src/types.cpp b/src/types.cpp index 74b192010..47007491d 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -694,6 +694,7 @@ gb_global Type *t_raw_map_ptr = nullptr; gb_global Type *t_equal_proc = nullptr; gb_global Type *t_hasher_proc = nullptr; gb_global Type *t_map_get_proc = nullptr; +gb_global Type *t_map_set_proc = nullptr; gb_global Type *t_objc_object = nullptr; gb_global Type *t_objc_selector = nullptr; -- cgit v1.2.3 From d2019e3e4d4b45c34bdc0ef7cf7d630ee61a02fb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 13 Nov 2022 23:50:45 +0000 Subject: Enforce pointer cast --- src/llvm_backend.cpp | 4 ++-- src/llvm_backend_expr.cpp | 3 ++- src/llvm_backend_proc.cpp | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src/llvm_backend_expr.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 2ee292880..594224e6a 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -962,7 +962,7 @@ void lb_internal_dynamic_map_set(lbProcedure *p, lbValue const &map_ptr, Type *m } } -void lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const capacity, TokenPos const &pos) { +lbValue lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const capacity, TokenPos const &pos) { GB_ASSERT(!build_context.no_dynamic_literals); String proc_name = {}; @@ -975,7 +975,7 @@ void lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const args[1] = lb_gen_map_info_ptr(p->module, 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); + return lb_emit_runtime_call(p, "__dynamic_map_reserve", args); } diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index e58c84c9c..034682855 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -4131,7 +4131,8 @@ lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { } GB_ASSERT(!build_context.no_dynamic_literals); - lb_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos); + lbValue err = lb_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos); + gb_unused(err); for_array(field_index, cl->elems) { Ast *elem = cl->elems[field_index]; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 2e508a939..510479440 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -599,6 +599,7 @@ void lb_begin_procedure_body(lbProcedure *p) { p->entity->decl_info != nullptr && p->entity->decl_info->defer_use_count == 0) { lbValue val = lb_emit_struct_ep(p, p->return_ptr.addr, cast(i32)i); + val = lb_emit_conv(p, val, alloc_type_pointer(e->type)); lb_add_entity(p->module, e, val); lb_add_debug_local_variable(p, val.value, e->type, e->token); -- cgit v1.2.3