diff --git a/base/runtime/internal.odin b/base/runtime/internal.odin index 12f0dceca..7a8b76917 100644 --- a/base/runtime/internal.odin +++ b/base/runtime/internal.odin @@ -698,26 +698,6 @@ cstring16_gt :: #force_inline proc "contextless" (a, b: cstring16) -> bool { ret cstring16_le :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return cstring16_cmp(a, b) <= 0 } cstring16_ge :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return cstring16_cmp(a, b) >= 0 } -complex32_eq :: #force_inline proc "contextless" (a, b: complex32) -> bool { return real(a) == real(b) && imag(a) == imag(b) } -complex32_ne :: #force_inline proc "contextless" (a, b: complex32) -> bool { return real(a) != real(b) || imag(a) != imag(b) } - -complex64_eq :: #force_inline proc "contextless" (a, b: complex64) -> bool { return real(a) == real(b) && imag(a) == imag(b) } -complex64_ne :: #force_inline proc "contextless" (a, b: complex64) -> bool { return real(a) != real(b) || imag(a) != imag(b) } - -complex128_eq :: #force_inline proc "contextless" (a, b: complex128) -> bool { return real(a) == real(b) && imag(a) == imag(b) } -complex128_ne :: #force_inline proc "contextless" (a, b: complex128) -> bool { return real(a) != real(b) || imag(a) != imag(b) } - - -quaternion64_eq :: #force_inline proc "contextless" (a, b: quaternion64) -> bool { return real(a) == real(b) && imag(a) == imag(b) && jmag(a) == jmag(b) && kmag(a) == kmag(b) } -quaternion64_ne :: #force_inline proc "contextless" (a, b: quaternion64) -> bool { return real(a) != real(b) || imag(a) != imag(b) || jmag(a) != jmag(b) || kmag(a) != kmag(b) } - -quaternion128_eq :: #force_inline proc "contextless" (a, b: quaternion128) -> bool { return real(a) == real(b) && imag(a) == imag(b) && jmag(a) == jmag(b) && kmag(a) == kmag(b) } -quaternion128_ne :: #force_inline proc "contextless" (a, b: quaternion128) -> bool { return real(a) != real(b) || imag(a) != imag(b) || jmag(a) != jmag(b) || kmag(a) != kmag(b) } - -quaternion256_eq :: #force_inline proc "contextless" (a, b: quaternion256) -> bool { return real(a) == real(b) && imag(a) == imag(b) && jmag(a) == jmag(b) && kmag(a) == kmag(b) } -quaternion256_ne :: #force_inline proc "contextless" (a, b: quaternion256) -> bool { return real(a) != real(b) || imag(a) != imag(b) || jmag(a) != jmag(b) || kmag(a) != kmag(b) } - - string_decode_rune :: proc "contextless" (s: string) -> (rune, int) #no_bounds_check { // NOTE(bill): Duplicated here to remove dependency on package unicode/utf8 diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 9044d8346..9fb1ac93a 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2911,37 +2911,13 @@ gb_internal void add_comparison_procedures_for_fields(CheckerContext *c, Type *t if (t == nullptr) { return; } - t = base_type(t); + t = core_type(t); if (!is_type_comparable(t)) { return; } switch (t->kind) { case Type_Basic: switch (t->Basic.kind) { - case Basic_complex32: - add_package_dependency(c, "runtime", "complex32_eq"); - add_package_dependency(c, "runtime", "complex32_ne"); - break; - case Basic_complex64: - add_package_dependency(c, "runtime", "complex64_eq"); - add_package_dependency(c, "runtime", "complex64_ne"); - break; - case Basic_complex128: - add_package_dependency(c, "runtime", "complex128_eq"); - add_package_dependency(c, "runtime", "complex128_ne"); - break; - case Basic_quaternion64: - add_package_dependency(c, "runtime", "quaternion64_eq"); - add_package_dependency(c, "runtime", "quaternion64_ne"); - break; - case Basic_quaternion128: - add_package_dependency(c, "runtime", "quaternion128_eq"); - add_package_dependency(c, "runtime", "quaternion128_ne"); - break; - case Basic_quaternion256: - add_package_dependency(c, "runtime", "quaternion256_eq"); - add_package_dependency(c, "runtime", "quaternion256_ne"); - break; case Basic_cstring: add_package_dependency(c, "runtime", "cstring_eq"); add_package_dependency(c, "runtime", "cstring_ne"); @@ -2965,6 +2941,39 @@ gb_internal void add_comparison_procedures_for_fields(CheckerContext *c, Type *t add_comparison_procedures_for_fields(c, field->type); } break; + + case Type_Union: + for (Type *variant : t->Union.variants) { + add_comparison_procedures_for_fields(c, variant); + } + break; + + case Type_Array: return add_comparison_procedures_for_fields(c, t->Array.elem); + case Type_EnumeratedArray: return add_comparison_procedures_for_fields(c, t->EnumeratedArray.elem); + case Type_SimdVector: return add_comparison_procedures_for_fields(c, t->SimdVector.elem); + case Type_Matrix: return add_comparison_procedures_for_fields(c, t->Matrix.elem); + case Type_FixedCapacityDynamicArray: return add_comparison_procedures_for_fields(c, t->FixedCapacityDynamicArray.elem); + + case Type_Enum: + case Type_Tuple: + GB_PANIC("Unreachable"); + break; + + case Type_Slice: + case Type_DynamicArray: + case Type_Map: + break; + + case Type_Pointer: + case Type_MultiPointer: + case Type_Proc: + case Type_BitSet: + case Type_BitField: + case Type_SoaPointer: + break; + + default: + break; } } @@ -3165,36 +3174,6 @@ gb_internal void check_comparison(CheckerContext *c, Ast *node, Operand *x, Oper case Token_LtEq: add_package_dependency(c, "runtime", "string_le"); break; case Token_GtEq: add_package_dependency(c, "runtime", "string_gt"); break; } - } else if (is_type_complex(x->type) || is_type_complex(y->type)) { - switch (op) { - case Token_CmpEq: - switch (8*size) { - case 64: add_package_dependency(c, "runtime", "complex64_eq"); break; - case 128: add_package_dependency(c, "runtime", "complex128_eq"); break; - } - break; - case Token_NotEq: - switch (8*size) { - case 64: add_package_dependency(c, "runtime", "complex64_ne"); break; - case 128: add_package_dependency(c, "runtime", "complex128_ne"); break; - } - break; - } - } else if (is_type_quaternion(x->type) || is_type_quaternion(y->type)) { - switch (op) { - case Token_CmpEq: - switch (8*size) { - case 128: add_package_dependency(c, "runtime", "quaternion128_eq"); break; - case 256: add_package_dependency(c, "runtime", "quaternion256_eq"); break; - } - break; - case Token_NotEq: - switch (8*size) { - case 128: add_package_dependency(c, "runtime", "quaternion128_ne"); break; - case 256: add_package_dependency(c, "runtime", "quaternion256_ne"); break; - } - break; - } } } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 8569af957..23f109ba6 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -2090,11 +2090,12 @@ gb_internal void lb_create_startup_runtime_generate_body(lbModule *m, lbProcedur continue; } - lbModule *entity_module = m; - Entity *e = var.decl->entity; GB_ASSERT(e->kind == Entity_Variable); - e->code_gen_module = entity_module; + + lbModule *entity_module = m; + + e->code_gen_module.store(entity_module); Ast *init_expr = var.decl->init_expr; if (init_expr == nullptr && var.init.value == nullptr) { @@ -2135,7 +2136,7 @@ gb_internal void lb_create_startup_runtime_generate_body(lbModule *m, lbProcedur } -gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *objc_names, Array &global_variables) { // Startup Runtime +gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *objc_names, Array *global_variables) { // Startup Runtime Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_Odin); lbProcedure *p = lb_create_dummy_procedure(main_module, str_lit(LB_STARTUP_RUNTIME_PROC_NAME), proc_type); @@ -2147,14 +2148,28 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc LLVMSetVisibility(p->value, LLVMHiddenVisibility); LLVM_SET_INTERNAL_WEAK_LINKAGE(p->value); - p->global_variables = &global_variables; - p->objc_names = objc_names; - - lb_create_startup_runtime_generate_body(main_module, p); + p->objc_names = objc_names; + p->global_variables = global_variables; return p; } +gb_internal void lb_create_cleanup_runtime_generate_body(lbModule *m, lbProcedure *p) { + lb_begin_procedure_body(p); + + CheckerInfo *info = m->gen->info; + + for (Entity *e : info->fini_procedures) { + lbValue value = lb_find_procedure_value_from_entity(m, e); + lb_emit_call(p, value, {}, ProcInlining_none, ProcTailing_none); + } + + lb_end_procedure_body(p); + + lb_verify_function(m, p); +} + + gb_internal lbProcedure *lb_create_cleanup_runtime(lbModule *main_module) { // Cleanup Runtime Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_Odin); @@ -2166,19 +2181,6 @@ gb_internal lbProcedure *lb_create_cleanup_runtime(lbModule *main_module) { // C // Make sure shared libraries call their own runtime cleanup on Linux. LLVMSetVisibility(p->value, LLVMHiddenVisibility); LLVM_SET_INTERNAL_WEAK_LINKAGE(p->value); - - lb_begin_procedure_body(p); - - CheckerInfo *info = main_module->gen->info; - - for (Entity *e : info->fini_procedures) { - lbValue value = lb_find_procedure_value_from_entity(main_module, e); - lb_emit_call(p, value, {}, ProcInlining_none, ProcTailing_none); - } - - lb_end_procedure_body(p); - - lb_verify_function(main_module, p); return p; } @@ -2566,14 +2568,44 @@ gb_internal WORKER_TASK_PROC(lb_generate_procedures_worker_proc) { return 0; } +gb_internal WORKER_TASK_PROC(lb_generate_procedures_worker_proc_new_one) { + lbGenerator *gen = cast(lbGenerator *)data; + static std::atomic index; + + for (;;) { + u32 job_index = index.fetch_add(1, std::memory_order_relaxed); + if (job_index >= gen->modules.capacity) { + return 0; + } + + lbModule *m = gen->modules.entries[job_index].value; + if (m == nullptr) { + continue; + } + for (lbProcedure *p = nullptr; mpsc_dequeue(&m->procedures_to_generate, &p); /**/) { + lb_generate_procedure(p->module, p); + } + } + + // return 0; +} + + gb_internal void lb_generate_procedures(lbGenerator *gen, bool do_threading) { if (do_threading) { + lb_generate_procedures_worker_proc(&gen->default_module); + for (auto const &entry : gen->modules) { lbModule *m = entry.value; + if (m == &gen->default_module) { + continue; + } thread_pool_add_task(lb_generate_procedures_worker_proc, m); } thread_pool_wait(); + + lb_generate_procedures_worker_proc(&gen->default_module); } else { for (auto const &entry : gen->modules) { lbModule *m = entry.value; @@ -2582,51 +2614,10 @@ gb_internal void lb_generate_procedures(lbGenerator *gen, bool do_threading) { } } -gb_internal WORKER_TASK_PROC(lb_generate_missing_procedures_to_check_worker_proc) { - lbModule *m = cast(lbModule *)data; - for (lbProcedure *p = nullptr; mpsc_dequeue(&m->missing_procedures_to_check, &p); /**/) { - if (!p->is_done.load(std::memory_order_relaxed)) { - debugf("Generate missing procedure: %.*s module %p\n", LIT(p->name), m); - lb_generate_procedure(m, p); - } - - for (lbProcedure *nested = nullptr; mpsc_dequeue(&m->procedures_to_generate, &nested); /**/) { - mpsc_enqueue(&m->missing_procedures_to_check, nested); - } - } - return 0; -} - -gb_internal void lb_generate_missing_procedures(lbGenerator *gen, bool do_threading) { - isize retry_count = 0; -retry:; - if (do_threading) { - for (auto const &entry : gen->modules) { - lbModule *m = entry.value; - // NOTE(bill): procedures may be added during generation - thread_pool_add_task(lb_generate_missing_procedures_to_check_worker_proc, m); - } - thread_pool_wait(); - } else { - for (auto const &entry : gen->modules) { - lbModule *m = entry.value; - // NOTE(bill): procedures may be added during generation - lb_generate_missing_procedures_to_check_worker_proc(m); - } - } - +gb_internal void lb_generate_check_missing_procedures(lbGenerator *gen, bool do_threading) { for (auto const &entry : gen->modules) { lbModule *m = entry.value; - if (m->missing_procedures_to_check.count != 0) { - if (retry_count > gen->modules.count) { - GB_ASSERT(m->missing_procedures_to_check.count == 0); - } - - retry_count += 1; - goto retry; - } - GB_ASSERT(m->missing_procedures_to_check.count == 0); - GB_ASSERT(m->procedures_to_generate.count == 0); + GB_ASSERT_MSG(m->procedures_to_generate.count == 0, "%s, %td remaining", m->module_name, m->procedures_to_generate.count.load()); } } @@ -3277,7 +3268,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { } } - TIME_SECTION("LLVM Global Variables"); + TIME_SECTION("LLVM Global RTII Variables"); if (!build_context.no_rtti) { lbModule *m = gen->rtti_module; @@ -3360,7 +3351,6 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { } } - isize global_variable_max_count = 0; bool already_has_entry_point = false; @@ -3394,6 +3384,24 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { auto global_variables = array_make(permanent_allocator(), 0, global_variable_max_count); + + TIME_SECTION("LLVM Runtime Objective-C Names Creation"); + gen->objc_names = lb_create_objc_names(default_module); + + + TIME_SECTION("LLVM Runtime Startup Creation Procedure"); + gen->startup_runtime = lb_create_startup_runtime(default_module, gen->objc_names, &global_variables); + + TIME_SECTION("LLVM Runtime Cleanup Creation Procedure"); + gen->cleanup_runtime = lb_create_cleanup_runtime(default_module); + + + TIME_SECTION("LLVM Global Procedures and Types"); + lb_create_global_procedures_and_types(gen, info, do_threading); + + + TIME_SECTION("LLVM Global Variables"); + for (DeclInfo *d : info->variable_init_order) { Entity *e = d->entity; @@ -3569,14 +3577,10 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { } } - TIME_SECTION("LLVM Runtime Objective-C Names Creation"); - gen->objc_names = lb_create_objc_names(default_module); - - TIME_SECTION("LLVM Runtime Startup Creation (Global Variables & @(init))"); - gen->startup_runtime = lb_create_startup_runtime(default_module, gen->objc_names, global_variables); - - TIME_SECTION("LLVM Runtime Cleanup Creation & @(fini)"); - gen->cleanup_runtime = lb_create_cleanup_runtime(default_module); + TIME_SECTION("LLVM Runtime Startup Body (Global Variables & @(init))"); + lb_create_startup_runtime_generate_body(default_module, gen->startup_runtime); + TIME_SECTION("LLVM Runtime Cleanup Body"); + lb_create_cleanup_runtime_generate_body(default_module, gen->cleanup_runtime); TIME_SECTION("LLVM Runtime Type Information (RTTI)"); if (do_threading) { @@ -3597,9 +3601,6 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { do_threading = false; } - TIME_SECTION("LLVM Global Procedures and Types"); - lb_create_global_procedures_and_types(gen, info, do_threading); - TIME_SECTION("LLVM Procedure Generation"); lb_generate_procedures(gen, do_threading); @@ -3608,8 +3609,8 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { lb_create_main_procedure(default_module, gen->startup_runtime, gen->cleanup_runtime); } - TIME_SECTION("LLVM Procedure Generation (missing)"); - lb_generate_missing_procedures(gen, do_threading); + TIME_SECTION("LLVM Procedure Generation (check missing)"); + lb_generate_check_missing_procedures(gen, do_threading); if (gen->objc_names) { TIME_SECTION("Finalize objc names"); diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 38aed1c16..48b1c68d4 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -162,8 +162,6 @@ struct lbModule { StringMap procedures; PtrMap procedure_values; - MPSCQueue missing_procedures_to_check; - StringMap const_strings; String16Map const_string16s; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 39cdcd54f..85096c2ac 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -3206,65 +3206,53 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left } if (is_type_complex(a)) { - char const *runtime_procedure = ""; - i64 sz = 8*type_size_of(a); - switch (sz) { - case 32: - switch (op_kind) { - case Token_CmpEq: runtime_procedure = "complex32_eq"; break; - case Token_NotEq: runtime_procedure = "complex32_ne"; break; - } - break; - case 64: - switch (op_kind) { - case Token_CmpEq: runtime_procedure = "complex64_eq"; break; - case Token_NotEq: runtime_procedure = "complex64_ne"; break; - } - break; - case 128: - switch (op_kind) { - case Token_CmpEq: runtime_procedure = "complex128_eq"; break; - case Token_NotEq: runtime_procedure = "complex128_ne"; break; - } - break; - } - GB_ASSERT(runtime_procedure != nullptr); + // NOTE(bill): is this actually a fast comparison? + lbValue a0 = lb_emit_struct_ev(p, left, 0); + lbValue a1 = lb_emit_struct_ev(p, left, 1); - auto args = array_make(permanent_allocator(), 2); - args[0] = left; - args[1] = right; - return lb_emit_runtime_call(p, runtime_procedure, args); + lbValue b0 = lb_emit_struct_ev(p, right, 0); + lbValue b1 = lb_emit_struct_ev(p, right, 1); + + LLVMValueRef cmp0 = LLVMBuildFCmp(p->builder, LLVMRealOEQ, a0.value, b0.value, ""); + LLVMValueRef cmp1 = LLVMBuildFCmp(p->builder, LLVMRealOEQ, a1.value, b1.value, ""); + LLVMValueRef cmp = LLVMBuildAnd(p->builder, cmp0, cmp1, ""); + + if (op_kind == Token_NotEq) { + cmp = LLVMBuildNot(p->builder, cmp, ""); + } + + cmp = LLVMBuildZExtOrBitCast(p->builder, cmp, lb_type(p->module, t_bool), ""); + return {cmp, t_bool}; } if (is_type_quaternion(a)) { - char const *runtime_procedure = ""; - i64 sz = 8*type_size_of(a); - switch (sz) { - case 64: - switch (op_kind) { - case Token_CmpEq: runtime_procedure = "quaternion64_eq"; break; - case Token_NotEq: runtime_procedure = "quaternion64_ne"; break; - } - break; - case 128: - switch (op_kind) { - case Token_CmpEq: runtime_procedure = "quaternion128_eq"; break; - case Token_NotEq: runtime_procedure = "quaternion128_ne"; break; - } - break; - case 256: - switch (op_kind) { - case Token_CmpEq: runtime_procedure = "quaternion256_eq"; break; - case Token_NotEq: runtime_procedure = "quaternion256_ne"; break; - } - break; - } - GB_ASSERT(runtime_procedure != nullptr); + // NOTE(bill): is this actually a fast comparison? + lbValue a0 = lb_emit_struct_ev(p, left, 0); + lbValue a1 = lb_emit_struct_ev(p, left, 1); + lbValue a2 = lb_emit_struct_ev(p, left, 2); + lbValue a3 = lb_emit_struct_ev(p, left, 3); - auto args = array_make(permanent_allocator(), 2); - args[0] = left; - args[1] = right; - return lb_emit_runtime_call(p, runtime_procedure, args); + lbValue b0 = lb_emit_struct_ev(p, right, 0); + lbValue b1 = lb_emit_struct_ev(p, right, 1); + lbValue b2 = lb_emit_struct_ev(p, right, 2); + lbValue b3 = lb_emit_struct_ev(p, right, 3); + + LLVMValueRef cmp0 = LLVMBuildFCmp(p->builder, LLVMRealOEQ, a0.value, b0.value, ""); + LLVMValueRef cmp1 = LLVMBuildFCmp(p->builder, LLVMRealOEQ, a1.value, b1.value, ""); + LLVMValueRef cmp2 = LLVMBuildFCmp(p->builder, LLVMRealOEQ, a2.value, b2.value, ""); + LLVMValueRef cmp3 = LLVMBuildFCmp(p->builder, LLVMRealOEQ, a3.value, b3.value, ""); + + LLVMValueRef cmp4 = LLVMBuildAnd(p->builder, cmp0, cmp1, ""); + LLVMValueRef cmp5 = LLVMBuildAnd(p->builder, cmp2, cmp3, ""); + + LLVMValueRef cmp = LLVMBuildAnd(p->builder, cmp4, cmp5, ""); + + if (op_kind == Token_NotEq) { + cmp = LLVMBuildNot(p->builder, cmp, ""); + } + + cmp = LLVMBuildZExtOrBitCast(p->builder, cmp, lb_type(p->module, t_bool), ""); + return {cmp, t_bool}; } if (is_type_bit_set(a)) { diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 6ee758993..2c7e16a3f 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -109,7 +109,6 @@ gb_internal WORKER_TASK_PROC(lb_init_module_worker_proc) { array_init(&m->global_procedures_to_create, a, 0, 1024); array_init(&m->global_types_to_create, a, 0, 1024); - mpsc_init(&m->missing_procedures_to_check, a); map_init(&m->debug_values); string_map_init(&m->objc_classes); @@ -504,7 +503,7 @@ gb_internal lbModule *lb_module_of_expr(lbGenerator *gen, Ast *expr) { return &gen->default_module; } -gb_internal lbModule *lb_module_of_entity_internal(lbGenerator *gen, Entity *e, lbModule *curr_module) { +gb_internal lbModule *lb_module_of_entity_internal(lbGenerator *gen, Entity *e) { lbModule **found = nullptr; if (e->kind == Entity_Procedure && e->decl_info) { @@ -534,7 +533,7 @@ gb_internal lbModule *lb_module_of_entity_internal(lbGenerator *gen, Entity *e, gb_internal lbModule *lb_module_of_entity(lbGenerator *gen, Entity *e, lbModule *curr_module) { GB_ASSERT(e != nullptr); GB_ASSERT(curr_module != nullptr); - lbModule *m = lb_module_of_entity_internal(gen, e, curr_module); + lbModule *m = lb_module_of_entity_internal(gen, e); if (USE_SEPARATE_MODULES) { if (e->kind == Entity_Procedure && e->Procedure.generated_from_polymorphic) { @@ -1802,7 +1801,7 @@ gb_internal LLVMTypeRef lb_type_internal_for_procedures_raw(lbModule *m, Type *t "\n\tFuncTypeCtx: %p\n\tCurrentCtx: %p\n\tGlobalCtx: %p", LLVMGetTypeContext(new_abi_fn_type), m->ctx, LLVMGetGlobalContext()); - map_set(&m->func_raw_types, type, new_abi_fn_type); + // map_set(&m->func_raw_types, type, new_abi_fn_type); return new_abi_fn_type; } @@ -2484,8 +2483,10 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { case Type_Proc: { - LLVMTypeRef proc_raw_type = lb_type_internal_for_procedures_raw(m, type); - gb_unused(proc_raw_type); + if (m->internal_type_level == 0) { + LLVMTypeRef proc_raw_type = lb_type_internal_for_procedures_raw(m, type); + gb_unused(proc_raw_type); + } return LLVMPointerType(LLVMIntTypeInContext(m->ctx, 8), 0); } break; @@ -2574,7 +2575,7 @@ gb_internal lbFunctionType *lb_get_function_type(lbModule *m, Type *pt) { lbFunctionType **ft_found = nullptr; ft_found = map_get(&m->function_type_map, pt); if (!ft_found) { - LLVMTypeRef llvm_proc_type = lb_type(m, pt); + LLVMTypeRef llvm_proc_type = lb_type_internal_for_procedures_raw(m, pt); gb_unused(llvm_proc_type); ft_found = map_get(&m->function_type_map, pt); } @@ -3262,12 +3263,10 @@ gb_internal lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) auto *found = map_get(&other_module->values, e); rw_mutex_shared_unlock(&other_module->values_mutex); if (found == nullptr) { - // THIS IS THE RACE CONDITION - lbProcedure *missing_proc_in_other_module = lb_create_procedure(other_module, e, false); - mpsc_enqueue(&other_module->missing_procedures_to_check, missing_proc_in_other_module); + GB_PANIC("Missing procedure %.*s from module %s", LIT(e->token.string), other_module->module_name); } } else { - mpsc_enqueue(&m->missing_procedures_to_check, missing_proc); + GB_PANIC("Missing procedure %.*s from module %s %d", LIT(e->token.string), other_module->module_name, e->min_dep_count.load()); } rw_mutex_shared_lock(&m->values_mutex); @@ -3312,13 +3311,17 @@ gb_internal lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &pr token.string = name; Entity *e = alloc_entity_procedure(nullptr, token, type, pl->tags); e->file = expr->file(); + if (e->file) { + e->pkg = e->file->pkg; + } e->scope = e->file->scope; - lbModule *target_module = m; + // lbModule *target_module = m; + lbModule *target_module = lb_module_of_entity_internal(gen, e); GB_ASSERT(target_module != nullptr); // NOTE(bill): this is to prevent a race condition since these procedure literals can be created anywhere at any time - pl->decl->code_gen_module = target_module; + // pl->decl->code_gen_module.store(target_module); e->decl_info = pl->decl; e->parent_proc_decl = pl->decl->parent; e->Procedure.is_anonymous = true; @@ -3328,33 +3331,40 @@ gb_internal lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &pr if (target_module != m) { - rw_mutex_shared_lock(&target_module->values_mutex); - lbValue *found = map_get(&target_module->values, e); - rw_mutex_shared_unlock(&target_module->values_mutex); - if (found == nullptr) { - lbProcedure *missing_proc_in_target_module = lb_create_procedure(target_module, e, false); - mpsc_enqueue(&target_module->missing_procedures_to_check, missing_proc_in_target_module); + GB_ASSERT_MSG(m == &gen->default_module, "%s %s", m->module_name, target_module->module_name); + + lbProcedure *local = lb_create_procedure(target_module, e, false); + + mpsc_enqueue(&m->procedures_to_generate, local); + if (parent != nullptr) { + array_add(&parent->children, local); + } else { + string_map_set(&m->members, name, {local->value, local->type}); } - lbProcedure *p = lb_create_procedure(m, e, true); + lbProcedure *proto = lb_create_procedure(m, e, true); lbValue value = {}; - value.value = p->value; - value.type = p->type; + value.value = proto->value; + value.type = proto->type; + + return value; } else { - lbProcedure *p = lb_create_procedure(m, e); + lbProcedure *local = lb_create_procedure(m, e, false); + + mpsc_enqueue(&m->procedures_to_generate, local); + if (parent != nullptr) { + array_add(&parent->children, local); + } else { + string_map_set(&m->members, name, {local->value, local->type}); + } lbValue value = {}; - value.value = p->value; - value.type = p->type; - mpsc_enqueue(&m->procedures_to_generate, p); - if (parent != nullptr) { - array_add(&parent->children, p); - } else { - string_map_set(&m->members, name, value); - } + value.value = local->value; + value.type = local->type; + return value; } } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 36d736b0f..545445ddc 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -102,8 +102,10 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i lbProcedure *p = permanent_alloc_item(); p->module = m; - entity->code_gen_module = m; - entity->code_gen_procedure = p; + if (!ignore_body) { + entity->code_gen_module.store(m); + entity->code_gen_procedure.store(p); + } p->entity = entity; p->name = link_name; @@ -392,7 +394,7 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i gb_internal lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name, Type *type) { { lbValue *found = string_map_get(&m->members, link_name); - GB_ASSERT_MSG(found == nullptr, "failed to create dummy procedure for: %.*s", LIT(link_name)); + GB_ASSERT_MSG(found == nullptr, "failed to create dummy procedure for: %.*s, %s", LIT(link_name), LLVMPrintValueToString(found->value)); } lbProcedure *p = permanent_alloc_item(); diff --git a/src/name_canonicalization.cpp b/src/name_canonicalization.cpp index 1a4ca6439..ccfc936fc 100644 --- a/src/name_canonicalization.cpp +++ b/src/name_canonicalization.cpp @@ -815,9 +815,9 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { case Type_Enum: type_writer_appendc(w, "enum"); if (type->Enum.base_type != nullptr) { - type_writer_appendb(w, ' '); + type_writer_appendb(w, '('); write_type_to_canonical_string(w, type->Enum.base_type); - type_writer_appendb(w, ' '); + type_writer_appendb(w, ')'); } type_writer_appendb(w, '{'); for_array(i, type->Enum.fields) { @@ -932,8 +932,10 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { case Type_BitField: type_writer_appendc(w, "bit_field"); + type_writer_appendb(w, '('); write_type_to_canonical_string(w, type->BitField.backing_type); - type_writer_appendc(w, " {"); + type_writer_appendb(w, ')'); + type_writer_appendc(w, "{"); for (isize i = 0; i < type->BitField.fields.count; i++) { Entity *f = type->BitField.fields[i]; if (i > 0) { @@ -945,7 +947,7 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { type_writer_appendc(w, CANONICAL_BIT_FIELD_SEPARATOR); type_writer_append_fmt(w, "%u", type->BitField.bit_sizes[i]); } - type_writer_appendc(w, " }"); + type_writer_appendc(w, "}"); return; case Type_Proc: