From 5a4d04c3c01deee42f77cfa117c7ec62d696d6eb Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Fri, 5 Aug 2022 20:49:26 +0100 Subject: [PATCH] Some constant expressions are not fully folded --- src/dump.c | 2 +- src/elab.c | 2 +- src/object.c | 43 +++++++++++++++++++++++++++-------------- test/bounds/bounds2.vhd | 4 ++-- test/elab/comp4.vhd | 23 ++++++++++++++++++++++ test/test_elab.c | 22 +++++++++++++++++++++ 6 files changed, 78 insertions(+), 18 deletions(-) create mode 100644 test/elab/comp4.vhd diff --git a/src/dump.c b/src/dump.c index c39ac565..731e1fd2 100644 --- a/src/dump.c +++ b/src/dump.c @@ -932,7 +932,7 @@ static void dump_stmt(tree_t t, int indent) if (tree_has_ident(t)) { const char *label = istr(tree_ident(t)); - if (label[0] != 'l') // Skip generated labels + if (label[0] != '_') // Skip generated labels printf("%s: ", label); } diff --git a/src/elab.c b/src/elab.c index 4e188346..5e567dcb 100644 --- a/src/elab.c +++ b/src/elab.c @@ -1078,7 +1078,7 @@ static void elab_generics(tree_t entity, tree_t comp, tree_t inst, // generics that need to be folded if (map != NULL) { hash_put(ctx->generics, cg, tree_value(map)); - simplify_global(m, ctx->generics, ctx->eval); + cg = eg; } map = m; diff --git a/src/object.c b/src/object.c index 2110313b..b4e06000 100644 --- a/src/object.c +++ b/src/object.c @@ -597,6 +597,20 @@ void object_visit(object_t *object, object_visit_ctx_t *ctx) } } +static object_t *object_rewrite_iter(object_t *object, + object_rewrite_ctx_t *ctx) +{ + // The callback may return a new object or a pointer to an existing + // object in the same arena that that needs to be rewritten so + // iterate rewriting until we reach a fixed point + for (;;) { + object_t *new = (*ctx->post_fn[object->tag])(object, ctx->context); + if (new == object || new == NULL) + return new; + object = object_rewrite(new, ctx); + } +} + object_t *object_rewrite(object_t *object, object_rewrite_ctx_t *ctx) { if (object == NULL) @@ -623,8 +637,7 @@ object_t *object_rewrite(object_t *object, object_rewrite_ctx_t *ctx) if (ctx->post_fn[object->tag] != NULL) { if (ctx->pre_fn[object->tag] != NULL) (*ctx->pre_fn[object->tag])(object, ctx->context); - object_t *new = - (object_t *)(*ctx->post_fn[object->tag])(object, ctx->context); + object_t *new = object_rewrite_iter(object, ctx); object_write_barrier(object, new); return (ctx->cache[index] = new); } @@ -656,16 +669,20 @@ object_t *object_rewrite(object_t *object, object_rewrite_ctx_t *ctx) else if (ITEM_OBJECT & mask) { object_t *o = object->items[n].object; object->items[n].object = object_rewrite(o, ctx); + object_write_barrier(object, o); } else if (ITEM_OBJ_ARRAY & mask) { - // The callback may add new items to the array obj_array_t **a = &(object->items[n].obj_array); - if (*a != NULL) { + if (object->items[n].obj_array != NULL) { + // The callback may add new items to the array so the + // array pointer cannot be cached between iterations unsigned wptr = 0; - for (size_t i = 0; i < (*a)->count; i++) { - object_t *o = (*a)->items[i]; - if ((o = object_rewrite(o, ctx))) - (*a)->items[wptr++] = o; + for (size_t i = 0; i < object->items[n].obj_array->count; i++) { + object_t *o = object->items[n].obj_array->items[i]; + if ((o = object_rewrite(o, ctx))) { + object_write_barrier(object, o); + object->items[n].obj_array->items[wptr++] = o; + } } if (wptr == 0) @@ -690,17 +707,15 @@ object_t *object_rewrite(object_t *object, object_rewrite_ctx_t *ctx) if (ctx->cache[index] != (object_t *)-1) { // The cache was already updated due to a circular reference + return ctx->cache[index]; } else if (ctx->post_fn[object->tag] != NULL) { - object_t *new = - (object_t *)(*ctx->post_fn[object->tag])(object, ctx->context); + object_t *new = object_rewrite_iter(object, ctx); object_write_barrier(object, new); - ctx->cache[index] = new; + return (ctx->cache[index] = new); } else - ctx->cache[index] = object; - - return ctx->cache[index]; + return (ctx->cache[index] = object); } static void object_write_ref(object_t *object, fbuf_t *f) diff --git a/test/bounds/bounds2.vhd b/test/bounds/bounds2.vhd index ac349f28..a6c71996 100644 --- a/test/bounds/bounds2.vhd +++ b/test/bounds/bounds2.vhd @@ -21,8 +21,8 @@ begin wait; end process; - b6 <= true after -10 ns when true else false; - b7 <= true when true else false after -10 ns; + b6 <= true after -10 ns when now = 5 ns else false; + b7 <= true when now = 1 ns else false after -10 ns; end block; diff --git a/test/elab/comp4.vhd b/test/elab/comp4.vhd new file mode 100644 index 00000000..e2af1708 --- /dev/null +++ b/test/elab/comp4.vhd @@ -0,0 +1,23 @@ +entity sub is + generic ( g1 : integer; g2 : integer := g1 + 1 ); +end entity; + +architecture test of sub is +begin + p1: assert g2 = g1 + 1; +end architecture; + +------------------------------------------------------------------------------- + +entity comp4 is +end entity; + +architecture test of comp4 is + component sub is + generic ( g1 : integer; g2 : integer := g1 + 1 ); + end component; +begin + + u: component sub generic map ( 5 ); + +end architecture; diff --git a/test/test_elab.c b/test/test_elab.c index f3749cf1..9e2fa133 100644 --- a/test/test_elab.c +++ b/test/test_elab.c @@ -1156,6 +1156,27 @@ START_TEST(test_toplevel4) } END_TEST +START_TEST(test_comp4) +{ + set_standard(STD_08); + + input_from_file(TESTDIR "/elab/comp4.vhd"); + + tree_t e = run_elab(); + fail_if(e == NULL); + + tree_t b0 = tree_stmt(e, 0); + fail_unless(tree_ident(b0) == ident_new("COMP4")); + fail_unless(tree_stmts(b0) == 1); + + tree_t u = tree_stmt(b0, 0); + fail_unless(tree_ident(u) == ident_new("U")); + fail_unless(tree_stmts(u) == 0); + + fail_if_errors(); +} +END_TEST + Suite *get_elab_tests(void) { Suite *s = suite_create("elab"); @@ -1222,6 +1243,7 @@ Suite *get_elab_tests(void) tcase_add_test(tc, test_generate1); tcase_add_test(tc, test_neorv1); tcase_add_test(tc, test_toplevel4); + tcase_add_test(tc, test_comp4); suite_add_tcase(s, tc); return s; -- 2.39.2