diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index f453fb0aa..41e037eeb 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -686,6 +686,14 @@ gb_internal bool check_builtin_objc_procedure(CheckerContext *c, Operand *operan } else { try_to_add_package_dependency(c, "runtime", "_NSConcreteStackBlock"); } + for (isize i = 0; i < capture_arg_count; i++) { + Type *t = param_operands[i].type; + if (is_type_pointer(t) && is_type_objc_object(t)) { + try_to_add_package_dependency(c, "runtime", "_Block_object_assign"); + try_to_add_package_dependency(c, "runtime", "_Block_object_dispose"); + break; + } + } *operand = poly_op; operand->type = alloc_type_pointer(operand->type); diff --git a/src/check_type.cpp b/src/check_type.cpp index 98e562501..959ce39a9 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -3358,6 +3358,7 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para Ast *expr = unparen_expr(op.expr); Entity *proc_entity = strip_entity_wrapping(expr); if (proc_entity) { + proc_entity->flags |= EntityFlag_PolyConstArg; poly_const = exact_value_procedure(proc_entity->identifier.load() ? proc_entity->identifier.load() : op.expr); valid = true; } else if (expr->kind == Ast_ProcLit) { diff --git a/src/checker.cpp b/src/checker.cpp index 0a4dec1fb..82e1dc154 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3377,6 +3377,18 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { str_lit("multi_pointer_slice_expr_error"), ); + FORCE_ADD_RUNTIME_ENTITIES(c->info.objc_class_implementations.count.load(std::memory_order_relaxed) > 0, + str_lit("objc_lookUpClass"), + str_lit("sel_registerName"), + str_lit("objc_allocateClassPair"), + str_lit("objc_registerClassPair"), + str_lit("class_addMethod"), + str_lit("class_addIvar"), + str_lit("class_getInstanceVariable"), + str_lit("ivar_getOffset"), + str_lit("object_getClass"), + ); + { // init min dep basic equal procs struct { BasicKind kind; char const *name; } const procs[] = { diff --git a/src/entity.cpp b/src/entity.cpp index 4a7800450..355bd1ca6 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -76,7 +76,8 @@ enum EntityFlag : u64 { EntityFlag_Init = 1ull<<31, EntityFlag_Subtype = 1ull<<32, EntityFlag_Fini = 1ull<<33, - + EntityFlag_PolyConstArg = 1ull<<34, // passed to a `$` parameter, so a local procedure may be called outside its parent + EntityFlag_CustomLinkName = 1ull<<40, EntityFlag_CustomLinkage_Internal = 1ull<<41, EntityFlag_CustomLinkage_Strong = 1ull<<42, diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 900a762f9..2d25e4703 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -2441,12 +2441,13 @@ gb_internal void lb_create_global_procedures_and_types(lbGenerator *gen, Checker Scope * scope = e->scope; if ((scope->flags & ScopeFlag_File) == 0) { - continue; + if (e->kind != Entity_Procedure || (e->flags & EntityFlag_PolyConstArg) == 0) { + continue; + } + } else { + GB_ASSERT(scope->parent->flags & ScopeFlag_Pkg); } - Scope *package_scope = scope->parent; - GB_ASSERT(package_scope->flags & ScopeFlag_Pkg); - switch (e->kind) { case Entity_Variable: // NOTE(bill): Handled above as it requires a specific load order @@ -3354,51 +3355,27 @@ gb_internal void lb_generate_procedures(lbGenerator *gen, bool do_threading) { lb_exit_if_worker_failed(); } -gb_internal WORKER_TASK_PROC(lb_generate_missing_procedures_to_check_worker_proc) { +gb_internal WORKER_TASK_PROC(lb_generate_queued_procedures_worker_proc) { lbModule *m = cast(lbModule *)data; - for (Entity *e = nullptr; mpsc_dequeue(&m->missing_procedures_to_check, &e); /**/) { - lbProcedure *p = lb_create_procedure(m, e, false); - if (!p->is_done.load(std::memory_order_relaxed)) { - debugf("Generate missing procedure: %.*s module %p\n", LIT(p->name), m); - } - mpsc_enqueue(&m->procedures_to_generate, p); - } for (lbProcedure *p = nullptr; mpsc_dequeue(&m->procedures_to_generate, &p); /**/) { lb_generate_procedure(m, p); } 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_queued_procedures(lbGenerator *gen, bool do_threading) { for (auto const &entry : gen->modules) { lbModule *m = entry.value; - if (m->missing_procedures_to_check.count != 0 || m->procedures_to_generate.count != 0) { - if (retry_count > gen->modules.count) { - GB_ASSERT(m->missing_procedures_to_check.count == 0 && m->procedures_to_generate.count == 0); - } - - retry_count += 1; - goto retry; + if (do_threading) { + thread_pool_add_task(lb_generate_queued_procedures_worker_proc, m); + } else { + lb_generate_queued_procedures_worker_proc(m); } - GB_ASSERT(m->missing_procedures_to_check.count == 0); - GB_ASSERT(m->procedures_to_generate.count == 0); + } + thread_pool_wait(); + + for (auto const &entry : gen->modules) { + GB_ASSERT(entry.value->procedures_to_generate.count == 0); } } @@ -4236,8 +4213,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 (queued)"); + lb_generate_queued_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 824fe2f88..7a3b12575 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -153,8 +153,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_general.cpp b/src/llvm_backend_general.cpp index a2b2a44b9..9893debbf 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -165,7 +165,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); array_init(&m->global_variables, a); - mpsc_init(&m->missing_procedures_to_check, a); map_init(&m->debug_values); string_map_init(&m->objc_classes); @@ -4086,25 +4085,16 @@ gb_internal lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) // NOTE(bill): Until the modules are generated in parallel, a procedure may be referenced before it is created // (e.g. an @(init) procedure by the startup procedure), but after that it was missed by the frontend - bool missing = gen->modules_in_parallel; - if (!ignore_body) { - if (missing) { - debugf("Missing Procedure (lb_find_procedure_value_from_entity): %.*s module %p\n", LIT(e->token.string), m); - } + GB_ASSERT_MSG(!gen->modules_in_parallel, "missing procedure '%.*s' (%s)", LIT(e->token.string), token_pos_to_string(e->token.pos)); mpsc_enqueue(&m->procedures_to_generate, proc); } else { rw_mutex_shared_lock(&other_module->values_mutex); auto *found = map_get(&other_module->values, e); rw_mutex_shared_unlock(&other_module->values_mutex); if (found == nullptr) { - if (missing) { - debugf("Missing Procedure (lb_find_procedure_value_from_entity): %.*s module %p\n", LIT(e->token.string), other_module); - // another module's context may only be used by the thread generating that module - mpsc_enqueue(&other_module->missing_procedures_to_check, e); - } else { - mpsc_enqueue(&other_module->procedures_to_generate, lb_create_procedure(other_module, e, false)); - } + GB_ASSERT_MSG(!gen->modules_in_parallel, "missing procedure '%.*s' (%s)", LIT(e->token.string), token_pos_to_string(e->token.pos)); + mpsc_enqueue(&other_module->procedures_to_generate, lb_create_procedure(other_module, e, false)); } } diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index d35b48835..eb51e6370 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -234,7 +234,8 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) lbValue *prev_value = string_map_get(&p->module->members, name); if (prev_value != nullptr) { // NOTE(bill): Don't do mutliple declarations in the IR - return; + lb_add_entity(p->module, e, *prev_value); + continue; } e->Procedure.link_name = name;