From 16d345b1b0463574ff7baad7df662254f168031a Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Tue, 18 Oct 2022 22:29:16 +0100 Subject: [PATCH] Incorrect copying of record initial value. Fixes #549 --- src/lower.c | 40 ++++++++++++++++++++++++++++------- test/regress/issue549.vhd | 44 +++++++++++++++++++++++++++++++++++++++ test/regress/testlist.txt | 1 + test/test_lower.c | 3 --- 4 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 test/regress/issue549.vhd diff --git a/src/lower.c b/src/lower.c index 88839e0d..6e075467 100644 --- a/src/lower.c +++ b/src/lower.c @@ -4393,8 +4393,11 @@ static vcode_reg_t lower_default_value(type_t type, vcode_reg_t hint_reg, const int nfields = type_fields(type); vcode_type_t vtype = lower_type(type); - vcode_var_t tmp_var = lower_temp_var("def", vtype, vtype); - vcode_reg_t mem_reg = emit_index(tmp_var, VCODE_INVALID_REG); + vcode_reg_t mem_reg = hint_reg; + if (hint_reg == VCODE_INVALID_REG) { + vcode_var_t tmp_var = lower_temp_var("def", vtype, vtype); + mem_reg = emit_index(tmp_var, VCODE_INVALID_REG); + } tree_t rcon = shift_constraints(&cons, &ncons, 1); assert(ncons == 0); // Cannot have more constraints following record @@ -4843,15 +4846,33 @@ static void lower_copy_record_cb(type_t ftype, vcode_reg_t dst_ptr, if (lower_have_uarray_ptr(src_reg)) src_reg = emit_load_indirect(src_ptr); + vcode_reg_t count_reg = lower_array_total_len(ftype, src_reg); + vcode_reg_t dst_reg = dst_ptr; - if (lower_have_uarray_ptr(dst_reg)) - dst_reg = emit_load_indirect(dst_ptr); + if (where == NULL) { + // Initialising a variable, need to allocate an array of the + // correct length + if (lower_have_uarray_ptr(dst_reg)) { + type_t scalar_elem = lower_elem_recur(ftype); + vcode_type_t vtype = lower_type(scalar_elem); + vcode_type_t vbounds = lower_bounds(scalar_elem); + vcode_reg_t mem_reg = emit_alloc(vtype, vbounds, count_reg); + vcode_reg_t wrap_reg = lower_rewrap(mem_reg, src_reg); - lower_check_array_sizes(where, ftype, ftype, dst_reg, src_reg); + emit_store_indirect(wrap_reg, dst_ptr); + dst_reg = wrap_reg; + } + } + else { + // Overwriting an existing array, check the length + if (lower_have_uarray_ptr(dst_reg)) + dst_reg = emit_load_indirect(dst_ptr); + + lower_check_array_sizes(where, ftype, ftype, dst_reg, src_reg); + } vcode_reg_t src_data = lower_array_data(src_reg); vcode_reg_t dst_data = lower_array_data(dst_reg); - vcode_reg_t count_reg = lower_array_total_len(ftype, dst_reg); emit_copy(dst_data, src_data, count_reg); } else if (type_is_record(ftype)) { @@ -6414,7 +6435,12 @@ static void lower_var_decl(tree_t decl) } } else if (type_is_record(type)) { - emit_copy(dest_reg, value_reg, VCODE_INVALID_REG); + if (value_reg != dest_reg && !lower_const_bounds(type)) { + // We need to allocate memory for some of the fields + lower_copy_record(type, dest_reg, value_reg, NULL); + } + else + emit_copy(dest_reg, value_reg, VCODE_INVALID_REG); } else if (type_is_scalar(type)) { lower_check_scalar_bounds(value_reg, type, decl, decl); diff --git a/test/regress/issue549.vhd b/test/regress/issue549.vhd new file mode 100644 index 00000000..14283a44 --- /dev/null +++ b/test/regress/issue549.vhd @@ -0,0 +1,44 @@ +package pack is + constant C : integer; + + type rec is record + x : integer; + y : bit_vector(1 to C); + end record; + +end package; + +package body pack is + constant C : integer := 4; +end package body; + +------------------------------------------------------------------------------- + +entity issue549 is +end entity; + +use work.pack.all; + +architecture test of issue549 is + + constant def : rec := (x => 0, y => "0000"); + + procedure modify (variable arg : inout rec) is + begin + arg.y(1) := '1'; + end procedure; + + procedure test (arg : in rec) is + variable copy : rec := def; + begin + copy.y := arg.y; + modify(copy); + assert def.y = "0000"; + assert copy.y = "1110"; + end procedure; + +begin + + p1: test((x => 1, y => "0110")); + +end architecture; diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index f39a62a4..2b8ea4a5 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -683,3 +683,4 @@ ename4 normal,2008 genpack12 normal,2008 wave8 shell signal28 normal,relaxed +issue549 normal diff --git a/test/test_lower.c b/test/test_lower.c index 050b8eb0..50b77ef9 100644 --- a/test/test_lower.c +++ b/test/test_lower.c @@ -4607,7 +4607,6 @@ START_TEST(test_vunit5) EXPECT_BB(0) = { { VCODE_OP_INDEX, .name = "R" }, - { VCODE_OP_INDEX, .name = "*def" }, { VCODE_OP_RECORD_REF, .field = 0 }, { VCODE_OP_UARRAY_LEN }, { VCODE_OP_CAST }, @@ -4624,8 +4623,6 @@ START_TEST(test_vunit5) { VCODE_OP_MEMSET }, { VCODE_OP_WRAP }, { VCODE_OP_STORE_INDIRECT }, - { VCODE_OP_COPY }, - { VCODE_OP_RECORD_REF, .field = 0 }, { VCODE_OP_LOAD_INDIRECT }, { VCODE_OP_UARRAY_LEN }, { VCODE_OP_UNWRAP }, -- 2.39.2