diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index c40df3e42..32ce21808 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -94,8 +94,8 @@ struct def_s *protocol_def (protocol_t *protocol); protocollist_t *new_protocollist (void); void add_protocol (protocollist_t *protocollist, protocol_t *protocol); -int emit_protocol (protocol_t *protocol); -int emit_protocol_list (protocollist_t *protocols, const char *name); +struct def_s *emit_protocol (protocol_t *protocol); +struct def_s *emit_protocol_list (protocollist_t *protocols, const char *name); void clear_classes (void); diff --git a/tools/qfcc/include/emit.h b/tools/qfcc/include/emit.h index daee60c61..20051f38b 100644 --- a/tools/qfcc/include/emit.h +++ b/tools/qfcc/include/emit.h @@ -49,4 +49,18 @@ struct def_s *emit_statement (struct expr_s *e, opcode_t *op, struct def_s *var_ struct def_s *emit_sub_expr (struct expr_s*e, struct def_s *dest); void emit_expr (struct expr_s *e); +#define EMIT_STRING(dest,str) \ + do { \ + (dest) = ReuseString (str); \ + reloc_def_string (POINTER_OFS (&(dest))); \ + } while (0) + +#define EMIT_DEF(dest,def) \ + do { \ + def_t *d = (def); \ + (dest) = d ? d->ofs : 0; \ + if (d) \ + reloc_def_def (d, POINTER_OFS (&(dest))); \ + } while (0) + #endif//__emit_h diff --git a/tools/qfcc/include/method.h b/tools/qfcc/include/method.h index 443ceb081..08d6f35aa 100644 --- a/tools/qfcc/include/method.h +++ b/tools/qfcc/include/method.h @@ -80,7 +80,8 @@ void selector_name (struct dstring_s *sel_id, keywordarg_t *selector); void selector_types (struct dstring_s *sel_types, keywordarg_t *selector); struct def_s *selector_def (const char *sel_id, const char *sel_types); -int emit_methods (methodlist_t *methods, const char *name, int instance); +struct def_s *emit_methods (methodlist_t *methods, const char *name, + int instance); void clear_selectors (void); diff --git a/tools/qfcc/include/reloc.h b/tools/qfcc/include/reloc.h index 86ba3f30d..a3af202d3 100644 --- a/tools/qfcc/include/reloc.h +++ b/tools/qfcc/include/reloc.h @@ -56,5 +56,8 @@ struct statement_s; reloc_t *new_reloc (int ofs, reloc_type type); 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); #endif//__reloc_h diff --git a/tools/qfcc/include/struct.h b/tools/qfcc/include/struct.h index 2c5b2a5f1..af322b84a 100644 --- a/tools/qfcc/include/struct.h +++ b/tools/qfcc/include/struct.h @@ -55,7 +55,7 @@ struct type_s *new_union (const char *name); struct type_s *find_struct (const char *name); void copy_struct_fields (struct type_s *dst, struct type_s *src); -int emit_struct (struct type_s *strct, const char *name); +struct def_s *emit_struct (struct type_s *strct, const char *name); void process_enum (struct expr_s *enm); struct expr_s *get_enum (const char *name); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 3fd42684e..4e29ca58e 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -176,12 +176,13 @@ class_begin (class_t *class) class->def->initialized = class->def->constant = 1; category = &G_STRUCT (pr_category_t, class->def->ofs); - category->category_name = ReuseString (class->category_name); - category->class_name = ReuseString (class->class_name); - category->protocols = emit_protocol_list (class->protocols, - va ("%s_%s", - class->class_name, - class->category_name)); + EMIT_STRING (category->category_name, class->category_name); + EMIT_STRING (category->class_name, class->class_name); + EMIT_DEF (category->protocols, + emit_protocol_list (class->protocols, + va ("%s_%s", + class->class_name, + class->category_name))); } else if (class->class_name) { def_t *meta_def; pr_class_t *meta; @@ -192,19 +193,19 @@ class_begin (class_t *class) pr.scope, st_static); meta_def->initialized = meta_def->constant = 1; meta = &G_STRUCT (pr_class_t, meta_def->ofs); - meta->class_pointer = ReuseString (class->class_name); + EMIT_STRING (meta->class_pointer, class->class_name); if (class->super_class) - meta->super_class = ReuseString (class->super_class->class_name); - meta->name = meta->class_pointer; + EMIT_STRING (meta->super_class, class->super_class->class_name); + EMIT_STRING (meta->name, class->class_name); meta->info = _PR_CLS_META; meta->instance_size = type_size (type_Class.aux_type); - meta->ivars = emit_struct (type_Class.aux_type, "Class"); - meta->protocols = emit_protocol_list (class->protocols, - class->class_name); + EMIT_DEF (meta->ivars, emit_struct (type_Class.aux_type, "Class")); + EMIT_DEF (meta->protocols, emit_protocol_list (class->protocols, + class->class_name)); class->def->initialized = class->def->constant = 1; cls = &G_STRUCT (pr_class_t, class->def->ofs); - cls->class_pointer = meta_def->ofs; + EMIT_DEF (cls->class_pointer, meta_def); cls->super_class = meta->super_class; cls->name = meta->name; meta->info = _PR_CLS_CLASS; @@ -219,16 +220,14 @@ class_finish (class_t *class) pr_category_t *category; category = &G_STRUCT (pr_category_t, class->def->ofs); - category->instance_methods = emit_methods (class->methods, - va ("%s_%s", - class->class_name, - class->category_name), - 1); - category->class_methods = emit_methods (class->methods, - va ("%s_%s", + EMIT_DEF (category->instance_methods, + emit_methods (class->methods, va ("%s_%s", class->class_name, - class->category_name), - 0); + class->category_name), 1)); + EMIT_DEF (category->class_methods, + emit_methods (class->methods, va ("%s_%s", + class->class_name, + class->category_name), 0)); } else if (class->class_name) { pr_class_t *meta; pr_class_t *cls; @@ -237,11 +236,13 @@ class_finish (class_t *class) meta = &G_STRUCT (pr_class_t, cls->class_pointer); - meta->methods = emit_methods (class->methods, class->class_name, 0); + EMIT_DEF (meta->methods, emit_methods (class->methods, + class->class_name, 0)); cls->instance_size = type_size (class->ivars); - cls->ivars = emit_struct (class->ivars, class->class_name); - cls->methods = emit_methods (class->methods, class->class_name, 1); + EMIT_DEF (cls->ivars, emit_struct (class->ivars, class->class_name)); + EMIT_DEF (cls->methods, emit_methods (class->methods, + class->class_name, 1)); } } @@ -417,7 +418,7 @@ class_pointer_def (class_t *class) class->def = class_def (class, 1); if (!class->def->external) G_INT (def->ofs) = class->def->ofs; - //FIXME need reloc + reloc_def_def (class->def, def->ofs); return def; } @@ -445,13 +446,13 @@ class_finish_module (void) if (class_hash) { classes = (class_t **) Hash_GetList (class_hash); for (t = classes; *t; t++) - if ((*t)->def) + if ((*t)->def && !(*t)->def->external) num_classes++; } if (category_hash) { categories = (class_t **) Hash_GetList (category_hash); for (t = categories; *t; t++) - if ((*t)->def) + if ((*t)->def && !(*t)->def->external) num_categories++; } if (!num_classes && !num_categories) @@ -468,33 +469,39 @@ class_finish_module (void) symtab->cls_def_cnt = num_classes; symtab->cat_def_cnt = num_categories; def_ptr = symtab->defs; - for (i = 0, t = classes; i < num_classes; i++, t++) - if ((*t)->def) + for (i = 0, t = classes; i < num_classes; i++, t++) { + if ((*t)->def && !(*t)->def->external) { + reloc_def_def ((*t)->def, POINTER_OFS (def_ptr)); *def_ptr++ = (*t)->def->ofs; - for (i = 0, t = categories; i < num_categories; i++, t++) - if ((*t)->def) + } + } + for (i = 0, t = categories; i < num_categories; i++, t++) { + if ((*t)->def && !(*t)->def->external) { + reloc_def_def ((*t)->def, POINTER_OFS (def_ptr)); *def_ptr++ = (*t)->def->ofs; + } + } module_def = get_def (type_module, "_OBJ_MODULE", pr.scope, st_static); module_def->initialized = module_def->constant = 1; module = &G_STRUCT (pr_module_t, module_def->ofs); module->size = type_size (type_module); - module->name = ReuseString (options.output_file); - module->symtab = symtab_def->ofs; + EMIT_STRING (module->name, options.output_file); + EMIT_DEF (module->symtab, symtab_def); exec_class_def = get_def (&type_obj_exec_class, "__obj_exec_class", pr.scope, st_static); exec_class_func = new_function ("__obj_exec_class"); exec_class_func->builtin = 0; exec_class_func->def = exec_class_def; - exec_class_func->refs = new_reloc (exec_class_def->ofs, rel_def_func); + reloc_def_func (exec_class_func, exec_class_def->ofs); build_function (exec_class_func); finish_function (exec_class_func); init_def = get_def (&type_function, ".ctor", pr.scope, st_static); init_func = new_function (".ctor"); init_func->def = init_def; - init_func->refs = new_reloc (init_def->ofs, rel_def_func); + reloc_def_func (init_func, init_def->ofs); init_func->code = pr.code->size; build_scope (init_func, init_def, 0); build_function (init_func); @@ -579,7 +586,7 @@ add_protocol (protocollist_t *protocollist, protocol_t *protocol) protocollist->list[protocollist->count++] = protocol; } -int +def_t * emit_protocol (protocol_t *protocol) { def_t *proto_def; @@ -591,17 +598,18 @@ emit_protocol (protocol_t *protocol) proto_def->initialized = proto_def->constant = 1; proto = &G_STRUCT (pr_protocol_t, proto_def->ofs); proto->class_pointer = 0; - proto->protocol_name = ReuseString (protocol->name); - proto->protocol_list = - emit_protocol_list (protocol->protocols, - va ("PROTOCOL_%s", protocol->name)); - proto->instance_methods = emit_methods (protocol->methods, - protocol->name, 1); - proto->class_methods = emit_methods (protocol->methods, protocol->name, 0); - return proto_def->ofs; + EMIT_STRING (proto->protocol_name, protocol->name); + EMIT_DEF (proto->protocol_list, + emit_protocol_list (protocol->protocols, + va ("PROTOCOLo_%s", protocol->name))); + EMIT_DEF (proto->instance_methods, + emit_methods (protocol->methods, protocol->name, 1)); + EMIT_DEF (proto->class_methods, + emit_methods (protocol->methods, protocol->name, 0)); + return proto_def; } -int +def_t * emit_protocol_list (protocollist_t *protocols, const char *name) { def_t *proto_list_def; @@ -624,8 +632,8 @@ emit_protocol_list (protocollist_t *protocols, const char *name) proto_list->next = 0; proto_list->count = protocols->count; for (i = 0; i < protocols->count; i++) - proto_list->list[i] = emit_protocol (protocols->list[i]); - return proto_list_def->ofs; + EMIT_DEF (proto_list->list[i], emit_protocol (protocols->list[i])); + return proto_list_def; } void diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index a977c1e4e..f3a049478 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -204,7 +204,7 @@ build_builtin_function (def_t *def, expr_t *bi_val) f->builtin = bi_val->type == ex_integer ? bi_val->e.integer_val : (int)bi_val->e.float_val; f->def = def; - f->refs = new_reloc (def->ofs, rel_def_func); + reloc_def_func (f, def->ofs); build_function (f); finish_function (f); return f; diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 416456d99..748c8de12 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -51,6 +51,7 @@ static const char rcsid[] = #include "expr.h" #include "class.h" #include "def.h" +#include "emit.h" #include "immediate.h" #include "method.h" #include "reloc.h" @@ -245,11 +246,9 @@ sel_def_compare (void *_sd1, void *_sd2, void *unused) } def_t * -selector_def (const char *_sel_id, const char *_sel_types) +selector_def (const char *sel_id, const char *sel_types) { - string_t sel_id = ReuseString (_sel_id); - string_t sel_types = ReuseString (_sel_types); - sel_def_t _sel_def = {sel_id, sel_types, 0}; + sel_def_t _sel_def = {ReuseString (sel_id), ReuseString (sel_types), 0}; sel_def_t *sel_def = &_sel_def; if (!sel_def_hash) { @@ -260,18 +259,18 @@ selector_def (const char *_sel_id, const char *_sel_types) if (sel_def) return sel_def->def; sel_def = malloc (sizeof (sel_def_t)); - sel_def->sel_id = sel_id; - sel_def->sel_types = sel_types; sel_def->def = new_def (type_SEL.aux_type, ".imm", pr.scope); sel_def->def->initialized = sel_def->def->constant = 1; sel_def->def->ofs = new_location (type_SEL.aux_type, pr.near_data); - G_INT (sel_def->def->ofs) = sel_id; - G_INT (sel_def->def->ofs + 1) = sel_types; + EMIT_STRING (G_INT (sel_def->def->ofs), sel_id); + EMIT_STRING (G_INT (sel_def->def->ofs + 1), sel_types); + sel_def->sel_id = G_INT (sel_def->def->ofs); + sel_def->sel_types = G_INT (sel_def->def->ofs + 1); Hash_AddElement (sel_def_hash, sel_def); return sel_def->def; } -int +def_t * emit_methods (methodlist_t *_methods, const char *name, int instance) { const char *type = instance ? "INSTANCE" : "CLASS"; @@ -304,24 +303,19 @@ emit_methods (methodlist_t *_methods, const char *name, int instance) methods->method_next = 0; methods->method_count = count; for (i = 0, method = _methods->head; method; method = method->next) { - reloc_t *ref; if (!method->instance != !instance || !method->def) continue; - methods->method_list[i].method_name.sel_id = ReuseString (method->name); - methods->method_list[i].method_name.sel_types = - ReuseString (method->types); - methods->method_list[i].method_types = - methods->method_list[i].method_name.sel_types; + EMIT_STRING (methods->method_list[i].method_name.sel_id, method->name); + EMIT_STRING (methods->method_list[i].method_name.sel_types, method->types); + EMIT_STRING (methods->method_list[i].method_types, method->types); methods->method_list[i].method_imp = G_FUNCTION (method->def->ofs); if (method->func) { - ref = new_reloc (POINTER_OFS (&methods->method_list[i].method_imp), - rel_def_func); - ref->next = method->func->refs; - method->func->refs = ref; + reloc_def_func (method->func, + POINTER_OFS (&methods->method_list[i].method_imp)); } i++; } - return methods_def->ofs; + return methods_def; } void diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 12c93478b..08b6dfcdb 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -492,11 +492,11 @@ qfo_to_progs (qfo_t *qfo, pr_info_t *pr) pd->line = qd->line; } - pr->num_functions = qfo->num_functions; - pr->func_head = calloc (pr->num_functions, sizeof (function_t)); + pr->num_functions = qfo->num_functions + 1; + pr->func_head = calloc (qfo->num_functions, sizeof (function_t)); pr->func_tail = &pr->func_head; for (i = 0, pf = pr->func_head, qf = qfo->functions; - i < pr->num_functions; i++, pf++, qf++) { + i < qfo->num_functions; i++, pf++, qf++) { *pr->func_tail = pf; pr->func_tail = &pf->next; pf->aux = new_auxfunction (); diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 4c5f9139c..0cfb7fe6a 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -170,7 +170,7 @@ WriteData (int crc) fields = calloc (pr.scope->num_defs + 1, sizeof (ddef_t)); for (def = pr.scope->head; def; def = def->def_next) { - if (!def->global || !def->name) + if (def->local || !def->name) continue; if (def->type->type == ev_func) { } else if (def->type->type == ev_field) { @@ -351,7 +351,6 @@ finish_compilation (void) ex_label_t *l; dfunction_t *df; - class_finish_module (); // check to make sure all functions prototyped have code if (options.warnings.undefined_function) for (d = pr.scope->head; d; d = d->def_next) { @@ -489,7 +488,10 @@ compile_to_obj (const char *file, const char *obj) } } if (!err) { - qfo_t *qfo = qfo_from_progs (&pr); + qfo_t *qfo; + + class_finish_module (); + qfo = qfo_from_progs (&pr); err = qfo_write (qfo, obj); qfo_delete (qfo); } @@ -633,6 +635,7 @@ progs_src_compile (void) qfo_write (qfo, options.output_file); qfo_delete (qfo); } else { + class_finish_module (); if (!finish_compilation ()) { fprintf (stderr, "compilation errors\n"); return 1; diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index 6c924325e..21a539c30 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -44,6 +44,7 @@ static const char rcsid[] = #include "def.h" #include "emit.h" #include "expr.h" +#include "function.h" #include "qfcc.h" #include "reloc.h" @@ -124,3 +125,27 @@ new_reloc (int ofs, reloc_type type) ref->type = type; return ref; } + +void +reloc_def_def (def_t *def, int ofs) +{ + reloc_t *ref = new_reloc (ofs, rel_def_def); + ref->next = def->refs; + def->refs = ref; +} + +void +reloc_def_func (function_t *func, int ofs) +{ + reloc_t *ref = new_reloc (ofs, rel_def_func); + ref->next = func->refs; + func->refs = ref; +} + +void +reloc_def_string (int ofs) +{ + reloc_t *ref = new_reloc (ofs, rel_def_string); + ref->next = pr.relocs; + pr.relocs = ref; +} diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 8ca27e4e5..cf01ad5aa 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -47,10 +47,12 @@ static const char rcsid[] = #include #include -#include "qfcc.h" #include "def.h" +#include "emit.h" #include "expr.h" #include "immediate.h" +#include "qfcc.h" +#include "reloc.h" #include "struct.h" #include "type.h" @@ -202,7 +204,7 @@ struct_compare_fields (struct type_s *s1, struct type_s *s2) return !((!f1) ^ !(f2)); } -int +def_t * emit_struct(type_t *strct, const char *name) { struct_field_t *field; @@ -234,8 +236,8 @@ emit_struct(type_t *strct, const char *name) if (!field->name) continue; encode_type (encoding, field->type); - ivars->ivar_list[i].ivar_name = ReuseString (field->name); - ivars->ivar_list[i].ivar_type = ReuseString (encoding->str); + EMIT_STRING (ivars->ivar_list[i].ivar_name, field->name); + EMIT_STRING (ivars->ivar_list[i].ivar_type, encoding->str); ivars->ivar_list[i].ivar_offset = field->offset; dstring_clearstr (encoding); i++; @@ -243,7 +245,7 @@ emit_struct(type_t *strct, const char *name) done: dstring_delete (encoding); dstring_delete (ivars_name); - return ivars_def->ofs; + return ivars_def; } void