From 619783ca1ba783d1248297127fa8e5d0a097d7ba Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 May 2018 18:46:39 +0100 Subject: [PATCH] Remove clutter parameters and begin parallelizing the type checker --- src/check_decl.cpp | 37 ++++++--- src/check_expr.cpp | 20 ++--- src/check_stmt.cpp | 6 +- src/checker.cpp | 192 +++++++++++++++++++++++++++++++++------------ src/checker.hpp | 12 ++- src/ir.cpp | 26 +++--- src/ir_print.cpp | 2 +- 7 files changed, 204 insertions(+), 91 deletions(-) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 42b578605..2ffd0cfda 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -111,7 +111,7 @@ void check_init_variables(CheckerContext *ctx, Entity **lhs, isize lhs_count, Ar isize max = gb_min(lhs_count, rhs_count); for (isize i = 0; i < max; i++) { Entity *e = lhs[i]; - DeclInfo *d = decl_info_of_entity(&ctx->checker->info, e); + DeclInfo *d = decl_info_of_entity(e); Operand *o = &operands[i]; check_init_variable(ctx, e, o, context_name); if (d != nullptr) { @@ -220,7 +220,7 @@ AstNode *remove_type_alias_clutter(AstNode *node) { void check_type_decl(CheckerContext *ctx, Entity *e, AstNode *type_expr, Type *def) { GB_ASSERT(e->type == nullptr); - DeclInfo *decl = decl_info_of_entity(&ctx->checker->info, e); + DeclInfo *decl = decl_info_of_entity(e); if (decl != nullptr && decl->attributes.count > 0) { error(decl->attributes[0], "Attributes are not allowed on type declarations"); } @@ -373,7 +373,7 @@ void check_const_decl(CheckerContext *ctx, Entity *e, AstNode *type_expr, AstNod } - DeclInfo *decl = decl_info_of_entity(&ctx->checker->info, e); + DeclInfo *decl = decl_info_of_entity(e); if (decl != nullptr && decl->attributes.count > 0) { error(decl->attributes[0], "Attributes are not allowed on constant value declarations"); } @@ -544,10 +544,13 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { } pt->calling_convention = ProcCC_Contextless; if (e->pkg->kind == Package_Init) { - if (ctx->checker->info.entry_point != nullptr) { + gb_mutex_lock(&ctx->info->mutex); + defer (gb_mutex_unlock(&ctx->info->mutex)); + + if (ctx->info->entry_point != nullptr) { error(e->token, "Redeclaration of the entry pointer procedure 'main'"); } else { - ctx->checker->info.entry_point = e; + ctx->info->entry_point = e; } } } @@ -609,7 +612,10 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { init_entity_foreign_library(ctx, e); - auto *fp = &ctx->checker->info.foreigns; + gb_mutex_lock(&ctx->info->mutex); + defer (gb_mutex_unlock(&ctx->info->mutex)); + + auto *fp = &ctx->info->foreigns; HashKey key = hash_string(name); Entity **found = map_get(fp, key); if (found) { @@ -641,7 +647,10 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { name = e->Procedure.link_name; } if (e->Procedure.link_name.len > 0 || is_export) { - auto *fp = &ctx->checker->info.foreigns; + gb_mutex_lock(&ctx->info->mutex); + defer (gb_mutex_unlock(&ctx->info->mutex)); + + auto *fp = &ctx->info->foreigns; HashKey key = hash_string(name); Entity **found = map_get(fp, key); if (found) { @@ -674,7 +683,7 @@ void check_var_decl(CheckerContext *ctx, Entity *e, Entity **entities, isize ent AttributeContext ac = make_attribute_context(e->Variable.link_prefix); ac.init_expr_list_count = init_expr_list.count; - DeclInfo *decl = decl_info_of_entity(&ctx->checker->info, e); + DeclInfo *decl = decl_info_of_entity(e); if (decl != nullptr) { check_decl_attributes(ctx, decl->attributes, var_decl_attribute, &ac); } @@ -717,7 +726,10 @@ void check_var_decl(CheckerContext *ctx, Entity *e, Entity **entities, isize ent if (e->Variable.link_name.len > 0) { name = e->Variable.link_name; } - auto *fp = &ctx->checker->info.foreigns; + gb_mutex_lock(&ctx->info->mutex); + defer (gb_mutex_unlock(&ctx->info->mutex)); + + auto *fp = &ctx->info->foreigns; HashKey key = hash_string(name); Entity **found = map_get(fp, key); if (found) { @@ -892,7 +904,7 @@ void check_entity_decl(CheckerContext *ctx, Entity *e, DeclInfo *d, Type *named_ #endif if (d == nullptr) { - d = decl_info_of_entity(&ctx->checker->info, e); + d = decl_info_of_entity(e); if (d == nullptr) { // TODO(bill): Err here? e->type = t_invalid; @@ -978,7 +990,7 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty if (t->kind == Type_Struct) { Scope *scope = t->Struct.scope; if (scope == nullptr) { - scope = scope_of_node(&ctx->checker->info, t->Struct.node); + scope = scope_of_node(t->Struct.node); } GB_ASSERT(scope != nullptr); for_array(i, scope->elements.entries) { @@ -1017,6 +1029,9 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty check_scope_usage(ctx->checker, ctx->scope); if (decl->parent != nullptr) { + gb_mutex_lock(&ctx->checker->mutex); + defer (gb_mutex_unlock(&ctx->checker->mutex)); + // NOTE(bill): Add the dependencies from the procedure literal (lambda) for_array(i, decl->deps.entries) { Entity *e = decl->deps.entries[i].ptr; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 181de0654..9c34faa49 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -123,7 +123,7 @@ void check_scope_decls(CheckerContext *c, Array nodes, isize reserve_ default: continue; } - DeclInfo *d = decl_info_of_entity(&c->checker->info, e); + DeclInfo *d = decl_info_of_entity(e); if (d != nullptr) { check_entity_decl(c, e, d, nullptr); } @@ -211,7 +211,7 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti } - DeclInfo *old_decl = decl_info_of_entity(&c->checker->info, base_entity); + DeclInfo *old_decl = decl_info_of_entity(base_entity); if (old_decl == nullptr) { return false; } @@ -267,10 +267,10 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti } - gb_mutex_lock(&nctx.checker->mutex); - defer (gb_mutex_unlock(&nctx.checker->mutex)); + gb_mutex_lock(&nctx.info->mutex); + defer (gb_mutex_unlock(&nctx.info->mutex)); - auto *found_gen_procs = map_get(&nctx.checker->info.gen_procs, hash_pointer(base_entity->identifier)); + auto *found_gen_procs = map_get(&nctx.info->gen_procs, hash_pointer(base_entity->identifier)); if (found_gen_procs) { auto procs = *found_gen_procs; for_array(i, procs) { @@ -382,7 +382,7 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti bool check_polymorphic_procedure_assignment(CheckerContext *c, Operand *operand, Type *type, PolyProcData *poly_proc_data) { if (operand->expr == nullptr) return false; - Entity *base_entity = entity_of_ident(&c->checker->info, operand->expr); + Entity *base_entity = entity_of_ident(operand->expr); if (base_entity == nullptr) return false; return find_or_generate_polymorphic_procedure(c, base_entity, type, nullptr, poly_proc_data); } @@ -966,7 +966,7 @@ Entity *check_ident(CheckerContext *c, Operand *o, AstNode *n, Type *named_type, if (e->kind == Entity_ProcGroup) { auto *pge = &e->ProcGroup; - DeclInfo *d = decl_info_of_entity(&c->checker->info, e); + DeclInfo *d = decl_info_of_entity(e); check_entity_decl(c, e, d, nullptr); @@ -4089,7 +4089,7 @@ isize add_dependencies_from_unpacking(CheckerContext *c, Entity **lhs, isize lhs if (lhs != nullptr) { for (isize j = 0; (tuple_index + j) < lhs_count && j < tuple_count; j++) { Entity *e = lhs[tuple_index + j]; - DeclInfo *decl = decl_info_of_entity(&c->checker->info, e); + DeclInfo *decl = decl_info_of_entity(e); if (decl != nullptr) { c->decl = decl; // will be reset by the 'defer' any way for_array(k, decl->deps.entries) { @@ -4117,7 +4117,7 @@ void check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count, if (lhs != nullptr && tuple_index < lhs_count) { // NOTE(bill): override DeclInfo for dependency Entity *e = lhs[tuple_index]; - DeclInfo *decl = decl_info_of_entity(&c->checker->info, e); + DeclInfo *decl = decl_info_of_entity(e); if (decl) c->decl = decl; type_hint = e->type; } @@ -4722,7 +4722,7 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type ident = s; } - Entity *e = entity_of_ident(&c->checker->info, ident); + Entity *e = entity_of_ident(ident); CallArgumentData data = {}; CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data); Entity *entity_to_use = data.gen_entity != nullptr ? data.gen_entity : e; diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 8e6406cc4..5cf8804e9 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -501,7 +501,7 @@ bool check_using_stmt_entity(CheckerContext *ctx, AstNodeUsingStmt *us, AstNode Type *t = base_type(type_deref(e->type)); if (t->kind == Type_Struct) { // TODO(bill): Make it work for unions too - Scope *found = scope_of_node(&ctx->checker->info, t->Struct.node); + Scope *found = scope_of_node(t->Struct.node); for_array(i, found->elements.entries) { Entity *f = found->elements.entries[i].value; if (f->kind == Entity_Variable) { @@ -1685,7 +1685,7 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) { Type *t = base_type(type_deref(e->type)); if (t->kind == Type_Struct) { // TODO(bill): Make it work for unions too - Scope *found = scope_of_node(&ctx->checker->info, t->Struct.node); + Scope *found = scope_of_node(t->Struct.node); for_array(list_index, uis->list) { AstNode *node = uis->list[list_index]; ast_node(ident, Ident, node); @@ -1933,7 +1933,7 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) { if (is_blank_ident(name)) { error(token, "'using' cannot be applied variable declared as '_'"); } else if (is_type_struct(t) || is_type_raw_union(t)) { - Scope *scope = scope_of_node(&ctx->checker->info, t->Struct.node); + Scope *scope = scope_of_node(t->Struct.node); for_array(i, scope->elements.entries) { Entity *f = scope->elements.entries[i].value; if (f->kind == Entity_Variable) { diff --git a/src/checker.cpp b/src/checker.cpp index 7791420e4..8aadb348c 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -623,6 +623,7 @@ void init_checker_info(CheckerInfo *i) { map_init(&i->files, a); map_init(&i->packages, a); array_init(&i->variable_init_order, a); + gb_mutex_init(&i->mutex); } void destroy_checker_info(CheckerInfo *i) { @@ -638,11 +639,13 @@ void destroy_checker_info(CheckerInfo *i) { map_destroy(&i->files); map_destroy(&i->packages); array_free(&i->variable_init_order); + gb_mutex_destroy(&i->mutex); } CheckerContext make_checker_context(Checker *c) { CheckerContext ctx = c->init_ctx; ctx.checker = c; + ctx.info = &c->info; ctx.allocator = c->allocator; ctx.scope = universal_scope; @@ -698,7 +701,7 @@ void destroy_checker(Checker *c) { } -Entity *entity_of_ident(CheckerInfo *i, AstNode *identifier) { +Entity *entity_of_ident(AstNode *identifier) { if (identifier->kind == AstNode_Ident) { return identifier->Ident.entity; } @@ -706,6 +709,9 @@ Entity *entity_of_ident(CheckerInfo *i, AstNode *identifier) { } TypeAndValue type_and_value_of_expr(CheckerInfo *i, AstNode *expr) { + gb_mutex_lock(&i->mutex); + defer (gb_mutex_unlock(&i->mutex)); + TypeAndValue result = {}; TypeAndValue *found = map_get(&i->types, hash_node(expr)); if (found) result = *found; @@ -713,12 +719,15 @@ TypeAndValue type_and_value_of_expr(CheckerInfo *i, AstNode *expr) { } Type *type_of_expr(CheckerInfo *i, AstNode *expr) { + gb_mutex_lock(&i->mutex); + defer (gb_mutex_unlock(&i->mutex)); + TypeAndValue tav = type_and_value_of_expr(i, expr); if (tav.mode != Addressing_Invalid) { return tav.type; } if (expr->kind == AstNode_Ident) { - Entity *entity = entity_of_ident(i, expr); + Entity *entity = entity_of_ident(expr); if (entity) { return entity->type; } @@ -747,12 +756,12 @@ Entity *entity_of_node(CheckerInfo *i, AstNode *expr) { expr = unparen_expr(expr); switch (expr->kind) { case_ast_node(ident, Ident, expr); - return entity_of_ident(i, expr); + return entity_of_ident(expr); case_end; case_ast_node(se, SelectorExpr, expr); AstNode *s = unselector_expr(se->selector); if (s->kind == AstNode_Ident) { - return entity_of_ident(i, s); + return entity_of_ident(s); } case_end; case_ast_node(cc, CaseClause, expr); @@ -763,34 +772,42 @@ Entity *entity_of_node(CheckerInfo *i, AstNode *expr) { } -DeclInfo *decl_info_of_entity(CheckerInfo *i, Entity *e) { +DeclInfo *decl_info_of_entity(Entity *e) { if (e != nullptr) { return e->decl_info; } return nullptr; } -DeclInfo *decl_info_of_ident(CheckerInfo *i, AstNode *ident) { - return decl_info_of_entity(i, entity_of_ident(i, ident)); +DeclInfo *decl_info_of_ident(AstNode *ident) { + return decl_info_of_entity(entity_of_ident(ident)); } AstFile *ast_file_of_filename(CheckerInfo *i, String filename) { + gb_mutex_lock(&i->mutex); + defer (gb_mutex_unlock(&i->mutex)); AstFile **found = map_get(&i->files, hash_string(filename)); if (found != nullptr) { return *found; } return nullptr; } -Scope *scope_of_node(CheckerInfo *i, AstNode *node) { +Scope *scope_of_node(AstNode *node) { return node->scope; } ExprInfo *check_get_expr_info(CheckerInfo *i, AstNode *expr) { + gb_mutex_lock(&i->mutex); + defer (gb_mutex_unlock(&i->mutex)); return map_get(&i->untyped, hash_node(expr)); } void check_set_expr_info(CheckerInfo *i, AstNode *expr, ExprInfo info) { + gb_mutex_lock(&i->mutex); + defer (gb_mutex_unlock(&i->mutex)); map_set(&i->untyped, hash_node(expr), info); } void check_remove_expr_info(CheckerInfo *i, AstNode *expr) { + gb_mutex_lock(&i->mutex); + defer (gb_mutex_unlock(&i->mutex)); map_remove(&i->untyped, hash_node(expr)); } @@ -802,6 +819,9 @@ isize type_info_index(CheckerInfo *info, Type *type, bool error_on_failure) { type = t_bool; } + gb_mutex_lock(&info->mutex); + defer (gb_mutex_unlock(&info->mutex)); + isize entry_index = -1; HashKey key = hash_type(type); isize *found_entry_index = map_get(&info->type_info_map, key); @@ -840,6 +860,8 @@ void add_untyped(CheckerInfo *i, AstNode *expression, bool lhs, AddressingMode m if (mode == Addressing_Constant && type == t_invalid) { compiler_error("add_untyped - invalid type: %s", type_to_string(type)); } + gb_mutex_lock(&i->mutex); + defer (gb_mutex_unlock(&i->mutex)); map_set(&i->untyped, hash_node(expression), make_expr_info(mode, type, value, lhs)); } @@ -854,6 +876,9 @@ void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode compiler_error("add_type_and_value - invalid type: %s", type_to_string(type)); } + gb_mutex_lock(&i->mutex); + defer (gb_mutex_unlock(&i->mutex)); + TypeAndValue tv = {}; tv.type = type; tv.value = value; @@ -873,6 +898,9 @@ void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity) } GB_ASSERT(entity != nullptr); + gb_mutex_lock(&i->mutex); + defer (gb_mutex_unlock(&i->mutex)); + identifier->Ident.entity = entity; entity->identifier = identifier; array_add(&i->definitions, entity); @@ -1002,7 +1030,10 @@ void add_type_info_type(CheckerContext *c, Type *t) { return; } - auto found = map_get(&c->checker->info.type_info_map, hash_type(t)); + gb_mutex_lock(&c->info->mutex); + defer (gb_mutex_unlock(&c->info->mutex)); + + auto found = map_get(&c->info->type_info_map, hash_type(t)); if (found != nullptr) { // Types have already been added add_type_info_dependency(c->decl, t); @@ -1011,8 +1042,8 @@ void add_type_info_type(CheckerContext *c, Type *t) { bool prev = false; isize ti_index = -1; - for_array(i, c->checker->info.type_info_map.entries) { - auto *e = &c->checker->info.type_info_map.entries[i]; + for_array(i, c->info->type_info_map.entries) { + auto *e = &c->info->type_info_map.entries[i]; Type *prev_type = cast(Type *)e->key.ptr; if (are_types_identical(t, prev_type)) { // Duplicate entry @@ -1024,8 +1055,8 @@ void add_type_info_type(CheckerContext *c, Type *t) { if (ti_index < 0) { // Unique entry // NOTE(bill): map entries grow linearly and in order - ti_index = c->checker->info.type_info_types.count; - array_add(&c->checker->info.type_info_types, t); + ti_index = c->info->type_info_types.count; + array_add(&c->info->type_info_types, t); } map_set(&c->checker->info.type_info_map, hash_type(t), ti_index); @@ -1140,7 +1171,9 @@ void add_type_info_type(CheckerContext *c, Type *t) { void check_procedure_later(Checker *c, ProcedureInfo info) { GB_ASSERT(info.decl != nullptr); + gb_mutex_lock(&c->mutex); array_add(&c->procs_to_check, info); + gb_mutex_unlock(&c->mutex); } void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *decl, Type *type, AstNode *body, u64 tags) { @@ -1303,7 +1336,7 @@ void add_dependency_to_set(Checker *c, Entity *entity) { if (entity->type != nullptr && is_type_polymorphic(entity->type)) { - DeclInfo *decl = decl_info_of_entity(&c->info, entity); + DeclInfo *decl = decl_info_of_entity(entity); if (decl != nullptr && decl->gen_proc_type == nullptr) { return; } @@ -1315,7 +1348,7 @@ void add_dependency_to_set(Checker *c, Entity *entity) { ptr_set_add(set, entity); - DeclInfo *decl = decl_info_of_entity(info, entity); + DeclInfo *decl = decl_info_of_entity(entity); if (decl == nullptr) { return; } @@ -1437,7 +1470,7 @@ Array generate_entity_dependency_graph(CheckerInfo *info) { Entity * e = cast(Entity *)M.entries[i].key.ptr; EntityGraphNode *n = M.entries[i].value; - DeclInfo *decl = decl_info_of_entity(info, e); + DeclInfo *decl = decl_info_of_entity(e); if (decl != nullptr) { for_array(j, decl->deps.entries) { auto entry = decl->deps.entries[j]; @@ -2874,7 +2907,7 @@ void calculate_global_init_order(Checker *c) { if (e == nullptr || e->kind != Entity_Variable) { continue; } - DeclInfo *d = decl_info_of_entity(info, e); + DeclInfo *d = decl_info_of_entity(e); if (ptr_set_exists(&emitted, d)) { continue; @@ -2908,8 +2941,99 @@ void calculate_global_init_order(Checker *c) { } +void check_proc_info(Checker *c, ProcedureInfo pi) { + if (pi.type == nullptr) { + return; + } + + CheckerContext ctx = make_checker_context(c); + defer (destroy_checker_context(&ctx)); + add_curr_ast_file(&ctx, pi.file); + + TypeProc *pt = &pi.type->Proc; + String name = pi.token.string; + if (pt->is_polymorphic) { + GB_ASSERT_MSG(pt->is_poly_specialized, "%.*s", LIT(name)); + } + + + bool bounds_check = (pi.tags & ProcTag_bounds_check) != 0; + bool no_bounds_check = (pi.tags & ProcTag_no_bounds_check) != 0; + + if (bounds_check) { + ctx.stmt_state_flags |= StmtStateFlag_bounds_check; + ctx.stmt_state_flags &= ~StmtStateFlag_no_bounds_check; + } else if (no_bounds_check) { + ctx.stmt_state_flags |= StmtStateFlag_no_bounds_check; + ctx.stmt_state_flags &= ~StmtStateFlag_bounds_check; + } + + check_proc_body(&ctx, pi.token, pi.decl, pi.type, pi.body); +} + +GB_THREAD_PROC(check_proc_info_worker_proc) { + if (thread == nullptr) return 0; + auto *c = cast(Checker *)thread->user_data; + isize index = thread->user_index; + check_proc_info(c, c->procs_to_check[index]); + return 0; +} + +void check_proc_bodies(Checker *c) { + // IMPORTANT TODO(bill): Figure out why this doesn't work on *nix sometimes +#if 0 && defined(GB_SYSTEM_WINDOWS) + isize thread_count = gb_max(build_context.thread_count, 1); + gb_printf_err("Threads: %td\n", thread_count); + // isize thread_count = 1; + if (thread_count > 1) { + isize volatile curr_proc_index = 0; + + auto worker_threads = array_make(heap_allocator(), thread_count); + defer (array_free(&worker_threads)); + + for_array(i, worker_threads) { + gbThread *t = &worker_threads[i]; + gb_thread_init(t); + } + defer (for_array(i, worker_threads) { + gb_thread_destroy(&worker_threads[i]); + }); + + + for (;;) { + bool are_any_alive = false; + for_array(i, worker_threads) { + gbThread *t = &worker_threads[i]; + if (gb_thread_is_running(t)) { + are_any_alive = true; + } else if (curr_proc_index < c->procs_to_check.count) { + t->user_index = curr_proc_index; + curr_proc_index++; + gb_thread_start(t, check_proc_info_worker_proc, c); + are_any_alive = true; + } + } + if (!are_any_alive && curr_proc_index >= c->procs_to_check.count) { + break; + } + } + + } else { + for_array(i, c->procs_to_check) { + ProcedureInfo pi = c->procs_to_check[i]; + check_proc_info(c, pi); + } + } +#else + for_array(i, c->procs_to_check) { + ProcedureInfo pi = c->procs_to_check[i]; + check_proc_info(c, pi); + } +#endif +} + void check_parsed_files(Checker *c) { -#if 0 +#if 1 Timings timings = {}; timings_init(&timings, str_lit("check_parsed_files"), 16); defer ({ @@ -2977,37 +3101,7 @@ void check_parsed_files(Checker *c) { TIME_SECTION("check procedure bodies"); // NOTE(bill): Nested procedures bodies will be added to this "queue" - for_array(i, c->procs_to_check) { - ProcedureInfo *pi = &c->procs_to_check[i]; - if (pi->type == nullptr) { - continue; - } - - CheckerContext ctx = make_checker_context(c); - defer (destroy_checker_context(&ctx)); - add_curr_ast_file(&ctx, pi->file); - - TypeProc *pt = &pi->type->Proc; - String name = pi->token.string; - if (pt->is_polymorphic) { - GB_ASSERT_MSG(pt->is_poly_specialized, "%.*s", LIT(name)); - } - - - bool bounds_check = (pi->tags & ProcTag_bounds_check) != 0; - bool no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0; - - if (bounds_check) { - ctx.stmt_state_flags |= StmtStateFlag_bounds_check; - ctx.stmt_state_flags &= ~StmtStateFlag_no_bounds_check; - } else if (no_bounds_check) { - ctx.stmt_state_flags |= StmtStateFlag_no_bounds_check; - ctx.stmt_state_flags &= ~StmtStateFlag_bounds_check; - } - - check_proc_body(&ctx, pi->token, pi->decl, pi->type, pi->body); - } - + check_proc_bodies(c); for_array(i, c->info.files.entries) { AstFile *f = c->info.files.entries[i].value; diff --git a/src/checker.hpp b/src/checker.hpp index b7fc2fc78..f58867479 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -6,6 +6,7 @@ struct Scope; struct DeclInfo; struct AstFile; struct Checker; +struct CheckerInfo; enum AddressingMode { Addressing_Invalid, // invalid addressing mode @@ -279,6 +280,7 @@ typedef Array CheckerTypePath; struct CheckerContext { Checker * checker; + CheckerInfo * info; AstPackage * pkg; AstFile * file; Scope * scope; @@ -327,6 +329,8 @@ struct CheckerInfo { Entity * entry_point; PtrSet minimum_dependency_set; PtrSet minimum_dependency_type_info_set; + + gbMutex mutex; }; struct Checker { @@ -359,11 +363,11 @@ HashKey hash_decl_info(DeclInfo *decl) { return hash_pointer(decl); } // CheckerInfo API TypeAndValue type_and_value_of_expr (CheckerInfo *i, AstNode *expr); Type * type_of_expr (CheckerInfo *i, AstNode *expr); -Entity * entity_of_ident (CheckerInfo *i, AstNode *identifier); +Entity * entity_of_ident (AstNode *identifier); Entity * implicit_entity_of_node(CheckerInfo *i, AstNode *clause); -Scope * scope_of_node (CheckerInfo *i, AstNode *node); -DeclInfo * decl_info_of_ident (CheckerInfo *i, AstNode *ident); -DeclInfo * decl_info_of_entity (CheckerInfo *i, Entity * e); +Scope * scope_of_node (AstNode *node); +DeclInfo * decl_info_of_ident (AstNode *ident); +DeclInfo * decl_info_of_entity (Entity * e); AstFile * ast_file_of_filename (CheckerInfo *i, String filename); // IMPORTANT: Only to use once checking is done isize type_info_index (CheckerInfo *i, Type * type, bool error_on_failure = true); diff --git a/src/ir.cpp b/src/ir.cpp index e773be111..154e7b2ad 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1199,7 +1199,7 @@ irValue *ir_generate_array(irModule *m, Type *elem_type, i64 count, String prefi irBlock *ir_new_block(irProcedure *proc, AstNode *node, char *label) { Scope *scope = nullptr; if (node != nullptr) { - scope = scope_of_node(proc->module->info, node); + scope = scope_of_node(node); GB_ASSERT_MSG(scope != nullptr, "Block scope not found for %.*s", LIT(ast_node_strings[node->kind])); } @@ -1374,7 +1374,7 @@ irValue *ir_add_local(irProcedure *proc, Entity *e, AstNode *expr, bool zero_ini } irValue *ir_add_local_for_identifier(irProcedure *proc, AstNode *ident, bool zero_initialized) { - Entity *e = entity_of_ident(proc->module->info, ident); + Entity *e = entity_of_ident(ident); if (e != nullptr) { String name = e->token.string; ir_emit_comment(proc, name); @@ -3885,7 +3885,7 @@ void ir_mangle_add_sub_type_name(irModule *m, Entity *field, String parent) { irBranchBlocks ir_lookup_branch_blocks(irProcedure *proc, AstNode *ident) { GB_ASSERT(ident->kind == AstNode_Ident); - Entity *e = entity_of_ident(proc->module->info, ident); + Entity *e = entity_of_ident(ident); GB_ASSERT(e->kind == Entity_Label); for_array(i, proc->branch_blocks) { irBranchBlocks *b = &proc->branch_blocks[i]; @@ -4194,7 +4194,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv if (ce->args.count > 0) { AstNode *ident = unselector_expr(ce->args[0]); GB_ASSERT(ident->kind == AstNode_Ident); - Entity *e = entity_of_ident(proc->module->info, ident); + Entity *e = entity_of_ident(ident); GB_ASSERT(e != nullptr); if (e->parent_proc_decl != nullptr && e->parent_proc_decl->entity_count > 0) { @@ -4906,7 +4906,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) { case_end; case_ast_node(i, Ident, expr); - Entity *e = entity_of_ident(proc->module->info, expr); + Entity *e = entity_of_ident(expr); GB_ASSERT_MSG(e != nullptr, "%s", expr_to_string(expr)); if (e->kind == Entity_Builtin) { Token token = ast_node_token(expr); @@ -5158,7 +5158,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) { AstNode *p = unparen_expr(ce->proc); if (proc_mode == Addressing_Builtin) { - Entity *e = entity_of_ident(proc->module->info, p); + Entity *e = entity_of_ident(p); BuiltinProcId id = BuiltinProc_Invalid; if (e != nullptr) { id = cast(BuiltinProcId)e->Builtin.id; @@ -5481,7 +5481,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { return val; } String name = i->token.string; - Entity *e = entity_of_ident(proc->module->info, expr); + Entity *e = entity_of_ident(expr); // GB_ASSERT(name == e->token.string); return ir_build_addr_from_entity(proc, e, expr); case_end; @@ -5499,7 +5499,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { if (tav.mode == Addressing_Invalid) { // NOTE(bill): Imports - Entity *imp = entity_of_ident(proc->module->info, se->expr); + Entity *imp = entity_of_ident(se->expr); if (imp != nullptr) { GB_ASSERT(imp->kind == Entity_ImportName); } @@ -6189,7 +6189,7 @@ void ir_build_constant_value_decl(irProcedure *proc, AstNodeValueDecl *vd) { for_array(i, vd->names) { AstNode *ident = vd->names[i]; GB_ASSERT(ident->kind == AstNode_Ident); - Entity *e = entity_of_ident(proc->module->info, ident); + Entity *e = entity_of_ident(ident); GB_ASSERT(e != nullptr); switch (e->kind) { case Entity_TypeName: @@ -6228,7 +6228,7 @@ void ir_build_constant_value_decl(irProcedure *proc, AstNodeValueDecl *vd) { ir_gen_global_type_name(m, e, name); } else if (e->kind == Entity_Procedure) { CheckerInfo *info = proc->module->info; - DeclInfo *decl = decl_info_of_entity(info, e); + DeclInfo *decl = decl_info_of_entity(e); ast_node(pl, ProcLit, decl->proc_lit); if (pl->body != nullptr) { auto *found = map_get(&info->gen_procs, hash_pointer(ident)); @@ -6239,7 +6239,7 @@ void ir_build_constant_value_decl(irProcedure *proc, AstNodeValueDecl *vd) { if (!ir_min_dep_entity(proc->module, e)) { continue; } - DeclInfo *d = decl_info_of_entity(info, e); + DeclInfo *d = decl_info_of_entity(e); ir_build_poly_proc(proc, &d->proc_lit->ProcLit, e); } } else { @@ -7406,7 +7406,7 @@ void ir_begin_procedure_body(irProcedure *proc) { array_init(&proc->branch_blocks, heap_allocator()); array_init(&proc->context_stack, heap_allocator()); - DeclInfo *decl = decl_info_of_entity(proc->module->info, proc->entity); + DeclInfo *decl = decl_info_of_entity(proc->entity); if (decl != nullptr) { for_array(i, decl->labels) { BlockLabel bl = decl->labels[i]; @@ -8358,7 +8358,7 @@ void ir_gen_tree(irGen *s) { if (!ir_min_dep_entity(m, e)) { continue; } - DeclInfo *decl = decl_info_of_entity(info, e); + DeclInfo *decl = decl_info_of_entity(e); if (decl == nullptr) { continue; } diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 4375cd7e1..fdbc8a950 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -772,7 +772,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type * found = map_get(&m->anonymous_proc_lits, hash_pointer(expr)); } else { GB_ASSERT(expr->kind == AstNode_Ident); - Entity *e = entity_of_ident(m->info, expr); + Entity *e = entity_of_ident(expr); GB_ASSERT(e != nullptr); found = map_get(&m->values, hash_entity(e)); }