diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 87fcbbe1b..adf62eb28 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -36,7 +36,7 @@ #include "QF/pr_debug.h" #define QFO "QFO" -#define QFO_VERSION 0x00001003 // MMmmmRRR 0.001.002 (hex) +#define QFO_VERSION 0x00001004 // MMmmmRRR 0.001.004 (hex) typedef struct qfo_header_s { char qfo[4]; @@ -50,6 +50,7 @@ typedef struct qfo_header_s { int num_funcs; int num_lines; int types_size; + int entity_fields; } qfo_header_t; typedef struct qfo_def_s { @@ -122,6 +123,7 @@ typedef struct qfo_s { int num_lines; char *types; int types_size; + int entity_fields; } qfo_t; #define QFO_var(q, t, o) ((q)->data[o].t##_var) diff --git a/tools/qfcc/include/reloc.h b/tools/qfcc/include/reloc.h index a3af202d3..4fc9d07d1 100644 --- a/tools/qfcc/include/reloc.h +++ b/tools/qfcc/include/reloc.h @@ -44,6 +44,7 @@ typedef enum { rel_def_def, rel_def_func, rel_def_string, + rel_def_field, } reloc_type; typedef struct reloc_s { @@ -59,5 +60,6 @@ void relocate_refs (reloc_t *refs, int ofs); void reloc_def_def (struct def_s *def, int ofs); void reloc_def_func (struct function_s *func, int ofs); void reloc_def_string (int ofs); +void reloc_def_field (struct def_s *def, int ofs); #endif//__reloc_h diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index e1edae96a..f3d6b2de1 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -37,6 +37,7 @@ static const char rcsid[] = #include "qfcc.h" #include "def.h" #include "expr.h" +#include "reloc.h" #include "strpool.h" #include "struct.h" #include "type.h" @@ -196,8 +197,10 @@ vector_component (int is_field, def_t *vec, int comp, scope_t *scope, d->parent = vec; d->ofs = vec->ofs + comp; set_storage_bits (d, storage); - if (is_field && (storage == st_global || storage == st_static)) + if (is_field && (storage == st_global || storage == st_static)) { G_INT (d->ofs) = G_INT (vec->ofs) + comp; + reloc_def_field (d, d->ofs); + } Hash_Add (defs_by_name, d); } @@ -258,8 +261,10 @@ get_def (type_t *type, const char *name, scope_t *scope, } if (type->type == ev_field) { - if (storage == st_global || storage == st_static) + if (storage == st_global || storage == st_static) { G_INT (def->ofs) = new_location (type->aux_type, pr.entity_data); + reloc_def_field (def, def->ofs); + } if (type->aux_type->type == ev_vector) { vector_component (1, def, 0, scope, storage); diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 41a3f72cb..7410d3688 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -67,14 +67,16 @@ Xgroup(func) // funcgroup_t static hashtab_t *extern_defs; static hashtab_t *defined_defs; +static hashtab_t *field_defs; static codespace_t *code; static defspace_t *data; static defspace_t *far_data; +static defspace_t *entity; static strpool_t *strings; static strpool_t *type_strings; static relocgroup_t relocs, final_relocs; -static defgroup_t global_defs, local_defs, defs; +static defgroup_t global_defs, local_defs, fields, defs; static funcgroup_t funcs; static struct { pr_lineno_t *lines; @@ -84,6 +86,7 @@ static struct { static int code_base; static int data_base; static int far_data_base; +static int entity_base; static int reloc_base; static int func_base; static int line_base; @@ -159,6 +162,10 @@ add_relocs (qfo_t *qfo) strpool_addstr (strings, qfo->strings + data->data[reloc->ofs].string_var); break; + case rel_def_field: + //FIXME more? + reloc->ofs += data_base; + break; } } } @@ -205,6 +212,24 @@ process_def (qfo_def_t *def) } } +static void +process_field (qfo_def_t *def) +{ + qfo_def_t *field_def; + pr_type_t *var = data->data + def->ofs; + + if ((field_def = Hash_Find (field_defs, strings->strings + def->name))) { + pr.source_file = def->file; + pr.source_line = def->line; + error (0, "%s redefined", strings->strings + def->name); + } + defgroup_add_defs (&fields, def, 1); + field_def = fields.defs + fields.num_defs - 1; + field_def->ofs = var->integer_var + entity_base; + Hash_Add (field_defs, field_def); + printf ("%s %d\n", strings->strings + field_def->name, field_def->ofs); +} + static void fixup_def (qfo_t *qfo, qfo_def_t *def, int def_num) { @@ -226,9 +251,19 @@ fixup_def (qfo_t *qfo, qfo_def_t *def, int def_num) return; if (!(def->flags & QFOD_EXTERNAL)) { def->ofs += data_base; - if (def->basic_type == ev_func && (def->flags & QFOD_INITIALIZED)) { - func = funcs.funcs + data->data[def->ofs].func_var - 1 + func_base; - func->def = def_num; + if (def->flags & QFOD_INITIALIZED) { + pr_type_t *var = data->data + def->ofs; + switch (def->basic_type) { + case ev_func: + func = funcs.funcs + var->func_var - 1 + func_base; + func->def = def_num; + break; + case ev_field: + process_field (def); + break; + default: + break; + } } } process_def (def); @@ -307,7 +342,7 @@ static void fixup_relocs () { qfo_reloc_t *reloc; - qfo_def_t *def; + qfo_def_t *def, *field_def; qfo_func_t *func; int i; @@ -322,6 +357,7 @@ fixup_relocs () case rel_op_b_def: case rel_op_c_def: case rel_def_def: + case rel_def_field: def = defs.defs + reloc->def; if (def->flags & (QFOD_EXTERNAL | QFOD_LOCAL | QFOD_ABSOLUTE)) continue; @@ -362,6 +398,11 @@ fixup_relocs () break; case rel_def_string: break; + case rel_def_field: + field_def = Hash_Find (field_defs, + strings->strings + def->name); + data->data[reloc->ofs].integer_var = field_def->ofs; + break; } } for (i = 0; i < defs.num_defs; i++) { @@ -449,10 +490,12 @@ merge_defgroups (void) } static void -define_def (const char *name, etype_t basic_type, const char *full_type) +define_def (const char *name, etype_t basic_type, const char *full_type, int v) { qfo_def_t d; - pr_type_t val = {0}; + pr_type_t val; + + val.integer_var = v; memset (&d, 0, sizeof (d)); d.basic_type = basic_type; @@ -463,6 +506,13 @@ define_def (const char *name, etype_t basic_type, const char *full_type) defspace_adddata (data, &val, 1); defgroup_add_defs (&global_defs, &d, 1); process_def (global_defs.defs + global_defs.num_defs - 1); + if (basic_type == ev_field) { + int def_num = global_defs.num_defs - 1; + qfo_def_t *def = global_defs.defs + def_num; + qfo_reloc_t rel = {def->ofs, rel_def_field, def_num}; + relocgroup_add_relocs (&relocs, &rel, 1); + process_field (def); + } } void @@ -470,9 +520,11 @@ linker_begin (void) { extern_defs = Hash_NewTable (16381, defs_get_key, 0, 0); defined_defs = Hash_NewTable (16381, defs_get_key, 0, 0); + field_defs = Hash_NewTable (16381, defs_get_key, 0, 0); code = codespace_new (); data = new_defspace (); far_data = new_defspace (); + entity = new_defspace (); strings = strpool_new (); type_strings = strpool_new (); @@ -496,10 +548,12 @@ linker_add_object_file (const char *filename) reloc_base = relocs.num_relocs; func_base = funcs.num_funcs; line_base = lines.num_lines; + entity_base = entity->size; codespace_addcode (code, qfo->code, qfo->code_size); defspace_adddata (data, qfo->data, qfo->data_size); defspace_adddata (far_data, qfo->far_data, qfo->far_data_size); + defspace_adddata (entity, 0, qfo->entity_fields); add_strings (qfo); add_relocs (qfo); add_funcs (qfo); @@ -523,10 +577,12 @@ linker_finish (void) const char *name = strings->strings + (*def)->name; if (strcmp (name, ".self") == 0 && !did_self) { - define_def (".self", ev_entity, "E"); + define_def (".self", ev_entity, "E", 0); did_self = 1; } else if (strcmp (name, ".this") == 0 && !did_this) { - define_def (".this", ev_field, "F@"); + entity_base = 0; + define_def (".this", ev_field, "F@", entity->size); + defspace_adddata (entity, 0, 1); did_this = 1; } } @@ -560,5 +616,6 @@ linker_finish (void) qfo_add_funcs (qfo, funcs.funcs, funcs.num_funcs); qfo_add_lines (qfo, lines.lines, lines.num_lines); qfo_add_types (qfo, type_strings->strings, type_strings->size); + qfo->entity_fields = entity->size; return qfo; } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index bf460fba5..a34dd9b41 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -255,6 +255,7 @@ qfo_from_progs (pr_info_t *pr) qfo_add_funcs (qfo, funcs, num_funcs); qfo_add_lines (qfo, linenos, num_linenos); qfo_add_types (qfo, types->strings, types->size); + qfo->entity_fields = pr->entity_data->size; free (defs); free (relocs); @@ -284,6 +285,7 @@ qfo_write (qfo_t *qfo, const char *filename) hdr.num_funcs = LittleLong (qfo->num_funcs); hdr.num_lines = LittleLong (qfo->num_lines); hdr.types_size = LittleLong (qfo->types_size); + hdr.entity_fields = LittleLong (qfo->entity_fields); Qwrite (file, &hdr, sizeof (hdr)); if (qfo->code_size) @@ -349,6 +351,7 @@ qfo_read (const char *filename) qfo->num_funcs = LittleLong (hdr.num_funcs); qfo->num_lines = LittleLong (hdr.num_lines); qfo->types_size = LittleLong (hdr.types_size); + qfo->entity_fields = LittleLong (hdr.entity_fields); if (hdr.version != QFO_VERSION) { fprintf (stderr, "can't read version %x.%03x.%03x\n", @@ -531,6 +534,7 @@ qfo_to_progs (qfo_t *qfo, pr_info_t *pr) pf->refs[qf->num_relocs - 1].next = 0; } } + pr->entity_data = init_space (qfo->entity_fields, 0); return 0; } diff --git a/tools/qfcc/source/qfodump.c b/tools/qfcc/source/qfodump.c index 20ba22ecf..56a2deb42 100644 --- a/tools/qfcc/source/qfodump.c +++ b/tools/qfcc/source/qfodump.c @@ -102,6 +102,8 @@ dump_defs (qfo_t *qfo) func = qfo->funcs + qfo->data[def->ofs].func_var - 1; printf (" %4d %s\n", qfo->data[def->ofs].func_var, func ? qfo->strings + func->name : "BORKAGE"); + } else if (def->basic_type == ev_field) { + printf (" %4d\n", qfo->data[def->ofs].integer_var); } else { // printf (" %4d\n", qfo->data[def->ofs].integer_var); } @@ -137,6 +139,7 @@ const char *reloc_names[] = { "def_def", "def_func", "def_string", + "def_field", }; void diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index 21a539c30..3b44a9d26 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -110,6 +110,8 @@ relocate_refs (reloc_t *refs, int ofs) break; case rel_def_string: break; + case rel_def_field: + break; } refs = refs->next; } @@ -149,3 +151,11 @@ reloc_def_string (int ofs) ref->next = pr.relocs; pr.relocs = ref; } + +void +reloc_def_field (def_t *def, int ofs) +{ + reloc_t *ref = new_reloc (ofs, rel_def_field); + ref->next = def->refs; + def->refs = ref; +}