From 054e24103329022b1d918505cc5a61f8540c0e13 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 12 Dec 2017 20:23:36 +0000 Subject: [PATCH] Localize checker data --- examples/demo.odin | 10 +-- src/check_stmt.cpp | 2 +- src/checker.cpp | 163 +++++++++++++++++++-------------------------- src/entity.cpp | 1 + src/ir.cpp | 12 ++-- src/main.cpp | 1 + src/parser.cpp | 18 +++-- 7 files changed, 95 insertions(+), 112 deletions(-) diff --git a/examples/demo.odin b/examples/demo.odin index e218bd7c2..ad9d6861a 100644 --- a/examples/demo.odin +++ b/examples/demo.odin @@ -40,12 +40,12 @@ general_stuff :: proc() { i := i32(137); ptr := &i; - fp1 := (^f32)(ptr); + _ = (^f32)(ptr); // ^f32(ptr) == ^(f32(ptr)) - fp2 := cast(^f32)ptr; + _ = cast(^f32)ptr; - f1 := (^f32)(ptr)^; - f2 := (cast(^f32)ptr)^; + _ = (^f32)(ptr)^; + _ = (cast(^f32)ptr)^; // Questions: Should there be two ways to do it? } @@ -540,7 +540,7 @@ threading_example :: proc() { threads := make([dynamic]^thread.Thread, 0, len(prefix_table)); defer free(threads); - for i in 0..len(prefix_table) { + for in 0..len(prefix_table) { if t := thread.create(worker_proc); t != nil { t.init_context = context; t.use_init_context = true; diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 140e5a5ea..31caca15a 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -845,7 +845,7 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { } - Map seen = {}; // Multimap + Map seen = {}; // Multimap, Key: Type * map_init(&seen, heap_allocator()); for_array(i, bs->stmts) { diff --git a/src/checker.cpp b/src/checker.cpp index b352ab780..bb4a5f159 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1,4 +1,3 @@ -#include "exact_value.cpp" #include "entity.cpp" enum ExprKind { @@ -226,7 +225,7 @@ struct Scope { Scope * first_child; Scope * last_child; Map elements; // Key: String - Map implicit; // Key: Entity * + PtrSet implicit; Array shared; Array delayed_file_decls; @@ -247,9 +246,9 @@ void scope_reset(Scope *scope) { scope->first_child = nullptr; scope->last_child = nullptr; - map_clear (&scope->elements); - map_clear (&scope->implicit); - array_clear(&scope->shared); + map_clear (&scope->elements); + array_clear (&scope->shared); + ptr_set_clear(&scope->implicit); ptr_set_clear(&scope->imported); ptr_set_clear(&scope->exported); } @@ -440,18 +439,15 @@ struct CheckerContext { // CheckerInfo stores all the symbol information for a type-checked program struct CheckerInfo { Map types; // Key: AstNode * | Expression -> Type (and value) - Map definitions; // Key: AstNode * | Identifier -> Entity - Map uses; // Key: AstNode * | Identifier -> Entity - Map scopes; // Key: AstNode * | Node -> Scope Map untyped; // Key: AstNode * | Expression -> ExprInfo - Map implicits; // Key: AstNode * - Map > gen_procs; // Key: AstNode * | Identifier -> Entity - Map > gen_types; // Key: Type * - Map entities; // Key: Entity * - Map foreigns; // Key: String Map files; // Key: String (full path) + Map foreigns; // Key: String + Array definitions; + Array entities; Array variable_init_order; + Map > gen_procs; // Key: AstNode * | Identifier -> Entity + Map > gen_types; // Key: Type * Map type_info_map; // Key: Type * isize type_info_count; @@ -469,11 +465,10 @@ struct Checker { AstFile * curr_ast_file; Scope * global_scope; // NOTE(bill): Procedures to check - Map procs; // Key: DeclInfo * + Array procs; Map file_scopes; // Key: String (fullpath) Array file_order; - Pool pool; gbAllocator allocator; gbArena arena; gbArena tmp_arena; @@ -523,7 +518,6 @@ void add_type_and_value (CheckerInfo *i, AstNode *expression, Addressi void add_entity_use (Checker *c, AstNode *identifier, Entity *entity); void add_implicit_entity (Checker *c, AstNode *node, Entity *e); void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclInfo *d); -void add_implicit_entity (Checker *c, AstNode *node, Entity *e); void check_add_import_decl(Checker *c, AstNodeImportDecl *id); void check_add_export_decl(Checker *c, AstNodeExportDecl *ed); @@ -573,8 +567,8 @@ Scope *create_scope(Scope *parent, gbAllocator allocator) { Scope *s = gb_alloc_item(allocator, Scope); s->parent = parent; map_init(&s->elements, heap_allocator()); - map_init(&s->implicit, heap_allocator()); array_init(&s->shared, heap_allocator()); + ptr_set_init(&s->implicit, heap_allocator()); ptr_set_init(&s->imported, heap_allocator()); ptr_set_init(&s->exported, heap_allocator()); @@ -629,9 +623,9 @@ void destroy_scope(Scope *scope) { } map_destroy(&scope->elements); - map_destroy(&scope->implicit); array_free(&scope->shared); array_free(&scope->delayed_file_decls); + ptr_set_destroy(&scope->implicit); ptr_set_destroy(&scope->imported); ptr_set_destroy(&scope->exported); @@ -643,7 +637,7 @@ void add_scope(Checker *c, AstNode *node, Scope *scope) { GB_ASSERT(node != nullptr); GB_ASSERT(scope != nullptr); scope->node = node; - map_set(&c->info.scopes, hash_node(node), scope); + node->scope = scope; } @@ -931,13 +925,10 @@ void init_universal_scope(void) { void init_checker_info(CheckerInfo *i) { gbAllocator a = heap_allocator(); map_init(&i->types, a); - map_init(&i->definitions, a); - map_init(&i->uses, a); - map_init(&i->scopes, a); - map_init(&i->entities, a); + array_init(&i->definitions, a); + array_init(&i->entities, a); map_init(&i->untyped, a); map_init(&i->foreigns, a); - map_init(&i->implicits, a); map_init(&i->gen_procs, a); map_init(&i->gen_types, a); map_init(&i->type_info_map, a); @@ -949,13 +940,10 @@ void init_checker_info(CheckerInfo *i) { void destroy_checker_info(CheckerInfo *i) { map_destroy(&i->types); - map_destroy(&i->definitions); - map_destroy(&i->uses); - map_destroy(&i->scopes); - map_destroy(&i->entities); + array_free(&i->definitions); + array_free(&i->entities); map_destroy(&i->untyped); map_destroy(&i->foreigns); - map_destroy(&i->implicits); map_destroy(&i->gen_procs); map_destroy(&i->gen_types); map_destroy(&i->type_info_map); @@ -977,7 +965,7 @@ void init_checker(Checker *c, Parser *parser) { gb_mutex_init(&c->mutex); array_init(&c->proc_stack, a); - map_init(&c->procs, a); + array_init(&c->procs, a); // NOTE(bill): Is this big enough or too small? isize item_size = gb_max3(gb_size_of(Entity), gb_size_of(Type), gb_size_of(Scope)); @@ -990,7 +978,6 @@ void init_checker(Checker *c, Parser *parser) { gb_arena_init_from_allocator(&c->tmp_arena, a, arena_size); gb_arena_init_from_allocator(&c->arena, a, arena_size); - pool_init(&c->pool, gb_megabytes(4), gb_kilobytes(384)); // c->allocator = pool_allocator(&c->pool); c->allocator = heap_allocator(); // c->allocator = gb_arena_allocator(&c->arena); @@ -1011,9 +998,8 @@ void destroy_checker(Checker *c) { destroy_scope(c->global_scope); array_free(&c->proc_stack); - map_destroy(&c->procs); + array_free(&c->procs); - pool_destroy(&c->pool); gb_arena_free(&c->tmp_arena); map_destroy(&c->file_scopes); @@ -1024,14 +1010,7 @@ void destroy_checker(Checker *c) { Entity *entity_of_ident(CheckerInfo *i, AstNode *identifier) { if (identifier->kind == AstNode_Ident) { - Entity **found = map_get(&i->definitions, hash_node(identifier)); - if (found) { - return *found; - } - found = map_get(&i->uses, hash_node(identifier)); - if (found) { - return *found; - } + return identifier->Ident.entity; } return nullptr; } @@ -1059,24 +1038,24 @@ Type *type_of_expr(CheckerInfo *i, AstNode *expr) { } Entity *implicit_entity_of_node(CheckerInfo *i, AstNode *clause) { - Entity **found = map_get(&i->implicits, hash_node(clause)); - if (found != nullptr) { - return *found; + // Entity **found = map_get(&i->implicits, hash_node(clause)); + // if (found != nullptr) { + // return *found; + // } + if (clause->kind == AstNode_CaseClause) { + return clause->CaseClause.implicit_entity; } return nullptr; } bool is_entity_implicitly_imported(Entity *import_name, Entity *e) { GB_ASSERT(import_name->kind == Entity_ImportName); - return map_get(&import_name->ImportName.scope->implicit, hash_entity(e)) != nullptr; + return ptr_set_exists(&import_name->ImportName.scope->implicit, e); } DeclInfo *decl_info_of_entity(CheckerInfo *i, Entity *e) { if (e != nullptr) { - DeclInfo **found = map_get(&i->entities, hash_entity(e)); - if (found != nullptr) { - return *found; - } + return e->decl_info; } return nullptr; } @@ -1093,11 +1072,7 @@ AstFile *ast_file_of_filename(CheckerInfo *i, String filename) { return nullptr; } Scope *scope_of_node(CheckerInfo *i, AstNode *node) { - Scope **found = map_get(&i->scopes, hash_node(node)); - if (found) { - return *found; - } - return nullptr; + return node->scope; } ExprInfo *check_get_expr_info(CheckerInfo *i, AstNode *expr) { return map_get(&i->untyped, hash_node(expr)); @@ -1156,10 +1131,6 @@ void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode if (mode == Addressing_Constant) { if (is_type_constant_type(type)) { - // if (value.kind == ExactValue_Invalid) { - // TODO(bill): Is this correct? - // return; - // } if (!(type != t_invalid || is_type_constant_type(type))) { compiler_error("add_type_and_value - invalid type: %s", type_to_string(type)); } @@ -1179,8 +1150,13 @@ void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity) if (is_blank_ident(identifier)) { return; } - HashKey key = hash_node(identifier); - map_set(&i->definitions, key, entity); + if (identifier->Ident.entity != nullptr) { + return; + } + + identifier->Ident.entity = entity; + entity->identifier = identifier; + array_add(&i->definitions, entity); } else { // NOTE(bill): Error should be handled elsewhere } @@ -1238,8 +1214,7 @@ void add_entity_use(Checker *c, AstNode *identifier, Entity *entity) { if (entity->identifier == nullptr) { entity->identifier = identifier; } - HashKey key = hash_node(identifier); - map_set(&c->info.uses, key, entity); + identifier->Ident.entity = entity; add_declaration_dependency(c, entity); // TODO(bill): Should this be here? } @@ -1250,15 +1225,20 @@ void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclIn GB_ASSERT(identifier->Ident.token.string == e->token.string); if (e->scope != nullptr) add_entity(c, e->scope, identifier, e); add_entity_definition(&c->info, identifier, e); - map_set(&c->info.entities, hash_entity(e), d); - e->order_in_src = c->info.entities.entries.count; + GB_ASSERT(e->decl_info == nullptr); + e->decl_info = d; + array_add(&c->info.entities, e); + e->order_in_src = c->info.entities.count; + // map_set(&c->info.entities, hash_entity(e), d); + // e->order_in_src = c->info.entities.entries.count; } -void add_implicit_entity(Checker *c, AstNode *node, Entity *e) { - GB_ASSERT(node != nullptr); +void add_implicit_entity(Checker *c, AstNode *clause, Entity *e) { + GB_ASSERT(clause != nullptr); GB_ASSERT(e != nullptr); - map_set(&c->info.implicits, hash_node(node), e); + GB_ASSERT(clause->kind == AstNode_CaseClause); + clause->CaseClause.implicit_entity = e; } @@ -1407,10 +1387,9 @@ void add_type_info_type(Checker *c, Type *t) { } } -void check_procedure_later(Checker *c, ProcedureInfo info) { - if (info.decl != nullptr) { - map_set(&c->procs, hash_decl_info(info.decl), info); - } +void check_procedure_later(Checker *c, ProcedureInfo const &info) { + GB_ASSERT(info.decl != nullptr); + array_add(&c->procs, info); } void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *decl, Type *type, AstNode *body, u64 tags) { @@ -1487,8 +1466,8 @@ PtrSet generate_minimum_dependency_set(CheckerInfo *info, Entity *star PtrSet map = {}; // Key: Entity * ptr_set_init(&map, heap_allocator()); - for_array(i, info->definitions.entries) { - Entity *e = info->definitions.entries[i].value; + for_array(i, info->definitions) { + Entity *e = info->definitions[i]; // if (e->scope->is_global && !is_type_poly_proc(e->type)) { // TODO(bill): is the check enough? if (e->scope->is_global) { // TODO(bill): is the check enough? if (e->type == nullptr || !is_type_poly_proc(e->type)) { @@ -1531,10 +1510,9 @@ Array generate_entity_dependency_graph(CheckerInfo *info) { Map M = {}; // Key: Entity * map_init(&M, a); defer (map_destroy(&M)); - for_array(i, info->entities.entries) { - auto *entry = &info->entities.entries[i]; - Entity * e = cast(Entity *)entry->key.ptr; - DeclInfo *d = entry->value; + for_array(i, info->entities) { + Entity *e = info->entities[i]; + DeclInfo *d = e->decl_info; if (is_entity_a_dependency(e)) { EntityGraphNode *n = gb_alloc_item(a, EntityGraphNode); n->entity = e; @@ -2320,10 +2298,9 @@ void check_all_global_entities(Checker *c) { Scope *prev_file = nullptr; bool processing_preload = true; - for_array(i, c->info.entities.entries) { - auto *entry = &c->info.entities.entries[i]; - Entity *e = cast(Entity *)entry->key.ptr; - DeclInfo *d = entry->value; + for_array(i, c->info.entities) { + Entity *e = c->info.entities[i]; + DeclInfo *d = e->decl_info; if (d->scope != e->scope) { continue; @@ -2696,12 +2673,12 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) { // gb_printf_err("%.*s %.*s get_proc_address\n", LIT(scope->file->fullpath), LIT(parent_scope->file->fullpath)); } - bool implicit_is_found = map_get(&scope->implicit, hash_entity(e)) != nullptr; + bool implicit_is_found = ptr_set_exists(&scope->implicit, e); if (is_entity_exported(e) && !implicit_is_found) { Entity *prev = scope_lookup_entity(parent_scope, e->token.string); // if (prev) gb_printf_err("%.*s\n", LIT(prev->token.string)); bool ok = add_entity(c, parent_scope, e->identifier, e); - if (ok) map_set(&parent_scope->implicit, hash_entity(e), true); + if (ok) ptr_set_add(&parent_scope->implicit, e); } } } @@ -3124,7 +3101,7 @@ void check_import_entities(Checker *c) { // gb_exit(1); } -Array find_entity_path(Map *map, Entity *start, Entity *end, Map *visited = nullptr) { +Array find_entity_path(Entity *start, Entity *end, Map *visited = nullptr) { Map visited_ = {}; bool made_visited = false; if (visited == nullptr) { @@ -3145,9 +3122,8 @@ Array find_entity_path(Map *map, Entity *start, Entity *en } map_set(visited, key, start); - DeclInfo **found = map_get(map, key); - if (found) { - DeclInfo *decl = *found; + DeclInfo *decl = start->decl_info; + if (decl) { for_array(i, decl->deps.entries) { Entity *dep = decl->deps.entries[i].ptr; if (dep == end) { @@ -3156,7 +3132,7 @@ Array find_entity_path(Map *map, Entity *start, Entity *en array_add(&path, dep); return path; } - Array next_path = find_entity_path(map, dep, end, visited); + Array next_path = find_entity_path(dep, end, visited); if (next_path.count > 0) { array_add(&next_path, dep); return next_path; @@ -3169,7 +3145,6 @@ Array find_entity_path(Map *map, Entity *start, Entity *en void calculate_global_init_order(Checker *c) { CheckerInfo *info = &c->info; - auto *m = &info->entities; Array dep_graph = generate_entity_dependency_graph(info); defer ({ @@ -3191,7 +3166,7 @@ void calculate_global_init_order(Checker *c) { Entity *e = n->entity; if (n->dep_count > 0) { - auto path = find_entity_path(m, e, e); + auto path = find_entity_path(e, e); defer (array_free(&path)); if (path.count > 0) { @@ -3299,8 +3274,8 @@ void check_parsed_files(Checker *c) { TIME_SECTION("check procedure bodies"); // Check procedure bodies // NOTE(bill): Nested procedures bodies will be added to this "queue" - for_array(i, c->procs.entries) { - ProcedureInfo *pi = &c->procs.entries[i].value; + for_array(i, c->procs) { + ProcedureInfo *pi = &c->procs[i]; if (pi->type == nullptr) { continue; } @@ -3367,8 +3342,8 @@ void check_parsed_files(Checker *c) { } // NOTE(bill): Check for illegal cyclic type declarations - for_array(i, c->info.definitions.entries) { - Entity *e = c->info.definitions.entries[i].value; + for_array(i, c->info.definitions) { + Entity *e = c->info.definitions[i]; if (e->kind == Entity_TypeName && e->type != nullptr) { // i64 size = type_size_of(c->sizes, c->allocator, e->type); i64 align = type_align_of(c->allocator, e->type); diff --git a/src/entity.cpp b/src/entity.cpp index fcc06f01e..857c5adee 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -66,6 +66,7 @@ struct Entity { Scope * scope; Type * type; AstNode * identifier; // Can be nullptr + DeclInfo * decl_info; DeclInfo * parent_proc_decl; // nullptr if in file/global scope // TODO(bill): Cleanup how `using` works for entities diff --git a/src/ir.cpp b/src/ir.cpp index 25e21ad2e..100beee4d 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -8171,9 +8171,8 @@ void ir_gen_tree(irGen *s) { bool has_dll_main = false; bool has_win_main = false; - for_array(i, info->entities.entries) { - auto *entry = &info->entities.entries[i]; - Entity *e = cast(Entity *)entry->key.ptr; + for_array(i, info->entities) { + Entity *e = info->entities[i]; String name = e->token.string; if (e->kind == Entity_Variable) { global_variable_max_count++; @@ -8283,11 +8282,10 @@ void ir_gen_tree(irGen *s) { } } - for_array(i, info->entities.entries) { - auto * entry = &info->entities.entries[i]; - Entity * e = cast(Entity *)entry->key.ptr; + for_array(i, info->entities) { + Entity * e = info->entities[i]; String name = e->token.string; - DeclInfo *decl = entry->value; + DeclInfo *decl = e->decl_info; Scope * scope = e->scope; if (!scope->is_file) { diff --git a/src/main.cpp b/src/main.cpp index 2a1ee6017..91bee0b03 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include "timings.cpp" #include "build_settings.cpp" #include "tokenizer.cpp" +#include "exact_value.cpp" #include "parser.cpp" #include "docs.cpp" #include "checker.cpp" diff --git a/src/parser.cpp b/src/parser.cpp index 8dd5881a2..f735744f1 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1,5 +1,6 @@ struct AstNode; struct Scope; +struct Entity; struct DeclInfo; enum ParseFileError { @@ -151,7 +152,8 @@ Array make_ast_node_array(AstFile *f, isize init_capacity = 8) { // all the nodes and even memcpy in a different kind of node #define AST_NODE_KINDS \ AST_NODE_KIND(Ident, "identifier", struct { \ - Token token; \ + Token token; \ + Entity *entity; \ }) \ AST_NODE_KIND(Implicit, "implicit", Token) \ AST_NODE_KIND(Undef, "undef", Token) \ @@ -279,9 +281,10 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \ AstNode *body; \ }) \ AST_NODE_KIND(CaseClause, "case clause", struct { \ - Token token; \ - Array list; \ - Array stmts; \ + Token token; \ + Array list; \ + Array stmts; \ + Entity *implicit_entity; \ }) \ AST_NODE_KIND(SwitchStmt, "switch statement", struct { \ Token token; \ @@ -498,6 +501,8 @@ struct AstNode { AstNodeKind kind; u32 stmt_state_flags; AstFile * file; + Scope * scope; + union { #define AST_NODE_KIND(_kind_name_, name, ...) GB_JOIN2(AstNode, _kind_name_) _kind_name_; AST_NODE_KINDS @@ -656,7 +661,9 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) { default: GB_PANIC("Unhandled AstNode %.*s", LIT(ast_node_strings[n->kind])); break; case AstNode_Invalid: break; - case AstNode_Ident: break; + case AstNode_Ident: + n->Ident.entity = nullptr; + break; case AstNode_Implicit: break; case AstNode_Undef: break; case AstNode_BasicLit: break; @@ -794,6 +801,7 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) { case AstNode_CaseClause: n->CaseClause.list = clone_ast_node_array(a, n->CaseClause.list); n->CaseClause.stmts = clone_ast_node_array(a, n->CaseClause.stmts); + n->CaseClause.implicit_entity = nullptr; break; case AstNode_SwitchStmt: n->SwitchStmt.label = clone_ast_node(a, n->SwitchStmt.label);