From 05a3bdad588d7d1194d4705b4f60506208e36b39 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 4 Dec 2020 11:28:14 +0000 Subject: [PATCH] Allow nested procedures to access `@(static)` and `@(thread_local)` variables --- src/check_expr.cpp | 6 ++++-- src/checker.cpp | 11 ++++++++--- src/llvm_backend.cpp | 32 +++++++++++++++++++++++--------- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 8e09c0320..ea460ce09 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1075,8 +1075,10 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ if (e->parent_proc_decl != nullptr && e->parent_proc_decl != c->curr_proc_decl) { if (e->kind == Entity_Variable) { - error(n, "Nested procedures do not capture its parent's variables: %.*s", LIT(name)); - return nullptr; + if ((e->flags & EntityFlag_Static) == 0) { + error(n, "Nested procedures do not capture its parent's variables: %.*s", LIT(name)); + return nullptr; + } } else if (e->kind == Entity_Label) { error(n, "Nested procedures do not capture its parent's labels: %.*s", LIT(name)); return nullptr; diff --git a/src/checker.cpp b/src/checker.cpp index 901f5439c..c1a107c15 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -368,9 +368,14 @@ void scope_lookup_parent(Scope *scope, String const &name, Scope **scope_, Entit if (e->kind == Entity_Label) { continue; } - if (e->kind == Entity_Variable && - !(e->scope->flags&ScopeFlag_File)) { - continue; + if (e->kind == Entity_Variable) { + if (e->scope->flags&ScopeFlag_File) { + // Global variables are file to access + } else if (e->flags&EntityFlag_Static) { + // Allow static/thread_local variables to be referenced + } else { + continue; + } } } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index b4edc4914..8063bdc8b 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -12875,6 +12875,7 @@ void lb_generate_code(lbGenerator *gen) { lbValue var; lbValue init; DeclInfo *decl; + bool is_initialized; }; auto global_variables = array_make(permanent_allocator(), 0, global_variable_max_count); @@ -12937,15 +12938,22 @@ void lb_generate_code(lbGenerator *gen) { var.var = g; var.decl = decl; - if (decl->init_expr != nullptr && !is_type_any(e->type)) { + if (decl->init_expr != nullptr) { TypeAndValue tav = type_and_value_of_expr(decl->init_expr); - if (tav.mode != Addressing_Invalid) { - if (tav.value.kind != ExactValue_Invalid) { - ExactValue v = tav.value; - lbValue init = lb_const_value(m, tav.type, v); - LLVMSetInitializer(g.value, init.value); + if (!is_type_any(e->type)) { + if (tav.mode != Addressing_Invalid) { + if (tav.value.kind != ExactValue_Invalid) { + ExactValue v = tav.value; + lbValue init = lb_const_value(m, tav.type, v); + LLVMSetInitializer(g.value, init.value); + var.is_initialized = true; + } } } + if (!var.is_initialized && + (is_type_untyped_nil(tav.type) || is_type_untyped_undef(tav.type))) { + var.is_initialized = true; + } } array_add(&global_variables, var); @@ -13146,10 +13154,13 @@ void lb_generate_code(lbGenerator *gen) { auto *var = &global_variables[i]; if (var->decl->init_expr != nullptr) { lbValue init = lb_build_expr(p, var->decl->init_expr); - if (!lb_is_const(init)) { - var->init = init; + if (lb_is_const(init)) { + if (!var->is_initialized) { + LLVMSetInitializer(var->var.value, init.value); + var->is_initialized = true; + } } else { - LLVMSetInitializer(var->var.value, init.value); + var->init = init; } } @@ -13166,6 +13177,7 @@ void lb_generate_code(lbGenerator *gen) { } if (var->init.value != nullptr) { + GB_ASSERT(!var->is_initialized); Type *t = type_deref(var->var.type); if (is_type_any(t)) { @@ -13182,6 +13194,8 @@ void lb_generate_code(lbGenerator *gen) { } else { lb_emit_store(p, var->var, lb_emit_conv(p, var->init, t)); } + + var->is_initialized = true; } }