diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index d9dd2be03..cbf49a2c7 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1934,7 +1934,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 Entity *new_field = alloc_entity_field(scope, token, array_type, false, cast(i32)i); soa_struct->Struct.fields[i] = new_field; - add_entity(c->checker, scope, nullptr, new_field); + add_entity(c, scope, nullptr, new_field); add_entity_use(c, nullptr, new_field); } @@ -1959,7 +1959,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 Type *array_type = alloc_type_array(old_field->type, count); Entity *new_field = alloc_entity_field(scope, old_field->token, array_type, false, old_field->Variable.field_src_index); soa_struct->Struct.fields[i] = new_field; - add_entity(c->checker, scope, nullptr, new_field); + add_entity(c, scope, nullptr, new_field); } else { soa_struct->Struct.fields[i] = old_field; } @@ -1971,7 +1971,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 Token token = {}; token.string = str_lit("Base_Type"); Entity *base_type_entity = alloc_entity_type_name(scope, token, elem, EntityState_Resolved); - add_entity(c->checker, scope, nullptr, base_type_entity); + add_entity(c, scope, nullptr, base_type_entity); add_type_info_type(c, soa_struct); diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 583c4f133..a2c40c9a2 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -313,7 +313,7 @@ void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, Type *def) if (is_blank_ident(name)) { continue; } - add_entity(ctx->checker, parent, nullptr, f); + add_entity(ctx, parent, nullptr, f); } } } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 4e1b69d20..4d2cd56d4 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2889,8 +2889,8 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) { GB_ASSERT(e != nullptr); - ExprInfo *found = check_get_expr_info(&c->checker->info, e); - if (found == nullptr) { + ExprInfo *old = check_get_expr_info(&c->checker->info, e); + if (old == nullptr) { if (type != nullptr && type != t_invalid) { if (e->tav.type == nullptr || e->tav.type == t_invalid) { add_type_and_value(&c->checker->info, e, e->tav.mode, type ? type : e->tav.type, e->tav.value); @@ -2898,11 +2898,10 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) { } return; } - ExprInfo old = *found; switch (e->kind) { case_ast_node(ue, UnaryExpr, e); - if (old.value.kind != ExactValue_Invalid) { + if (old->value.kind != ExactValue_Invalid) { // NOTE(bill): if 'e' is constant, the operands will be constant too. // They don't need to be updated as they will be updated later and // checked at the end of general checking stage. @@ -2912,7 +2911,7 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) { case_end; case_ast_node(be, BinaryExpr, e); - if (old.value.kind != ExactValue_Invalid) { + if (old->value.kind != ExactValue_Invalid) { // See above note in UnaryExpr case break; } @@ -2927,7 +2926,7 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) { case_end; case_ast_node(te, TernaryIfExpr, e); - if (old.value.kind != ExactValue_Invalid) { + if (old->value.kind != ExactValue_Invalid) { // See above note in UnaryExpr case break; } @@ -2937,7 +2936,7 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) { case_end; case_ast_node(te, TernaryWhenExpr, e); - if (old.value.kind != ExactValue_Invalid) { + if (old->value.kind != ExactValue_Invalid) { // See above note in UnaryExpr case break; } @@ -2952,15 +2951,14 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) { } if (!final && is_type_untyped(type)) { - old.type = base_type(type); - check_set_expr_info(&c->checker->info, e, old); + old->type = base_type(type); return; } // We need to remove it and then give it a new one check_remove_expr_info(&c->checker->info, e); - if (old.is_lhs && !is_type_integer(type)) { + if (old->is_lhs && !is_type_integer(type)) { gbString expr_str = expr_to_string(e); gbString type_str = type_to_string(type); error(e, "Shifted operand %s must be an integer, got %s", expr_str, type_str); @@ -2969,7 +2967,7 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) { return; } - add_type_and_value(&c->checker->info, e, old.mode, type, old.value); + add_type_and_value(&c->checker->info, e, old->mode, type, old->value); } void update_expr_value(CheckerContext *c, Ast *e, ExactValue value) { diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 5ae82bc5e..501fb7abf 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -558,7 +558,7 @@ void check_label(CheckerContext *ctx, Ast *label, Ast *parent) { } Entity *e = alloc_entity_label(ctx->scope, l->name->Ident.token, t_invalid, label, parent); - add_entity(ctx->checker, ctx->scope, l->name, e); + add_entity(ctx, ctx->scope, l->name, e); e->parent_proc_decl = ctx->curr_proc_decl; if (ok) { @@ -861,7 +861,7 @@ void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { } for (isize i = 0; i < entity_count; i++) { - add_entity(ctx->checker, ctx->scope, entities[i]->identifier, entities[i]); + add_entity(ctx, ctx->scope, entities[i]->identifier, entities[i]); } @@ -1344,7 +1344,7 @@ void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { if (!is_reference) { tag_var->flags |= EntityFlag_Value; } - add_entity(ctx->checker, ctx->scope, lhs, tag_var); + add_entity(ctx, ctx->scope, lhs, tag_var); add_entity_use(ctx, lhs, tag_var); add_implicit_entity(ctx, stmt, tag_var); } @@ -1966,7 +1966,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { Entity *e = entities[i]; DeclInfo *d = decl_info_of_entity(e); GB_ASSERT(d == nullptr); - add_entity(ctx->checker, ctx->scope, e->identifier, e); + add_entity(ctx, ctx->scope, e->identifier, e); d = make_decl_info(ctx->scope, ctx->decl); add_entity_and_decl_info(ctx, e->identifier, e, d); } @@ -2286,7 +2286,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { } } } - add_entity(ctx->checker, ctx->scope, e->identifier, e); + add_entity(ctx, ctx->scope, e->identifier, e); } if (vd->is_using != 0) { diff --git a/src/check_type.cpp b/src/check_type.cpp index 47726a15b..578538106 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -23,7 +23,7 @@ void populate_using_array_index(CheckerContext *ctx, Ast *node, AstField *field, tok.pos = ast_token(field->type).pos; } Entity *f = alloc_entity_array_elem(nullptr, tok, t->Array.elem, idx); - add_entity(ctx->checker, ctx->scope, nullptr, f); + add_entity(ctx, ctx->scope, nullptr, f); } } @@ -52,7 +52,7 @@ void populate_using_entity_scope(CheckerContext *ctx, Ast *node, AstField *field error(e->token, "'%.*s' is already declared", LIT(name)); } } else { - add_entity(ctx->checker, ctx->scope, nullptr, f); + add_entity(ctx, ctx->scope, nullptr, f); if (f->flags & EntityFlag_Using) { populate_using_entity_scope(ctx, node, field, f->type); } @@ -157,7 +157,7 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Array *fields Token name_token = name->Ident.token; Entity *field = alloc_entity_field(ctx->scope, name_token, type, is_using, field_src_index); - add_entity(ctx->checker, ctx->scope, name, field); + add_entity(ctx, ctx->scope, name, field); array_add(fields, field); array_add(tags, p->tag.string); @@ -483,7 +483,7 @@ Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *polymorphic_para } e->state = EntityState_Resolved; - add_entity(ctx->checker, scope, name, e); + add_entity(ctx, scope, name, e); array_add(&entities, e); } } @@ -795,7 +795,7 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast if (scope_lookup_current(ctx->scope, name) != nullptr) { error(ident, "'%.*s' is already declared in this enumeration", LIT(name)); } else { - add_entity(ctx->checker, ctx->scope, nullptr, e); + add_entity(ctx, ctx->scope, nullptr, e); array_add(&fields, e); // TODO(bill): Should I add a use for the enum value? add_entity_use(ctx, field, e); @@ -1622,7 +1622,7 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is } param->state = EntityState_Resolved; // NOTE(bill): This should have be resolved whilst determining it - add_entity(ctx->checker, scope, name, param); + add_entity(ctx, scope, name, param); if (is_using) { add_entity_use(ctx, name, param); } @@ -1749,7 +1749,7 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) { param->flags |= EntityFlag_Result; param->Variable.param_value = param_value; array_add(&variables, param); - add_entity(ctx->checker, scope, name, param); + add_entity(ctx, scope, name, param); // NOTE(bill): Removes `declared but not used` when using -vet add_entity_use(ctx, name, param); } @@ -2243,7 +2243,7 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el Entity *new_field = alloc_entity_field(scope, token, field_type, false, cast(i32)i); soa_struct->Struct.fields[i] = new_field; - add_entity(ctx->checker, scope, nullptr, new_field); + add_entity(ctx, scope, nullptr, new_field); add_entity_use(ctx, nullptr, new_field); } @@ -2277,7 +2277,7 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el } Entity *new_field = alloc_entity_field(scope, old_field->token, field_type, false, old_field->Variable.field_src_index); soa_struct->Struct.fields[i] = new_field; - add_entity(ctx->checker, scope, nullptr, new_field); + add_entity(ctx, scope, nullptr, new_field); add_entity_use(ctx, nullptr, new_field); } else { soa_struct->Struct.fields[i] = old_field; @@ -2290,13 +2290,13 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el if (soa_kind != StructSoa_Fixed) { Entity *len_field = alloc_entity_field(scope, empty_token, t_int, false, cast(i32)field_count+0); soa_struct->Struct.fields[field_count+0] = len_field; - add_entity(ctx->checker, scope, nullptr, len_field); + add_entity(ctx, scope, nullptr, len_field); add_entity_use(ctx, nullptr, len_field); if (soa_kind == StructSoa_Dynamic) { Entity *cap_field = alloc_entity_field(scope, empty_token, t_int, false, cast(i32)field_count+1); soa_struct->Struct.fields[field_count+1] = cap_field; - add_entity(ctx->checker, scope, nullptr, cap_field); + add_entity(ctx, scope, nullptr, cap_field); add_entity_use(ctx, nullptr, cap_field); Token token = {}; @@ -2304,7 +2304,7 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el init_mem_allocator(ctx->checker); Entity *allocator_field = alloc_entity_field(scope, token, t_allocator, false, cast(i32)field_count+2); soa_struct->Struct.fields[field_count+2] = allocator_field; - add_entity(ctx->checker, scope, nullptr, allocator_field); + add_entity(ctx, scope, nullptr, allocator_field); add_entity_use(ctx, nullptr, allocator_field); } } @@ -2312,7 +2312,7 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el Token token = {}; token.string = str_lit("Base_Type"); Entity *base_type_entity = alloc_entity_type_name(scope, token, elem, EntityState_Resolved); - add_entity(ctx->checker, scope, nullptr, base_type_entity); + add_entity(ctx, scope, nullptr, base_type_entity); add_type_info_type(ctx, soa_struct); @@ -2425,8 +2425,8 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t t->Generic.entity = e; e->TypeName.is_type_alias = true; e->state = EntityState_Resolved; - add_entity(ctx->checker, ps, ident, e); - add_entity(ctx->checker, s, ident, e); + add_entity(ctx, ps, ident, e); + add_entity(ctx, s, ident, e); } else { error(ident, "Invalid use of a polymorphic parameter '$%.*s'", LIT(token.string)); *type = t_invalid; diff --git a/src/checker.cpp b/src/checker.cpp index 34a8680ac..7ca56cccc 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -242,7 +242,7 @@ Scope *create_scope(Scope *parent, isize init_elements_capacity=DEFAULT_SCOPE_CA return s; } -Scope *create_scope_from_file(CheckerContext *c, AstFile *f) { +Scope *create_scope_from_file(AstFile *f) { GB_ASSERT(f != nullptr); GB_ASSERT(f->pkg != nullptr); GB_ASSERT(f->pkg->scope != nullptr); @@ -870,7 +870,7 @@ void destroy_checker_info(CheckerInfo *i) { } CheckerContext make_checker_context(Checker *c) { - CheckerContext ctx = c->init_ctx; + CheckerContext ctx = {}; ctx.checker = c; ctx.info = &c->info; ctx.scope = builtin_pkg->scope; @@ -883,6 +883,40 @@ CheckerContext make_checker_context(Checker *c) { return ctx; } +void add_curr_ast_file(CheckerContext *ctx, AstFile *file) { + if (file != nullptr) { + TokenPos zero_pos = {}; + global_error_collector.prev = zero_pos; + ctx->file = file; + ctx->decl = file->pkg->decl_info; + ctx->scope = file->scope; + ctx->pkg = file->pkg; + } +} +void reset_checker_context(CheckerContext *ctx, AstFile *file) { + if (ctx == nullptr) { + return; + } + auto checker = ctx->checker; + auto info = ctx->info; + auto type_path = ctx->type_path; + auto poly_path = ctx->poly_path; + array_clear(type_path); + array_clear(poly_path); + + gb_zero_item(ctx); + ctx->checker = checker; + ctx->info = info; + ctx->type_path = type_path; + ctx->poly_path = poly_path; + ctx->scope = builtin_pkg->scope; + ctx->pkg = builtin_pkg; + + add_curr_ast_file(ctx, file); +} + + + void destroy_checker_context(CheckerContext *ctx) { destroy_checker_type_path(ctx->type_path); destroy_checker_poly_path(ctx->poly_path); @@ -907,7 +941,7 @@ bool init_checker(Checker *c, Parser *parser) { isize total_token_count = c->parser->total_token_count; isize arena_size = 2 * item_size * total_token_count; - c->init_ctx = make_checker_context(c); + c->builtin_ctx = make_checker_context(c); return true; } @@ -917,7 +951,7 @@ void destroy_checker(Checker *c) { array_free(&c->procs_to_check); array_free(&c->procs_with_deferred_to_check); - destroy_checker_context(&c->init_ctx); + destroy_checker_context(&c->builtin_ctx); } @@ -994,10 +1028,11 @@ Scope *scope_of_node(Ast *node) { return node->scope; } ExprInfo *check_get_expr_info(CheckerInfo *i, Ast *expr) { - return map_get(&i->untyped, hash_node(expr)); -} -void check_set_expr_info(CheckerInfo *i, Ast *expr, ExprInfo info) { - map_set(&i->untyped, hash_node(expr), info); + ExprInfo **found = map_get(&i->untyped, hash_node(expr)); + if (found) { + return *found; + } + return nullptr; } void check_remove_expr_info(CheckerInfo *i, Ast *expr) { map_remove(&i->untyped, hash_node(expr)); @@ -1143,7 +1178,7 @@ bool redeclaration_error(String name, Entity *prev, Entity *found) { return false; } -bool add_entity_with_name(Checker *c, Scope *scope, Ast *identifier, Entity *entity, String name) { +bool add_entity_with_name(CheckerContext *c, Scope *scope, Ast *identifier, Entity *entity, String name) { if (scope == nullptr) { return false; } @@ -1155,14 +1190,13 @@ bool add_entity_with_name(Checker *c, Scope *scope, Ast *identifier, Entity *ent } if (identifier != nullptr) { if (entity->file == nullptr) { - GB_ASSERT(c->curr_ctx != nullptr); - entity->file = c->curr_ctx->file; + entity->file = c->file; } - add_entity_definition(&c->info, identifier, entity); + add_entity_definition(c->info, identifier, entity); } return true; } -bool add_entity(Checker *c, Scope *scope, Ast *identifier, Entity *entity) { +bool add_entity(CheckerContext *c, Scope *scope, Ast *identifier, Entity *entity) { return add_entity_with_name(c, scope, identifier, entity, entity->token.string); } @@ -1213,7 +1247,7 @@ void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, Entity *e, Dec scope = pkg->scope; } } - add_entity(c->checker, scope, identifier, e); + add_entity(c, scope, identifier, e); } add_entity_definition(&c->checker->info, identifier, e); @@ -1460,17 +1494,6 @@ void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *dec check_procedure_later(c, info); } -void add_curr_ast_file(CheckerContext *ctx, AstFile *file) { - if (file != nullptr) { - TokenPos zero_pos = {}; - global_error_collector.prev = zero_pos; - ctx->file = file; - ctx->decl = file->pkg->decl_info; - ctx->scope = file->scope; - ctx->pkg = file->pkg; - ctx->checker->curr_ctx = ctx; - } -} void add_min_dep_type_info(Checker *c, Type *t) { if (t == nullptr) { @@ -1488,7 +1511,7 @@ void add_min_dep_type_info(Checker *c, Type *t) { isize ti_index = type_info_index(&c->info, t, false); if (ti_index < 0) { - add_type_info_type(&c->init_ctx, t); // Missing the type information + add_type_info_type(&c->builtin_ctx, t); // Missing the type information ti_index = type_info_index(&c->info, t, false); } GB_ASSERT(ti_index >= 0); @@ -2282,8 +2305,7 @@ void init_core_map_type(Checker *c) { if (t_map_hash == nullptr) { Entity *e = find_core_entity(c, str_lit("Map_Hash")); if (e->state == EntityState_Unresolved) { - auto ctx = c->init_ctx; - check_entity_decl(&ctx, e, nullptr, nullptr); + check_entity_decl(&c->builtin_ctx, e, nullptr, nullptr); } t_map_hash = e->type; GB_ASSERT(t_map_hash != nullptr); @@ -2292,8 +2314,7 @@ void init_core_map_type(Checker *c) { if (t_map_header == nullptr) { Entity *e = find_core_entity(c, str_lit("Map_Header")); if (e->state == EntityState_Unresolved) { - auto ctx = c->init_ctx; - check_entity_decl(&ctx, e, nullptr, nullptr); + check_entity_decl(&c->builtin_ctx, e, nullptr, nullptr); } t_map_header = e->type; GB_ASSERT(t_map_header != nullptr); @@ -2887,7 +2908,7 @@ void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array *attr } if (name == "builtin") { - add_entity(ctx->checker, builtin_pkg->scope, nullptr, e); + add_entity(ctx, builtin_pkg->scope, nullptr, e); GB_ASSERT(scope_lookup(builtin_pkg->scope, e->token.string) != nullptr); if (value != nullptr) { error(value, "'builtin' cannot have a field value"); @@ -3236,8 +3257,8 @@ void check_collect_entities(CheckerContext *c, Slice const &nodes) { } CheckerContext *create_checker_context(Checker *c) { - CheckerContext *ctx = gb_alloc_item(heap_allocator(), CheckerContext); - *ctx = c->init_ctx; + CheckerContext *ctx = gb_alloc_item(permanent_allocator(), CheckerContext); + *ctx = make_checker_context(c); return ctx; } @@ -3611,7 +3632,7 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { id->fullpath, id->import_name.string, scope); - add_entity(ctx->checker, parent_scope, nullptr, e); + add_entity(ctx, parent_scope, nullptr, e); if (force_use || id->is_using) { add_entity_use(ctx, nullptr, e); } @@ -3638,7 +3659,7 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { // file scope otherwise the error would be the wrong way around redeclaration_error(name, found, e); } else { - add_entity_with_name(ctx->checker, parent_scope, e->identifier, e, name); + add_entity_with_name(ctx, parent_scope, e->identifier, e, name); } } } @@ -3700,7 +3721,7 @@ void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) { Entity *e = alloc_entity_library_name(parent_scope, fl->library_name, t_invalid, fl->fullpaths, library_name); - add_entity(ctx->checker, parent_scope, nullptr, e); + add_entity(ctx, parent_scope, nullptr, e); AttributeContext ac = {}; @@ -3958,6 +3979,8 @@ void check_import_entities(Checker *c) { } } + CheckerContext ctx = make_checker_context(c); + for (isize loop_count = 0; ; loop_count++) { bool new_files = false; for_array(i, package_order) { @@ -3970,8 +3993,7 @@ void check_import_entities(Checker *c) { for_array(i, pkg->files) { AstFile *f = pkg->files[i]; - CheckerContext ctx = c->init_ctx; - add_curr_ast_file(&ctx, f); + reset_checker_context(&ctx, f); new_files |= collect_checked_packages_from_decl_list(c, f->decls); } } @@ -3994,9 +4016,8 @@ void check_import_entities(Checker *c) { for_array(i, pkg->files) { AstFile *f = pkg->files[i]; - CheckerContext ctx = c->init_ctx; + reset_checker_context(&ctx, f); ctx.collect_delayed_decls = true; - add_curr_ast_file(&ctx, f); if (collect_file_decls(&ctx, f->decls)) { new_packages = true; @@ -4017,8 +4038,7 @@ void check_import_entities(Checker *c) { for_array(i, pkg->files) { AstFile *f = pkg->files[i]; - CheckerContext ctx = c->init_ctx; - add_curr_ast_file(&ctx, f); + reset_checker_context(&ctx, f); for_array(j, f->scope->delayed_imports) { Ast *decl = f->scope->delayed_imports[j]; @@ -4027,8 +4047,7 @@ void check_import_entities(Checker *c) { } for_array(i, pkg->files) { AstFile *f = pkg->files[i]; - CheckerContext ctx = c->init_ctx; - add_curr_ast_file(&ctx, f); + reset_checker_context(&ctx, f); for_array(j, f->scope->delayed_directives) { Ast *expr = f->scope->delayed_directives[j]; @@ -4214,7 +4233,7 @@ void check_proc_info(Checker *c, ProcInfo pi) { CheckerContext ctx = make_checker_context(c); defer (destroy_checker_context(&ctx)); - add_curr_ast_file(&ctx, pi.file); + reset_checker_context(&ctx, pi.file); ctx.decl = pi.decl; TypeProc *pt = &pi.type->Proc; @@ -4332,13 +4351,13 @@ void check_parsed_files(Checker *c) { #define TIME_SECTION(str) do { if (build_context.show_more_timings) timings_start_section(&global_timings, str_lit(str)); } while (0) TIME_SECTION("map full filepaths to scope"); - add_type_info_type(&c->init_ctx, t_invalid); + add_type_info_type(&c->builtin_ctx, t_invalid); // Map full filepaths to Scopes for_array(i, c->parser->packages) { AstPackage *p = c->parser->packages[i]; - Scope *scope = create_scope_from_package(&c->init_ctx, p); - p->decl_info = make_decl_info(scope, c->init_ctx.decl); + Scope *scope = create_scope_from_package(&c->builtin_ctx, p); + p->decl_info = make_decl_info(scope, c->builtin_ctx.decl); string_map_set(&c->info.packages, p->fullpath, p); if (scope->flags&ScopeFlag_Init) { @@ -4353,21 +4372,20 @@ void check_parsed_files(Checker *c) { TIME_SECTION("collect entities"); // Collect Entities + CheckerContext collect_entity_ctx = make_checker_context(c); + defer (destroy_checker_context(&collect_entity_ctx)); for_array(i, c->parser->packages) { AstPackage *pkg = c->parser->packages[i]; - CheckerContext ctx = make_checker_context(c); - defer (destroy_checker_context(&ctx)); - ctx.pkg = pkg; - ctx.collect_delayed_decls = false; + CheckerContext *ctx = &collect_entity_ctx; for_array(j, pkg->files) { AstFile *f = pkg->files[j]; - create_scope_from_file(&ctx, f); string_map_set(&c->info.files, f->fullpath, f); - add_curr_ast_file(&ctx, f); - check_collect_entities(&ctx, f->decls); + create_scope_from_file(f); + reset_checker_context(ctx, f); + check_collect_entities(ctx, f->decls); } pkg->used = true; @@ -4382,9 +4400,9 @@ void check_parsed_files(Checker *c) { TIME_SECTION("init preload"); init_preload(c); - CheckerContext prev_context = c->init_ctx; - defer (c->init_ctx = prev_context); - c->init_ctx.decl = make_decl_info(nullptr, nullptr); + CheckerContext prev_context = c->builtin_ctx; + defer (c->builtin_ctx = prev_context); + c->builtin_ctx.decl = make_decl_info(nullptr, nullptr); TIME_SECTION("check procedure bodies"); // NOTE(bill): Nested procedures bodies will be added to this "queue" @@ -4418,7 +4436,7 @@ void check_parsed_files(Checker *c) { auto *entry = &c->info.untyped.entries[i]; HashKey key = entry->key; Ast *expr = cast(Ast *)cast(uintptr)key.key; - ExprInfo *info = &entry->value; + ExprInfo *info = entry->value; if (info != nullptr && expr != nullptr) { if (is_type_typed(info->type)) { compiler_error("%s (type %s) is typed!", expr_to_string(expr), type_to_string(info->type)); @@ -4444,7 +4462,7 @@ void check_parsed_files(Checker *c) { Type *t = &basic_types[i]; if (t->Basic.size > 0 && (t->Basic.flags & BasicFlag_LLVM) == 0) { - add_type_info_type(&c->init_ctx, t); + add_type_info_type(&c->builtin_ctx, t); } } @@ -4456,7 +4474,7 @@ void check_parsed_files(Checker *c) { // i64 size = type_size_of(c->allocator, e->type); i64 align = type_align_of(e->type); if (align > 0 && ptr_set_exists(&c->info.minimum_dependency_set, e)) { - add_type_info_type(&c->init_ctx, e->type); + add_type_info_type(&c->builtin_ctx, e->type); } } else if (e->kind == Entity_Procedure) { diff --git a/src/checker.hpp b/src/checker.hpp index 0d5974f67..b60440bf0 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -20,12 +20,12 @@ struct ExprInfo { bool is_lhs; // Debug info }; -gb_inline ExprInfo make_expr_info(AddressingMode mode, Type *type, ExactValue value, bool is_lhs) { - ExprInfo ei = {}; - ei.mode = mode; - ei.type = type; - ei.value = value; - ei.is_lhs = is_lhs; +gb_inline ExprInfo *make_expr_info(AddressingMode mode, Type *type, ExactValue const &value, bool is_lhs) { + ExprInfo *ei = gb_alloc_item(permanent_allocator(), ExprInfo); + ei->mode = mode; + ei->type = type; + ei->value = value; + ei->is_lhs = is_lhs; return ei; } @@ -262,9 +262,6 @@ struct CheckerContext; struct CheckerInfo { Checker *checker; - Map untyped; // Key: Ast * | Expression -> ExprInfo - // NOTE(bill): This needs to be a map and not on the Ast - // as it needs to be iterated across StringMap files; // Key (full path) StringMap packages; // Key (full path) StringMap foreigns; @@ -272,12 +269,6 @@ struct CheckerInfo { Array entities; Array variable_init_order; - Map > gen_procs; // Key: Ast * | Identifier -> Entity - Map > gen_types; // Key: Type * - - Array type_info_types; - Map type_info_map; // Key: Type * - AstPackage * builtin_package; AstPackage * runtime_package; @@ -294,6 +285,20 @@ struct CheckerInfo { bool allow_identifier_uses; Array identifier_uses; // only used by 'odin query' + + // Below are accessed within procedures + // NOTE(bill): If the semantic checker (check_proc_body) is to ever to be multithreaded, + // these variables will be of contention + + Map untyped; // Key: Ast * | Expression -> ExprInfo * + // NOTE(bill): This needs to be a map and not on the Ast + // as it needs to be iterated across + + Map > gen_procs; // Key: Ast * | Identifier -> Entity + Map > gen_types; // Key: Type * + + Array type_info_types; + Map type_info_map; // Key: Type * }; struct CheckerContext { @@ -339,11 +344,10 @@ struct Checker { Parser * parser; CheckerInfo info; + CheckerContext builtin_ctx; + Array procs_to_check; Array procs_with_deferred_to_check; - - CheckerContext *curr_ctx; - CheckerContext init_ctx; }; @@ -382,7 +386,6 @@ Entity *scope_insert (Scope *s, Entity *entity); ExprInfo *check_get_expr_info (CheckerInfo *i, Ast *expr); -void check_set_expr_info (CheckerInfo *i, Ast *expr, ExprInfo info); void check_remove_expr_info (CheckerInfo *i, Ast *expr); void add_untyped (CheckerInfo *i, Ast *expression, bool lhs, AddressingMode mode, Type *basic_type, ExactValue value); void add_type_and_value (CheckerInfo *i, Ast *expression, AddressingMode mode, Type *type, ExactValue value);