Browse Source

Localize checker data

gingerBill 7 years ago
parent
commit
054e241033
7 changed files with 95 additions and 112 deletions
  1. 5 5
      examples/demo.odin
  2. 1 1
      src/check_stmt.cpp
  3. 69 94
      src/checker.cpp
  4. 1 0
      src/entity.cpp
  5. 5 7
      src/ir.cpp
  6. 1 0
      src/main.cpp
  7. 13 5
      src/parser.cpp

+ 5 - 5
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;

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

+ 69 - 94
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;
 }
 
 
@@ -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<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))  {
@@ -1531,10 +1510,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;
@@ -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<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) {
@@ -3145,9 +3122,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) {
@@ -3156,7 +3132,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;
@@ -3169,7 +3145,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 ({
@@ -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);

+ 1 - 0
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

+ 5 - 7
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) {

+ 1 - 0
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"

+ 13 - 5
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);