From 1b717469670a586eba44506e3de37c11895f4bfc Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 25 Jun 2023 17:50:42 +0100 Subject: [PATCH] Add empty array value/subtype mirrors --- lib/std.19/reflection-body.vhd | 21 ++++++++---- src/jit/jit-exits.c | 2 +- src/jit/jit-exits.h | 3 +- src/jit/jit-irgen.c | 13 +++++++ src/lower.c | 51 ++++++++++++++++++---------- src/rt/reflect.c | 62 ++++++++++++++++++++++++++++++---- src/vcode.c | 9 ++++- src/vcode.h | 3 +- test/regress/reflect1.vhd | 10 ++++++ 9 files changed, 141 insertions(+), 33 deletions(-) diff --git a/lib/std.19/reflection-body.vhd b/lib/std.19/reflection-body.vhd index ef883a33..c4d1aac6 100644 --- a/lib/std.19/reflection-body.vhd +++ b/lib/std.19/reflection-body.vhd @@ -107,7 +107,7 @@ package body reflection is impure function get_subtype_mirror return integer_subtype_mirror is begin - report "unimplemented" severity failure; + return f_subtype; end function; impure function to_value_mirror return value_mirror is @@ -399,14 +399,17 @@ package body reflection is --------------------------------------------------------------------------- type array_value_mirror_pt is protected body + variable f_owner : value_mirror; + variable f_subtype : array_subtype_mirror; + impure function get_subtype_mirror return array_subtype_mirror is begin - report "unimplemented" severity failure; + return f_subtype; end function; impure function to_value_mirror return value_mirror is begin - report "unimplemented" severity failure; + return f_owner; end function; impure function get (idx : index) return value_mirror is @@ -433,14 +436,17 @@ package body reflection is --------------------------------------------------------------------------- type array_subtype_mirror_pt is protected body + variable f_owner : subtype_mirror; + variable f_dimensions : dimension; + impure function to_subtype_mirror return subtype_mirror is begin - report "unimplemented" severity failure; + return f_owner; end function; impure function dimensions return dimension is begin - report "unimplemented" severity failure; + return f_dimensions; end function; impure function index_subtype(idx : dimension := 1) return subtype_mirror is @@ -609,6 +615,7 @@ package body reflection is variable f_class : type_class; variable f_name : string_ptr; variable f_integer : integer_subtype_mirror; + variable f_array : array_subtype_mirror; impure function get_type_class return type_class is begin @@ -673,6 +680,7 @@ package body reflection is variable f_class : value_class; variable f_subtype : subtype_mirror; variable f_integer : integer_value_mirror; + variable f_array : array_value_mirror; impure function get_value_class return value_class is begin @@ -712,7 +720,8 @@ package body reflection is impure function to_array return array_value_mirror is begin - report "unimplemented" severity failure; + assert f_class = CLASS_ARRAY; + return f_array; end function; impure function to_access return access_value_mirror is diff --git a/src/jit/jit-exits.c b/src/jit/jit-exits.c index 5da2b493..2d64b7a0 100644 --- a/src/jit/jit-exits.c +++ b/src/jit/jit-exits.c @@ -1140,7 +1140,7 @@ void __nvc_do_exit(jit_exit_t which, jit_anchor_t *anchor, jit_scalar_t *args, jit_scalar_t value = args[1]; tree_t where = args[2].pointer; - args[0].pointer = x_reflect_value(context, value, where); + args[0].pointer = x_reflect_value(context, value, where, args + 3); } break; diff --git a/src/jit/jit-exits.h b/src/jit/jit-exits.h index fb3fed5c..9e93a6f3 100644 --- a/src/jit/jit-exits.h +++ b/src/jit/jit-exits.h @@ -96,6 +96,7 @@ void x_cover_setup_toggle_cb(sig_shared_t *ss, int32_t *toggle_mask); void x_process_init(jit_handle_t handle, tree_t where); void x_clear_event(sig_shared_t *ss, uint32_t offset, int32_t count); void x_enter_state(int32_t state); -void *x_reflect_value(void *context, jit_scalar_t value, tree_t where); +void *x_reflect_value(void *context, jit_scalar_t value, tree_t where, + const jit_scalar_t *bounds); #endif // _JIT_EXITS_H diff --git a/src/jit/jit-irgen.c b/src/jit/jit-irgen.c index 22ee7936..bb10f1f8 100644 --- a/src/jit/jit-irgen.c +++ b/src/jit/jit-irgen.c @@ -2352,6 +2352,19 @@ static void irgen_op_reflect_value(jit_irgen_t *g, int op) j_send(g, 0, context); j_send(g, 1, value); j_send(g, 2, locus); + + if (vcode_count_args(op) > 3) { + vcode_reg_t vreg = vcode_get_arg(op, 3); + const int slots = irgen_slots_for_type(vcode_reg_type(vreg)); + if (slots > 1) { + jit_reg_t base = jit_value_as_reg(irgen_get_value(g, vreg)); + for (int j = 0; j < slots; j++) + j_send(g, j + 3, jit_value_from_reg(base + j)); + } + else + j_send(g, 3, irgen_get_value(g, vreg)); + } + macro_exit(g, JIT_EXIT_REFLECT_VALUE); g->map[vcode_get_result(op)] = j_recv(g, 0); diff --git a/src/lower.c b/src/lower.c index 47dc5d98..05fcb327 100644 --- a/src/lower.c +++ b/src/lower.c @@ -4425,6 +4425,39 @@ static vcode_reg_t lower_attr_prefix(lower_unit_t *lu, tree_t prefix) } } +static vcode_reg_t lower_reflect_attr(lower_unit_t *lu, tree_t expr) +{ + tree_t name = tree_name(expr); + + type_t type = tree_type(expr), pt = type_designated(type); + assert(type_is_protected(pt)); + + ident_t init_func = type_ident(pt); + vcode_reg_t context_reg = lower_context_for_call(init_func); + + type_t value_mirror = reflection_type(REFLECT_VALUE_MIRROR); + const bool is_value_mirror = type_eq(type, value_mirror); + + vcode_reg_t value_reg = VCODE_INVALID_REG, bounds_reg = VCODE_INVALID_REG; + if (is_value_mirror) + value_reg = lower_attr_prefix(lu, name); + + type_t value_type = tree_type(name); + if (type_is_array(value_type)) + bounds_reg = lower_wrap(lu, value_type, value_reg); + + vcode_reg_t result_reg; + if (is_value_mirror) { + vcode_reg_t locus = lower_debug_locus(name); + result_reg = emit_reflect_value(init_func, value_reg, context_reg, + locus, bounds_reg); + } + else + fatal_at(tree_loc(expr), "sorry, subtype mirrors not yet supported"); + + return result_reg; +} + static vcode_reg_t lower_attr_ref(lower_unit_t *lu, tree_t expr) { tree_t name = tree_name(expr); @@ -4706,23 +4739,7 @@ static vcode_reg_t lower_attr_ref(lower_unit_t *lu, tree_t expr) } case ATTR_REFLECT: - { - type_t type = tree_type(expr), pt = type_designated(type); - assert(type_is_protected(pt)); - - ident_t init_func = type_ident(pt); - vcode_reg_t context_reg = lower_context_for_call(init_func); - - type_t value_mirror = reflection_type(REFLECT_VALUE_MIRROR); - if (type_eq(type, value_mirror)) { - vcode_reg_t name_reg = lower_attr_prefix(lu, name); - vcode_reg_t locus = lower_debug_locus(name); - return emit_reflect_value(init_func, name_reg, context_reg, locus); - } - else - fatal_at(tree_loc(expr), "sorry, subtype mirrors not yet supported"); - } - break; + return lower_reflect_attr(lu, expr); default: fatal_at(tree_loc(expr), "cannot lower attribute %s (%d)", diff --git a/src/rt/reflect.c b/src/rt/reflect.c index 79585f4a..723178c7 100644 --- a/src/rt/reflect.c +++ b/src/rt/reflect.c @@ -49,6 +49,17 @@ typedef struct { integer_subtype_mirror_pt pt; } integer_subtype_mirror; +typedef struct { + void *context; + subtype_mirror *f_owner; + uint64_t f_dimensions; +} array_subtype_mirror_pt; + +typedef struct { + void *access; + array_subtype_mirror_pt pt; +} array_subtype_mirror; + typedef struct { void *context; value_mirror *f_owner; @@ -61,11 +72,23 @@ typedef struct { integer_value_mirror_pt pt; } integer_value_mirror; +typedef struct { + void *context; + value_mirror *f_owner; + array_subtype_mirror *f_subtype; +} array_value_mirror_pt; + +typedef struct { + void *access; + array_value_mirror_pt pt; +} array_value_mirror; + typedef struct { void *context; uint8_t f_class; subtype_mirror *f_subtype; integer_value_mirror *f_integer; + array_value_mirror *f_array; } value_mirror_pt; typedef struct _value_mirror { @@ -78,6 +101,7 @@ typedef struct { uint8_t f_class; ffi_uarray_t *f_name; integer_subtype_mirror *f_integer; + array_subtype_mirror *f_array; } subtype_mirror_pt; typedef struct _subtype_mirror { @@ -85,7 +109,8 @@ typedef struct _subtype_mirror { subtype_mirror_pt pt; } subtype_mirror; -static subtype_mirror *get_subtype_mirror(void *context, type_t type); +static subtype_mirror *get_subtype_mirror(void *context, type_t type, + const jit_scalar_t *bounds); static void *zero_alloc(size_t size) { @@ -109,13 +134,13 @@ static ffi_uarray_t *get_string(const char *str) } static value_mirror *get_value_mirror(void *context, jit_scalar_t value, - type_t type) + type_t type, const jit_scalar_t *bounds) { value_mirror *vm = zero_alloc(sizeof(value_mirror)); vm->access = &(vm->pt); vm->pt.context = context; - vm->pt.f_subtype = get_subtype_mirror(context, type); + vm->pt.f_subtype = get_subtype_mirror(context, type, bounds); if (type_is_integer(type)) { integer_value_mirror *ivm = zero_alloc(sizeof(integer_value_mirror)); @@ -124,10 +149,22 @@ static value_mirror *get_value_mirror(void *context, jit_scalar_t value, ivm->pt.context = context; ivm->pt.f_value = value.integer; ivm->pt.f_owner = vm; + ivm->pt.f_subtype = vm->pt.f_subtype->pt.f_integer; vm->pt.f_class = CLASS_INTEGER; vm->pt.f_integer = ivm; } + else if (type_is_array(type)) { + array_value_mirror *avm = zero_alloc(sizeof(array_value_mirror)); + avm->access = &(avm->pt); + + avm->pt.context = context; + avm->pt.f_owner = vm; + avm->pt.f_subtype = vm->pt.f_subtype->pt.f_array; + + vm->pt.f_class = CLASS_ARRAY; + vm->pt.f_array = avm; + } else jit_msg(NULL, DIAG_FATAL, "unsupported type %s in prefix of REFLECT " "attribute", type_pp(type)); @@ -135,7 +172,8 @@ static value_mirror *get_value_mirror(void *context, jit_scalar_t value, return vm; } -static subtype_mirror *get_subtype_mirror(void *context, type_t type) +static subtype_mirror *get_subtype_mirror(void *context, type_t type, + const jit_scalar_t *bounds) { // TODO: cache this (safely) @@ -156,6 +194,17 @@ static subtype_mirror *get_subtype_mirror(void *context, type_t type) sm->pt.f_class = CLASS_INTEGER; sm->pt.f_integer = ism; } + else if (type_is_array(type)) { + array_subtype_mirror *astm = zero_alloc(sizeof(array_subtype_mirror)); + astm->access = &(astm->pt); + + astm->pt.context = context; + astm->pt.f_owner = sm; + astm->pt.f_dimensions = dimension_of(type); + + sm->pt.f_class = CLASS_ARRAY; + sm->pt.f_array = astm; + } else jit_msg(NULL, DIAG_FATAL, "unsupported type %s in prefix of REFLECT " "attribute", type_pp(type)); @@ -163,9 +212,10 @@ static subtype_mirror *get_subtype_mirror(void *context, type_t type) return sm; } -void *x_reflect_value(void *context, jit_scalar_t value, tree_t where) +void *x_reflect_value(void *context, jit_scalar_t value, tree_t where, + const jit_scalar_t *bounds) { - return get_value_mirror(context, value, tree_type(where)); + return get_value_mirror(context, value, tree_type(where), bounds); } void _std_reflection_init(void) diff --git a/src/vcode.c b/src/vcode.c index d288fdb0..46546c8d 100644 --- a/src/vcode.c +++ b/src/vcode.c @@ -2254,6 +2254,10 @@ void vcode_dump_with_mark(int mark_op, vcode_dump_fn_t callback, void *arg) vcode_dump_reg(op->args.items[1]); col += printf(" locus "); col += vcode_dump_reg(op->args.items[2]); + if (op->args.count > 3) { + col += printf(" bounds "); + col += vcode_dump_reg(op->args.items[3]); + } vcode_dump_result_type(col, op); } break; @@ -5863,12 +5867,15 @@ void emit_enter_state(vcode_reg_t state) } vcode_reg_t emit_reflect_value(ident_t ptype, vcode_reg_t value, - vcode_reg_t context, vcode_reg_t locus) + vcode_reg_t context, vcode_reg_t locus, + vcode_reg_t bounds) { op_t *op = vcode_add_op(VCODE_OP_REFLECT_VALUE); vcode_add_arg(op, value); vcode_add_arg(op, context); vcode_add_arg(op, locus); + if (bounds != VCODE_INVALID_REG) + vcode_add_arg(op, bounds); VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT, "invalid reflect value context argument"); diff --git a/src/vcode.h b/src/vcode.h index 0a88b29d..ff8d6508 100644 --- a/src/vcode.h +++ b/src/vcode.h @@ -518,6 +518,7 @@ vcode_reg_t emit_canon_value(vcode_reg_t ptr, vcode_reg_t len); vcode_reg_t emit_convstr(vcode_reg_t value); void emit_enter_state(vcode_reg_t state); vcode_reg_t emit_reflect_value(ident_t ptype, vcode_reg_t value, - vcode_reg_t context, vcode_reg_t locus); + vcode_reg_t context, vcode_reg_t locus, + vcode_reg_t bounds); #endif // _VCODE_H diff --git a/test/regress/reflect1.vhd b/test/regress/reflect1.vhd index 50daa79b..3e7e91cc 100644 --- a/test/regress/reflect1.vhd +++ b/test/regress/reflect1.vhd @@ -8,10 +8,13 @@ begin p1: process is variable v1 : integer := 42; + variable v2 : integer_vector(1 to 3) := (1, 2, 3); variable vm : value_mirror; variable ivm : integer_value_mirror; + variable avm : array_value_mirror; variable stm : subtype_mirror; variable istm : integer_subtype_mirror; + variable astm : array_subtype_mirror; begin vm := v1'reflect; assert vm.get_value_class = CLASS_INTEGER; @@ -29,6 +32,13 @@ begin istm := stm.to_integer; assert istm.simple_name = "INTEGER"; assert istm.to_subtype_mirror = stm; + assert ivm.get_subtype_mirror = istm; + + vm := v2'reflect; + assert vm.get_value_class = CLASS_ARRAY; + avm := vm.to_array; + astm := avm.get_subtype_mirror; + assert astm.dimensions = 1; wait; end process; -- 2.39.2