diff --git a/src/jit/jit-irgen.c b/src/jit/jit-irgen.c index a4cb74d61..415673218 100644 --- a/src/jit/jit-irgen.c +++ b/src/jit/jit-irgen.c @@ -2369,6 +2369,8 @@ static void irgen_op_reflect_value(jit_irgen_t *g, int op) else j_send(g, 3, irgen_get_value(g, vreg)); } + else + j_send(g, 3, value); macro_exit(g, JIT_EXIT_REFLECT_VALUE); diff --git a/src/jit/jit-layout.c b/src/jit/jit-layout.c index a2acc8495..ef8a5e976 100644 --- a/src/jit/jit-layout.c +++ b/src/jit/jit-layout.c @@ -74,7 +74,7 @@ const jit_layout_t *layout_of(type_t type) l->parts[0].align = l->parts[0].size; l->parts[1].offset = sizeof(void *); - l->parts[1].size = sizeof(int32_t); + l->parts[1].size = sizeof(int64_t); l->parts[1].repeat = ndims * 2; l->parts[1].align = l->parts[1].size; } diff --git a/src/rt/reflect.c b/src/rt/reflect.c index 51940543f..effe64ce7 100644 --- a/src/rt/reflect.c +++ b/src/rt/reflect.c @@ -278,25 +278,36 @@ static jit_scalar_t load_scalar(const void *base, size_t off, size_t size) return elt; } -static jit_scalar_t *get_array_bounds(type_t type) +static jit_scalar_t *get_array_bounds(type_t type, void *ptr) { const int ndims = dimension_of(type); - jit_scalar_t *fbounds = xmalloc_array(ndims*2 + 1, sizeof(jit_scalar_t)); - fbounds[0].pointer = NULL; - for (int i = 0; i < ndims; i++) { - tree_t r = range_of(type, i); + if (type_is_unconstrained(type)) { + ffi_uarray_t *u = ptr; + fbounds[0].pointer = u->ptr; + + for (int i = 0; i < ndims; i++) { + fbounds[i*2+1].integer = u->dims[i].left; + fbounds[i*2+2].integer = u->dims[i].length; + } + } + else { + fbounds[0].pointer = ptr; - int64_t left, length; - if (!folded_int(tree_left(r), &left)) - goto not_const; - else if (!folded_length(r, &length)) - goto not_const; + for (int i = 0; i < ndims; i++) { + tree_t r = range_of(type, i); - const range_kind_t dir = tree_subkind(r); - fbounds[i*2+1].integer = left; - fbounds[i*2+2].integer = (dir == RANGE_DOWNTO ? ~length : length); + int64_t left, length; + if (!folded_int(tree_left(r), &left)) + goto not_const; + else if (!folded_length(r, &length)) + goto not_const; + + const range_kind_t dir = tree_subkind(r); + fbounds[i*2+1].integer = left; + fbounds[i*2+2].integer = (dir == RANGE_DOWNTO ? ~length : length); + } } return fbounds; @@ -421,8 +432,7 @@ static value_mirror *get_value_mirror(void *context, jit_scalar_t value, elements[i] = get_value_mirror(context, elt, ft, NULL); } else if (type_is_array(ft)) { - jit_scalar_t *fbounds LOCAL = get_array_bounds(ft); - fbounds[0].pointer = ptr; + jit_scalar_t *fbounds LOCAL = get_array_bounds(ft, ptr); elements[i] = get_value_mirror(context, fbounds[0], ft, fbounds); } else { @@ -676,6 +686,9 @@ static subtype_mirror *get_subtype_mirror(void *context, type_t type, rsm->pt.f_fields->dims[0].length = nfields; rsm->pt.f_fields->ptr = rsm->pt.f_fields + 1; + const jit_layout_t *l = layout_of(type); + assert(l->nparts == nfields); + field_rec *fields = rsm->pt.f_fields->ptr; for (int i = 0; i < nfields; i++) { tree_t f = type_field(base, i); @@ -683,7 +696,8 @@ static subtype_mirror *get_subtype_mirror(void *context, type_t type, type_t ft = tree_type(f); if (type_is_array(ft)) { - jit_scalar_t *fbounds LOCAL = get_array_bounds(ft); + void *ptr = bounds[0].pointer + l->parts[i].offset; + jit_scalar_t *fbounds LOCAL = get_array_bounds(ft, ptr); fields[i].f_subtype = get_subtype_mirror(context, ft, fbounds); } else @@ -708,7 +722,9 @@ void *x_reflect_value(void *context, jit_scalar_t value, tree_t where, void *x_reflect_subtype(void *context, tree_t where, const jit_scalar_t *bounds) { - return get_subtype_mirror(context, tree_type(where), bounds); + type_t type = tree_type(where); + assert(!type_is_unconstrained(type)); // Should be caught earlier + return get_subtype_mirror(context, type, bounds); } void _std_reflection_init(void) diff --git a/src/sem.c b/src/sem.c index 428bf6ff9..5caabff9d 100644 --- a/src/sem.c +++ b/src/sem.c @@ -3914,6 +3914,9 @@ static bool sem_check_attr_ref(tree_t t, bool allow_range, nametab_t *tab) if (get_type_or_null(name) == NULL) sem_error(t, "prefix of attribute REFLECT is not a type mark or " "an object with a type"); + else if (named_type != NULL && type_is_unconstrained(named_type)) + sem_error(t, "prefix of 'REFLECT attribute must be a fully " + "constrained subtype"); return true; diff --git a/test/regress/reflect4.vhd b/test/regress/reflect4.vhd new file mode 100644 index 000000000..095afe556 --- /dev/null +++ b/test/regress/reflect4.vhd @@ -0,0 +1,45 @@ +entity reflect4 is +end entity; + +use std.reflection.all; + +architecture test of reflect4 is + type rec1 is record + a, b : integer; + c : string; + end record; +begin + + p1: process is + variable v1 : rec1 := (1, 2, "abc"); + variable vm : value_mirror; + variable rvm : record_value_mirror; + variable rstm : record_subtype_mirror; + variable astm : array_subtype_mirror; + begin + vm := v1'reflect; + rvm := vm.to_record; + rstm := rvm.get_subtype_mirror; + assert rstm.length = 3; + assert rstm.element_name(0) = "A"; + assert rstm.element_name(1) = "B"; + assert rstm.element_name(2) = "C"; + assert rstm.element_index("B") = 1; + assert rstm.element_subtype("A") = integer'reflect; + assert rstm.element_subtype("C").get_type_class = class_array; + + assert rvm.get(0).to_integer.value = 1; + assert rvm.get("b").to_integer.value = 2; + + astm := rstm.element_subtype("C").to_array; + assert astm.length = 3; + assert astm.left = 1; + assert astm.right = 3; + assert astm.ascending; + + assert rvm.get("c").to_array.get(1).to_enumeration.image = "'a'"; + assert rvm.get("c").to_array.get(3).to_enumeration.image = "'c'"; + wait; + end process; + +end architecture; diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index 248738628..596ec6c24 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -829,3 +829,4 @@ toplevel3 normal,guut.i=2,guut.s=2 predef4 normal,2008 protected11 fail,gold,2002 issue744 normal,vhpi +reflect4 normal,2019 diff --git a/test/sem/lcs2016_41.vhd b/test/sem/lcs2016_41.vhd index 8684e1027..9e651484f 100644 --- a/test/sem/lcs2016_41.vhd +++ b/test/sem/lcs2016_41.vhd @@ -22,6 +22,7 @@ begin astm := stm.to_array; -- OK vm := p1'reflect; -- Error assert v'subtype'reflect.get_type_class = CLASS_ARRAY; -- OK + stm := bit_vector'reflect; -- Error wait; end process; diff --git a/test/test_jit.c b/test/test_jit.c index b3fc1c3a9..c619ad561 100644 --- a/test/test_jit.c +++ b/test/test_jit.c @@ -867,7 +867,7 @@ START_TEST(test_layout) ck_assert_int_eq(l->parts[0].repeat, 1); ck_assert_int_eq(l->parts[0].align, 8); ck_assert_int_eq(l->parts[1].offset, sizeof(void *)); - ck_assert_int_eq(l->parts[1].size, 4); + ck_assert_int_eq(l->parts[1].size, sizeof(int64_t)); ck_assert_int_eq(l->parts[1].repeat, 2); input_from_file(TESTDIR "/jit/layout.vhd"); diff --git a/test/test_sem.c b/test/test_sem.c index b5a96f66d..994b02a54 100644 --- a/test/test_sem.c +++ b/test/test_sem.c @@ -3099,6 +3099,7 @@ START_TEST(test_lcs2016_41) { 19, "value VALUE_MIRROR does not match type of target INTEGER" }, { 23, "prefix of attribute REFLECT is not a type mark or an object " "with a type" }, + { 25, "prefix of 'REFLECT attribute must be a fully constrained " }, { -1, NULL } }; expect_errors(expect);