From 3565f6d85b745e3990acd73ecdc3170125348557 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Wed, 13 Dec 2023 21:37:14 +0000 Subject: [PATCH] Correct 'VALUE behaviour for arrays of character literals --- lib/nvc/text_util-body.vhd | 20 +++++++++++++++++++- lib/nvc/text_util.vhd | 3 +-- src/lower.c | 34 +++++++++++++++------------------- src/object.c | 2 +- test/regress/value2.vhd | 4 ++-- test/regress/value4.vhd | 2 +- test/test_jit.c | 4 ++-- 7 files changed, 41 insertions(+), 28 deletions(-) diff --git a/lib/nvc/text_util-body.vhd b/lib/nvc/text_util-body.vhd index 61961bea..4c8ff978 100644 --- a/lib/nvc/text_util-body.vhd +++ b/lib/nvc/text_util-body.vhd @@ -84,6 +84,24 @@ package body text_util is severity failure; end function; + procedure trim_ws (s : in string; first, last : out natural) is + constant len : integer := s'length; + alias ss : string(1 to len) is s; + begin + for i in 1 to len loop + first := i - 1; + if ss(i) /= ' ' then + exit; + end if; + end loop; + for i in len downto 1 loop + last := i - 1; + if ss(i) /= ' ' then + exit; + end if; + end loop; + end procedure; + function find_quote (s : string) return natural is constant len : integer := s'length; alias ss : string(1 to len) is s; @@ -128,7 +146,7 @@ package body text_util is procedure report_bad_char (s : string; c : character) is begin report "invalid character " & character'image(c) - & " in string " & s severity failure; + & " in string """ & s & """" severity failure; end procedure; function toupper (x : in character) return character is diff --git a/lib/nvc/text_util.vhd b/lib/nvc/text_util.vhd index 598e7346..d4ec9b7b 100644 --- a/lib/nvc/text_util.vhd +++ b/lib/nvc/text_util.vhd @@ -43,9 +43,8 @@ package text_util is -- Used to implement 'VALUE for composite types function next_delimiter (s : string; pos : natural) return string; function count_delimiters (s : string) return natural; + procedure trim_ws (s : in string; first, last : out natural); function find_open (s : string) return natural; - function find_quote (s : string) return natural; procedure find_close (s : string; pos : natural); - function find_unquote (s : string; pos : natural) return natural; procedure report_bad_char (s : string; c : character); end package; diff --git a/src/lower.c b/src/lower.c index 37caef75..de217376 100644 --- a/src/lower.c +++ b/src/lower.c @@ -9130,7 +9130,9 @@ static void lower_array_value_helper(lower_unit_t *lu, type_t type, vcode_type_t voffset = vtype_offset(); vcode_type_t ctype = vtype_char(); vcode_type_t strtype = vtype_uarray(1, ctype, ctype); - vcode_type_t vnat = vtype_int(0, INT64_MAX); + + // TODO: this should not be called before 2019 + vcode_type_t vnat = vtype_int(0, standard() < STD_19 ? INT32_MAX : INT64_MAX); vcode_reg_t locus = lower_debug_locus(decl); @@ -9142,9 +9144,8 @@ static void lower_array_value_helper(lower_unit_t *lu, type_t type, ident_t next_delim_fn = ident_new("NVC.TEXT_UTIL.NEXT_DELIMITER(SN)S"); ident_t count_delim_fn = ident_new("NVC.TEXT_UTIL.COUNT_DELIMITERS(S)N"); + ident_t trim_ws_fn = ident_new("NVC.TEXT_UTIL.TRIM_WS(SNN)"); ident_t find_open_fn = ident_new("NVC.TEXT_UTIL.FIND_OPEN(S)N"); - ident_t find_quote_fn = ident_new("NVC.TEXT_UTIL.FIND_QUOTE(S)N"); - ident_t find_unquote_fn = ident_new("NVC.TEXT_UTIL.FIND_UNQUOTE(SN)N"); ident_t find_close_fn = ident_new("NVC.TEXT_UTIL.FIND_CLOSE(SN)"); ident_t bad_char_fn = ident_new("NVC.TEXT_UTIL.REPORT_BAD_CHAR(SC)"); vcode_reg_t text_util_reg = lower_context_for_call(lu, next_delim_fn); @@ -9154,35 +9155,30 @@ static void lower_array_value_helper(lower_unit_t *lu, type_t type, vcode_type_t vbounds = lower_bounds(elem); if (type_is_character_array(type)) { - vcode_block_t quote_bb = emit_block(); vcode_block_t body_bb = emit_block(); vcode_block_t bad_bb = emit_block(); vcode_block_t good_bb = emit_block(); vcode_block_t exit_bb = emit_block(); vcode_block_t paren_bb = emit_block(); - vcode_reg_t quote_args[] = { text_util_reg, preg }; - vcode_reg_t quote_result_reg = emit_fcall(find_quote_fn, vnat, vnat, - VCODE_CC_VHDL, quote_args, 2); - vcode_reg_t quote_pos_reg = emit_cast(voffset, voffset, quote_result_reg); + vcode_var_t first_var = emit_var(vnat, vnat, ident_new("first"), 0); + vcode_var_t last_var = emit_var(vnat, vnat, ident_new("last"), 0); - vcode_reg_t quoted_reg = emit_cmp(VCODE_CMP_EQ, quote_pos_reg, zero_reg); - emit_cond(quoted_reg, paren_bb, quote_bb); + vcode_reg_t first_ptr = emit_index(first_var, VCODE_INVALID_REG); + vcode_reg_t last_ptr = emit_index(last_var, VCODE_INVALID_REG); - vcode_select_block(quote_bb); + vcode_reg_t trim_args[] = { text_util_reg, preg, first_ptr, last_ptr }; + emit_fcall(trim_ws_fn, VCODE_INVALID_TYPE, VCODE_INVALID_TYPE, + VCODE_CC_VHDL, trim_args, ARRAY_LEN(trim_args)); - vcode_reg_t unquote_args[] = { text_util_reg, preg, quote_result_reg }; - vcode_reg_t unquote_result_reg = emit_fcall(find_unquote_fn, vnat, vnat, - VCODE_CC_VHDL, unquote_args, - ARRAY_LEN(unquote_args)); - vcode_reg_t unquote_pos_reg = - emit_cast(voffset, voffset, unquote_result_reg); + vcode_reg_t first_reg = emit_cast(voffset, voffset, emit_load(first_var)); + vcode_reg_t last_reg = emit_cast(voffset, voffset, emit_load(last_var)); - vcode_reg_t count_reg = emit_sub(unquote_pos_reg, quote_pos_reg); + vcode_reg_t count_reg = emit_add(emit_sub(last_reg, first_reg), one_reg); vcode_reg_t mem_reg = emit_alloc(velem, vbounds, count_reg); vcode_var_t pos_var = lower_temp_var(lu, "pos", voffset, voffset); - emit_store(emit_cast(voffset, voffset, quote_pos_reg), pos_var); + emit_store(emit_cast(voffset, voffset, first_reg), pos_var); const int nlits = type_enum_literals(elem); vcode_reg_t entry_vtype = vtype_int(0, nlits); diff --git a/src/object.c b/src/object.c index 624273d0..8d8ca72e 100644 --- a/src/object.c +++ b/src/object.c @@ -377,7 +377,7 @@ void object_one_time_init(void) // Increment this each time a incompatible change is made to // the on-disk format not expressed in the object items table - const uint32_t format_fudge = 33; + const uint32_t format_fudge = 34; format_digest += format_fudge * UINT32_C(2654435761); diff --git a/test/regress/value2.vhd b/test/regress/value2.vhd index d4fba1dd..bc6762fa 100644 --- a/test/regress/value2.vhd +++ b/test/regress/value2.vhd @@ -28,8 +28,8 @@ begin assert t_nested'value("((1, 2), true, 1.5, (5, 6))") = ((1, 2), true, 1.5, (5, 6)); assert t_int_vec'value("(1,2,3)") = (1, 2, 3); assert t_pair_pair'value("((1,2), (3, 4))") = ((1,2), (3,4)); - assert t_abc_vec'value("('a', 'b', 'c')") = "abc"; - assert t_abc_vec'value("""abc""") = "abc"; + assert t_abc_vec'value("abc") = "abc"; + assert t_abc_vec'value(" bbc ") = "bbc"; wait; end process; diff --git a/test/regress/value4.vhd b/test/regress/value4.vhd index c73b153c..4a311c57 100644 --- a/test/regress/value4.vhd +++ b/test/regress/value4.vhd @@ -8,7 +8,7 @@ begin process is begin - assert t_abc_vec'value("""abX""") = "abc"; -- Error + assert t_abc_vec'value("abX") = "abc"; -- Error wait; end process; diff --git a/test/test_jit.c b/test/test_jit.c index c87f8337..f72a8f58 100644 --- a/test/test_jit.c +++ b/test/test_jit.c @@ -1098,8 +1098,8 @@ START_TEST(test_value1) input_from_file(TESTDIR "/jit/value1.vhd"); const error_t expect[] = { - { 239, "found invalid characters \"x\" after value \"42x\"" }, - { 387, "found invalid characters \".4\" after value \"4..4\"" }, + { 257, "found invalid characters \"x\" after value \"42x\"" }, + { 405, "found invalid characters \".4\" after value \"4..4\"" }, { 80, "\" FOO\" is not a valid unit name" }, { 23, "\"FOO\" is not a valid enumeration value" }, { -1, NULL }, -- 2.39.2