From 94c1331c071d4816bec44345393dfd07f75c97dc Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 15 Feb 2023 11:31:51 +0000 Subject: Implement `@(fini)` (opposite of `@(init)`) --- src/checker.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 6 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 303a2449e..5163fe675 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1148,6 +1148,7 @@ gb_internal void init_checker_info(CheckerInfo *i) { array_init(&i->variable_init_order, a); array_init(&i->testing_procedures, a, 0, 0); array_init(&i->init_procedures, a, 0, 0); + array_init(&i->fini_procedures, a, 0, 0); array_init(&i->required_foreign_imports_through_force, a, 0, 0); map_init(&i->objc_msgSend_types); @@ -1539,7 +1540,7 @@ gb_internal void add_entity_flags_from_file(CheckerContext *c, Entity *e, Scope AstPackage *pkg = c->file->pkg; if (pkg->kind == Package_Init && e->kind == Entity_Procedure && e->token.string == "main") { // Do nothing - } else if (e->flags & (EntityFlag_Test|EntityFlag_Init)) { + } else if (e->flags & (EntityFlag_Test|EntityFlag_Init|EntityFlag_Fini)) { // Do nothing } else { e->flags |= EntityFlag_Lazy; @@ -1607,7 +1608,7 @@ gb_internal bool could_entity_be_lazy(Entity *e, DeclInfo *d) { return false; } - if (e->flags & (EntityFlag_Test|EntityFlag_Init)) { + if (e->flags & (EntityFlag_Test|EntityFlag_Init|EntityFlag_Fini)) { return false; } else if (e->kind == Entity_Variable && e->Variable.is_export) { return false; @@ -2416,6 +2417,28 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { add_dependency_to_set(c, e); array_add(&c->info.init_procedures, e); } + } else if (e->flags & EntityFlag_Fini) { + Type *t = base_type(e->type); + GB_ASSERT(t->kind == Type_Proc); + + bool is_fini = true; + + if (t->Proc.param_count != 0 || t->Proc.result_count != 0) { + gbString str = type_to_string(t); + error(e->token, "@(fini) procedures must have a signature type with no parameters nor results, got %s", str); + gb_string_free(str); + is_fini = false; + } + + if ((e->scope->flags & (ScopeFlag_File|ScopeFlag_Pkg)) == 0) { + error(e->token, "@(fini) procedures must be declared at the file scope"); + is_fini = false; + } + + if (is_fini) { + add_dependency_to_set(c, e); + array_add(&c->info.fini_procedures, e); + } } break; } @@ -2967,6 +2990,12 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) { } ac->init = true; return true; + } else if (name == "fini") { + if (value != nullptr) { + error(value, "'%.*s' expects no parameter, or a string literal containing \"file\" or \"package\"", LIT(name)); + } + ac->fini = true; + return true; } else if (name == "deferred") { if (value != nullptr) { Operand o = {}; @@ -3608,6 +3637,7 @@ gb_internal void check_collect_value_decl(CheckerContext *c, Ast *decl) { EntityVisiblityKind entity_visibility_kind = c->foreign_context.visibility_kind; bool is_test = false; bool is_init = false; + bool is_fini = false; for_array(i, vd->attributes) { Ast *attr = vd->attributes[i]; @@ -3667,6 +3697,8 @@ gb_internal void check_collect_value_decl(CheckerContext *c, Ast *decl) { is_test = true; } else if (name == "init") { is_init = true; + } else if (name == "fini") { + is_fini = true; } } } @@ -3800,8 +3832,12 @@ gb_internal void check_collect_value_decl(CheckerContext *c, Ast *decl) { if (is_test) { e->flags |= EntityFlag_Test; } - if (is_init) { + if (is_init && is_fini) { + error(name, "A procedure cannot be both declared as @(init) and @(fini)"); + } else if (is_init) { e->flags |= EntityFlag_Init; + } else if (is_fini) { + e->flags |= EntityFlag_Fini; } } else if (init->kind == Ast_ProcGroup) { ast_node(pg, ProcGroup, init); @@ -5627,9 +5663,14 @@ gb_internal GB_COMPARE_PROC(init_procedures_cmp) { return i32_cmp(x->token.pos.offset, y->token.pos.offset); } +gb_internal GB_COMPARE_PROC(fini_procedures_cmp) { + return init_procedures_cmp(b, a); +} + -gb_internal void check_sort_init_procedures(Checker *c) { +gb_internal void check_sort_init_and_fini_procedures(Checker *c) { gb_sort_array(c->info.init_procedures.data, c->info.init_procedures.count, init_procedures_cmp); + gb_sort_array(c->info.fini_procedures.data, c->info.fini_procedures.count, fini_procedures_cmp); } gb_internal void add_type_info_for_type_definitions(Checker *c) { @@ -5839,8 +5880,8 @@ gb_internal void check_parsed_files(Checker *c) { add_type_and_value(&c->builtin_ctx, u.expr, u.info->mode, u.info->type, u.info->value); } - TIME_SECTION("sort init procedures"); - check_sort_init_procedures(c); + TIME_SECTION("sort init and fini procedures"); + check_sort_init_and_fini_procedures(c); if (c->info.intrinsics_entry_point_usage.count > 0) { TIME_SECTION("check intrinsics.__entry_point usage"); -- cgit v1.2.3 From 8a2a70a3c2a7ac14687d100325e12b8d3d02256e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 17 Feb 2023 13:00:37 +0000 Subject: Fix overriding procedure information for literals --- src/check_decl.cpp | 17 +++++++++++++++++ src/check_expr.cpp | 4 +++- src/check_type.cpp | 12 ++++++++---- src/checker.cpp | 4 ++-- src/checker.hpp | 4 ++-- src/llvm_backend_const.cpp | 1 - src/llvm_backend_expr.cpp | 2 +- 7 files changed, 33 insertions(+), 11 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 63e6514e0..dc929cbca 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1480,6 +1480,23 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de ctx->curr_proc_sig = type; ctx->curr_proc_calling_convention = type->Proc.calling_convention; + if (ctx->proc_name == "sort") { + if (type->Proc.param_count > 0) { + TypeTuple *params = &type->Proc.params->Tuple; + for (Entity *e : params->variables) { + if (e->kind == Entity_Constant) { + Ast *ident = e->identifier.load(); + if (ident) { + add_entity(ctx, e->scope, ident, e); + ident->tav.mode = Addressing_Constant; + ident->tav.value = e->Constant.value; + ident->tav.type = e->type; + } + } + } + } + } + if (ctx->pkg->name != "runtime") { switch (type->Proc.calling_convention) { case ProcCC_None: diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 58372f7a3..93db559f8 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -5418,7 +5418,9 @@ gb_internal CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { data->score = score; data->result_type = final_proc_type->Proc.results; data->gen_entity = gen_entity; - add_type_and_value(c, ce->proc, Addressing_Value, final_proc_type, {}); + if (!are_types_identical(final_proc_type, ce->proc->tav.type)) { + add_type_and_value(c, ce->proc, Addressing_Value, final_proc_type, {}); + } } return err; diff --git a/src/check_type.cpp b/src/check_type.cpp index ec661134b..24ca8628e 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1666,17 +1666,21 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para if (is_poly_name) { bool valid = false; if (is_type_proc(op.type)) { - Entity *proc_entity = entity_from_expr(op.expr); - valid = (proc_entity != nullptr) && (op.value.kind == ExactValue_Procedure); - if (valid) { + Ast *expr = unparen_expr(op.expr); + Entity *proc_entity = entity_from_expr(expr); + if (proc_entity) { poly_const = exact_value_procedure(proc_entity->identifier.load() ? proc_entity->identifier.load() : op.expr); + valid = true; + } else if (expr->kind == Ast_ProcLit) { + poly_const = exact_value_procedure(expr); + valid = true; } } if (!valid) { if (op.mode == Addressing_Constant) { poly_const = op.value; } else { - error(op.expr, "Expected a constant value for this polymorphic name parameter"); + error(op.expr, "Expected a constant value for this polymorphic name parameter, got %s", expr_to_string(op.expr)); success = false; } } diff --git a/src/checker.cpp b/src/checker.cpp index 5163fe675..94bbb32e6 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1416,7 +1416,7 @@ gb_internal isize type_info_index(CheckerInfo *info, Type *type, bool error_on_f } -gb_internal void add_untyped(CheckerContext *c, Ast *expr, AddressingMode mode, Type *type, ExactValue value) { +gb_internal void add_untyped(CheckerContext *c, Ast *expr, AddressingMode mode, Type *type, ExactValue const &value) { if (expr == nullptr) { return; } @@ -1433,7 +1433,7 @@ gb_internal void add_untyped(CheckerContext *c, Ast *expr, AddressingMode mode, check_set_expr_info(c, expr, mode, type, value); } -gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMode mode, Type *type, ExactValue value) { +gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMode mode, Type *type, ExactValue const &value) { if (expr == nullptr) { return; } diff --git a/src/checker.hpp b/src/checker.hpp index 4c3b8725a..b82612813 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -485,9 +485,9 @@ gb_internal void scope_lookup_parent (Scope *s, String const &name, Scope **s gb_internal Entity *scope_insert (Scope *s, Entity *entity); -gb_internal void add_type_and_value (CheckerContext *c, Ast *expression, AddressingMode mode, Type *type, ExactValue value); +gb_internal void add_type_and_value (CheckerContext *c, Ast *expression, AddressingMode mode, Type *type, ExactValue const &value); gb_internal ExprInfo *check_get_expr_info (CheckerContext *c, Ast *expr); -gb_internal void add_untyped (CheckerContext *c, Ast *expression, AddressingMode mode, Type *basic_type, ExactValue value); +gb_internal void add_untyped (CheckerContext *c, Ast *expression, AddressingMode mode, Type *basic_type, ExactValue const &value); gb_internal void add_entity_use (CheckerContext *c, Ast *identifier, Entity *entity); gb_internal void add_implicit_entity (CheckerContext *c, Ast *node, Entity *e); gb_internal void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, Entity *e, DeclInfo *d, bool is_exported=true); diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index ee564bbf1..fc1598024 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -411,7 +411,6 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo Ast *expr = unparen_expr(value.value_procedure); if (expr->kind == Ast_ProcLit) { res = lb_generate_anonymous_proc_lit(m, str_lit("_proclit"), expr); - } else { Entity *e = entity_from_expr(expr); res = lb_find_procedure_value_from_entity(m, e); diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 7cf8d56db..480831a68 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -3138,7 +3138,7 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) { Entity *e = entity_from_expr(expr); e = strip_entity_wrapping(e); - GB_ASSERT_MSG(e != nullptr, "%s", expr_to_string(expr)); + GB_ASSERT_MSG(e != nullptr, "%s in %.*s %p", expr_to_string(expr), LIT(p->name), expr); if (e->kind == Entity_Builtin) { Token token = ast_token(expr); GB_PANIC("TODO(bill): lb_build_expr Entity_Builtin '%.*s'\n" -- cgit v1.2.3