Skip to content

Commit

Permalink
Correct 'VALUE behaviour for arrays of character literals
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Dec 13, 2023
1 parent 3a0333e commit a8fcb82
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 28 deletions.
20 changes: 19 additions & 1 deletion lib/nvc/text_util-body.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions lib/nvc/text_util.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -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;
34 changes: 15 additions & 19 deletions src/lower.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
4 changes: 2 additions & 2 deletions test/regress/value2.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion test/regress/value4.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
4 changes: 2 additions & 2 deletions test/test_jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down

0 comments on commit a8fcb82

Please sign in to comment.