Skip to content

Commit

Permalink
Implement reflection for files
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Jul 30, 2023
1 parent 2bf0278 commit 90f190b
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 9 deletions.
30 changes: 21 additions & 9 deletions lib/std.19/reflection-body.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -704,43 +704,51 @@ package body reflection is
---------------------------------------------------------------------------

type file_value_mirror_pt is protected body
variable f_owner : value_mirror;
variable f_subtype : file_subtype_mirror;
variable f_logical_name : string_ptr;
variable f_open_kind : file_open_kind;

impure function get_subtype_mirror return file_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_file_logical_name return string is
begin
report "unimplemented" severity failure;
return f_logical_name.all;
end function;

impure function get_file_open_kind return file_open_kind is
begin
report "unimplemented" severity failure;
return f_open_kind;
end function;
end protected body;

---------------------------------------------------------------------------

type file_subtype_mirror_pt is protected body
variable f_owner : subtype_mirror;
variable f_designated : 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 designated_subtype return subtype_mirror is
begin
report "unimplemented" severity failure;
return f_designated;
end function;
end protected body;

Expand Down Expand Up @@ -782,6 +790,7 @@ package body reflection is
variable f_floating : floating_subtype_mirror;
variable f_array : array_subtype_mirror;
variable f_record : record_subtype_mirror;
variable f_file : file_subtype_mirror;

impure function get_type_class return type_class is
begin
Expand Down Expand Up @@ -830,7 +839,8 @@ package body reflection is

impure function to_file return file_subtype_mirror is
begin
report "unimplemented" severity failure;
assert f_class = CLASS_FILE;
return f_file;
end function;

impure function to_protected return protected_subtype_mirror is
Expand All @@ -854,6 +864,7 @@ package body reflection is
variable f_floating : floating_value_mirror;
variable f_array : array_value_mirror;
variable f_record : record_value_mirror;
variable f_file : file_value_mirror;

impure function get_value_class return value_class is
begin
Expand Down Expand Up @@ -907,7 +918,8 @@ package body reflection is

impure function to_file return file_value_mirror is
begin
report "unimplemented" severity failure;
assert f_class = CLASS_FILE;
return f_file;
end function;

impure function to_protected return protected_value_mirror is
Expand Down
86 changes: 86 additions & 0 deletions src/rt/reflect.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,17 @@ typedef struct {
record_subtype_mirror_pt pt;
} record_subtype_mirror;

typedef struct {
void *context;
subtype_mirror *f_owner;
subtype_mirror *f_designated;
} file_subtype_mirror_pt;

typedef struct {
void *access;
file_subtype_mirror_pt pt;
} file_subtype_mirror;

typedef struct {
void *context;
value_mirror *f_owner;
Expand Down Expand Up @@ -198,6 +209,19 @@ typedef struct {
record_value_mirror_pt pt;
} record_value_mirror;

typedef struct {
void *context;
value_mirror *f_owner;
file_subtype_mirror *f_subtype;
ffi_uarray_t *f_logical_name;
uint8_t f_open_kind;
} file_value_mirror_pt;

typedef struct {
void *access;
file_value_mirror_pt pt;
} file_value_mirror;

typedef struct {
void *context;
uint8_t f_class;
Expand All @@ -207,6 +231,7 @@ typedef struct {
floating_value_mirror *f_floating;
array_value_mirror *f_array;
record_value_mirror *f_record;
file_value_mirror *f_file;
} value_mirror_pt;

typedef struct _value_mirror {
Expand All @@ -223,6 +248,7 @@ typedef struct {
floating_subtype_mirror *f_floating;
array_subtype_mirror *f_array;
record_subtype_mirror *f_record;
file_subtype_mirror *f_file;
} subtype_mirror_pt;

typedef struct _subtype_mirror {
Expand Down Expand Up @@ -317,6 +343,31 @@ static jit_scalar_t *get_array_bounds(type_t type, void *ptr)
return NULL;
}

static jit_scalar_t *get_null_array(type_t type)
{
const int ndims = dimension_of(type);
jit_scalar_t *bounds = xmalloc_array(ndims*2 + 1, sizeof(jit_scalar_t));
bounds[0].pointer = NULL;

for (int i = 0; i < ndims; i++) {
bounds[i*2+1].integer = 0;
bounds[i*2+2].integer = 0;
}

return bounds;
}

static ffi_uarray_t *get_file_logical_name(FILE *fp)
{
LOCAL_TEXT_BUF tb = tb_new();
if (get_handle_path(fileno(fp), tb))
return get_string(tb_get(tb));
else {
jit_msg(NULL, DIAG_WARN, "unable to get file logical name");
return NULL;
}
}

static value_mirror *get_value_mirror(void *context, jit_scalar_t value,
type_t type, const jit_scalar_t *bounds)
{
Expand Down Expand Up @@ -444,6 +495,22 @@ static value_mirror *get_value_mirror(void *context, jit_scalar_t value,
vm->pt.f_class = CLASS_RECORD;
vm->pt.f_record = rvm;
}
else if (type_is_file(type)) {
file_value_mirror *fvm = zero_alloc(sizeof(file_value_mirror));
fvm->access = &(fvm->pt);

fvm->pt.context = context;
fvm->pt.f_owner = vm;

FILE *fp = value.pointer;

extern int8_t __nvc_file_mode(FILE **fp);
fvm->pt.f_open_kind = __nvc_file_mode(&fp);
fvm->pt.f_logical_name = get_file_logical_name(fp);

vm->pt.f_class = CLASS_FILE;
vm->pt.f_file = fvm;
}
else
jit_msg(NULL, DIAG_FATAL, "unsupported type %s in prefix of REFLECT "
"attribute", type_pp(type));
Expand Down Expand Up @@ -707,6 +774,25 @@ static subtype_mirror *get_subtype_mirror(void *context, type_t type,
sm->pt.f_class = CLASS_RECORD;
sm->pt.f_record = rsm;
}
else if (type_is_file(type)) {
file_subtype_mirror *fsm =
zero_alloc(sizeof(file_subtype_mirror));
fsm->access = &(fsm->pt);

fsm->pt.context = context;
fsm->pt.f_owner = sm;

type_t designated = type_designated(type);

jit_scalar_t *dbounds LOCAL = NULL;
if (type_is_array(designated))
dbounds = get_null_array(designated);

fsm->pt.f_designated = get_subtype_mirror(context, designated, dbounds);

sm->pt.f_class = CLASS_FILE;
sm->pt.f_file = fsm;
}
else
jit_msg(NULL, DIAG_FATAL, "unsupported type %s in prefix of REFLECT "
"attribute", type_pp(type));
Expand Down
34 changes: 34 additions & 0 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1668,6 +1668,40 @@ bool get_handle_info(int fd, file_info_t *info)
#endif
}

bool get_handle_path(int fd, text_buf_t *tb)
{
#ifdef __MINGW32__
HANDLE handle = (HANDLE)_get_osfhandle(fd);
char buf[PATH_MAX];

DWORD nchars = GetFinalPathNameByHandle(handle, buf, PATH_MAX, 0);
if (nchars == 0)
return false;

tb_catn(tb, buf, nchars);
return true;
#elif defined __linux__
char path[64], buf[PATH_MAX];
checked_sprintf(path, sizeof(path), "/proc/self/fd/%d", fd);

size_t nchars = readlink(path, buf, PATH_MAX);
if (nchars == -1)
return false;

tb_catn(tb, buf, nchars);
return true;
#elif defined F_GETPATH
char buf[PATH_MAX];
if (fcntl(fd, F_GETPATH, buf) == -1)
return false;

tb_cat(tb, buf);
return true;
#else
return false;
#endif
}

void run_program(const char *const *args)
{
#if defined __CYGWIN__ || defined __MINGW32__
Expand Down
1 change: 1 addition & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ typedef struct {

bool get_file_info(const char *path, file_info_t *info);
bool get_handle_info(int fd, file_info_t *info);
bool get_handle_path(int fd, text_buf_t *tb);

void progress(const char *fmt, ...)
__attribute__((format(printf, 1, 2)));
Expand Down
39 changes: 39 additions & 0 deletions test/regress/reflect5.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
entity reflect5 is
end entity;

use std.reflection.all;
use std.textio.all;

architecture test of reflect5 is
function basename(path : string) return string is
begin
for i in path'reverse_range loop
if path(i) = '\' or path(i) = '/' then
return path(i + 1 to path'length);
end if;
end loop;
return path;
end function;
begin

p1: process is
variable stm : subtype_mirror;
variable fstm : file_subtype_mirror;
variable fvm : file_value_mirror;
file f : text;
begin
stm := text'reflect;
assert stm.get_type_class = CLASS_FILE;
fstm := stm.to_file;
assert fstm.designated_subtype.simple_name = "STRING";

file_open(f, "temp.txt", WRITE_MODE);

fvm := f'reflect.to_file;
assert fvm.get_file_open_kind = WRITE_MODE;
assert basename(fvm.get_file_logical_name) = "temp.txt";

wait;
end process;

end architecture;
1 change: 1 addition & 0 deletions test/regress/testlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -830,3 +830,4 @@ predef4 normal,2008
protected11 fail,gold,2002
issue744 normal,vhpi
reflect4 normal,2019
reflect5 normal,2019

0 comments on commit 90f190b

Please sign in to comment.