mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-06 06:38:20 +00:00
Remove old bodge which checked for missing procedures by reordering things
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user