From f7826e5a085b6ed2a4dcd96e572498cf90a271ff Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 25 Jun 2023 09:49:33 +0100 Subject: [PATCH] Add plumbing for subtype mirrors --- lib/std.19/reflection-body.vhd | 29 +++++++--- src/rt/reflect.c | 101 +++++++++++++++++++++++++++++---- test/regress/reflect1.vhd | 16 ++++-- 3 files changed, 124 insertions(+), 22 deletions(-) diff --git a/lib/std.19/reflection-body.vhd b/lib/std.19/reflection-body.vhd index 47803b0e..ef883a33 100644 --- a/lib/std.19/reflection-body.vhd +++ b/lib/std.19/reflection-body.vhd @@ -16,6 +16,10 @@ package body reflection is + type string_ptr is access string; + + --------------------------------------------------------------------------- + type enumeration_value_mirror_pt is protected body impure function get_subtype_mirror return enumeration_subtype_mirror is begin @@ -97,8 +101,9 @@ package body reflection is --------------------------------------------------------------------------- type integer_value_mirror_pt is protected body - variable f_value : integer; - variable f_owner : value_mirror; + variable f_owner : value_mirror; + variable f_subtype : integer_subtype_mirror; + variable f_value : integer; impure function get_subtype_mirror return integer_subtype_mirror is begin @@ -124,14 +129,16 @@ package body reflection is --------------------------------------------------------------------------- type integer_subtype_mirror_pt is protected body + variable f_owner : subtype_mirror; + impure function to_subtype_mirror return subtype_mirror is begin - report "unimplemented" severity failure; + return f_owner; end function; impure function simple_name return string is begin - report "unimplemented" severity failure; + return f_owner.simple_name; end function; impure function left return integer_value_mirror is @@ -599,9 +606,13 @@ package body reflection is --------------------------------------------------------------------------- type subtype_mirror_pt is protected body + variable f_class : type_class; + variable f_name : string_ptr; + variable f_integer : integer_subtype_mirror; + impure function get_type_class return type_class is begin - report "unimplemented" severity failure; + return f_class; end function; impure function to_enumeration return enumeration_subtype_mirror is @@ -611,7 +622,8 @@ package body reflection is impure function to_integer return integer_subtype_mirror is begin - report "unimplemented" severity failure; + assert f_class = CLASS_INTEGER; + return f_integer; end function; impure function to_floating return floating_subtype_mirror is @@ -651,7 +663,7 @@ package body reflection is impure function simple_name return string is begin - report "unimplemented" severity failure; + return f_name.all; end function; end protected body; @@ -659,6 +671,7 @@ package body reflection is type value_mirror_pt is protected body variable f_class : value_class; + variable f_subtype : subtype_mirror; variable f_integer : integer_value_mirror; impure function get_value_class return value_class is @@ -668,7 +681,7 @@ package body reflection is impure function get_subtype_mirror return subtype_mirror is begin - report "unimplemented" severity failure; + return f_subtype; end function; impure function to_enumeration return enumeration_value_mirror is diff --git a/src/rt/reflect.c b/src/rt/reflect.c index 542c4e15..79585f4a 100644 --- a/src/rt/reflect.c +++ b/src/rt/reflect.c @@ -22,6 +22,7 @@ #include "type.h" #include +#include typedef enum { CLASS_ENUMERATION, @@ -36,11 +37,23 @@ typedef enum { } reflect_class_t; typedef struct _value_mirror value_mirror; +typedef struct _subtype_mirror subtype_mirror; typedef struct { - void *context; - int64_t f_value; - value_mirror *f_owner; + void *context; + subtype_mirror *f_owner; +} integer_subtype_mirror_pt; + +typedef struct { + void *access; + integer_subtype_mirror_pt pt; +} integer_subtype_mirror; + +typedef struct { + void *context; + value_mirror *f_owner; + integer_subtype_mirror *f_subtype; + int64_t f_value; } integer_value_mirror_pt; typedef struct { @@ -51,6 +64,7 @@ typedef struct { typedef struct { void *context; uint8_t f_class; + subtype_mirror *f_subtype; integer_value_mirror *f_integer; } value_mirror_pt; @@ -59,18 +73,52 @@ typedef struct _value_mirror { value_mirror_pt pt; } value_mirror; -void *x_reflect_value(void *context, jit_scalar_t value, tree_t where) +typedef struct { + void *context; + uint8_t f_class; + ffi_uarray_t *f_name; + integer_subtype_mirror *f_integer; +} subtype_mirror_pt; + +typedef struct _subtype_mirror { + void *access; + subtype_mirror_pt pt; +} subtype_mirror; + +static subtype_mirror *get_subtype_mirror(void *context, type_t type); + +static void *zero_alloc(size_t size) +{ + void *ptr = jit_mspace_alloc(size); + memset(ptr, '\0', size); + return ptr; +} + +static ffi_uarray_t *get_string(const char *str) { - type_t type = tree_type(where); + const size_t nchars = strlen(str); + void *mem = jit_mspace_alloc(sizeof(ffi_uarray_t) + nchars); + memcpy(mem + sizeof(ffi_uarray_t), str, nchars); - value_mirror *vm = jit_mspace_alloc(sizeof(value_mirror)); + ffi_uarray_t *u = mem; + u->ptr = mem + sizeof(ffi_uarray_t); + u->dims[0].left = 1; + u->dims[0].length = nchars; + + return u; +} + +static value_mirror *get_value_mirror(void *context, jit_scalar_t value, + type_t type) +{ + 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); if (type_is_integer(type)) { - integer_value_mirror *ivm = - jit_mspace_alloc(sizeof(integer_value_mirror)); + integer_value_mirror *ivm = zero_alloc(sizeof(integer_value_mirror)); ivm->access = &(ivm->pt); ivm->pt.context = context; @@ -81,12 +129,45 @@ void *x_reflect_value(void *context, jit_scalar_t value, tree_t where) vm->pt.f_integer = ivm; } else - fatal_at(tree_loc(where), "unsupported type %s in prefix of REFLECT " - "attribute", type_pp(type)); + jit_msg(NULL, DIAG_FATAL, "unsupported type %s in prefix of REFLECT " + "attribute", type_pp(type)); return vm; } +static subtype_mirror *get_subtype_mirror(void *context, type_t type) +{ + // TODO: cache this (safely) + + subtype_mirror *sm = zero_alloc(sizeof(subtype_mirror)); + sm->access = &(sm->pt); + sm->pt.context = context; + + const char *simple = strrchr(istr(type_ident(type)), '.') + 1; + sm->pt.f_name = get_string(simple); + + if (type_is_integer(type)) { + integer_subtype_mirror *ism = zero_alloc(sizeof(integer_subtype_mirror)); + ism->access = &(ism->pt); + + ism->pt.context = context; + ism->pt.f_owner = sm; + + sm->pt.f_class = CLASS_INTEGER; + sm->pt.f_integer = ism; + } + else + jit_msg(NULL, DIAG_FATAL, "unsupported type %s in prefix of REFLECT " + "attribute", type_pp(type)); + + return sm; +} + +void *x_reflect_value(void *context, jit_scalar_t value, tree_t where) +{ + return get_value_mirror(context, value, tree_type(where)); +} + void _std_reflection_init(void) { // Dummy function to force linking diff --git a/test/regress/reflect1.vhd b/test/regress/reflect1.vhd index d0e370a8..50daa79b 100644 --- a/test/regress/reflect1.vhd +++ b/test/regress/reflect1.vhd @@ -7,10 +7,11 @@ architecture test of reflect1 is begin p1: process is - variable v1 : integer := 42; - variable vm : value_mirror; - variable ivm : integer_value_mirror; - variable stm : subtype_mirror; + variable v1 : integer := 42; + variable vm : value_mirror; + variable ivm : integer_value_mirror; + variable stm : subtype_mirror; + variable istm : integer_subtype_mirror; begin vm := v1'reflect; assert vm.get_value_class = CLASS_INTEGER; @@ -22,6 +23,13 @@ begin assert ivm.image = "42"; assert v1'reflect.all.to_integer.value = 100; assert ivm.to_value_mirror = vm; + + stm := vm.get_subtype_mirror; + assert stm.get_type_class = CLASS_INTEGER; + istm := stm.to_integer; + assert istm.simple_name = "INTEGER"; + assert istm.to_subtype_mirror = stm; + wait; end process; -- 2.39.2