Browse Source

Correct procedure checking flag handling, and correct the (bodge) handle of unchecked procedure bodies

gingerBill 4 years ago
parent
commit
382ca20916
6 changed files with 58 additions and 28 deletions
  1. 15 1
      src/check_decl.cpp
  2. 15 16
      src/check_expr.cpp
  3. 3 0
      src/check_stmt.cpp
  4. 23 10
      src/checker.cpp
  5. 1 0
      src/llvm_backend.cpp
  6. 1 1
      src/llvm_backend_proc.cpp

+ 15 - 1
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) {

+ 15 - 16
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<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) {
 		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;

+ 3 - 0
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) {

+ 23 - 10
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) {

+ 1 - 0
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 = {};

+ 1 - 1
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 = {};