Minimal Type Info Dependency handling

This commit is contained in:
gingerBill
2018-05-12 16:53:44 +01:00
parent 20fbece14c
commit 56ff5496bc
6 changed files with 226 additions and 41 deletions
+173 -32
View File
@@ -173,16 +173,17 @@ GB_COMPARE_PROC(ast_node_cmp) {
void init_declaration_info(DeclInfo *d, Scope *scope, DeclInfo *parent) {
void init_decl_info(DeclInfo *d, Scope *scope, DeclInfo *parent) {
d->parent = parent;
d->scope = scope;
ptr_set_init(&d->deps, heap_allocator());
array_init (&d->labels, heap_allocator());
ptr_set_init(&d->deps, heap_allocator());
ptr_set_init(&d->type_info_deps, heap_allocator());
array_init (&d->labels, heap_allocator());
}
DeclInfo *make_declaration_info(gbAllocator a, Scope *scope, DeclInfo *parent) {
DeclInfo *make_decl_info(gbAllocator a, Scope *scope, DeclInfo *parent) {
DeclInfo *d = gb_alloc_item(a, DeclInfo);
init_declaration_info(d, scope, parent);
init_decl_info(d, scope, parent);
return d;
}
@@ -483,12 +484,20 @@ void check_scope_usage(Checker *c, Scope *scope) {
void add_dependency(DeclInfo *d, Entity *e) {
ptr_set_add(&d->deps, e);
}
void add_type_info_dependency(DeclInfo *d, Type *type) {
if (d == nullptr) {
GB_ASSERT(type == t_invalid);
return;
}
ptr_set_add(&d->type_info_deps, type);
}
void add_preload_dependency(Checker *c, char *name) {
String n = make_string_c(name);
Entity *e = scope_lookup_entity(c->global_scope, n);
GB_ASSERT(e != nullptr);
ptr_set_add(&c->context.decl->deps, e);
// add_type_info_type(c, e->type);
}
void add_declaration_dependency(Checker *c, Entity *e) {
@@ -959,8 +968,10 @@ void add_type_info_type(Checker *c, Type *t) {
return;
}
if (map_get(&c->info.type_info_map, hash_type(t)) != nullptr) {
auto found = map_get(&c->info.type_info_map, hash_type(t));
if (found != nullptr) {
// Types have already been added
add_type_info_dependency(c->context.decl, t);
return;
}
@@ -986,6 +997,7 @@ void add_type_info_type(Checker *c, Type *t) {
if (prev) {
// NOTE(bill): If a previous one exists already, no need to continue
add_type_info_dependency(c->context.decl, t);
return;
}
@@ -1133,43 +1145,175 @@ void add_curr_ast_file(Checker *c, AstFile *file) {
}
}
void add_min_dep_type_info(Checker *c, Type *t) {
if (t == nullptr) {
return;
}
t = default_type(t);
if (is_type_bit_field_value(t)) {
t = default_bit_field_value_type(t);
}
if (is_type_untyped(t)) {
return; // Could be nil
}
if (is_type_polymorphic(base_type(t))) {
return;
}
void add_dependency_to_map(PtrSet<Entity *> *map, CheckerInfo *info, Entity *entity) {
auto *set = &c->info.minimum_dependency_type_info_set;
isize ti_index = type_info_index(&c->info, t);
if (ptr_set_exists(set, ti_index)) {
// Type Already exists
return;
}
ptr_set_add(set, ti_index);
// Add nested types
if (t->kind == Type_Named) {
// NOTE(bill): Just in case
add_min_dep_type_info(c, t->Named.base);
return;
}
Type *bt = base_type(t);
add_min_dep_type_info(c, bt);
switch (bt->kind) {
case Type_Basic:
switch (bt->Basic.kind) {
case Basic_string:
add_min_dep_type_info(c, t_u8_ptr);
add_min_dep_type_info(c, t_int);
break;
case Basic_any:
add_min_dep_type_info(c, t_type_info_ptr);
add_min_dep_type_info(c, t_rawptr);
break;
case Basic_complex64:
add_min_dep_type_info(c, t_type_info_float);
add_min_dep_type_info(c, t_f32);
break;
case Basic_complex128:
add_min_dep_type_info(c, t_type_info_float);
add_min_dep_type_info(c, t_f64);
break;
}
break;
case Type_Pointer:
add_min_dep_type_info(c, bt->Pointer.elem);
break;
case Type_Array:
add_min_dep_type_info(c, bt->Array.elem);
add_min_dep_type_info(c, alloc_type_pointer(bt->Array.elem));
add_min_dep_type_info(c, t_int);
break;
case Type_DynamicArray:
add_min_dep_type_info(c, bt->DynamicArray.elem);
add_min_dep_type_info(c, alloc_type_pointer(bt->DynamicArray.elem));
add_min_dep_type_info(c, t_int);
add_min_dep_type_info(c, t_allocator);
break;
case Type_Slice:
add_min_dep_type_info(c, bt->Slice.elem);
add_min_dep_type_info(c, alloc_type_pointer(bt->Slice.elem));
add_min_dep_type_info(c, t_int);
break;
case Type_Enum:
add_min_dep_type_info(c, bt->Enum.base_type);
break;
case Type_Union:
add_min_dep_type_info(c, t_int);
add_min_dep_type_info(c, t_type_info_ptr);
for_array(i, bt->Union.variants) {
add_min_dep_type_info(c, bt->Union.variants[i]);
}
break;
case Type_Struct:
if (bt->Struct.scope != nullptr) {
for_array(i, bt->Struct.scope->elements.entries) {
Entity *e = bt->Struct.scope->elements.entries[i].value;
add_min_dep_type_info(c, e->type);
}
}
for_array(i, bt->Struct.fields) {
Entity *f = bt->Struct.fields[i];
add_min_dep_type_info(c, f->type);
}
break;
case Type_Map:
init_map_internal_types(bt);
add_min_dep_type_info(c, bt->Map.key);
add_min_dep_type_info(c, bt->Map.value);
add_min_dep_type_info(c, bt->Map.generated_struct_type);
break;
case Type_Tuple:
for_array(i, bt->Tuple.variables) {
Entity *var = bt->Tuple.variables[i];
add_min_dep_type_info(c, var->type);
}
break;
case Type_Proc:
add_min_dep_type_info(c, bt->Proc.params);
add_min_dep_type_info(c, bt->Proc.results);
break;
}
}
void add_dependency_to_set(Checker *c, Entity *entity) {
if (entity == nullptr) {
return;
}
CheckerInfo *info = &c->info;
auto *set = &info->minimum_dependency_set;
String name = entity->token.string;
if (entity->type != nullptr &&
is_type_polymorphic(entity->type)) {
DeclInfo *decl = decl_info_of_entity(info, entity);
DeclInfo *decl = decl_info_of_entity(&c->info, entity);
if (decl != nullptr && decl->gen_proc_type == nullptr) {
return;
}
}
if (ptr_set_exists(map, entity)) {
if (ptr_set_exists(set, entity)) {
return;
}
ptr_set_add(map, entity);
ptr_set_add(set, entity);
DeclInfo *decl = decl_info_of_entity(info, entity);
if (decl == nullptr) {
return;
}
for_array(i, decl->type_info_deps.entries) {
Type *type = decl->type_info_deps.entries[i].ptr;
add_min_dep_type_info(c, type);
}
for_array(i, decl->deps.entries) {
Entity *e = decl->deps.entries[i].ptr;
add_dependency_to_map(map, info, e);
add_dependency_to_set(c, e);
if (e->kind == Entity_Procedure && e->Procedure.is_foreign) {
Entity *fl = e->Procedure.foreign_library;
if (fl != nullptr) {
GB_ASSERT_MSG(fl->kind == Entity_LibraryName &&
fl->LibraryName.used,
"%.*s", LIT(name));
add_dependency_to_map(map, info, fl);
add_dependency_to_set(c, fl);
}
}
if (e->kind == Entity_Variable && e->Variable.is_foreign) {
@@ -1178,16 +1322,15 @@ void add_dependency_to_map(PtrSet<Entity *> *map, CheckerInfo *info, Entity *ent
GB_ASSERT_MSG(fl->kind == Entity_LibraryName &&
fl->LibraryName.used,
"%.*s", LIT(name));
add_dependency_to_map(map, info, fl);
add_dependency_to_set(c, fl);
}
}
}
}
PtrSet<Entity *> generate_minimum_dependency_set(Checker *c, Entity *start) {
CheckerInfo *info = &c->info;
PtrSet<Entity *> map = {}; // Key: Entity *
ptr_set_init(&map, heap_allocator());
void generate_minimum_dependency_set(Checker *c, Entity *start) {
ptr_set_init(&c->info.minimum_dependency_set, heap_allocator());
ptr_set_init(&c->info.minimum_dependency_type_info_set, heap_allocator());
String required_entities[] = {
str_lit("__mem_zero"),
@@ -1204,7 +1347,7 @@ PtrSet<Entity *> generate_minimum_dependency_set(Checker *c, Entity *start) {
str_lit("Context"),
};
for (isize i = 0; i < gb_count_of(required_entities); i++) {
add_dependency_to_map(&map, info, scope_lookup_entity(c->global_scope, required_entities[i]));
add_dependency_to_set(c, scope_lookup_entity(c->global_scope, required_entities[i]));
}
if (!build_context.no_bounds_check) {
@@ -1214,27 +1357,25 @@ PtrSet<Entity *> generate_minimum_dependency_set(Checker *c, Entity *start) {
str_lit("__dynamic_array_expr_error"),
};
for (isize i = 0; i < gb_count_of(bounds_check_entities); i++) {
add_dependency_to_map(&map, info, scope_lookup_entity(c->global_scope, bounds_check_entities[i]));
add_dependency_to_set(c, scope_lookup_entity(c->global_scope, bounds_check_entities[i]));
}
}
for_array(i, info->definitions) {
Entity *e = info->definitions[i];
for_array(i, c->info.definitions) {
Entity *e = c->info.definitions[i];
// if (e->scope->is_global && !is_type_poly_proc(e->type)) { // TODO(bill): is the check enough?
if (e->scope == universal_scope) { // TODO(bill): is the check enough?
if (e->type == nullptr || !is_type_poly_proc(e->type)) {
add_dependency_to_map(&map, info, e);
add_dependency_to_set(c, e);
}
} else if (e->kind == Entity_Procedure && e->Procedure.is_export) {
add_dependency_to_map(&map, info, e);
add_dependency_to_set(c, e);
} else if (e->kind == Entity_Variable && e->Procedure.is_export) {
add_dependency_to_map(&map, info, e);
add_dependency_to_set(c, e);
}
}
add_dependency_to_map(&map, info, start);
return map;
add_dependency_to_set(c, start);
}
bool is_entity_a_dependency(Entity *e) {
@@ -1794,7 +1935,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_cap);
DeclInfo *di = nullptr;
if (vd->values.count > 0) {
di = make_declaration_info(heap_allocator(), c->context.scope, c->context.decl);
di = make_decl_info(heap_allocator(), c->context.scope, c->context.decl);
di->entities = entities;
di->type_expr = vd->type;
di->init_expr = vd->values[0];
@@ -1838,7 +1979,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
DeclInfo *d = di;
if (d == nullptr || i > 0) {
AstNode *init_expr = value;
d = make_declaration_info(heap_allocator(), e->scope, c->context.decl);
d = make_decl_info(heap_allocator(), e->scope, c->context.decl);
d->type_expr = vd->type;
d->init_expr = init_expr;
}
@@ -1869,7 +2010,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
Token token = name->Ident.token;
AstNode *fl = c->context.foreign_context.curr_library;
DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, c->context.decl);
DeclInfo *d = make_decl_info(c->allocator, c->context.scope, c->context.decl);
Entity *e = nullptr;
d->attributes = vd->attributes;
@@ -3088,7 +3229,7 @@ void check_parsed_files(Checker *c) {
for_array(i, c->parser->files) {
AstFile *f = c->parser->files[i];
Scope *scope = create_scope_from_file(c, f);
f->decl_info = make_declaration_info(c->allocator, f->scope, c->context.decl);
f->decl_info = make_decl_info(c->allocator, f->scope, c->context.decl);
HashKey key = hash_string(f->tokenizer.fullpath);
map_set(&c->file_scopes, key, scope);
map_set(&c->info.files, key, f);
@@ -3151,7 +3292,7 @@ void check_parsed_files(Checker *c) {
}
TIME_SECTION("generate minimum dependency set");
c->info.minimum_dependency_set = generate_minimum_dependency_set(c, c->info.entry_point);
generate_minimum_dependency_set(c, c->info.entry_point);
TIME_SECTION("calculate global init order");