From 382ca20916aaecd6f6b18ea1bd1b849aca2a4f13 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 23 Aug 2021 19:24:53 +0100 Subject: [PATCH] Correct procedure checking flag handling, and correct the (bodge) handle of unchecked procedure bodies --- src/check_decl.cpp | 16 +++++++++++++++- src/check_expr.cpp | 31 +++++++++++++++---------------- src/check_stmt.cpp | 3 +++ src/checker.cpp | 33 +++++++++++++++++++++++---------- src/llvm_backend.cpp | 1 + src/llvm_backend_proc.cpp | 2 +- 6 files changed, 58 insertions(+), 28 deletions(-) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index ec200354e..d9229ee9b 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1249,7 +1249,7 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty if (!(e->flags & EntityFlag_Using)) { continue; } - bool is_value = (e->flags & EntityFlag_Value) != 0 && !is_type_pointer(e->type); + bool is_value = (e->flags & EntityFlag_Value) != 0 && !is_type_pointer(e->type); String name = e->token.string; Type *t = base_type(type_deref(e->type)); if (t->kind == Type_Struct) { @@ -1306,6 +1306,20 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty check_stmt_list(ctx, bs->stmts, Stmt_CheckScopeDecls); + for_array(i, bs->stmts) { + Ast *stmt = bs->stmts[i]; + if (stmt->kind == Ast_ValueDecl) { + ast_node(vd, ValueDecl, stmt); + for_array(j, vd->names) { + Ast *name = vd->names[j]; + if (!is_blank_ident(name)) { + GB_ASSERT(name->kind == Ast_Ident); + GB_ASSERT(name->Ident.entity != nullptr); + } + } + } + } + if (type->Proc.result_count > 0) { if (!check_is_terminating(body, str_lit(""))) { if (token.kind == Token_Ident) { diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 329bd0fc9..f632da5c1 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -212,7 +212,7 @@ isize check_is_assignable_to_using_subtype(Type *src, Type *dst, isize level = 0 return 0; } -bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_entity, Type *type, +bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, Entity *base_entity, Type *type, Array *param_operands, Ast *poly_def_node, PolyProcData *poly_proc_data) { /////////////////////////////////////////////////////////////////////////////// // // @@ -220,7 +220,7 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti // // /////////////////////////////////////////////////////////////////////////////// - CheckerInfo *info = c->info; + CheckerInfo *info = old_c->info; if (base_entity == nullptr) { return false; @@ -290,24 +290,21 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti }); - CheckerContext nctx = *c; + CheckerContext nctx = *old_c; - Scope *scope = create_scope(c->info, base_entity->scope); + nctx.procs_to_check_queue = old_c->procs_to_check_queue; + + Scope *scope = create_scope(info, base_entity->scope); scope->flags |= ScopeFlag_Proc; nctx.scope = scope; nctx.allow_polymorphic_types = true; if (nctx.polymorphic_scope == nullptr) { nctx.polymorphic_scope = scope; } - if (param_operands == nullptr) { - // c->no_polymorphic_errors = false; - } auto *pt = &src->Proc; - - // NOTE(bill): This is slightly memory leaking if the type already exists // Maybe it's better to check with the previous types first? Type *final_proc_type = alloc_type_proc(scope, nullptr, 0, nullptr, 0, false, pt->calling_convention); @@ -332,12 +329,7 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti } } -#if 0 - bool generate_type_again = nctx.no_polymorphic_errors; - if (generate_type_again) { -#else { -#endif // LEAK TODO(bill): This is technically a memory leak as it has to generate the type twice bool prev_no_polymorphic_errors = nctx.no_polymorphic_errors; defer (nctx.no_polymorphic_errors = prev_no_polymorphic_errors); @@ -395,6 +387,14 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti d->gen_proc_type = final_proc_type; d->type_expr = pl->type; d->proc_lit = proc_lit; + d->proc_checked = false; + + if (token.string == "raw_slice_data") { + Type *elem = final_proc_type->Proc.params->Tuple.variables[0]->type->Slice.elem; + if (elem->kind == Type_Basic && elem->Basic.kind == Basic_f64) { + gb_printf_err("%.*s %s\n", LIT(token.string), type_to_string(final_proc_type)); + } + } Entity *entity = alloc_entity_procedure(nullptr, token, final_proc_type, tags); entity->identifier = ident; @@ -404,6 +404,7 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti entity->scope = scope->parent; entity->file = base_entity->file; entity->pkg = base_entity->pkg; + entity->flags &= ~EntityFlag_ProcBodyChecked; AstFile *file = nullptr; { @@ -432,8 +433,6 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti map_set(&info->gen_procs, hash_pointer(base_entity->identifier), array); } - GB_ASSERT(entity != nullptr); - if (poly_proc_data) { poly_proc_data->gen_entity = entity; poly_proc_data->proc_info = proc_info; diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index fc6dd757e..7b039e001 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -2189,6 +2189,9 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { } entity->parent_proc_decl = ctx->curr_proc_decl; entities[entity_count++] = entity; + if (name->kind == Ast_Ident) { + name->Ident.entity = entity; + } } if (new_name_count == 0) { diff --git a/src/checker.cpp b/src/checker.cpp index 987d08e8d..7e9b2c672 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4591,6 +4591,7 @@ void check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped, Proc reset_checker_context(&ctx, pi->file, untyped); ctx.decl = pi->decl; ctx.procs_to_check_queue = procs_to_check_queue; + GB_ASSERT(procs_to_check_queue != nullptr); TypeProc *pt = &pi->type->Proc; String name = pi->token.string; @@ -4635,6 +4636,8 @@ void check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped, Proc GB_STATIC_ASSERT(sizeof(isize) == sizeof(void *)); +bool consume_proc_info_queue(Checker *c, ProcInfo *pi, ProcBodyQueue *q, UntypedExprInfoMap *untyped); + void check_unchecked_bodies(Checker *c) { // NOTE(2021-02-26, bill): Sanity checker // This is a partial hack to make sure all procedure bodies have been checked @@ -4656,24 +4659,33 @@ void check_unchecked_bodies(Checker *c) { if ((e->flags & EntityFlag_ProcBodyChecked) == 0) { GB_ASSERT(e->decl_info != nullptr); - ProcInfo pi = {}; - pi.file = e->file; - pi.token = e->token; - pi.decl = e->decl_info; - pi.type = e->type; + ProcInfo *pi = gb_alloc_item(permanent_allocator(), ProcInfo); + pi->file = e->file; + pi->token = e->token; + pi->decl = e->decl_info; + pi->type = e->type; Ast *pl = e->decl_info->proc_lit; GB_ASSERT(pl != nullptr); - pi.body = pl->ProcLit.body; - pi.tags = pl->ProcLit.tags; - if (pi.body == nullptr) { + pi->body = pl->ProcLit.body; + pi->tags = pl->ProcLit.tags; + if (pi->body == nullptr) { continue; } - map_clear(&untyped); - check_proc_info(c, &pi, &untyped, nullptr); + mpmc_enqueue(&c->procs_to_check_queue, pi); } } + + auto *q = &c->procs_to_check_queue; + ProcInfo *pi = nullptr; + while (mpmc_dequeue(q, &pi)) { + Entity *e = pi->decl->entity; + consume_proc_info_queue(c, pi, q, &untyped); + add_dependency_to_set(c, e); + GB_ASSERT(e->flags & EntityFlag_ProcBodyChecked); + } + } void check_test_procedures(Checker *c) { @@ -4839,6 +4851,7 @@ void check_procedure_bodies(Checker *c) { debugf("Total Procedure Bodies Checked: %td\n", total_bodies_checked.load(std::memory_order_relaxed)); + global_procedure_body_in_worker_queue = false; } void add_untyped_expressions(CheckerInfo *cinfo, UntypedExprInfoMap *untyped) { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 1f897fe4c..d00883bd9 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -458,6 +458,7 @@ lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, A e->file = expr->file; e->decl_info = pl->decl; e->code_gen_module = m; + e->flags |= EntityFlag_ProcBodyChecked; lbProcedure *p = lb_create_procedure(m, e); lbValue value = {}; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 366fba780..58f03f4e8 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -3,7 +3,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) GB_ASSERT(entity != nullptr); GB_ASSERT(entity->kind == Entity_Procedure); if (!entity->Procedure.is_foreign) { - GB_ASSERT(entity->flags |= EntityFlag_ProcBodyChecked); + GB_ASSERT(entity->flags & EntityFlag_ProcBodyChecked); } String link_name = {};