From: Rhys Weatherley Date: Mon, 10 May 2004 03:43:11 +0000 (+0000) Subject: Loading and storing record fields in Dynamic Pascal. X-Git-Tag: r.0.0.2~22 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=c8c232e1c7a975ff352d4d4268b37ac60d3bac9b;p=francis%2Flibjit.git Loading and storing record fields in Dynamic Pascal. --- diff --git a/ChangeLog b/ChangeLog index 6b318dc..5f09442 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,9 @@ interpreter code conversion for relative pointer and copy opcodes; fix some bugs in stack-based register allocation. + * dpas/dpas-parser.y, dpas/dpas-types.c, dpas/dpas-types.h: + loading and storing record fields in Dynamic Pascal. + 2004-05-08 Rhys Weatherley * jit/jit-cache.c, jit/jit-cache.h, jit/jit-dump.c, jit/jit-interp.h, diff --git a/dpas/dpas-parser.y b/dpas/dpas-parser.y index 1a55a8b..a05c3e0 100644 --- a/dpas/dpas-parser.y +++ b/dpas/dpas-parser.y @@ -2645,8 +2645,69 @@ Variable /* TODO */ } | Variable '.' Identifier { - /* Fetch the effective address of a structure field */ - /* TODO */ + /* Fetch the effective address of a record field */ + jit_type_t type = dpas_sem_get_type($1); + jit_type_t field_type; + jit_value_t address; + jit_nint offset; + if(dpas_sem_is_lvalue_ea($1)) + { + address = dpas_sem_get_value($1); + } + else if(dpas_sem_is_lvalue($1)) + { + address = jit_insn_address_of + (dpas_current_function(), dpas_sem_get_value($1)); + if(!address) + { + dpas_out_of_memory(); + } + } + else + { + if(!dpas_sem_is_error($1)) + { + dpas_error("invalid left hand side for `.'"); + } + type = 0; + address = 0; + } + if(type && dpas_type_is_record(type)) + { + field_type = dpas_type_get_field(type, $3, &offset); + if(field_type) + { + if(offset != 0) + { + address = jit_insn_add_relative + (dpas_current_function(), address, offset); + if(!address) + { + dpas_out_of_memory(); + } + } + dpas_sem_set_lvalue_ea($$, field_type, address); + } + else + { + char *name = dpas_type_name(type); + dpas_error("`%s' is not a member of `%s'", $3, name); + jit_free(name); + dpas_sem_set_error($$); + } + } + else if(type) + { + char *name = dpas_type_name(type); + dpas_error("`%s' is not a record type", name); + jit_free(name); + dpas_sem_set_error($$); + } + else + { + dpas_sem_set_error($$); + } + jit_free($3); } | Variable '^' { /* Dereference a pointer value */ diff --git a/dpas/dpas-types.c b/dpas/dpas-types.c index 56cafc8..056daa5 100644 --- a/dpas/dpas-types.c +++ b/dpas/dpas-types.c @@ -220,6 +220,41 @@ unsigned int dpas_type_find_name(jit_type_t type, const char *name) return JIT_INVALID_NAME; } +jit_type_t dpas_type_get_field(jit_type_t type, const char *name, + jit_nint *offset) +{ + unsigned int field; + const char *fname; + jit_type_t field_type; + type = jit_type_normalize(type); + field = jit_type_num_fields(type); + while(field > 0) + { + --field; + fname = jit_type_get_name(type, field); + field_type = jit_type_get_field(type, field); + if(fname && !jit_stricmp(fname, name)) + { + *offset = jit_type_get_offset(type, field); + return field_type; + } + else if(!fname) + { + /* Probably a nested struct or union in a variant record */ + if(dpas_type_is_record(field_type)) + { + field_type = dpas_type_get_field(field_type, name, offset); + if(field_type != 0) + { + *offset += jit_type_get_offset(type, field); + return field_type; + } + } + } + } + return 0; +} + /* * Concatenate two strings. */ diff --git a/dpas/dpas-types.h b/dpas/dpas-types.h index 295769c..855d913 100644 --- a/dpas/dpas-types.h +++ b/dpas/dpas-types.h @@ -101,6 +101,12 @@ void dpas_init_types(void); */ unsigned int dpas_type_find_name(jit_type_t type, const char *name); +/* + * Get the type and offset of a field within a record type. + */ +jit_type_t dpas_type_get_field(jit_type_t type, const char *name, + jit_nint *offset); + /* * Get the name of a type, for printing in error messages. */