diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-09-09 19:48:28 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-09-09 19:48:28 +0100 |
| commit | 1ca752ce049b934df5d03af2f06265e219f5f402 (patch) | |
| tree | fddb26b40309a433bf7b04834be692c8e7758b03 /src/checker/checker.cpp | |
| parent | 56dd12c54c20b2e4a7f896999ece1cf184f09e88 (diff) | |
Remove duplicates in type info data.
Diffstat (limited to 'src/checker/checker.cpp')
| -rw-r--r-- | src/checker/checker.cpp | 100 |
1 files changed, 91 insertions, 9 deletions
diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index 9fd61eec8..218f3517b 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -208,7 +208,8 @@ struct CheckerInfo { Map<ExpressionInfo> untyped; // Key: AstNode * | Expression -> ExpressionInfo Map<DeclInfo *> entities; // Key: Entity * Map<Entity *> foreign_procs; // Key: String - Map<Type *> type_info_types; // Key: Type * + Map<isize> type_info_map; // Key: Type * + isize type_info_index; }; struct Checker { @@ -441,7 +442,8 @@ void init_checker_info(CheckerInfo *i) { map_init(&i->entities, a); map_init(&i->untyped, a); map_init(&i->foreign_procs, a); - map_init(&i->type_info_types, a); + map_init(&i->type_info_map, a); + i->type_info_index = 0; } @@ -453,7 +455,7 @@ void destroy_checker_info(CheckerInfo *i) { map_destroy(&i->entities); map_destroy(&i->untyped); map_destroy(&i->foreign_procs); - map_destroy(&i->type_info_types); + map_destroy(&i->type_info_map); } @@ -670,6 +672,82 @@ void add_file_entity(Checker *c, AstNode *identifier, Entity *e, DeclInfo *d) { map_set(&c->info.entities, hash_pointer(e), d); } +void add_type_info_type(Checker *c, Type *t) { + if (t == NULL) { + return; + } + t = default_type(t); + if (map_get(&c->info.type_info_map, hash_pointer(t)) != NULL) { + // Types have already been added + return; + } + + isize found = -1; + gb_for_array(i, c->info.type_info_map.entries) { + auto *e = &c->info.type_info_map.entries[i]; + Type *prev_type = cast(Type *)cast(uintptr)e->key.key; + if (are_types_identical(t, prev_type)) { + found = i; + break; + } + } + if (found >= 0) { + // Duplicate entry + map_set(&c->info.type_info_map, hash_pointer(t), found); + } else { + // Unique entry + isize index = c->info.type_info_index; + c->info.type_info_index++; + map_set(&c->info.type_info_map, hash_pointer(t), index); + } + + + if (t->kind == Type_Named) { + // NOTE(bill): Just in case + add_type_info_type(c, t->Named.base); + return; + } + + Type *bt = get_base_type(t); + switch (bt->kind) { + case Type_Basic: { + if (bt->Basic.kind == Basic_string) { + add_type_info_type(c, make_type_pointer(c->allocator, t_u8)); + add_type_info_type(c, t_int); + } + } break; + case Type_Array: + add_type_info_type(c, bt->Array.elem); + add_type_info_type(c, make_type_pointer(c->allocator, bt->Array.elem)); + add_type_info_type(c, t_int); + break; + case Type_Slice: + add_type_info_type(c, bt->Slice.elem); + add_type_info_type(c, make_type_pointer(c->allocator, bt->Slice.elem)); + add_type_info_type(c, t_int); + break; + case Type_Vector: add_type_info_type(c, bt->Vector.elem); break; + case Type_Pointer: add_type_info_type(c, bt->Pointer.elem); break; + case Type_Record: { + switch (bt->Record.kind) { + case TypeRecord_Enum: + add_type_info_type(c, bt->Record.enum_base); + break; + default: + for (isize i = 0; i < bt->Record.field_count; i++) { + Entity *f = bt->Record.fields[i]; + add_type_info_type(c, f->type); + } + break; + } + } break; + } + // TODO(bill): Type info for procedures and tuples + // TODO(bill): Remove duplicate identical types efficiently +} + + + void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *decl, Type *type, AstNode *body) { ProcedureInfo info = {}; @@ -866,7 +944,11 @@ void check_parsed_files(Checker *c) { t_type_info_ptr = make_type_pointer(c->allocator, t_type_info); auto *record = &get_base_type(e->type)->Record; - GB_ASSERT_MSG(record->field_count == 15, "Internal Compiler Error: Invalid `Type_Info` layout"); + + t_type_info_member = record->other_fields[0]->type; + t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member); + + GB_ASSERT_MSG(record->field_count == 16, "Internal Compiler Error: Invalid `Type_Info` layout"); t_type_info_named = record->fields[ 1]->type; t_type_info_integer = record->fields[ 2]->type; t_type_info_float = record->fields[ 3]->type; @@ -877,11 +959,11 @@ void check_parsed_files(Checker *c) { t_type_info_array = record->fields[ 8]->type; t_type_info_slice = record->fields[ 9]->type; t_type_info_vector = record->fields[10]->type; - t_type_info_struct = record->fields[11]->type; - t_type_info_union = record->fields[12]->type; - t_type_info_raw_union = record->fields[13]->type; - t_type_info_enum = record->fields[14]->type; - // t_type_info_any = record->fields[15]->type; + t_type_info_tuple = record->fields[11]->type; + t_type_info_struct = record->fields[12]->type; + t_type_info_union = record->fields[13]->type; + t_type_info_raw_union = record->fields[14]->type; + t_type_info_enum = record->fields[15]->type; } check_global_entity(c, Entity_Constant); |