From 2025713e16a993c5cc6ac9836ff715ab72ef6a4d Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Wed, 13 Dec 2023 22:31:38 +0000 Subject: [PATCH] Fix crash when subtype bounds depend on package instance generic Fixes #815 --- src/lower.c | 54 ++++++++++++++++++++++----------------- test/regress/issue815.vhd | 43 +++++++++++++++++++++++++++++++ test/regress/testlist.txt | 1 + 3 files changed, 74 insertions(+), 24 deletions(-) create mode 100644 test/regress/issue815.vhd diff --git a/src/lower.c b/src/lower.c index de217376..40220f98 100644 --- a/src/lower.c +++ b/src/lower.c @@ -160,6 +160,7 @@ static void lower_check_indexes(lower_unit_t *lu, type_t from, type_t to, vcode_reg_t array, tree_t where); static vcode_reg_t lower_conversion(lower_unit_t *lu, vcode_reg_t value_reg, tree_t where, type_t from, type_t to); +static vcode_reg_t lower_get_type_bounds(lower_unit_t *lu, type_t type); typedef vcode_reg_t (*lower_signal_flag_fn_t)(vcode_reg_t, vcode_reg_t); typedef vcode_reg_t (*arith_fn_t)(vcode_reg_t, vcode_reg_t); @@ -479,20 +480,22 @@ static vcode_reg_t lower_array_len(lower_unit_t *lu, type_t type, int dim, { assert(type_is_array(type)); - if (have_array_metadata(type, reg)) - return emit_uarray_len(reg, dim); - else { + if (type_const_bounds(type)) { tree_t r = range_of(type, dim); int64_t low, high; - if (folded_bounds(r, &low, &high)) - return emit_const(vtype_offset(), MAX(high - low + 1, 0)); + if (!folded_bounds(r, &low, &high)) + fatal_trace("type %s bounds not constant", type_pp(type)); - vcode_reg_t left_reg = lower_range_left(lu, r); - vcode_reg_t right_reg = lower_range_right(lu, r); - vcode_reg_t dir_reg = lower_range_dir(lu, r); - - return emit_range_length(left_reg, right_reg, dir_reg); + return emit_const(vtype_offset(), MAX(high - low + 1, 0)); + } + else if (reg != VCODE_INVALID_REG + // TODO: fix lower_default_value to not pass garbage + && vcode_reg_kind(reg) == VCODE_TYPE_UARRAY) + return emit_uarray_len(reg, dim); + else { + vcode_reg_t bounds_reg = lower_get_type_bounds(lu, type); + return emit_uarray_len(bounds_reg, dim); } } @@ -526,6 +529,8 @@ static vcode_reg_t lower_array_stride(lower_unit_t *lu, type_t type, if (folded_bounds(r, &low, &high)) len_reg = emit_const(vtype_offset(), MAX(high - low + 1, 0)); + // TODO: this should use lower_get_type_bounds + vcode_reg_t left_reg = lower_range_left(lu, r); vcode_reg_t right_reg = lower_range_right(lu, r); vcode_reg_t dir_reg = lower_range_dir(lu, r); @@ -2725,6 +2730,8 @@ static vcode_var_t lower_get_var(lower_unit_t *lu, tree_t decl, int *hops) static vcode_reg_t lower_get_type_bounds(lower_unit_t *lu, type_t type) { + assert(!type_is_unconstrained(type)); + if (type_is_record(type)) return VCODE_INVALID_REG; // TODO else if (type_has_ident(type)) { @@ -2859,22 +2866,21 @@ static vcode_reg_t lower_signal_ref(lower_unit_t *lu, tree_t decl) vcode_var_t var = lower_search_vcode_obj(decl, lu, &hops); vcode_reg_t ptr_reg; - if (var == VCODE_INVALID_VAR || (var & INSTANCE_BIT)) { + if (var == VCODE_INVALID_VAR) { // Link to external package signal - if (var == VCODE_INVALID_VAR) - ptr_reg = lower_link_var(lu, decl); - else { - // This signal 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)); + ptr_reg = lower_link_var(lu, decl); + } + else if (var & INSTANCE_BIT) { + // This signal 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_signal_type(tree_type(decl)); - ptr_reg = emit_link_var(pkg_reg, tree_ident(decl), vtype); - } + vcode_type_t vtype = lower_signal_type(tree_type(decl)); + ptr_reg = emit_link_var(pkg_reg, tree_ident(decl), vtype); } else if (hops == 0 && vtype_is_scalar(vcode_var_type(var))) return emit_load(var); diff --git a/test/regress/issue815.vhd b/test/regress/issue815.vhd new file mode 100644 index 00000000..d6935bc8 --- /dev/null +++ b/test/regress/issue815.vhd @@ -0,0 +1,43 @@ +package bar is + function gen_baz(l: positive) return bit_vector; +end; + +package body bar is + function gen_baz(l: positive) return bit_vector is begin + return 10X"240"; + end; +end; + +package qux is + generic ( + X: positive; + BAZ: bit_vector := work.bar.gen_baz(X) + ); + + subtype baz_t is bit_vector(BAZ'high downto BAZ'low); + + function get_qux(state: baz_t) return baz_t; +end; + +package body qux is + function get_qux(state: baz_t) return baz_t is begin + return 10D"501"; + end; +end; + +entity issue815 is end; + +architecture test of issue815 is + package pkg is new work.qux generic map (X => 10); + signal s0: pkg.baz_t; +begin + process begin + s0 <= pkg.baz_t'value(10D"500"); + wait for 0 ns; + assert s0 = "0111110100"; + s0 <= pkg.get_qux(s0); + wait for 0 ns; + assert s0 = "0111110101"; + wait; + end process; +end; diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index 8b3f6f50..a6d1acf3 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -911,3 +911,4 @@ issue810 normal,2008 elab40 normal,2008 cmdline9 shell,slow genpack16 normal,2008 +issue815 normal,2019 -- 2.39.2