From 6fb27d41ea55deb2bc245d044b14b0a5d5aee4ea Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 19 Nov 2022 09:49:40 +0000 Subject: [PATCH] Calls to IEEE functions are locally static in -2008. Issue #574 --- src/common.c | 5 +++++ src/common.h | 4 ++++ src/eval.c | 6 ++++-- src/nvc.c | 2 +- src/sem.c | 30 ++++++++++++++++++++++++++++-- src/simp.c | 4 +--- test/simp/issue574.vhd | 12 ++++++++++++ test/test_simp.c | 24 ++++++++++++++++++++++++ test/test_util.c | 4 ++-- 9 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 test/simp/issue574.vhd diff --git a/src/common.c b/src/common.c index 7e2436fd..78565e9f 100644 --- a/src/common.c +++ b/src/common.c @@ -998,11 +998,16 @@ void intern_strings(void) id_cache[W_ERROR] = ident_new("error"); id_cache[W_CCONV] = ident_new("\"??\""); id_cache[W_ELAB] = ident_new("elab"); + id_cache[W_NUMERIC_STD] = ident_new("IEEE.NUMERIC_STD"); + id_cache[W_NUMERIC_BIT] = ident_new("IEEE.NUMERIC_BIT"); id_cache[W_IEEE_LOGIC_VECTOR] = ident_new("IEEE.STD_LOGIC_1164.STD_LOGIC_VECTOR"); id_cache[W_IEEE_ULOGIC_VECTOR] = ident_new("IEEE.STD_LOGIC_1164.STD_ULOGIC_VECTOR"); + + id_cache[W_NUMERIC_STD_UNSIGNED] = ident_new("IEEE.NUMERIC_STD_UNSIGNED"); + id_cache[W_NUMERIC_BIT_UNSIGNED] = ident_new("IEEE.NUMERIC_BIT_UNSIGNED"); } bool is_uninstantiated_package(tree_t pack) diff --git a/src/common.h b/src/common.h index 1fbae4da..56ace168 100644 --- a/src/common.h +++ b/src/common.h @@ -189,6 +189,10 @@ typedef enum { W_ERROR, W_CCONV, W_ELAB, + W_NUMERIC_STD, + W_NUMERIC_BIT, + W_NUMERIC_STD_UNSIGNED, + W_NUMERIC_BIT_UNSIGNED, NUM_WELL_KNOWN } well_known_t; diff --git a/src/eval.c b/src/eval.c index 8b6f4217..08556aca 100644 --- a/src/eval.c +++ b/src/eval.c @@ -188,6 +188,10 @@ bool eval_possible(eval_t *e, tree_t t) switch (tree_kind(t)) { case T_FCALL: { + const tree_flags_t flags = tree_flags(t); + if (!(flags & (TREE_F_LOCALLY_STATIC | TREE_F_GLOBALLY_STATIC))) + return eval_not_possible(e, t, "non-static expression"); + tree_t decl = tree_ref(t); const subprogram_kind_t kind = tree_subkind(decl); if (kind == S_USER && !(e->flags & EVAL_FCALL)) @@ -196,8 +200,6 @@ bool eval_possible(eval_t *e, tree_t t) return eval_not_possible(e, t, "call to foreign function"); else if (tree_flags(decl) & TREE_F_IMPURE) return eval_not_possible(e, t, "call to impure function"); - else if (!(tree_flags(t) & TREE_F_GLOBALLY_STATIC)) - return eval_not_possible(e, t, "non-static expression"); else if (kind != S_USER && !is_open_coded_builtin(kind) && vcode_find_unit(tree_ident2(decl)) == NULL) return eval_not_possible(e, t, "not yet lowered predef"); diff --git a/src/nvc.c b/src/nvc.c index 4043f1c4..37a57985 100644 --- a/src/nvc.c +++ b/src/nvc.c @@ -152,7 +152,7 @@ static int analyse(int argc, char **argv) } lib_t work = lib_work(); - eval_t *eval = eval_new(0); + eval_t *eval = eval_new(EVAL_FCALL); for (int i = optind; i < next_cmd; i++) { input_from_file(argv[i]); diff --git a/src/sem.c b/src/sem.c index 774d0938..f0bbf1b0 100644 --- a/src/sem.c +++ b/src/sem.c @@ -4255,6 +4255,28 @@ static bool sem_static_subtype(type_t type, static_fn_t fn) } } +static bool sem_ieee_locally_static(tree_t decl) +{ + // Subprograms definined in certain IEEE packages are treated the + // same as builtin operators in VHDL-2008 + + if (standard() < STD_08) + return false; + + ident_t unit_name = tree_ident(tree_container(decl)); + + switch (is_well_known(unit_name)) { + case W_NUMERIC_STD: + case W_NUMERIC_BIT: + case W_IEEE_1164: + case W_NUMERIC_BIT_UNSIGNED: + case W_NUMERIC_STD_UNSIGNED: + return true; + default: + return false; + } +} + static bool sem_locally_static(tree_t t) { // Rules for locally static expressions are in LRM 93 7.4.1 @@ -4319,7 +4341,10 @@ static bool sem_locally_static(tree_t t) } } - // A function call of an implicit operator with locally static actuals + // A function call of an implicit operator or [2008] an operation + // defined in one of the packages STD_LOGIC_1164, NUMERIC_BIT, + // NUMERIC_STD, NUMERIC_BIT_UNSIGNED, or NUMERIC_STD_UNSIGNED in + // library IEEE whose actuals are locally static expressions. if (kind == T_FCALL) { if (!tree_has_ref(t)) return true; // Suppress further errors @@ -4329,7 +4354,8 @@ static bool sem_locally_static(tree_t t) tree_t decl = tree_ref(t); if (tree_kind(decl) == T_GENERIC_DECL) return false; // Not known at this point - else if (!is_builtin(tree_subkind(decl))) + else if (!is_builtin(tree_subkind(decl)) + && !sem_ieee_locally_static(decl)) return false; const int nparams = tree_params(t); diff --git a/src/simp.c b/src/simp.c index 497c2d52..bf16129a 100644 --- a/src/simp.c +++ b/src/simp.c @@ -165,9 +165,7 @@ static tree_t simp_fold(tree_t t, simp_ctx_t *ctx) else if (!eval_possible(ctx->eval, t)) return t; - tree_t folded = eval_try_fold(ctx->eval, t); - - return folded; + return eval_try_fold(ctx->eval, t); } static void simp_generic_subprogram(tree_t t, simp_ctx_t *ctx) diff --git a/test/simp/issue574.vhd b/test/simp/issue574.vhd new file mode 100644 index 00000000..d77f16cd --- /dev/null +++ b/test/simp/issue574.vhd @@ -0,0 +1,12 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package test is + type t_memory_map_array is array (natural range 0 to 10) of natural; + constant C_VER : unsigned(4 downto 0) := "00001"; + constant C_MEMORY_MAP_ITEM_DEFAULT : natural := 0; + constant C_MEMORY_MAP_DEFAULT : t_memory_map_array := ( + to_integer(C_VER) => 1, + others => C_MEMORY_MAP_ITEM_DEFAULT); +end package; diff --git a/test/test_simp.c b/test/test_simp.c index 2ad52b42..c38f0427 100644 --- a/test/test_simp.c +++ b/test/test_simp.c @@ -1380,6 +1380,29 @@ START_TEST(test_casefold1) } END_TEST +START_TEST(test_issue574) +{ + set_standard(STD_08); + + input_from_file(TESTDIR "/simp/issue574.vhd"); + + tree_t p = parse_check_and_simplify(T_PACKAGE); + + tree_t d = search_decls(p, ident_new("C_MEMORY_MAP_DEFAULT"), 0); + fail_if(d == NULL); + + tree_t agg = tree_value(d); + fail_unless(tree_kind(agg) == T_AGGREGATE); + + tree_t n0 = tree_name(tree_assoc(agg, 0)); + fail_unless(tree_kind(n0) == T_LITERAL); + fail_unless(tree_subkind(n0) == L_INT); + fail_unless(tree_ival(n0) == 1); + + fail_if_errors(); +} +END_TEST + Suite *get_simp_tests(void) { Suite *s = suite_create("simplify"); @@ -1434,6 +1457,7 @@ Suite *get_simp_tests(void) tcase_add_test(tc_core, test_issue496); tcase_add_test(tc_core, test_genpack1); tcase_add_test(tc_core, test_casefold1); + tcase_add_test(tc_core, test_issue574); suite_add_tcase(s, tc_core); return s; diff --git a/test/test_util.c b/test/test_util.c index cfde3735..06ce8f4e 100644 --- a/test/test_util.c +++ b/test/test_util.c @@ -141,7 +141,7 @@ TCase *nvc_unit_test(void) tree_t run_elab(void) { - eval_t *eval = eval_new(0); + eval_t *eval = eval_new(EVAL_FCALL); tree_t t, last_ent = NULL; while ((t = parse())) { @@ -168,7 +168,7 @@ tree_t run_elab(void) tree_t _parse_and_check(const tree_kind_t *array, int num, bool simp, bool lower) { - eval_t *eval = simp ? eval_new(0) : NULL; + eval_t *eval = simp ? eval_new(EVAL_FCALL) : NULL; tree_t last = NULL; for (int i = 0; i < num; i++) { -- 2.39.2