mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 07:08:48 +00:00
Correct procedure checking flag handling, and correct the (bodge) handle of unchecked procedure bodies
This commit is contained in:
+15
-1
@@ -1249,7 +1249,7 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty
|
|||||||
if (!(e->flags & EntityFlag_Using)) {
|
if (!(e->flags & EntityFlag_Using)) {
|
||||||
continue;
|
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;
|
String name = e->token.string;
|
||||||
Type *t = base_type(type_deref(e->type));
|
Type *t = base_type(type_deref(e->type));
|
||||||
if (t->kind == Type_Struct) {
|
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);
|
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 (type->Proc.result_count > 0) {
|
||||||
if (!check_is_terminating(body, str_lit(""))) {
|
if (!check_is_terminating(body, str_lit(""))) {
|
||||||
if (token.kind == Token_Ident) {
|
if (token.kind == Token_Ident) {
|
||||||
|
|||||||
+15
-16
@@ -212,7 +212,7 @@ isize check_is_assignable_to_using_subtype(Type *src, Type *dst, isize level = 0
|
|||||||
return 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<Operand> *param_operands, Ast *poly_def_node, PolyProcData *poly_proc_data) {
|
Array<Operand> *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) {
|
if (base_entity == nullptr) {
|
||||||
return false;
|
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;
|
scope->flags |= ScopeFlag_Proc;
|
||||||
nctx.scope = scope;
|
nctx.scope = scope;
|
||||||
nctx.allow_polymorphic_types = true;
|
nctx.allow_polymorphic_types = true;
|
||||||
if (nctx.polymorphic_scope == nullptr) {
|
if (nctx.polymorphic_scope == nullptr) {
|
||||||
nctx.polymorphic_scope = scope;
|
nctx.polymorphic_scope = scope;
|
||||||
}
|
}
|
||||||
if (param_operands == nullptr) {
|
|
||||||
// c->no_polymorphic_errors = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
auto *pt = &src->Proc;
|
auto *pt = &src->Proc;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// NOTE(bill): This is slightly memory leaking if the type already exists
|
// NOTE(bill): This is slightly memory leaking if the type already exists
|
||||||
// Maybe it's better to check with the previous types first?
|
// 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);
|
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
|
// 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;
|
bool prev_no_polymorphic_errors = nctx.no_polymorphic_errors;
|
||||||
defer (nctx.no_polymorphic_errors = prev_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->gen_proc_type = final_proc_type;
|
||||||
d->type_expr = pl->type;
|
d->type_expr = pl->type;
|
||||||
d->proc_lit = proc_lit;
|
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 *entity = alloc_entity_procedure(nullptr, token, final_proc_type, tags);
|
||||||
entity->identifier = ident;
|
entity->identifier = ident;
|
||||||
@@ -404,6 +404,7 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti
|
|||||||
entity->scope = scope->parent;
|
entity->scope = scope->parent;
|
||||||
entity->file = base_entity->file;
|
entity->file = base_entity->file;
|
||||||
entity->pkg = base_entity->pkg;
|
entity->pkg = base_entity->pkg;
|
||||||
|
entity->flags &= ~EntityFlag_ProcBodyChecked;
|
||||||
|
|
||||||
AstFile *file = nullptr;
|
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);
|
map_set(&info->gen_procs, hash_pointer(base_entity->identifier), array);
|
||||||
}
|
}
|
||||||
|
|
||||||
GB_ASSERT(entity != nullptr);
|
|
||||||
|
|
||||||
if (poly_proc_data) {
|
if (poly_proc_data) {
|
||||||
poly_proc_data->gen_entity = entity;
|
poly_proc_data->gen_entity = entity;
|
||||||
poly_proc_data->proc_info = proc_info;
|
poly_proc_data->proc_info = proc_info;
|
||||||
|
|||||||
@@ -2189,6 +2189,9 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
|
|||||||
}
|
}
|
||||||
entity->parent_proc_decl = ctx->curr_proc_decl;
|
entity->parent_proc_decl = ctx->curr_proc_decl;
|
||||||
entities[entity_count++] = entity;
|
entities[entity_count++] = entity;
|
||||||
|
if (name->kind == Ast_Ident) {
|
||||||
|
name->Ident.entity = entity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_name_count == 0) {
|
if (new_name_count == 0) {
|
||||||
|
|||||||
+23
-10
@@ -4591,6 +4591,7 @@ void check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped, Proc
|
|||||||
reset_checker_context(&ctx, pi->file, untyped);
|
reset_checker_context(&ctx, pi->file, untyped);
|
||||||
ctx.decl = pi->decl;
|
ctx.decl = pi->decl;
|
||||||
ctx.procs_to_check_queue = procs_to_check_queue;
|
ctx.procs_to_check_queue = procs_to_check_queue;
|
||||||
|
GB_ASSERT(procs_to_check_queue != nullptr);
|
||||||
|
|
||||||
TypeProc *pt = &pi->type->Proc;
|
TypeProc *pt = &pi->type->Proc;
|
||||||
String name = pi->token.string;
|
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 *));
|
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) {
|
void check_unchecked_bodies(Checker *c) {
|
||||||
// NOTE(2021-02-26, bill): Sanity checker
|
// NOTE(2021-02-26, bill): Sanity checker
|
||||||
// This is a partial hack to make sure all procedure bodies have been checked
|
// 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) {
|
if ((e->flags & EntityFlag_ProcBodyChecked) == 0) {
|
||||||
GB_ASSERT(e->decl_info != nullptr);
|
GB_ASSERT(e->decl_info != nullptr);
|
||||||
|
|
||||||
ProcInfo pi = {};
|
ProcInfo *pi = gb_alloc_item(permanent_allocator(), ProcInfo);
|
||||||
pi.file = e->file;
|
pi->file = e->file;
|
||||||
pi.token = e->token;
|
pi->token = e->token;
|
||||||
pi.decl = e->decl_info;
|
pi->decl = e->decl_info;
|
||||||
pi.type = e->type;
|
pi->type = e->type;
|
||||||
|
|
||||||
Ast *pl = e->decl_info->proc_lit;
|
Ast *pl = e->decl_info->proc_lit;
|
||||||
GB_ASSERT(pl != nullptr);
|
GB_ASSERT(pl != nullptr);
|
||||||
pi.body = pl->ProcLit.body;
|
pi->body = pl->ProcLit.body;
|
||||||
pi.tags = pl->ProcLit.tags;
|
pi->tags = pl->ProcLit.tags;
|
||||||
if (pi.body == nullptr) {
|
if (pi->body == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
map_clear(&untyped);
|
mpmc_enqueue(&c->procs_to_check_queue, pi);
|
||||||
check_proc_info(c, &pi, &untyped, nullptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
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));
|
debugf("Total Procedure Bodies Checked: %td\n", total_bodies_checked.load(std::memory_order_relaxed));
|
||||||
|
|
||||||
|
|
||||||
global_procedure_body_in_worker_queue = false;
|
global_procedure_body_in_worker_queue = false;
|
||||||
}
|
}
|
||||||
void add_untyped_expressions(CheckerInfo *cinfo, UntypedExprInfoMap *untyped) {
|
void add_untyped_expressions(CheckerInfo *cinfo, UntypedExprInfoMap *untyped) {
|
||||||
|
|||||||
@@ -458,6 +458,7 @@ lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, A
|
|||||||
e->file = expr->file;
|
e->file = expr->file;
|
||||||
e->decl_info = pl->decl;
|
e->decl_info = pl->decl;
|
||||||
e->code_gen_module = m;
|
e->code_gen_module = m;
|
||||||
|
e->flags |= EntityFlag_ProcBodyChecked;
|
||||||
lbProcedure *p = lb_create_procedure(m, e);
|
lbProcedure *p = lb_create_procedure(m, e);
|
||||||
|
|
||||||
lbValue value = {};
|
lbValue value = {};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body)
|
|||||||
GB_ASSERT(entity != nullptr);
|
GB_ASSERT(entity != nullptr);
|
||||||
GB_ASSERT(entity->kind == Entity_Procedure);
|
GB_ASSERT(entity->kind == Entity_Procedure);
|
||||||
if (!entity->Procedure.is_foreign) {
|
if (!entity->Procedure.is_foreign) {
|
||||||
GB_ASSERT(entity->flags |= EntityFlag_ProcBodyChecked);
|
GB_ASSERT(entity->flags & EntityFlag_ProcBodyChecked);
|
||||||
}
|
}
|
||||||
|
|
||||||
String link_name = {};
|
String link_name = {};
|
||||||
|
|||||||
Reference in New Issue
Block a user