From 696495d1137d92327fca86d6444af1589a3172d3 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 2 Mar 2024 11:59:47 +0000 Subject: [PATCH] Fix crash when view element indication references whole record Fixes #854 --- NEWS.md | 1 + src/lower.c | 76 ++++++++++++++++++++------------------- test/regress/issue854.vhd | 47 ++++++++++++++++++++++++ test/regress/testlist.txt | 1 + 4 files changed, 89 insertions(+), 36 deletions(-) create mode 100644 test/regress/issue854.vhd diff --git a/NEWS.md b/NEWS.md index c3ed0a76..95b29d4b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -18,6 +18,7 @@ results in a non-zero exit code (#850). - Improvements to waveform dumping for signals with record types or types with non-locally-static bounds (#851, #852). +- Resolved several other minor issues (#654, #854). ## Version 1.11.3 - 2024-02-04 - Fixed incorrect effective value when a signal has multiple sources due diff --git a/src/lower.c b/src/lower.c index 386825a1..2da3c233 100644 --- a/src/lower.c +++ b/src/lower.c @@ -11572,6 +11572,41 @@ static ident_t lower_converter(lower_unit_t *parent, tree_t expr, return name; } +static void lower_map_signal_field_cb(lower_unit_t *lu, tree_t field, + vcode_reg_t src_ptr, vcode_reg_t dst_ptr, + vcode_reg_t locus, void *ctx) +{ + type_t ftype = tree_type(field); + + if (type_is_homogeneous(ftype)) { + vcode_reg_t dst_reg = emit_load_indirect(dst_ptr); + + vcode_reg_t src_reg; + if (lower_have_signal(src_ptr)) + src_reg = emit_load_indirect(src_ptr); + else if (have_uarray_ptr(src_ptr)) + src_reg = emit_load_indirect(src_ptr); + else + src_reg = src_ptr; + + if (type_is_array(ftype)) + lower_check_array_sizes(lu, ftype, ftype, src_reg, dst_reg, locus); + + vcode_reg_t count_reg = lower_type_width(lu, ftype, dst_reg); + + src_reg = lower_array_data(src_reg); + dst_reg = lower_array_data(dst_reg); + + if (lower_have_signal(src_reg)) + emit_map_signal(src_reg, dst_reg, count_reg); + else + emit_map_const(src_reg, dst_reg, count_reg); + } + else + lower_for_each_field(lu, ftype, src_ptr, dst_ptr, locus, + lower_map_signal_field_cb, ctx); +} + static void lower_map_view_field_cb(lower_unit_t *lu, tree_t field, vcode_reg_t src_ptr, vcode_reg_t dst_ptr, vcode_reg_t locus, void *__ctx) @@ -11608,48 +11643,17 @@ static void lower_map_view_field_cb(lower_unit_t *lu, tree_t field, fatal_trace("unhandled port mode in lower_map_view_field_cb"); } } - else { - assert(tree_subkind(elem) == PORT_RECORD_VIEW); - + else if (tree_subkind(elem) == PORT_RECORD_VIEW) { void *new_ctx = tag_pointer(tree_value(elem), converse); lower_for_each_field(lu, ftype, src_ptr, dst_ptr, locus, lower_map_view_field_cb, new_ctx); } -} - -static void lower_map_signal_field_cb(lower_unit_t *lu, tree_t field, - vcode_reg_t src_ptr, vcode_reg_t dst_ptr, - vcode_reg_t locus, void *ctx) -{ - type_t ftype = tree_type(field); - - if (type_is_homogeneous(ftype)) { - vcode_reg_t dst_reg = emit_load_indirect(dst_ptr); - - vcode_reg_t src_reg; - if (lower_have_signal(src_ptr)) - src_reg = emit_load_indirect(src_ptr); - else if (have_uarray_ptr(src_ptr)) - src_reg = emit_load_indirect(src_ptr); - else - src_reg = src_ptr; - - if (type_is_array(ftype)) - lower_check_array_sizes(lu, ftype, ftype, src_reg, dst_reg, locus); - - vcode_reg_t count_reg = lower_type_width(lu, ftype, dst_reg); - - src_reg = lower_array_data(src_reg); - dst_reg = lower_array_data(dst_reg); - - if (lower_have_signal(src_reg)) - emit_map_signal(src_reg, dst_reg, count_reg); - else - emit_map_const(src_reg, dst_reg, count_reg); - } + else if (converse) + lower_for_each_field(lu, ftype, dst_ptr, src_ptr, locus, + lower_map_signal_field_cb, NULL); else lower_for_each_field(lu, ftype, src_ptr, dst_ptr, locus, - lower_map_signal_field_cb, ctx); + lower_map_signal_field_cb, NULL); } static void lower_map_signal(lower_unit_t *lu, vcode_reg_t src_reg, diff --git a/test/regress/issue854.vhd b/test/regress/issue854.vhd new file mode 100644 index 00000000..5f9318a6 --- /dev/null +++ b/test/regress/issue854.vhd @@ -0,0 +1,47 @@ +entity issue854 is +end entity; + +architecture test of issue854 is + type t_rec1 is record + f : integer; + end record; + + type t_rec2 is record + a : integer; + b : t_rec1; + end record; + + view t_rec2_view of t_rec2 is + a : in; + b : out; + end view; + + signal s1, s2 : t_rec2; +begin + + b1: block is + port ( p : view t_rec2_view); + port map ( s1 ); + begin + p.b.f <= p.a + 1; + end block; + + b2: block is + port ( p : view t_rec2_view'converse); + port map ( s2 ); + begin + p.a <= p.b.f * 2; + end block; + + check: process is + begin + s1.a <= 1; + s2.b.f <= 5; + wait for 0 ns; + wait for 0 ns; + assert s1.b.f = 2; + assert s2.a = 10; + wait; + end process; + +end architecture; diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index 196292ee..b2261d87 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -951,3 +951,4 @@ issue852 wave,2019,dump-arrays wave11 wave,2008,dump-arrays vlog9 verilog issue654 normal,2008 +issue854 normal,2019 -- 2.39.2