From 30f5a3bb9358ded6a48e8d8ba6f5eb0b3743a807 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 23 Mar 2018 20:48:30 +0000 Subject: [PATCH] Move cycle checking to much earlier on in the semantic stage --- src/check_decl.cpp | 9 +++- src/check_expr.cpp | 33 ++++++++++++-- src/check_stmt.cpp | 20 ++++----- src/check_type.cpp | 86 ++++++++++++++++++++----------------- src/checker.cpp | 104 +++++++++++++++++++++++++++++---------------- src/checker.hpp | 13 +++++- src/entity.cpp | 76 ++++++++++++++++----------------- src/ir.cpp | 74 ++++++++++++++------------------ src/main.cpp | 2 + src/types.cpp | 19 ++++++--- 10 files changed, 259 insertions(+), 177 deletions(-) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index b16536f70..a2a7a1fb4 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -227,6 +227,8 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) { error(decl->attributes[0], "Attributes are not allowed on type declarations"); } + + bool is_distinct = is_type_distinct(type_expr); AstNode *te = remove_type_alias_clutter(type_expr); e->type = t_invalid; @@ -238,7 +240,10 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) { } e->type = named; - Type *bt = check_type(c, te, named); + check_type_path_push(c, e); + Type *bt = check_type_expr(c, te, named); + check_type_path_pop(c); + named->Named.base = base_type(bt); if (!is_distinct) { e->type = bt; @@ -985,7 +990,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod for_array(i, scope->elements.entries) { Entity *f = scope->elements.entries[i].value; if (f->kind == Entity_Variable) { - Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type); + Entity *uvar = alloc_entity_using_variable(e, f->token, f->type); uvar->Variable.is_immutable = is_immutable; if (is_value) uvar->flags |= EntityFlag_Value; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 4996d7853..12aae53a1 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -55,7 +55,8 @@ void check_multi_expr (Checker *c, Operand *operand, AstNode * void check_expr_or_type (Checker *c, Operand *operand, AstNode *expression, Type *type_hint = nullptr); ExprKind check_expr_base (Checker *c, Operand *operand, AstNode *expression, Type *type_hint); void check_expr_with_type_hint (Checker *c, Operand *o, AstNode *e, Type *t); -Type * check_type (Checker *c, AstNode *expression, Type *named_type = nullptr); +Type * check_type (Checker *c, AstNode *expression); +Type * check_type_expr (Checker *c, AstNode *expression, Type *named_type); Type * make_optional_ok_type (Type *value); void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, Type *def); Entity * check_selector (Checker *c, Operand *operand, AstNode *node, Type *type_hint); @@ -334,7 +335,7 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ d->proc_lit = proc_lit; - Entity *entity = make_entity_procedure(c->allocator, nullptr, token, final_proc_type, tags); + Entity *entity = alloc_entity_procedure(nullptr, token, final_proc_type, tags); entity->identifier = ident; add_entity_and_decl_info(c, ident, entity, d); @@ -903,6 +904,27 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c return false; } +bool check_cycle(Checker *c, Entity *curr, bool report) { + if (curr->state != EntityState_InProgress) { + return false; + } + for_array(i, *c->context.type_path) { + Entity *prev = (*c->context.type_path)[i]; + if (prev == curr) { + if (report) { + error(curr->token, "Illegal declaration cycle of `%.*s`", LIT(curr->token.string)); + for (isize j = i; j < c->context.type_path->count; j++) { + Entity *curr = (*c->context.type_path)[j]; + error(curr->token, "\t%.*s refers to", LIT(curr->token.string)); + } + error(curr->token, "\t%.*s", LIT(curr->token.string)); + } + return true; + } + } + return false; +} + Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint, bool allow_import_name) { GB_ASSERT(n->kind == AstNode_Ident); @@ -1036,6 +1058,9 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type * case Entity_TypeName: o->mode = Addressing_Type; + if (check_cycle(c, e, true)) { + type = t_invalid; + } break; case Entity_ImportName: @@ -3152,8 +3177,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id Type *proc_type_params = alloc_type_tuple(c->allocator); proc_type_params->Tuple.variables = gb_alloc_array(c->allocator, Entity *, 2); proc_type_params->Tuple.variable_count = 2; - proc_type_params->Tuple.variables[0] = make_entity_param(c->allocator, nullptr, blank_token, operand->type, false, false); - proc_type_params->Tuple.variables[1] = make_entity_param(c->allocator, nullptr, blank_token, slice_elem, false, false); + proc_type_params->Tuple.variables[0] = alloc_entity_param(c->allocator, nullptr, blank_token, operand->type, false, false); + proc_type_params->Tuple.variables[1] = alloc_entity_param(c->allocator, nullptr, blank_token, slice_elem, false, false); Type *proc_type = alloc_type_proc(nullptr, proc_type_params, 2, nullptr, false, true, ProcCC_Odin); check_call_arguments(c, &prev_operand, proc_type, call); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index ff04fed14..80e5baf37 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -431,7 +431,7 @@ void check_label(Checker *c, AstNode *label) { } } - Entity *e = make_entity_label(c->allocator, c->context.scope, l->name->Ident.token, t_invalid, label); + Entity *e = alloc_entity_label(c->context.scope, l->name->Ident.token, t_invalid, label); add_entity(c, c->context.scope, l->name, e); e->parent_proc_decl = c->context.curr_proc_decl; @@ -507,7 +507,7 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo for_array(i, found->elements.entries) { Entity *f = found->elements.entries[i].value; if (f->kind == Entity_Variable) { - Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type); + Entity *uvar = alloc_entity_using_variable(e, f->token, f->type); uvar->using_expr = expr; Entity *prev = scope_insert_entity(c->context.scope, uvar); if (prev != nullptr) { @@ -1000,7 +1000,7 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { check_open_scope(c, stmt); { - Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, lhs->Ident.token, case_type, false, EntityState_Resolved); + Entity *tag_var = alloc_entity_variable(c->context.scope, lhs->Ident.token, case_type, false, EntityState_Resolved); tag_var->flags |= EntityFlag_Used; tag_var->flags |= EntityFlag_Value; add_entity(c, c->context.scope, lhs, tag_var); @@ -1467,7 +1467,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { } if (found == nullptr) { bool is_immutable = true; - entity = make_entity_variable(c->allocator, c->context.scope, token, type, is_immutable, EntityState_Resolved); + entity = alloc_entity_variable(c->context.scope, token, type, is_immutable, EntityState_Resolved); add_entity_definition(&c->info, name, entity); } else { TokenPos pos = found->token.pos; @@ -1482,7 +1482,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { } if (entity == nullptr) { - entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name)); + entity = alloc_entity_dummy_variable(c->global_scope, ast_node_token(name)); } entities[entity_count++] = entity; @@ -1700,7 +1700,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { continue; } - Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type); + Entity *uvar = alloc_entity_using_variable(e, f->token, f->type); uvar->using_expr = expr; Entity *prev = scope_insert_entity(c->context.scope, uvar); if (prev != nullptr) { @@ -1797,7 +1797,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { new_name_count += 1; } if (found == nullptr) { - entity = make_entity_variable(c->allocator, c->context.scope, token, nullptr, false); + entity = alloc_entity_variable(c->context.scope, token, nullptr, false); entity->identifier = name; AstNode *fl = c->context.foreign_context.curr_library; @@ -1816,7 +1816,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { } } if (entity == nullptr) { - entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name)); + entity = alloc_entity_dummy_variable(c->global_scope, ast_node_token(name)); } entity->parent_proc_decl = c->context.curr_proc_decl; entities[entity_count++] = entity; @@ -1828,7 +1828,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { Type *init_type = nullptr; if (vd->type != nullptr) { - init_type = check_type(c, vd->type, nullptr); + init_type = check_type(c, vd->type); if (init_type == nullptr) { init_type = t_invalid; } else if (is_type_polymorphic(base_type(init_type))) { @@ -1938,7 +1938,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { for_array(i, scope->elements.entries) { Entity *f = scope->elements.entries[i].value; if (f->kind == Entity_Variable) { - Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type); + Entity *uvar = alloc_entity_using_variable(e, f->token, f->type); uvar->Variable.is_immutable = is_immutable; Entity *prev = scope_insert_entity(c->context.scope, uvar); if (prev != nullptr) { diff --git a/src/check_type.cpp b/src/check_type.cpp index c96269356..c3ee0a51a 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -111,7 +111,7 @@ void check_struct_fields(Checker *c, AstNode *node, Array *fields, Arr gb_printf_err("Element\n"); } - type = check_type(c, type_expr); + type = check_type_expr(c, type_expr, nullptr); if (default_value != nullptr) { Operand o = {}; @@ -179,7 +179,7 @@ void check_struct_fields(Checker *c, AstNode *node, Array *fields, Arr Token name_token = name->Ident.token; Entity *field = nullptr; - field = make_entity_field(c->allocator, c->context.scope, name_token, type, is_using, field_src_index); + field = alloc_entity_field(c->context.scope, name_token, type, is_using, field_src_index); field->Variable.default_value = value; field->Variable.default_is_nil = default_is_nil; @@ -211,8 +211,7 @@ void check_struct_fields(Checker *c, AstNode *node, Array *fields, Arr Entity *make_names_field_for_struct(Checker *c, Scope *scope) { - Entity *e = make_entity_field(c->allocator, scope, - make_token_ident(str_lit("names")), t_string_slice, false, 0); + Entity *e = alloc_entity_field(scope, make_token_ident(str_lit("names")), t_string_slice, false, 0); e->Variable.is_immutable = true; e->flags |= EntityFlag_TypeField; return e; @@ -311,7 +310,7 @@ void add_polymorphic_struct_entity(Checker *c, AstNode *node, Type *named_type, node->kind = AstNode_Ident; node->Ident.token = token; - e = make_entity_type_name(a, s, token, named_type); + e = alloc_entity_type_name(s, token, named_type); e->state = EntityState_Resolved; add_entity_use(c, node, e); } @@ -454,18 +453,18 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Arrayallocator, scope, token, operand.type); + e = alloc_entity_type_name(scope, token, operand.type); e->TypeName.is_type_alias = true; } else { GB_ASSERT(operand.mode == Addressing_Constant); - e = make_entity_constant(c->allocator, scope, token, operand.type, operand.value); + e = alloc_entity_constant(scope, token, operand.type, operand.value); } } else { if (is_type_param) { - e = make_entity_type_name(c->allocator, scope, token, type); + e = alloc_entity_type_name(scope, token, type); e->TypeName.is_type_alias = true; } else { - e = make_entity_constant(c->allocator, scope, token, type, empty_exact_value); + e = alloc_entity_constant(scope, token, type, empty_exact_value); } } @@ -551,7 +550,7 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) { for_array(i, ut->variants) { AstNode *node = ut->variants[i]; - Type *t = check_type(c, node); + Type *t = check_type_expr(c, node, nullptr); if (t != nullptr && t != t_invalid) { bool ok = true; t = default_type(t); @@ -697,7 +696,7 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod max_value = iota; } - Entity *e = make_entity_constant(c->allocator, c->context.scope, ident->Ident.token, constant_type, iota); + Entity *e = alloc_entity_constant(c->context.scope, ident->Ident.token, constant_type, iota); e->identifier = ident; e->flags |= EntityFlag_Visited; e->state = EntityState_Resolved; @@ -732,12 +731,10 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod } } - enum_type->Enum.count = make_entity_constant(c->allocator, c->context.scope, - make_token_ident(str_lit("count")), t_int, exact_value_i64(fields.count)); - enum_type->Enum.min_value = make_entity_constant(c->allocator, c->context.scope, - make_token_ident(str_lit("min_value")), constant_type, min_value); - enum_type->Enum.max_value = make_entity_constant(c->allocator, c->context.scope, - make_token_ident(str_lit("max_value")), constant_type, max_value); + Scope *s = c->context.scope; + enum_type->Enum.count = alloc_entity_constant(s, make_token_ident(str_lit("count")), t_int, exact_value_i64(fields.count)); + enum_type->Enum.min_value = alloc_entity_constant(s, make_token_ident(str_lit("min_value")), constant_type, min_value); + enum_type->Enum.max_value = alloc_entity_constant(s, make_token_ident(str_lit("max_value")), constant_type, max_value); enum_type->Enum.names = make_names_field_for_struct(c, c->context.scope); } @@ -789,7 +786,7 @@ void check_bit_field_type(Checker *c, Type *bit_field_type, AstNode *node) { u32 bits = cast(u32)bits_; Type *value_type = alloc_type_bit_field_value(bits); - Entity *e = make_entity_variable(c->allocator, bit_field_type->BitField.scope, ident->Ident.token, value_type, false); + Entity *e = alloc_entity_variable(bit_field_type->BitField.scope, ident->Ident.token, value_type, false); e->identifier = ident; e->flags |= EntityFlag_BitFieldValue; @@ -1184,7 +1181,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari type = t_invalid; } } - param = make_entity_type_name(c->allocator, scope, name->Ident.token, type, EntityState_Resolved); + param = alloc_entity_type_name(scope, name->Ident.token, type, EntityState_Resolved); param->TypeName.is_type_alias = true; } else { if (operands != nullptr && variables.count < operands->count) { @@ -1207,7 +1204,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari } } - param = make_entity_param(c->allocator, scope, name->Ident.token, type, is_using, is_in); + param = alloc_entity_param(scope, name->Ident.token, type, is_using, is_in); param->Variable.default_value = value; param->Variable.default_is_nil = default_is_nil; param->Variable.default_is_location = default_is_location; @@ -1336,7 +1333,7 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) { if (field->names.count == 0) { Token token = ast_node_token(field->type); token.string = str_lit(""); - Entity *param = make_entity_param(c->allocator, scope, token, type, false, false); + Entity *param = alloc_entity_param(scope, token, type, false, false); param->Variable.default_value = value; param->Variable.default_is_nil = default_is_nil; array_add(&variables, param); @@ -1359,7 +1356,7 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) { error(name, "Result value cannot be a blank identifer `_`"); } - Entity *param = make_entity_param(c->allocator, scope, token, type, false, false); + Entity *param = alloc_entity_param(scope, token, type, false, false); param->flags |= EntityFlag_Result; param->Variable.default_value = value; param->Variable.default_is_nil = default_is_nil; @@ -1542,7 +1539,7 @@ Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type) { if (new_type != original_type) { Type *tuple = alloc_type_tuple(); auto variables = array_make(a, 0, 1); - array_add(&variables, make_entity_param(a, original_type->Tuple.variables[0]->scope, empty_token, new_type, false, false)); + array_add(&variables, alloc_entity_param(original_type->Tuple.variables[0]->scope, empty_token, new_type, false, false)); tuple->Tuple.variables = variables; new_type = tuple; } @@ -1732,8 +1729,8 @@ Type *make_optional_ok_type(Type *value) { bool typed = true; Type *t = alloc_type_tuple(); array_init(&t->Tuple.variables, a, 0, 2); - array_add (&t->Tuple.variables, make_entity_field(a, nullptr, blank_token, value, false, 0)); - array_add (&t->Tuple.variables, make_entity_field(a, nullptr, blank_token, typed ? t_bool : t_untyped_bool, false, 1)); + array_add (&t->Tuple.variables, alloc_entity_field(nullptr, blank_token, value, false, 0)); + array_add (&t->Tuple.variables, alloc_entity_field(nullptr, blank_token, typed ? t_bool : t_untyped_bool, false, 1)); return t; } @@ -1759,9 +1756,9 @@ void init_map_entry_type(Type *type) { Scope *s = create_scope(universal_scope, a); auto fields = array_make(a, 0, 3); - array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("key")), t_map_key, false, 0, EntityState_Resolved)); - array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("next")), t_int, false, 1, EntityState_Resolved)); - array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("value")), type->Map.value, false, 2, EntityState_Resolved)); + array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("key")), t_map_key, false, 0, EntityState_Resolved)); + array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("next")), t_int, false, 1, EntityState_Resolved)); + array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("value")), type->Map.value, false, 2, EntityState_Resolved)); entry_type->Struct.fields = fields; @@ -1799,8 +1796,8 @@ void init_map_internal_types(Type *type) { auto fields = array_make(a, 0, 2); - array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("hashes")), hashes_type, false, 0, EntityState_Resolved)); - array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("entries")), entries_type, false, 1, EntityState_Resolved)); + array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("hashes")), hashes_type, false, 0, EntityState_Resolved)); + array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("entries")), entries_type, false, 1, EntityState_Resolved)); generated_struct_type->Struct.fields = fields; @@ -1837,6 +1834,8 @@ void check_map_type(Checker *c, Type *type, AstNode *node) { // error(node, "'map' types are not yet implemented"); } + + bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) { GB_ASSERT_NOT_NULL(type); if (e == nullptr) { @@ -1846,7 +1845,6 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) switch (e->kind) { case_ast_node(i, Ident, e); - Operand o = {}; Entity *entity = check_ident(c, &o, e, named_type, nullptr, false); @@ -1867,9 +1865,15 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) } } - if (c->context.type_level == 0 && entity->state == EntityState_InProgress) { - error(e, "Illegal declaration cycle of `%.*s`", LIT(entity->token.string)); - } + // if (c->context.type_level == 0 && entity->state == EntityState_InProgress) { + // error(entity->token, "Illegal declaration cycle of `%.*s`", LIT(entity->token.string)); + // for_array(j, *c->context.type_path) { + // Entity *k = (*c->context.type_path)[j]; + // error(k->token, "\t%.*s refers to", LIT(k->token.string)); + // } + // error(entity->token, "\t%.*s", LIT(entity->token.string)); + // *type = t_invalid; + // } return true; } @@ -1927,7 +1931,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) GB_ASSERT(is_scope_an_ancestor(ps, s) >= 0); entity_scope = ps; } - Entity *e = make_entity_type_name(c->allocator, entity_scope, token, t); + Entity *e = alloc_entity_type_name(entity_scope, token, t); e->TypeName.is_type_alias = true; e->state = EntityState_Resolved; add_entity(c, ps, ident, e); @@ -1968,7 +1972,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) case_end; case_ast_node(pe, ParenExpr, e); - *type = check_type(c, pe->expr, named_type); + *type = check_type_expr(c, pe->expr, named_type); set_base_type(named_type, *type); return true; case_end; @@ -2000,7 +2004,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) error(at->count, "... can only be used in conjuction with compound literals"); count = 0; } - Type *elem = check_type(c, at->elem, nullptr); + Type *elem = check_type_expr(c, at->elem, nullptr); *type = alloc_type_array(elem, count, generic_type); } else { Type *elem = check_type(c, at->elem); @@ -2117,9 +2121,15 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) return false; } +Type *check_type(Checker *c, AstNode *e) { + auto prev_context = c->context; defer (c->context = prev_context); + c->context.type_path = new_checker_type_path(); + defer (destroy_checker_type_path(c->context.type_path)); + return check_type_expr(c, e, nullptr); +} -Type *check_type(Checker *c, AstNode *e, Type *named_type) { +Type *check_type_expr(Checker *c, AstNode *e, Type *named_type) { Type *type = nullptr; bool ok = check_type_internal(c, e, &type, named_type); diff --git a/src/checker.cpp b/src/checker.cpp index df0db1333..70ad8e4b6 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -507,20 +507,20 @@ Entity *add_global_entity(Entity *entity) { return entity; } -void add_global_constant(gbAllocator a, String name, Type *type, ExactValue value) { - Entity *entity = alloc_entity(a, Entity_Constant, nullptr, make_token_ident(name), type); +void add_global_constant(String name, Type *type, ExactValue value) { + Entity *entity = alloc_entity(Entity_Constant, nullptr, make_token_ident(name), type); entity->Constant.value = value; add_global_entity(entity); } -void add_global_string_constant(gbAllocator a, String name, String value) { - add_global_constant(a, name, t_untyped_string, exact_value_string(value)); +void add_global_string_constant(String name, String value) { + add_global_constant(name, t_untyped_string, exact_value_string(value)); } -void add_global_type_entity(gbAllocator a, String name, Type *type) { - add_global_entity(make_entity_type_name(a, nullptr, make_token_ident(name), type)); +void add_global_type_entity(String name, Type *type) { + add_global_entity(alloc_entity_type_name(nullptr, make_token_ident(name), type)); } @@ -533,27 +533,27 @@ void init_universal_scope(void) { // Types for (isize i = 0; i < gb_count_of(basic_types); i++) { - add_global_type_entity(a, basic_types[i].Basic.name, &basic_types[i]); + add_global_type_entity(basic_types[i].Basic.name, &basic_types[i]); } - add_global_type_entity(a, str_lit("byte"), &basic_types[Basic_u8]); + add_global_type_entity(str_lit("byte"), &basic_types[Basic_u8]); // Constants - add_global_constant(a, str_lit("true"), t_untyped_bool, exact_value_bool(true)); - add_global_constant(a, str_lit("false"), t_untyped_bool, exact_value_bool(false)); + add_global_constant(str_lit("true"), t_untyped_bool, exact_value_bool(true)); + add_global_constant(str_lit("false"), t_untyped_bool, exact_value_bool(false)); - add_global_entity(make_entity_nil(a, str_lit("nil"), t_untyped_nil)); - add_global_entity(make_entity_library_name(a, universal_scope, - make_token_ident(str_lit("__llvm_core")), t_invalid, - str_lit(""), str_lit("__llvm_core"))); + add_global_entity(alloc_entity_nil(str_lit("nil"), t_untyped_nil)); + add_global_entity(alloc_entity_library_name(universal_scope, + make_token_ident(str_lit("__llvm_core")), t_invalid, + str_lit(""), str_lit("__llvm_core"))); // TODO(bill): Set through flags in the compiler - add_global_string_constant(a, str_lit("ODIN_OS"), bc->ODIN_OS); - add_global_string_constant(a, str_lit("ODIN_ARCH"), bc->ODIN_ARCH); - add_global_string_constant(a, str_lit("ODIN_ENDIAN"), bc->ODIN_ENDIAN); - add_global_string_constant(a, str_lit("ODIN_VENDOR"), bc->ODIN_VENDOR); - add_global_string_constant(a, str_lit("ODIN_VERSION"), bc->ODIN_VERSION); - add_global_string_constant(a, str_lit("ODIN_ROOT"), bc->ODIN_ROOT); - add_global_constant(a, str_lit("ODIN_DEBUG"), t_untyped_bool, exact_value_bool(bc->ODIN_DEBUG)); + add_global_string_constant(str_lit("ODIN_OS"), bc->ODIN_OS); + add_global_string_constant(str_lit("ODIN_ARCH"), bc->ODIN_ARCH); + add_global_string_constant(str_lit("ODIN_ENDIAN"), bc->ODIN_ENDIAN); + add_global_string_constant(str_lit("ODIN_VENDOR"), bc->ODIN_VENDOR); + add_global_string_constant(str_lit("ODIN_VERSION"), bc->ODIN_VERSION); + add_global_string_constant(str_lit("ODIN_ROOT"), bc->ODIN_ROOT); + add_global_constant(str_lit("ODIN_DEBUG"), t_untyped_bool, exact_value_bool(bc->ODIN_DEBUG)); // Builtin Procedures @@ -561,7 +561,7 @@ void init_universal_scope(void) { BuiltinProcId id = cast(BuiltinProcId)i; String name = builtin_procs[i].name; if (name != "") { - Entity *entity = alloc_entity(a, Entity_Builtin, nullptr, make_token_ident(name), t_invalid); + Entity *entity = alloc_entity(Entity_Builtin, nullptr, make_token_ident(name), t_invalid); entity->Builtin.id = id; add_global_entity(entity); } @@ -639,12 +639,17 @@ void init_checker(Checker *c, Parser *parser) { c->tmp_allocator = gb_arena_allocator(&c->tmp_arena); c->global_scope = create_scope(universal_scope, c->allocator); - c->context.scope = c->global_scope; map_init(&c->file_scopes, heap_allocator()); ptr_set_init(&c->checked_files, heap_allocator()); array_init(&c->file_order, heap_allocator(), 0, c->parser->files.count); + + // Init context + c->context.scope = c->global_scope; + + c->context.type_path = new_checker_type_path(); + c->context.type_level = 0; } void destroy_checker(Checker *c) { @@ -660,6 +665,8 @@ void destroy_checker(Checker *c) { map_destroy(&c->file_scopes); ptr_set_destroy(&c->checked_files); array_free(&c->file_order); + + destroy_checker_type_path(c->context.type_path); } @@ -1312,6 +1319,31 @@ Type *find_core_type(Checker *c, String name) { return e->type; } +CheckerTypePath *new_checker_type_path() { + gbAllocator a = heap_allocator(); + auto *tp = gb_alloc_item(a, CheckerTypePath); + array_init(tp, a, 0, 16); + return tp; +} + +void destroy_checker_type_path(CheckerTypePath *tp) { + array_free(tp); + gb_free(heap_allocator(), tp); +} + + +void check_type_path_push(Checker *c, Entity *e) { + GB_ASSERT(c->context.type_path != nullptr); + GB_ASSERT(e != nullptr); + array_add(c->context.type_path, e); +} +Entity *check_type_path_pop(Checker *c) { + GB_ASSERT(c->context.type_path != nullptr); + return array_pop(c->context.type_path); +} + + + void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type); @@ -1424,9 +1456,9 @@ void init_preload(Checker *c) { Entity *type_info_entity = find_core_entity(c, str_lit("Type_Info")); Scope *preload_scope = type_info_entity->scope; - Entity *e = make_entity_import_name(c->allocator, preload_scope, make_token_ident(_global), t_invalid, - str_lit(""), _global, - preload_scope); + Entity *e = alloc_entity_import_name(preload_scope, make_token_ident(_global), t_invalid, + str_lit(""), _global, + preload_scope); add_entity(c, universal_scope, nullptr, e); } @@ -1745,7 +1777,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) { error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind])); continue; } - Entity *e = make_entity_variable(c->allocator, c->context.scope, name->Ident.token, nullptr, false); + Entity *e = alloc_entity_variable(c->context.scope, name->Ident.token, nullptr, false); e->identifier = name; if (vd->is_using) { @@ -1808,7 +1840,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) { if (is_ast_node_type(init) || (vd->type != nullptr && vd->type->kind == AstNode_TypeType)) { - e = make_entity_type_name(c->allocator, d->scope, token, nullptr); + e = alloc_entity_type_name(d->scope, token, nullptr); if (vd->type != nullptr) { error(name, "A type declaration cannot have an type parameter"); } @@ -1820,7 +1852,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) { continue; } ast_node(pl, ProcLit, init); - e = make_entity_procedure(c->allocator, d->scope, token, nullptr, pl->tags); + e = alloc_entity_procedure(d->scope, token, nullptr, pl->tags); if (fl != nullptr) { GB_ASSERT(fl->kind == AstNode_Ident); e->Procedure.foreign_library_ident = fl; @@ -1846,13 +1878,13 @@ void check_collect_value_decl(Checker *c, AstNode *decl) { d->type_expr = pl->type; } else if (init->kind == AstNode_ProcGroup) { ast_node(pg, ProcGroup, init); - e = make_entity_proc_group(c->allocator, d->scope, token, nullptr); + e = alloc_entity_proc_group(d->scope, token, nullptr); if (fl != nullptr) { error(name, "Procedure groups are not allowed within a foreign block"); } d->init_expr = init; } else { - e = make_entity_constant(c->allocator, d->scope, token, nullptr, empty_exact_value); + e = alloc_entity_constant(d->scope, token, nullptr, empty_exact_value); d->type_expr = vd->type; d->init_expr = init; } @@ -2340,9 +2372,9 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) { } else { GB_ASSERT(id->import_name.pos.line != 0); id->import_name.string = import_name; - Entity *e = make_entity_import_name(c->allocator, parent_scope, id->import_name, t_invalid, - id->fullpath, id->import_name.string, - scope); + Entity *e = alloc_entity_import_name(parent_scope, id->import_name, t_invalid, + id->fullpath, id->import_name.string, + scope); add_entity(c, parent_scope, nullptr, e); } @@ -2524,8 +2556,8 @@ void check_add_foreign_import_decl(Checker *c, AstNode *decl) { GB_ASSERT(fl->library_name.pos.line != 0); fl->library_name.string = library_name; - Entity *e = make_entity_library_name(c->allocator, parent_scope, fl->library_name, t_invalid, - fl->fullpath, library_name); + Entity *e = alloc_entity_library_name(parent_scope, fl->library_name, t_invalid, + fl->fullpath, library_name); add_entity(c, parent_scope, nullptr, e); } diff --git a/src/checker.hpp b/src/checker.hpp index 172768835..ff930667d 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -262,19 +262,23 @@ struct ForeignContext { bool in_export; }; +typedef Array CheckerTypePath; + struct CheckerContext { Scope * file_scope; Scope * scope; DeclInfo * decl; u32 stmt_state_flags; bool in_defer; // TODO(bill): Actually handle correctly - isize type_level; // TODO(bill): Actually handle correctly String proc_name; Type * type_hint; DeclInfo * curr_proc_decl; Type * curr_proc_sig; ForeignContext foreign_context; + CheckerTypePath *type_path; + isize type_level; // TODO(bill): Actually handle correctly + bool collect_delayed_decls; bool allow_polymorphic_types; bool no_polymorphic_errors; @@ -382,7 +386,6 @@ void check_collect_entities(Checker *c, Array nodes); void check_collect_entities_from_when_stmt(Checker *c, AstNodeWhenStmt *ws); void check_delayed_file_import_entity(Checker *c, AstNode *decl); - struct AttributeContext { String link_name; String link_prefix; @@ -401,3 +404,9 @@ AttributeContext make_attribute_context(String link_prefix) { typedef DECL_ATTRIBUTE_PROC(DeclAttributeProc); void check_decl_attributes(Checker *c, Array attributes, DeclAttributeProc *proc, AttributeContext *ac); + +CheckerTypePath *new_checker_type_path(); +void destroy_checker_type_path(CheckerTypePath *tp); + +void check_type_path_push(Checker *c, Entity *e); +Entity *check_type_path_pop (Checker *c); diff --git a/src/entity.cpp b/src/entity.cpp index 5dcb3ff7b..182df8c05 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -177,7 +177,8 @@ bool is_entity_exported(Entity *e) { gb_global u64 global_entity_id = 0; -Entity *alloc_entity(gbAllocator a, EntityKind kind, Scope *scope, Token token, Type *type) { +Entity *alloc_entity(EntityKind kind, Scope *scope, Token token, Type *type) { + gbAllocator a = heap_allocator(); Entity *entity = gb_alloc_item(a, Entity); entity->kind = kind; entity->state = EntityState_Unresolved; @@ -188,17 +189,17 @@ Entity *alloc_entity(gbAllocator a, EntityKind kind, Scope *scope, Token token, return entity; } -Entity *make_entity_variable(gbAllocator a, Scope *scope, Token token, Type *type, bool is_immutable, EntityState state = EntityState_Unresolved) { - Entity *entity = alloc_entity(a, Entity_Variable, scope, token, type); +Entity *alloc_entity_variable(Scope *scope, Token token, Type *type, bool is_immutable, EntityState state = EntityState_Unresolved) { + Entity *entity = alloc_entity(Entity_Variable, scope, token, type); entity->Variable.is_immutable = is_immutable; entity->state = state; return entity; } -Entity *make_entity_using_variable(gbAllocator a, Entity *parent, Token token, Type *type) { +Entity *alloc_entity_using_variable(Entity *parent, Token token, Type *type) { GB_ASSERT(parent != nullptr); token.pos = parent->token.pos; - Entity *entity = alloc_entity(a, Entity_Variable, parent->scope, token, type); + Entity *entity = alloc_entity(Entity_Variable, parent->scope, token, type); entity->using_parent = parent; entity->parent_proc_decl = parent->parent_proc_decl; entity->flags |= EntityFlag_Using; @@ -208,21 +209,21 @@ Entity *make_entity_using_variable(gbAllocator a, Entity *parent, Token token, T } -Entity *make_entity_constant(gbAllocator a, Scope *scope, Token token, Type *type, ExactValue value) { - Entity *entity = alloc_entity(a, Entity_Constant, scope, token, type); +Entity *alloc_entity_constant(Scope *scope, Token token, Type *type, ExactValue value) { + Entity *entity = alloc_entity(Entity_Constant, scope, token, type); entity->Constant.value = value; return entity; } -Entity *make_entity_type_name(gbAllocator a, Scope *scope, Token token, Type *type, EntityState state = EntityState_Unresolved) { - Entity *entity = alloc_entity(a, Entity_TypeName, scope, token, type); +Entity *alloc_entity_type_name(Scope *scope, Token token, Type *type, EntityState state = EntityState_Unresolved) { + Entity *entity = alloc_entity(Entity_TypeName, scope, token, type); entity->state = state; return entity; } -Entity *make_entity_param(gbAllocator a, Scope *scope, Token token, Type *type, bool is_using, bool is_value) { +Entity *alloc_entity_param(Scope *scope, Token token, Type *type, bool is_using, bool is_value) { bool is_immutable = false; - Entity *entity = make_entity_variable(a, scope, token, type, is_immutable); + Entity *entity = alloc_entity_variable(scope, token, type, is_immutable); entity->flags |= EntityFlag_Used; entity->flags |= EntityFlag_Param; entity->state = EntityState_Resolved; @@ -232,8 +233,8 @@ Entity *make_entity_param(gbAllocator a, Scope *scope, Token token, Type *type, } -Entity *make_entity_const_param(gbAllocator a, Scope *scope, Token token, Type *type, ExactValue value, bool poly_const) { - Entity *entity = make_entity_constant(a, scope, token, type, value); +Entity *alloc_entity_const_param(Scope *scope, Token token, Type *type, ExactValue value, bool poly_const) { + Entity *entity = alloc_entity_constant(scope, token, type, value); entity->flags |= EntityFlag_Used; if (poly_const) entity->flags |= EntityFlag_PolyConst; entity->flags |= EntityFlag_Param; @@ -241,8 +242,8 @@ Entity *make_entity_const_param(gbAllocator a, Scope *scope, Token token, Type * } -Entity *make_entity_field(gbAllocator a, Scope *scope, Token token, Type *type, bool is_using, i32 field_src_index, EntityState state = EntityState_Unresolved) { - Entity *entity = make_entity_variable(a, scope, token, type, false); +Entity *alloc_entity_field(Scope *scope, Token token, Type *type, bool is_using, i32 field_src_index, EntityState state = EntityState_Unresolved) { + Entity *entity = alloc_entity_variable(scope, token, type, false); entity->Variable.field_src_index = field_src_index; entity->Variable.field_index = field_src_index; if (is_using) entity->flags |= EntityFlag_Using; @@ -251,8 +252,8 @@ Entity *make_entity_field(gbAllocator a, Scope *scope, Token token, Type *type, return entity; } -Entity *make_entity_array_elem(gbAllocator a, Scope *scope, Token token, Type *type, i32 field_src_index) { - Entity *entity = make_entity_variable(a, scope, token, type, false); +Entity *alloc_entity_array_elem(Scope *scope, Token token, Type *type, i32 field_src_index) { + Entity *entity = alloc_entity_variable(scope, token, type, false); entity->Variable.field_src_index = field_src_index; entity->Variable.field_index = field_src_index; entity->flags |= EntityFlag_Field; @@ -261,34 +262,34 @@ Entity *make_entity_array_elem(gbAllocator a, Scope *scope, Token token, Type *t return entity; } -Entity *make_entity_procedure(gbAllocator a, Scope *scope, Token token, Type *signature_type, u64 tags) { - Entity *entity = alloc_entity(a, Entity_Procedure, scope, token, signature_type); +Entity *alloc_entity_procedure(Scope *scope, Token token, Type *signature_type, u64 tags) { + Entity *entity = alloc_entity(Entity_Procedure, scope, token, signature_type); entity->Procedure.tags = tags; return entity; } -Entity *make_entity_proc_group(gbAllocator a, Scope *scope, Token token, Type *type) { - Entity *entity = alloc_entity(a, Entity_ProcGroup, scope, token, type); +Entity *alloc_entity_proc_group(Scope *scope, Token token, Type *type) { + Entity *entity = alloc_entity(Entity_ProcGroup, scope, token, type); return entity; } -Entity *make_entity_builtin(gbAllocator a, Scope *scope, Token token, Type *type, i32 id) { - Entity *entity = alloc_entity(a, Entity_Builtin, scope, token, type); +Entity *alloc_entity_builtin(Scope *scope, Token token, Type *type, i32 id) { + Entity *entity = alloc_entity(Entity_Builtin, scope, token, type); entity->Builtin.id = id; entity->state = EntityState_Resolved; return entity; } -Entity *make_entity_alias(gbAllocator a, Scope *scope, Token token, Type *type, Entity *base) { - Entity *entity = alloc_entity(a, Entity_Alias, scope, token, type); +Entity *alloc_entity_alias(Scope *scope, Token token, Type *type, Entity *base) { + Entity *entity = alloc_entity(Entity_Alias, scope, token, type); entity->Alias.base = base; return entity; } -Entity *make_entity_import_name(gbAllocator a, Scope *scope, Token token, Type *type, - String path, String name, Scope *import_scope) { - Entity *entity = alloc_entity(a, Entity_ImportName, scope, token, type); +Entity *alloc_entity_import_name(Scope *scope, Token token, Type *type, + String path, String name, Scope *import_scope) { + Entity *entity = alloc_entity(Entity_ImportName, scope, token, type); entity->ImportName.path = path; entity->ImportName.name = name; entity->ImportName.scope = import_scope; @@ -296,9 +297,9 @@ Entity *make_entity_import_name(gbAllocator a, Scope *scope, Token token, Type * return entity; } -Entity *make_entity_library_name(gbAllocator a, Scope *scope, Token token, Type *type, - String path, String name) { - Entity *entity = alloc_entity(a, Entity_LibraryName, scope, token, type); +Entity *alloc_entity_library_name(Scope *scope, Token token, Type *type, + String path, String name) { + Entity *entity = alloc_entity(Entity_LibraryName, scope, token, type); entity->LibraryName.path = path; entity->LibraryName.name = name; entity->state = EntityState_Resolved; // TODO(bill): Is this correct? @@ -309,21 +310,20 @@ Entity *make_entity_library_name(gbAllocator a, Scope *scope, Token token, Type -Entity *make_entity_nil(gbAllocator a, String name, Type *type) { - Entity *entity = alloc_entity(a, Entity_Nil, nullptr, make_token_ident(name), type); +Entity *alloc_entity_nil(String name, Type *type) { + Entity *entity = alloc_entity(Entity_Nil, nullptr, make_token_ident(name), type); return entity; } -Entity *make_entity_label(gbAllocator a, Scope *scope, Token token, Type *type, - AstNode *node) { - Entity *entity = alloc_entity(a, Entity_Label, scope, token, type); +Entity *alloc_entity_label(Scope *scope, Token token, Type *type, AstNode *node) { + Entity *entity = alloc_entity(Entity_Label, scope, token, type); entity->Label.node = node; entity->state = EntityState_Resolved; return entity; } -Entity *make_entity_dummy_variable(gbAllocator a, Scope *scope, Token token) { +Entity *alloc_entity_dummy_variable(Scope *scope, Token token) { token.string = str_lit("_"); - return make_entity_variable(a, scope, token, nullptr, false); + return alloc_entity_variable(scope, token, nullptr, false); } diff --git a/src/ir.cpp b/src/ir.cpp index ed61da4af..9ed06a617 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1206,10 +1206,7 @@ irValue *ir_generate_array(irModule *m, Type *elem_type, i64 count, String prefi String s = make_string_c(text); - Entity *e = make_entity_variable(a, nullptr, - make_token_ident(s), - alloc_type_array(elem_type, count), - false); + Entity *e = alloc_entity_variable(nullptr, make_token_ident(s), alloc_type_array(elem_type, count), false); irValue *value = ir_value_global(a, e, nullptr); value->Global.is_private = true; ir_module_add_value(m, e, value); @@ -1308,7 +1305,7 @@ irValue *ir_add_module_constant(irModule *m, Type *type, ExactValue value) { String name = make_string(str, len-1); - Entity *e = make_entity_constant(a, nullptr, make_token_ident(name), t, value); + Entity *e = alloc_entity_constant(nullptr, make_token_ident(name), t, value); irValue *g = ir_value_global(a, e, backing_array); ir_module_add_value(m, e, g); map_set(&m->members, hash_string(name), g); @@ -1335,7 +1332,7 @@ irValue *ir_add_global_string_array(irModule *m, String string) { token.string = name; Type *type = alloc_type_array(t_u8, string.len+1); ExactValue ev = exact_value_string(string); - Entity *entity = make_entity_constant(a, nullptr, token, type, ev); + Entity *entity = alloc_entity_constant(nullptr, token, type, ev); irValue *g = ir_value_global(a, entity, ir_add_module_constant(m, type, ev)); g->Global.is_private = true; g->Global.is_unnamed_addr = true; @@ -1429,10 +1426,7 @@ irValue *ir_add_local_generated(irProcedure *proc, Type *type, bool zero_initial if (proc->curr_block) { scope = proc->curr_block->scope; } - Entity *e = make_entity_variable(proc->module->allocator, - scope, - empty_token, - type, false); + Entity *e = alloc_entity_variable(scope, empty_token, type, false); return ir_add_local(proc, e, nullptr, zero_initialized); } @@ -1450,11 +1444,7 @@ irValue *ir_add_global_generated(irModule *m, Type *type, irValue *value) { String name = make_string(str, len-1); Scope *scope = nullptr; - Entity *e = make_entity_variable(a, - scope, - make_token_ident(name), - type, false); - + Entity *e = alloc_entity_variable(scope, make_token_ident(name), type, false); irValue *g = ir_value_global(a, e, value); ir_module_add_value(m, e, g); map_set(&m->members, hash_string(name), g); @@ -7389,7 +7379,7 @@ void ir_begin_procedure_body(irProcedure *proc) { if (proc->type->Proc.return_by_pointer) { // NOTE(bill): this must be the first parameter stored Type *ptr_type = alloc_type_pointer(reduce_tuple_to_single_type(proc->type->Proc.results)); - Entity *e = make_entity_param(a, nullptr, make_token_ident(str_lit("agg.result")), ptr_type, false, false); + Entity *e = alloc_entity_param(nullptr, make_token_ident(str_lit("agg.result")), ptr_type, false, false); e->flags |= EntityFlag_Sret | EntityFlag_NoAlias; irValue *param = ir_value_param(a, proc, e, ptr_type); @@ -7472,7 +7462,7 @@ void ir_begin_procedure_body(irProcedure *proc) { if (proc->type->Proc.calling_convention == ProcCC_Odin) { - Entity *e = make_entity_param(a, nullptr, make_token_ident(str_lit("__.context_ptr")), t_context_ptr, false, false); + Entity *e = alloc_entity_param(nullptr, make_token_ident(str_lit("__.context_ptr")), t_context_ptr, false, false); e->flags |= EntityFlag_NoAlias; irValue *param = ir_value_param(a, proc, e, e->type); ir_module_add_value(proc->module, e, param); @@ -7633,7 +7623,7 @@ void ir_init_module(irModule *m, Checker *c) { isize max_type_info_count = m->info->type_info_types.count; String name = str_lit(IR_TYPE_INFO_DATA_NAME); - Entity *e = make_entity_variable(m->allocator, nullptr, make_token_ident(name), alloc_type_array(t_type_info, max_type_info_count), false); + Entity *e = alloc_entity_variable(nullptr, make_token_ident(name), alloc_type_array(t_type_info, max_type_info_count), false); irValue *g = ir_value_global(m->allocator, e, nullptr); g->Global.is_private = true; ir_module_add_value(m, e, g); @@ -7664,8 +7654,8 @@ void ir_init_module(irModule *m, Checker *c) { { String name = str_lit(IR_TYPE_INFO_TYPES_NAME); - Entity *e = make_entity_variable(m->allocator, nullptr, make_token_ident(name), - alloc_type_array(t_type_info_ptr, count), false); + Entity *e = alloc_entity_variable(nullptr, make_token_ident(name), + alloc_type_array(t_type_info_ptr, count), false); irValue *g = ir_value_global(m->allocator, e, nullptr); ir_module_add_value(m, e, g); map_set(&m->members, hash_string(name), g); @@ -7673,8 +7663,8 @@ void ir_init_module(irModule *m, Checker *c) { } { String name = str_lit(IR_TYPE_INFO_NAMES_NAME); - Entity *e = make_entity_variable(m->allocator, nullptr, make_token_ident(name), - alloc_type_array(t_string, count), false); + Entity *e = alloc_entity_variable(nullptr, make_token_ident(name), + alloc_type_array(t_string, count), false); irValue *g = ir_value_global(m->allocator, e, nullptr); ir_module_add_value(m, e, g); map_set(&m->members, hash_string(name), g); @@ -7682,8 +7672,8 @@ void ir_init_module(irModule *m, Checker *c) { } { String name = str_lit(IR_TYPE_INFO_OFFSETS_NAME); - Entity *e = make_entity_variable(m->allocator, nullptr, make_token_ident(name), - alloc_type_array(t_uintptr, count), false); + Entity *e = alloc_entity_variable(nullptr, make_token_ident(name), + alloc_type_array(t_uintptr, count), false); irValue *g = ir_value_global(m->allocator, e, nullptr); ir_module_add_value(m, e, g); map_set(&m->members, hash_string(name), g); @@ -7692,8 +7682,8 @@ void ir_init_module(irModule *m, Checker *c) { { String name = str_lit(IR_TYPE_INFO_USINGS_NAME); - Entity *e = make_entity_variable(m->allocator, nullptr, make_token_ident(name), - alloc_type_array(t_bool, count), false); + Entity *e = alloc_entity_variable(nullptr, make_token_ident(name), + alloc_type_array(t_bool, count), false); irValue *g = ir_value_global(m->allocator, e, nullptr); ir_module_add_value(m, e, g); map_set(&m->members, hash_string(name), g); @@ -8487,12 +8477,12 @@ void ir_gen_tree(irGen *s) { array_init(&proc_params->Tuple.variables, a, 3); array_init(&proc_results->Tuple.variables, a, 1); - proc_params->Tuple.variables[0] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false, false); - proc_params->Tuple.variables[1] = make_entity_param(a, proc_scope, make_token_ident(str_lit("reason")), t_i32, false, false); - proc_params->Tuple.variables[2] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false, false); + proc_params->Tuple.variables[0] = alloc_entity_param(proc_scope, blank_token, t_rawptr, false, false); + proc_params->Tuple.variables[1] = alloc_entity_param(proc_scope, make_token_ident(str_lit("reason")), t_i32, false, false); + proc_params->Tuple.variables[2] = alloc_entity_param(proc_scope, blank_token, t_rawptr, false, false); - proc_results->Tuple.variables[0] = make_entity_param(a, proc_scope, empty_token, t_i32, false, false); + proc_results->Tuple.variables[0] = alloc_entity_param(proc_scope, empty_token, t_i32, false, false); Type *proc_type = alloc_type_proc(proc_scope, @@ -8507,7 +8497,7 @@ void ir_gen_tree(irGen *s) { proc_type->Proc.abi_compat_result_type = proc_results->Tuple.variables[0]->type; AstNode *body = gb_alloc_item(a, AstNode); - Entity *e = make_entity_procedure(a, nullptr, make_token_ident(name), proc_type, 0); + Entity *e = alloc_entity_procedure(nullptr, make_token_ident(name), proc_type, 0); irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name); map_set(&m->values, hash_entity(e), p); @@ -8566,11 +8556,11 @@ void ir_gen_tree(irGen *s) { array_init(&proc_results->Tuple.variables, a, 1); Type *cstring_ptr = alloc_type_pointer(t_cstring); - proc_params->Tuple.variables[0] = make_entity_param(a, proc_scope, make_token_ident(str_lit("argc")), t_i32, false, false); - proc_params->Tuple.variables[1] = make_entity_param(a, proc_scope, make_token_ident(str_lit("argv")), cstring_ptr, false, false); + proc_params->Tuple.variables[0] = alloc_entity_param(proc_scope, make_token_ident(str_lit("argc")), t_i32, false, false); + proc_params->Tuple.variables[1] = alloc_entity_param(proc_scope, make_token_ident(str_lit("argv")), cstring_ptr, false, false); - proc_results->Tuple.variables[0] = make_entity_param(a, proc_scope, empty_token, t_i32, false, false); + proc_results->Tuple.variables[0] = alloc_entity_param(proc_scope, empty_token, t_i32, false, false); Type *proc_type = alloc_type_proc(proc_scope, @@ -8585,7 +8575,7 @@ void ir_gen_tree(irGen *s) { proc_type->Proc.abi_compat_result_type = proc_results->Tuple.variables[0]->type; AstNode *body = gb_alloc_item(a, AstNode); - Entity *e = make_entity_procedure(a, nullptr, make_token_ident(name), proc_type, 0); + Entity *e = alloc_entity_procedure(nullptr, make_token_ident(name), proc_type, 0); irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name); map_set(&m->values, hash_entity(e), p); @@ -8636,12 +8626,12 @@ void ir_gen_tree(irGen *s) { proc_results->Tuple.variables = gb_alloc_array(a, Entity *, 1); proc_results->Tuple.variable_count = 1; - proc_params->Tuple.variables[0] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false); - proc_params->Tuple.variables[1] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false); - proc_params->Tuple.variables[2] = make_entity_param(a, proc_scope, blank_token, t_u8_ptr, false); - proc_params->Tuple.variables[3] = make_entity_param(a, proc_scope, blank_token, t_i32, false); + proc_params->Tuple.variables[0] = alloc_entity_param(proc_scope, blank_token, t_rawptr, false); + proc_params->Tuple.variables[1] = alloc_entity_param(proc_scope, blank_token, t_rawptr, false); + proc_params->Tuple.variables[2] = alloc_entity_param(proc_scope, blank_token, t_u8_ptr, false); + proc_params->Tuple.variables[3] = alloc_entity_param(proc_scope, blank_token, t_i32, false); - proc_results->Tuple.variables[0] = make_entity_param(a, proc_scope, empty_token, t_i32, false); + proc_results->Tuple.variables[0] = alloc_entity_param(proc_scope, empty_token, t_i32, false); Type *proc_type = alloc_type_proc(a, proc_scope, @@ -8649,7 +8639,7 @@ void ir_gen_tree(irGen *s) { proc_results, 1, false, ProcCC_Std); AstNode *body = gb_alloc_item(a, AstNode); - Entity *e = make_entity_procedure(a, nullptr, make_token_ident(name), proc_type, 0); + Entity *e = alloc_entity_procedure(a, nullptr, make_token_ident(name), proc_type, 0); irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name); m->entry_point_entity = e; @@ -8675,7 +8665,7 @@ void ir_gen_tree(irGen *s) { nullptr, 0, false, ProcCC_Contextless); AstNode *body = gb_alloc_item(a, AstNode); - Entity *e = make_entity_procedure(a, nullptr, make_token_ident(name), proc_type, 0); + Entity *e = alloc_entity_procedure(nullptr, make_token_ident(name), proc_type, 0); irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name); map_set(&m->values, hash_entity(e), p); diff --git a/src/main.cpp b/src/main.cpp index c1999e766..bf4d19d30 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -685,6 +685,8 @@ i32 exec_llvm_llc(String output_base) { #endif } + + int main(int arg_count, char **arg_ptr) { if (arg_count < 2) { usage(make_string_c(arg_ptr[0])); diff --git a/src/types.cpp b/src/types.cpp index 7ff1517be..d3029cd6c 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -435,8 +435,12 @@ HashKey hash_cache_type_array(Type *elem, i64 count) { return hash_ptr_and_id(elem, cast(u64)count); } HashKey hash_cache_type_map(Type *key, Type *value) { - u64 v = cast(u64)cast(uintptr)value; - return hash_ptr_and_id(key, v); + HashKey hkey = {}; + if ((key != nullptr) == (value != nullptr)) { + u64 v = cast(u64)cast(uintptr)value; + hkey = hash_ptr_and_id(key, v); + } + return hkey; } @@ -453,6 +457,7 @@ void init_cached_type_maps() { CachedType *find_cached_type(CachedTypeKind kind, HashKey key) { GB_ASSERT(key.kind == HashKey_PtrAndId); if (key.ptr_and_id.ptr == nullptr) { + // NOTE(bill): uncachable types return nullptr; } auto *m = &cached_type_maps[kind]; @@ -462,6 +467,7 @@ CachedType *find_cached_type(CachedTypeKind kind, HashKey key) { void add_cached_type(CachedTypeKind kind, HashKey key, Type *type) { GB_ASSERT(key.kind == HashKey_PtrAndId); if (key.ptr_and_id.ptr == nullptr) { + // NOTE(bill): uncachable types return; } CachedType ct = {}; @@ -1694,10 +1700,10 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty String data_str = str_lit("data"); String type_info_str = str_lit("type_info"); if (entity__any_data == nullptr) { - entity__any_data = make_entity_field(a, nullptr, make_token_ident(data_str), t_rawptr, false, 0); + entity__any_data = alloc_entity_field(nullptr, make_token_ident(data_str), t_rawptr, false, 0); } if (entity__any_type_info == nullptr) { - entity__any_type_info = make_entity_field(a, nullptr, make_token_ident(type_info_str), t_type_info_ptr, false, 1); + entity__any_type_info = alloc_entity_field(nullptr, make_token_ident(type_info_str), t_type_info_ptr, false, 1); } if (field_name == data_str) { @@ -1722,7 +1728,7 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty case (_length): \ if (field_name == _name) { \ selection_add_index(&sel, (_length)-1); \ - sel.entity = make_entity_array_elem(a, nullptr, make_token_ident(str_lit(_name)), type->Array.elem, (_length)-1); \ + sel.entity = alloc_entity_array_elem(nullptr, make_token_ident(str_lit(_name)), type->Array.elem, (_length)-1); \ return sel; \ } \ /*fallthrough*/ @@ -1853,11 +1859,14 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty } +// IMPORTANT TODO(bill): SHould this TypePath code be removed since type cycle checking is handled much earlier on? + struct TypePath { Array path; // Entity_TypeName; bool failure; }; + void type_path_init(TypePath *tp) { // TODO(bill): Use an allocator that uses a backing array if it can and then use alternative allocator when exhausted array_init(&tp->path, heap_allocator());