Skip to content

Commit

Permalink
Fix crash when subtype bounds depend on package instance generic
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Dec 13, 2023
1 parent a8fcb82 commit 5634bac
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 24 deletions.
54 changes: 30 additions & 24 deletions src/lower.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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);
Expand Down
43 changes: 43 additions & 0 deletions test/regress/issue815.vhd
Original file line number Diff line number Diff line change
@@ -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;
1 change: 1 addition & 0 deletions test/regress/testlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -911,3 +911,4 @@ issue810 normal,2008
elab40 normal,2008
cmdline9 shell,slow
genpack16 normal,2008
issue815 normal,2019

0 comments on commit 5634bac

Please sign in to comment.