diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 76381f10d..ae8ec57b9 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -132,8 +132,13 @@ typedef struct qfo_s { #define QFO_POINTER(q, t,o) ((t *)((q)->data + o)) #define QFO_STRUCT(q, t,o) (*QFO_POINTER (q, t, o)) -int write_obj_file (const char *filename); -qfo_t *read_obj_file (const char *filename); +struct pr_info_s; + +qfo_t *qfo_from_progs (struct pr_info_s *pr); +int qfo_write (qfo_t *qfo, const char *filename); +qfo_t *qfo_read (const char *filename); +int qfo_to_progs (qfo_t *qfo, struct pr_info_s *pr); + qfo_t *qfo_new (void); void qfo_add_code (qfo_t *qfo, dstatement_t *code, int code_size); void qfo_add_data (qfo_t *qfo, pr_type_t *data, int data_size); @@ -142,6 +147,7 @@ void qfo_add_strings (qfo_t *qfo, const char *strings, int strings_size); void qfo_add_relocs (qfo_t *qfo, qfo_reloc_t *relocs, int num_relocs); void qfo_add_defs (qfo_t *qfo, qfo_def_t *defs, int num_defs); void qfo_add_functions (qfo_t *qfo, qfo_function_t *functions, int num_functions); +void qfo_add_lines (qfo_t *qfo, pr_lineno_t *lines, int num_lines); void qfo_add_types (qfo_t *qfo, const char *types, int types_size); void qfo_delete (qfo_t *qfo); diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index d7adf0377..135519c16 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -75,12 +75,18 @@ static struct { int num_funcs; int max_funcs; } funcs; +static struct { + pr_lineno_t *lines; + int num_lines; + int max_lines; +} lines; static int code_base; static int data_base; static int far_data_base; static int reloc_base; static int def_base; static int func_base; +static int line_base; static const char * defs_get_key (void *_def, void *unused) @@ -219,10 +225,34 @@ add_funcs (qfo_t *qfo) func->def += def_base; if (func->local_defs) func->local_defs += def_base; + if (func->line_info) + func->line_info += line_base; func->relocs += reloc_base; } } +static void +add_lines (qfo_t *qfo) +{ + int i; + + if (lines.num_lines + qfo->num_lines > lines.max_lines) { + lines.max_lines = RUP (lines.num_lines + qfo->num_lines, 16384); + lines.lines = realloc (lines.lines, + lines.max_lines * sizeof (pr_lineno_t)); + } + lines.num_lines += qfo->num_lines; + memcpy (lines.lines + line_base, qfo->lines, + qfo->num_lines * sizeof (pr_lineno_t)); + for (i = line_base; i < lines.num_lines; i++) { + pr_lineno_t *line = lines.lines + i; + if (line->line) + line->fa.addr += code_base; + else + line->fa.func += func_base; + } +} + static void fixup_relocs (qfo_t *qfo) { @@ -283,7 +313,7 @@ linker_add_object_file (const char *filename) { qfo_t *qfo; - qfo = read_obj_file (filename); + qfo = qfo_read (filename); if (!qfo) return; @@ -295,6 +325,7 @@ linker_add_object_file (const char *filename) reloc_base = relocs.num_relocs; def_base = defs.num_defs; func_base = funcs.num_funcs; + line_base = lines.num_lines; codespace_addcode (code, qfo->code, qfo->code_size); defspace_adddata (data, qfo->data, qfo->data_size); @@ -303,6 +334,7 @@ linker_add_object_file (const char *filename) add_relocs (qfo); add_defs (qfo); add_funcs (qfo); + add_lines (qfo); fixup_relocs (qfo); diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 4d7d523f7..e521fe2d8 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -170,9 +170,9 @@ setup_data (void) pr_type_t *var; pr_lineno_t *line; - for (d = pr.scope->head; d; d = d->def_next) - write_def (d, def++, &reloc); - for (f = pr.func_head; f; f = f->next) { + for (d = pr.scope->head; d; d = d->def_next, def++) + write_def (d, def, &reloc); + for (f = pr.func_head; f; f = f->next, func++) { func->name = LittleLong (f->s_name); func->file = LittleLong (f->s_file); func->line = LittleLong (f->def->line); @@ -219,71 +219,87 @@ setup_data (void) } } -int -write_obj_file (const char *filename) +qfo_t * +qfo_from_progs (pr_info_t *pr) { - qfo_header_t hdr; - VFile *file; + qfo_t *qfo; types = strpool_new (); allocate_stuff (); setup_data (); - file = Qopen (filename, "wbz9"); + pr->strings->size = RUP (pr->strings->size, 4); + types->size = RUP (types->size, 4); - pr.strings->size = (pr.strings->size + 3) & ~3; - types->size = (types->size + 3) & ~3; - - memset (&hdr, 0, sizeof (hdr)); - - memcpy (hdr.qfo, QFO, sizeof (hdr.qfo)); - hdr.version = LittleLong (QFO_VERSION); - hdr.code_size = LittleLong (pr.code->size); - hdr.data_size = LittleLong (pr.near_data->size); - if (pr.far_data) { - hdr.far_data_size = LittleLong (pr.far_data->size); - } - hdr.strings_size = LittleLong (pr.strings->size); - hdr.num_relocs = LittleLong (num_relocs); - hdr.num_defs = LittleLong (num_defs); - hdr.num_functions = LittleLong (num_functions); - hdr.num_lines = LittleLong (num_linenos); - hdr.types_size = LittleLong (types->size); - - Qwrite (file, &hdr, sizeof (hdr)); - if (pr.code->size) - Qwrite (file, pr.code->code, pr.code->size * sizeof (dstatement_t)); - if (pr.near_data->size) - Qwrite (file, pr.near_data->data, - pr.near_data->size * sizeof (pr_type_t)); - if (pr.far_data && pr.far_data->size) { - Qwrite (file, pr.far_data->data, - pr.far_data->size * sizeof (pr_type_t)); - } - if (pr.strings->size) - Qwrite (file, pr.strings->strings, pr.strings->size); - if (num_relocs) - Qwrite (file, relocs, num_relocs * sizeof (qfo_reloc_t)); - if (num_defs) - Qwrite (file, defs, num_defs * sizeof (qfo_def_t)); - if (num_functions) - Qwrite (file, functions, num_functions * sizeof (qfo_function_t)); - if (num_linenos) - Qwrite (file, linenos, num_linenos * sizeof (pr_lineno_t)); - if (types->size) - Qwrite (file, types->strings, types->size); - - Qclose (file); + qfo = qfo_new (); + qfo_add_code (qfo, pr->code->code, pr->code->size); + qfo_add_data (qfo, pr->near_data->data, pr->near_data->size); + if (pr->far_data) + qfo_add_far_data (qfo, pr->far_data->data, pr->far_data->size); + qfo_add_strings (qfo, pr->strings->strings, pr->strings->size); + qfo_add_relocs (qfo, relocs, num_relocs); + qfo_add_defs (qfo, defs, num_defs); + qfo_add_functions (qfo, functions, num_functions); + qfo_add_lines (qfo, linenos, num_linenos); + qfo_add_types (qfo, types->strings, types->size); free (defs); free (relocs); free (functions); strpool_delete (types); + return qfo; +} + +int +qfo_write (qfo_t *qfo, const char *filename) +{ + qfo_header_t hdr; + VFile *file; + + file = Qopen (filename, "wbz9"); + + memset (&hdr, 0, sizeof (hdr)); + + memcpy (hdr.qfo, QFO, sizeof (hdr.qfo)); + hdr.version = LittleLong (QFO_VERSION); + hdr.code_size = LittleLong (qfo->code_size); + hdr.data_size = LittleLong (qfo->data_size); + hdr.far_data_size = LittleLong (qfo->far_data_size); + hdr.strings_size = LittleLong (qfo->strings_size); + hdr.num_relocs = LittleLong (qfo->num_relocs); + hdr.num_defs = LittleLong (qfo->num_defs); + hdr.num_functions = LittleLong (qfo->num_functions); + hdr.num_lines = LittleLong (qfo->num_lines); + hdr.types_size = LittleLong (qfo->types_size); + + Qwrite (file, &hdr, sizeof (hdr)); + if (qfo->code_size) + Qwrite (file, qfo->code, qfo->code_size * sizeof (dstatement_t)); + if (qfo->data_size) + Qwrite (file, qfo->data, qfo->data_size * sizeof (pr_type_t)); + if (qfo->far_data_size) + Qwrite (file, qfo->far_data, qfo->far_data_size * sizeof (pr_type_t)); + if (qfo->strings_size) + Qwrite (file, qfo->strings, qfo->strings_size); + if (qfo->num_relocs) + Qwrite (file, qfo->relocs, qfo->num_relocs * sizeof (qfo_reloc_t)); + if (qfo->num_defs) + Qwrite (file, qfo->defs, qfo->num_defs * sizeof (qfo_def_t)); + if (qfo->num_functions) + Qwrite (file, qfo->functions, + qfo->num_functions * sizeof (qfo_function_t)); + if (qfo->num_lines) + Qwrite (file, qfo->lines, qfo->num_lines * sizeof (pr_lineno_t)); + if (qfo->types_size) + Qwrite (file, qfo->types, qfo->types_size); + + Qclose (file); + return 0; } qfo_t * -read_obj_file (const char *filename) +qfo_read (const char *filename) { VFile *file; qfo_header_t hdr; @@ -510,6 +526,7 @@ void qfo_add_code (qfo_t *qfo, dstatement_t *code, int code_size) { qfo->code = malloc (code_size * sizeof (dstatement_t)); + qfo->code_size = code_size; memcpy (qfo->code, code, code_size * sizeof (dstatement_t)); } @@ -517,6 +534,7 @@ void qfo_add_data (qfo_t *qfo, pr_type_t *data, int data_size) { qfo->data = malloc (data_size * sizeof (pr_type_t)); + qfo->data_size = data_size; memcpy (qfo->data, data, data_size * sizeof (pr_type_t)); } @@ -524,6 +542,7 @@ void qfo_add_far_data (qfo_t *qfo, pr_type_t *far_data, int far_data_size) { qfo->far_data = malloc (far_data_size * sizeof (pr_type_t)); + qfo->far_data_size = far_data_size; memcpy (qfo->far_data, far_data, far_data_size * sizeof (pr_type_t)); } @@ -531,6 +550,7 @@ void qfo_add_strings (qfo_t *qfo, const char *strings, int strings_size) { qfo->strings = malloc (strings_size); + qfo->strings_size = strings_size; memcpy (qfo->strings, strings, strings_size); } @@ -538,6 +558,7 @@ void qfo_add_relocs (qfo_t *qfo, qfo_reloc_t *relocs, int num_relocs) { qfo->relocs = malloc (num_relocs * sizeof (qfo_reloc_t)); + qfo->num_relocs = num_relocs; memcpy (qfo->relocs, relocs, num_relocs * sizeof (qfo_reloc_t)); } @@ -545,6 +566,7 @@ void qfo_add_defs (qfo_t *qfo, qfo_def_t *defs, int num_defs) { qfo->defs = malloc (num_defs * sizeof (qfo_def_t)); + qfo->num_defs = num_defs; memcpy (qfo->defs, defs, num_defs * sizeof (qfo_def_t)); } @@ -552,13 +574,23 @@ void qfo_add_functions (qfo_t *qfo, qfo_function_t *functions, int num_functions) { qfo->functions = malloc (num_functions * sizeof (qfo_function_t)); + qfo->num_functions = num_functions; memcpy (qfo->functions, functions, num_functions * sizeof (qfo_function_t)); } +void +qfo_add_lines (qfo_t *qfo, pr_lineno_t *lines, int num_lines) +{ + qfo->lines = malloc (num_lines * sizeof (pr_lineno_t)); + qfo->num_lines = num_lines; + memcpy (qfo->lines, lines, num_lines * sizeof (pr_lineno_t)); +} + void qfo_add_types (qfo_t *qfo, const char *types, int types_size) { qfo->types = malloc (types_size); + qfo->types_size = types_size; memcpy (qfo->types, types, types_size); } @@ -581,6 +613,8 @@ qfo_delete (qfo_t *qfo) free (qfo->defs); if (qfo->functions) free (qfo->functions); + if (qfo->lines) + free (qfo->lines); if (qfo->types) free (qfo->types); free (qfo); diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 841d42def..d96f11489 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -488,8 +488,11 @@ compile_to_obj (const char *file, const char *obj) exit (1); } } - if (!err) - write_obj_file (obj); + if (!err) { + qfo_t *qfo = qfo_from_progs (&pr); + err = qfo_write (qfo, obj); + qfo_delete (qfo); + } return err; } @@ -615,7 +618,9 @@ progs_src_compile (void) } if (options.compile) { - write_obj_file (options.output_file); + qfo_t *qfo = qfo_from_progs (&pr); + qfo_write (qfo, options.output_file); + qfo_delete (qfo); } else { if (!finish_compilation ()) { fprintf (stderr, "compilation errors\n");