Remove old bodge which checked for missing procedures by reordering things

This commit is contained in:
gingerBill
2026-03-18 14:42:44 +00:00
parent 559f882b9b
commit 0fafa30bfe
8 changed files with 208 additions and 248 deletions

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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<lbGlobalVariable> &global_variables) { // Startup Runtime
gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *objc_names, Array<lbGlobalVariable> *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<u32> 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<lbGlobalVariable>(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");

View File

@@ -162,8 +162,6 @@ struct lbModule {
StringMap<lbProcedure *> procedures;
PtrMap<LLVMValueRef, Entity *> procedure_values;
MPSCQueue<lbProcedure *> missing_procedures_to_check;
StringMap<LLVMValueRef> const_strings;
String16Map<LLVMValueRef> const_string16s;

View File

@@ -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<lbValue>(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<lbValue>(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)) {

View File

@@ -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;
}
}

View File

@@ -102,8 +102,10 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i
lbProcedure *p = permanent_alloc_item<lbProcedure>();
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<lbProcedure>();

View File

@@ -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: