aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2017-12-12 21:22:46 +0000
committergingerBill <bill@gingerbill.org>2017-12-12 21:22:46 +0000
commitc980a30bad9fc98c21e4ea36b4e27568650cd601 (patch)
tree2c337ce2fb3ffc0004f607470b7381b0eea58d59 /src
parent78b459590c5b81ece8747cc2fdbb01e2b8dbdd42 (diff)
parent054e24103329022b1d918505cc5a61f8540c0e13 (diff)
Merge branch 'checker-optimizations' into explicit-overloading
# Conflicts: # examples/demo.odin
Diffstat (limited to 'src')
-rw-r--r--src/check_stmt.cpp2
-rw-r--r--src/checker.cpp163
-rw-r--r--src/entity.cpp1
-rw-r--r--src/ir.cpp12
-rw-r--r--src/main.cpp1
-rw-r--r--src/parser.cpp18
6 files changed, 90 insertions, 107 deletions
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<bool> seen = {}; // Multimap
+ Map<bool> 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 c56b0d284..6fc4ca8da 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<Entity *> elements; // Key: String
- Map<bool> implicit; // Key: Entity *
+ PtrSet<Entity *> implicit;
Array<Scope *> shared;
Array<AstNode *> 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<TypeAndValue> types; // Key: AstNode * | Expression -> Type (and value)
- Map<Entity *> definitions; // Key: AstNode * | Identifier -> Entity
- Map<Entity *> uses; // Key: AstNode * | Identifier -> Entity
- Map<Scope *> scopes; // Key: AstNode * | Node -> Scope
Map<ExprInfo> untyped; // Key: AstNode * | Expression -> ExprInfo
- Map<Entity *> implicits; // Key: AstNode *
- Map<Array<Entity *> > gen_procs; // Key: AstNode * | Identifier -> Entity
- Map<Array<Entity *> > gen_types; // Key: Type *
- Map<DeclInfo *> entities; // Key: Entity *
- Map<Entity *> foreigns; // Key: String
Map<AstFile *> files; // Key: String (full path)
+ Map<Entity *> foreigns; // Key: String
+ Array<Entity *> definitions;
+ Array<Entity *> entities;
Array<DeclInfo *> variable_init_order;
+ Map<Array<Entity *> > gen_procs; // Key: AstNode * | Identifier -> Entity
+ Map<Array<Entity *> > gen_types; // Key: Type *
Map<isize> 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<ProcedureInfo> procs; // Key: DeclInfo *
+ Array<ProcedureInfo> procs;
Map<Scope *> file_scopes; // Key: String (fullpath)
Array<ImportGraphNode *> 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;
}
@@ -933,13 +927,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);
@@ -951,13 +942,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);
@@ -979,7 +967,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));
@@ -992,7 +980,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);
@@ -1013,9 +1000,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);
@@ -1026,14 +1012,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;
}
@@ -1061,24 +1040,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;
}
@@ -1095,11 +1074,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));
@@ -1158,10 +1133,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));
}
@@ -1181,8 +1152,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
}
@@ -1240,8 +1216,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?
}
@@ -1252,15 +1227,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;
}
@@ -1409,10 +1389,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) {
@@ -1489,8 +1468,8 @@ PtrSet<Entity *> generate_minimum_dependency_set(CheckerInfo *info, Entity *star
PtrSet<Entity *> 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)) {
@@ -1533,10 +1512,9 @@ Array<EntityGraphNode *> generate_entity_dependency_graph(CheckerInfo *info) {
Map<EntityGraphNode *> 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;
@@ -2322,10 +2300,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;
@@ -2698,12 +2675,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);
}
}
}
@@ -3126,7 +3103,7 @@ void check_import_entities(Checker *c) {
// gb_exit(1);
}
-Array<Entity *> find_entity_path(Map<DeclInfo *> *map, Entity *start, Entity *end, Map<Entity *> *visited = nullptr) {
+Array<Entity *> find_entity_path(Entity *start, Entity *end, Map<Entity *> *visited = nullptr) {
Map<Entity *> visited_ = {};
bool made_visited = false;
if (visited == nullptr) {
@@ -3147,9 +3124,8 @@ Array<Entity *> find_entity_path(Map<DeclInfo *> *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) {
@@ -3158,7 +3134,7 @@ Array<Entity *> find_entity_path(Map<DeclInfo *> *map, Entity *start, Entity *en
array_add(&path, dep);
return path;
}
- Array<Entity *> next_path = find_entity_path(map, dep, end, visited);
+ Array<Entity *> next_path = find_entity_path(dep, end, visited);
if (next_path.count > 0) {
array_add(&next_path, dep);
return next_path;
@@ -3171,7 +3147,6 @@ Array<Entity *> find_entity_path(Map<DeclInfo *> *map, Entity *start, Entity *en
void calculate_global_init_order(Checker *c) {
CheckerInfo *info = &c->info;
- auto *m = &info->entities;
Array<EntityGraphNode *> dep_graph = generate_entity_dependency_graph(info);
defer ({
@@ -3193,7 +3168,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) {
@@ -3301,8 +3276,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;
}
@@ -3369,8 +3344,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 7c1d6d343..66d0f3ee4 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -8173,9 +8173,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++;
@@ -8285,11 +8284,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<AstNode *> 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<AstNode *> list; \
- Array<AstNode *> stmts; \
+ Token token; \
+ Array<AstNode *> list; \
+ Array<AstNode *> 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);