From 891fdf41a481e8d16bd0736b39e432d2b0f54128 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Fri, 29 Jul 2022 21:55:24 +0100 Subject: [PATCH] Improve handling of constants in generic package instances --- src/lower.c | 63 +++++++++++++++++++------------------- src/names.c | 5 +-- src/parse.c | 41 +++++++++++++------------ test/jit/issue496.vhd | 2 +- test/regress/genpack11.vhd | 41 +++++++++++++++++++++++++ test/regress/testlist.txt | 1 + test/test_jit.c | 3 ++ 7 files changed, 102 insertions(+), 54 deletions(-) create mode 100644 test/regress/genpack11.vhd diff --git a/src/lower.c b/src/lower.c index ce39bb10..351022b3 100644 --- a/src/lower.c +++ b/src/lower.c @@ -63,10 +63,12 @@ typedef enum { } short_circuit_op_t; typedef enum { - SCOPE_PACK_INST = (1 << 0), SCOPE_HAS_PROTECTED = (1 << 1), } scope_flags_t; +#define INSTANCE_BIT 0x80000000 +#define PARAM_VAR_BIT 0x40000000 + typedef A(vcode_var_t) var_list_t; struct lower_scope { @@ -116,7 +118,6 @@ typedef A(concat_param_t) concat_list_t; static lower_mode_t mode = LOWER_NORMAL; static lower_scope_t *top_scope = NULL; static cover_tagging_t *cover_tags = NULL; -static hash_t *globals = NULL; static vcode_reg_t lower_expr(tree_t expr, expr_ctx_t ctx); static vcode_reg_t lower_reify_expr(tree_t expr); @@ -2189,13 +2190,7 @@ static vcode_reg_t lower_link_var(tree_t decl) const tree_kind_t kind = tree_kind(container); vcode_reg_t context = VCODE_INVALID_REG; - if (kind == T_ELAB) { - ident_t name; - if ((name = hash_get(globals, decl)) == NULL) - fatal_trace("missing global variable for %s", istr(tree_ident(decl))); - context = emit_link_package(ident_runtil(name, '.')); - } - else if (kind != T_PACKAGE && kind != T_PACK_INST) + if (kind != T_PACKAGE && kind != T_PACK_INST) fatal_trace("invalid container kind %s for %s", tree_kind_str(kind), istr(tree_ident(decl))); else if (mode == LOWER_THUNK) @@ -2247,6 +2242,18 @@ static vcode_reg_t lower_var_ref(tree_t decl, expr_ctx_t ctx) else ptr_reg = lower_link_var(decl); // External variable } + else if (var & INSTANCE_BIT) { + // This variable is declared in an instantiated package + vcode_var_t pkg_var = var & ~INSTANCE_BIT; + vcode_reg_t pkg_reg; + if (hops == 0) + pkg_reg = emit_load(pkg_var); + else + pkg_reg = emit_load_indirect(emit_var_upref(hops, pkg_var)); + + vcode_type_t vtype = lower_var_type(decl); + ptr_reg = emit_link_var(pkg_reg, tree_ident(decl), vtype); + } else if (hops > 0) ptr_reg = emit_var_upref(hops, var); @@ -2358,18 +2365,15 @@ static vcode_reg_t lower_param_ref(tree_t decl, expr_ctx_t ctx) int hops = 0; int obj = lower_search_vcode_obj(decl, top_scope, &hops); - // TODO: remove this.... - const bool is_proc_var = - obj != VCODE_INVALID_VAR && !!(obj & 0x20000000); + const bool is_proc_var = (obj != -1 && !!(obj & PARAM_VAR_BIT)); + obj &= ~PARAM_VAR_BIT; if (hops > 0) { // Reference to parameter in parent subprogram - return emit_load_indirect(emit_var_upref(hops, obj & 0x1fffffff)); - } - else if (is_proc_var) { - vcode_var_t var = obj & 0x1fffffff; - return emit_load(var); + return emit_load_indirect(emit_var_upref(hops, obj)); } + else if (is_proc_var) + return emit_load(obj); else { vcode_reg_t reg = obj; const bool undefined_in_thunk = @@ -5426,7 +5430,7 @@ static void lower_for(tree_t stmt, loop_stack_t *loops) lower_put_vcode_obj(idecl, ireg, top_scope); } else - lower_put_vcode_obj(idecl, ivar | 0x20000000, top_scope); + lower_put_vcode_obj(idecl, ivar | PARAM_VAR_BIT, top_scope); if (exit_bb == VCODE_INVALID_BLOCK) exit_bb = emit_block(); @@ -6126,9 +6130,6 @@ static vcode_var_t lower_var_for(tree_t decl, vcode_type_t vtype, { ident_t name = tree_ident(decl); - if (top_scope->flags & SCOPE_PACK_INST) - hash_put(globals, decl, ident_prefix(vcode_unit_name(), name, '.')); - vcode_var_t var = emit_var(vtype, vbounds, name, flags); lower_put_vcode_obj(decl, var, top_scope); @@ -7189,7 +7190,6 @@ static void lower_instantiated_package(tree_t decl, vcode_unit_t context) vcode_unit_t vu = emit_package(name, tree_loc(decl), context); lower_push_scope(decl); - top_scope->flags |= SCOPE_PACK_INST; lower_generics(decl, NULL); lower_decls(decl, vu); @@ -7200,7 +7200,15 @@ static void lower_instantiated_package(tree_t decl, vcode_unit_t context) lower_finished(); vcode_state_restore(&state); - emit_package_init(name, emit_context_upref(0)); + vcode_type_t vcontext = vtype_context(name); + vcode_var_t var = emit_var(vcontext, vcontext, name, 0); + + vcode_reg_t pkg_reg = emit_package_init(name, emit_context_upref(0)); + emit_store(pkg_reg, var); + + const int ndecls = tree_decls(tree_ref(decl)); + for (int i = 0; i < ndecls; i++) + lower_put_vcode_obj(tree_decl(decl, i), var | INSTANCE_BIT, top_scope); } static void lower_decl(tree_t decl, vcode_unit_t context) @@ -7374,7 +7382,7 @@ static void lower_subprogram_ports(tree_t body, bool params_as_vars) if (params_as_vars) { vcode_var_t var = emit_var(vtype, vbounds, tree_ident(p), 0); emit_store(preg, var); - lower_put_vcode_obj(p, var | 0x20000000, top_scope); + lower_put_vcode_obj(p, var | PARAM_VAR_BIT, top_scope); } else lower_put_vcode_obj(p, preg, top_scope); @@ -9494,9 +9502,6 @@ vcode_unit_t lower_unit(tree_t unit, cover_tagging_t *cover) cover_tags = cover; mode = LOWER_NORMAL; - assert(globals == NULL); - globals = hash_new(128); - vcode_unit_t root = NULL; switch (tree_kind(unit)) { case T_ELAB: @@ -9516,9 +9521,6 @@ vcode_unit_t lower_unit(tree_t unit, cover_tagging_t *cover) tree_kind_str(tree_kind(unit))); } - hash_free(globals); - globals = NULL; - vcode_close(); return root; } @@ -9574,7 +9576,6 @@ static void lower_subprogram_for_thunk(tree_t body, vcode_unit_t context) vcode_unit_t lower_thunk(tree_t t) { mode = LOWER_THUNK; - assert(globals == NULL); ident_t name = NULL; if (is_subprogram(t)) { diff --git a/src/names.c b/src/names.c index ed192acd..8db0c83d 100644 --- a/src/names.c +++ b/src/names.c @@ -1002,8 +1002,9 @@ static scope_t *private_scope_for(nametab_t *tab, tree_t unit) else { // For package instances do not export the names declared only in // the body - const int ndecls = - tree_decls(kind == T_PACK_INST ? tree_ref(unit) : unit); + const int ndecls = kind == T_PACK_INST && tree_has_ref(unit) + ? tree_decls(tree_ref(unit)) + : tree_decls(unit); for (int i = 0; i < ndecls; i++) { tree_t d = tree_decl(unit, i); diff --git a/src/parse.c b/src/parse.c index 01662459..08c3d8df 100644 --- a/src/parse.c +++ b/src/parse.c @@ -64,9 +64,11 @@ typedef A(tree_t) tree_list_t; typedef A(type_t) type_list_t; typedef struct { + tree_t decl; + tree_t body; tree_list_t copied_subs; type_list_t copied_types; -} package_copy_ctx_t; +} instantiate_copy_ctx_t; typedef struct _ident_list ident_list_t; @@ -1874,12 +1876,12 @@ static tree_t fcall_to_conv_func(tree_t value) return conv; } -static bool package_should_copy_type(type_t type, void *__ctx) +static bool instantiate_should_copy_type(type_t type, void *__ctx) { return type_kind(type) == T_GENERIC; } -static bool package_should_copy_tree(tree_t t, void *__ctx) +static bool instantiate_should_copy_tree(tree_t t, void *__ctx) { switch (tree_kind(t)) { case T_FUNC_DECL: @@ -1911,17 +1913,17 @@ static bool package_should_copy_tree(tree_t t, void *__ctx) } } -static void package_tree_copy_cb(tree_t t, void *__ctx) +static void instantiate_tree_copy_cb(tree_t t, void *__ctx) { - package_copy_ctx_t *ctx = __ctx; + instantiate_copy_ctx_t *ctx = __ctx; if (is_subprogram(t)) APUSH(ctx->copied_subs, t); } -static void package_type_copy_cb(type_t type, void *__ctx) +static void instantiate_type_copy_cb(type_t type, void *__ctx) { - package_copy_ctx_t *ctx = __ctx; + instantiate_copy_ctx_t *ctx = __ctx; if (type_has_ident(type)) APUSH(ctx->copied_types, type); @@ -1929,25 +1931,26 @@ static void package_type_copy_cb(type_t type, void *__ctx) static void instantiate_helper(tree_t new, tree_t *pdecl, tree_t *pbody) { - package_copy_ctx_t copy_ctx = {}; - - tree_t decl = *pdecl, body = *pbody; + instantiate_copy_ctx_t copy_ctx = { + .decl = *pdecl, + .body = *pbody + }; SCOPED_A(tree_t) roots = AINIT; - APUSH(roots, decl); - if (body != NULL) - APUSH(roots, body); + APUSH(roots, copy_ctx.decl); + if (copy_ctx.body != NULL) + APUSH(roots, copy_ctx.body); tree_copy(roots.items, roots.count, - package_should_copy_tree, - package_should_copy_type, - package_tree_copy_cb, package_type_copy_cb, + instantiate_should_copy_tree, + instantiate_should_copy_type, + instantiate_tree_copy_cb, instantiate_type_copy_cb, ©_ctx); *pdecl = roots.items[0]; - *pbody = body != NULL ? roots.items[1] : NULL; + *pbody = copy_ctx.body != NULL ? roots.items[1] : NULL; - ident_t prefixes[] = { tree_ident(decl) }; + ident_t prefixes[] = { tree_ident(copy_ctx.decl) }; ident_t dotted = ident_prefix(scope_prefix(nametab), tree_ident(new), '.'); // Change the name of any copied types to reflect the new hiearchy @@ -2008,8 +2011,6 @@ static void instantiate_helper(tree_t new, tree_t *pdecl, tree_t *pbody) } } ACLEAR(copy_ctx.copied_subs); - - } static void instantiate_subprogram(tree_t new, tree_t decl, tree_t body) diff --git a/test/jit/issue496.vhd b/test/jit/issue496.vhd index 35e8f7be..6e029e0f 100644 --- a/test/jit/issue496.vhd +++ b/test/jit/issue496.vhd @@ -6,5 +6,5 @@ end package; package issue496 is constant one : string := "one"; package gen_one is new work.genpack generic map ( t => string, n => one ); - --constant c : string := gen_one.k; + constant c : string(1 to 3) := gen_one.k; end package; diff --git a/test/regress/genpack11.vhd b/test/regress/genpack11.vhd new file mode 100644 index 00000000..ed6968ff --- /dev/null +++ b/test/regress/genpack11.vhd @@ -0,0 +1,41 @@ +package pack is generic ( x : string := "foo" ) ; + constant s : string := x ; +end package ; + +------------------------------------------------------------------------------- + +package pack2 is + function get_str return string; +end package ; + +package body pack2 is + package pack3 is new work.pack generic map (x => "bar") ; + + use pack3.all; + + function get_str return string is + begin + return pack3.s; + end function; + +end package body ; + +------------------------------------------------------------------------------- + +entity genpack11 is +end entity; + +use work.pack2.all; + +architecture test of genpack11 is + signal s : string(1 to 3) := "bar"; +begin + + p1: process is + begin + assert get_str = "bar"; + assert get_str = s; + wait; + end process; + +end architecture; diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index 9419aaa5..3832b0e9 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -635,3 +635,4 @@ issue494 fail,gold record36 normal,2008 issue497 normal,2008 implicit4 normal +genpack11 normal,2008 diff --git a/test/test_jit.c b/test/test_jit.c index 26866d25..d805fcc0 100644 --- a/test/test_jit.c +++ b/test/test_jit.c @@ -920,6 +920,9 @@ START_TEST(test_issue496) void *pkg = jit_link(j, handle); fail_if(pkg == NULL); + char *c = jit_get_frame_var(j, handle, 2); + ck_assert_mem_eq(c, "one", 3); + jit_free(j); fail_if_errors(); } -- 2.39.2