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 <rweather@southern-storm.com.au>
* jit/jit-cache.c, jit/jit-cache.h, jit/jit-dump.c, jit/jit-interp.h,
/* 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 */
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.
*/
*/
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.
*/