diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index 185e284a1..d8a0e4dfb 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -53,6 +53,7 @@ typedef struct def_s { unsigned external:1; // externally declared def unsigned local:1; // function local def unsigned system:1; // system def + unsigned nosave:1; // don't set DEF_SAVEGLOBAL string_t file; // source file int line; // source line diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 4aa8bfd81..0838694ce 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -76,6 +76,7 @@ typedef struct qfo_def_s { #define QFOD_EXTERNAL (1u<<4) #define QFOD_LOCAL (1u<<5) #define QFOD_SYSTEM (1u<<6) +#define QFOD_NOSAVE (1u<<7) typedef struct qfo_func_s { string_t name; diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 274d7a514..5359e0085 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -183,6 +183,7 @@ class_begin (class_type_t *class_type) current_class = &category->class_type; category->def = class_def (class_type, 0); category->def->initialized = category->def->constant = 1; + category->def->nosave = 1; pr_category = &G_STRUCT (pr_category_t, category->def->ofs); EMIT_STRING (pr_category->category_name, category->name); EMIT_STRING (pr_category->class_name, class->name); @@ -203,6 +204,7 @@ class_begin (class_type_t *class_type) va ("_OBJ_METACLASS_%s", class->name), pr.scope, st_static); meta_def->initialized = meta_def->constant = 1; + meta_def->nosave = 1; meta = &G_STRUCT (pr_class_t, meta_def->ofs); EMIT_STRING (meta->class_pointer, class->name); if (class->super_class) @@ -215,6 +217,7 @@ class_begin (class_type_t *class_type) class->name)); class->def->initialized = class->def->constant = 1; + class->def->nosave = 1; cls = &G_STRUCT (pr_class_t, class->def->ofs); EMIT_DEF (cls->class_pointer, meta_def); if (class->super_class) { @@ -240,6 +243,7 @@ emit_class_ref (const char *class_name) if (def->initialized) return; def->initialized = def->constant = 1; + def->nosave = 1; ref = get_def (&type_integer, va (".obj_class_name_%s", class_name), pr.scope, st_extern); if (!ref->external) @@ -257,6 +261,7 @@ emit_class_name (const char *class_name) if (def->initialized) return; def->initialized = def->constant = 1; + def->nosave = 1; G_INT (def->ofs) = 0; } @@ -271,6 +276,7 @@ emit_category_name (const char *class_name, const char *category_name) if (def->initialized) return; def->initialized = def->constant = 1; + def->nosave = 1; G_INT (def->ofs) = 0; } @@ -573,6 +579,7 @@ class_pointer_def (class_t *class) if (def->initialized) return def; def->initialized = def->constant = 1; + def->nosave = 1; if (!class->def) class->def = class_def (&class_type, 1); if (!class->def->external) @@ -622,6 +629,7 @@ class_finish_module (void) new_struct_field (symtab_type, &type_pointer, 0, vis_public); symtab_def = get_def (symtab_type, "_OBJ_SYMTAB", pr.scope, st_static); symtab_def->initialized = symtab_def->constant = 1; + symtab_def->nosave = 1; symtab = &G_STRUCT (pr_symtab_t, symtab_def->ofs); symtab->cls_def_cnt = num_classes; symtab->cat_def_cnt = num_categories; @@ -645,6 +653,7 @@ class_finish_module (void) module_def = get_def (type_module, "_OBJ_MODULE", pr.scope, st_static); module_def->initialized = module_def->constant = 1; + module_def->nosave = 1; module = &G_STRUCT (pr_module_t, module_def->ofs); module->size = type_size (type_module); EMIT_STRING (module->name, options.output_file); @@ -742,6 +751,7 @@ emit_protocol (protocol_t *protocol) va ("_OBJ_PROTOCOL_%s", protocol->name), pr.scope, st_static); proto_def->initialized = proto_def->constant = 1; + proto_def->nosave = 1; proto = &G_STRUCT (pr_protocol_t, proto_def->ofs); proto->class_pointer = 0; EMIT_STRING (proto->protocol_name, protocol->name); @@ -774,6 +784,7 @@ emit_protocol_list (protocollist_t *protocols, const char *name) va ("_OBJ_PROTOCOLS_%s", name), pr.scope, st_static); proto_list_def->initialized = proto_list_def->constant = 1; + proto_list_def->nosave = 1; proto_list = &G_STRUCT (pr_protocol_list_t, proto_list_def->ofs); proto_list->next = 0; proto_list->count = protocols->count; diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 01823e77c..f6bd0f880 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -288,6 +288,7 @@ get_def (type_t *type, const char *name, scope_t *scope, pr.entity_data); reloc_def_field (def, def->ofs); def->constant = 1; + def->nosave = 1; } if (type->aux_type->type == ev_vector) { diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index fcc5a253a..2804c037f 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -264,6 +264,7 @@ emit_assign_expr (int oper, expr_t *e) size); def_a->ofs = ofs; def_a->constant = 0; + def_a->nosave = 1; if (options.warnings.cow) warning (e1, "assignment to constant %s (Moooooooo!)", def_a->name); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index e34b4a068..f3936cf96 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -665,6 +665,7 @@ new_this_expr (void) def_t *def = get_def (type, ".this", pr.scope, st_extern); def_initialized (def); + def->nosave = 1; return new_def_expr (def); } @@ -675,6 +676,7 @@ param_expr (const char *name, type_t *type) expr_t *def_expr; def_initialized (def); + def->nosave = 1; def_expr = new_def_expr (def); return unary_expr ('.', address_expr (def_expr, 0, type)); } diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 2d1419b48..727fc0617 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -226,6 +226,7 @@ void build_function (function_t *f) { f->def->constant = 1; + f->def->nosave = 1; f->def->initialized = 1; G_FUNCTION (f->def->ofs) = f->function_num; } diff --git a/tools/qfcc/source/immediate.c b/tools/qfcc/source/immediate.c index 92011087b..d3ad25db0 100644 --- a/tools/qfcc/source/immediate.c +++ b/tools/qfcc/source/immediate.c @@ -237,6 +237,7 @@ ReuseConstant (expr_t *expr, def_t *def) free_location (def); def->ofs = cn->ofs; def->initialized = def->constant = 1; + def->nosave = 1; cn = def; } else { if (cn->type != type) { @@ -261,6 +262,7 @@ ReuseConstant (expr_t *expr, def_t *def) cn->ofs = new_location (type, pr.near_data); } cn->initialized = cn->constant = 1; + cn->nosave = 1; // copy the immediate to the global area switch (e.type) { case ex_string: @@ -340,6 +342,7 @@ clear_immediates (void) imm = calloc (1, sizeof (immediate_t)); imm->def = get_def (&type_zero, ".zero", pr.scope, st_extern); + imm->def->nosave = 1; Hash_AddElement (string_imm_defs, imm); Hash_AddElement (float_imm_defs, imm); diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 806047cc0..dcbcc88ed 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -92,19 +92,20 @@ typedef union defref_s { typedef struct builtin_sym_s { const char *name; type_t *type; + unsigned flags; } builtin_sym_t; static builtin_sym_t builtin_symbols[] = { - {".zero", &type_zero}, - {".return", &type_param}, - {".param_0", &type_param}, - {".param_1", &type_param}, - {".param_2", &type_param}, - {".param_3", &type_param}, - {".param_4", &type_param}, - {".param_5", &type_param}, - {".param_6", &type_param}, - {".param_7", &type_param}, + {".zero", &type_zero, QFOD_NOSAVE}, + {".return", &type_param, QFOD_NOSAVE}, + {".param_0", &type_param, QFOD_NOSAVE}, + {".param_1", &type_param, QFOD_NOSAVE}, + {".param_2", &type_param, QFOD_NOSAVE}, + {".param_3", &type_param, QFOD_NOSAVE}, + {".param_4", &type_param, QFOD_NOSAVE}, + {".param_5", &type_param, QFOD_NOSAVE}, + {".param_6", &type_param, QFOD_NOSAVE}, + {".param_7", &type_param, QFOD_NOSAVE}, }; static defref_t *free_defrefs; @@ -655,7 +656,7 @@ merge_defgroups (void) static void define_def (const char *name, etype_t basic_type, const char *full_type, - int size, int v) + unsigned flags, int size, int v) { qfo_def_t d; pr_type_t *val = calloc (size, sizeof (pr_type_t)); @@ -667,7 +668,7 @@ define_def (const char *name, etype_t basic_type, const char *full_type, d.full_type = strpool_addstr (type_strings, full_type); d.name = strpool_addstr (strings, name); d.ofs = data->size; - d.flags = QFOD_GLOBAL; + d.flags = QFOD_GLOBAL | flags; if (basic_type == ev_field) { d.relocs = relocs.num_relocs; d.num_relocs = 1; @@ -713,7 +714,7 @@ linker_begin (void) dstring_clearstr (encoding); encode_type (encoding, builtin_symbols[i].type); define_def (builtin_symbols[i].name, basic_type, encoding->str, - size, 0); + builtin_symbols[i].flags, size, 0); } } } @@ -851,11 +852,12 @@ linker_finish (void) if (d->basic_type == ev_entity) def_warning (d, "@self and self used together"); } - define_def (".self", ev_entity, "E", 1, 0); + define_def (".self", ev_entity, "E", 0, 1, 0); did_self = 1; } else if (strcmp (name, ".this") == 0 && !did_this) { entity_base = 0; - define_def (".this", ev_field, "F@", 1, entity->size); + define_def (".this", ev_field, "F@", QFOD_NOSAVE, 1, + entity->size); defspace_adddata (entity, 0, 1); did_this = 1; } diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 199576109..f1b074ef2 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -264,6 +264,7 @@ selector_def (const char *sel_id, const char *sel_types) sel_def = malloc (sizeof (sel_def_t)); sel_def->def = new_def (type_SEL.aux_type, ".imm", pr.scope); sel_def->def->initialized = sel_def->def->constant = 1; + sel_def->def->nosave = 1; sel_def->def->ofs = new_location (type_SEL.aux_type, pr.near_data); EMIT_STRING (G_INT (sel_def->def->ofs), sel_id); EMIT_STRING (G_INT (sel_def->def->ofs + 1), sel_types); @@ -302,6 +303,7 @@ emit_methods (methodlist_t *_methods, const char *name, int instance) methods_def = get_def (method_list, va ("_OBJ_%s_METHODS_%s", type, name), pr.scope, st_static); methods_def->initialized = methods_def->constant = 1; + methods_def->nosave = 1; methods = &G_STRUCT (pr_method_list_t, methods_def->ofs); methods->method_next = 0; methods->method_count = count; diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 11d48cb2e..2d3b875f8 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -138,6 +138,8 @@ flags (def_t *d) flags |= QFOD_LOCAL; if (d->system) flags |= QFOD_SYSTEM; + if (d->nosave) + flags |= QFOD_NOSAVE; return flags; } @@ -545,6 +547,7 @@ qfo_to_progs (qfo_t *qfo, pr_info_t *pr) pd->external = (qd->flags & QFOD_EXTERNAL) != 0; pd->local = (qd->flags & QFOD_LOCAL) != 0; pd->system = (qd->flags & QFOD_SYSTEM) != 0; + pd->nosave = (qd->flags & QFOD_NOSAVE) != 0; pd->file = qd->file; pd->line = qd->line; } diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index cbda561c0..198e32759 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -191,7 +191,8 @@ WriteData (int crc) dd = &globals[numglobaldefs++]; def_to_ddef (def, dd, 0); - if (!def->constant + if (!def->nosave + && !def->constant && def->type->type != ev_func && def->type->type != ev_field && def->global) dd->type |= DEF_SAVEGLOBAL; @@ -349,16 +350,29 @@ begin_compilation (void) static void setup_param_block (void) { - def_initialized (get_def (&type_zero, ".zero", pr.scope, st_global)); - def_initialized (get_def (&type_param, ".return", pr.scope, st_global)); - def_initialized (get_def (&type_param, ".param_0", pr.scope, st_global)); - def_initialized (get_def (&type_param, ".param_1", pr.scope, st_global)); - def_initialized (get_def (&type_param, ".param_2", pr.scope, st_global)); - def_initialized (get_def (&type_param, ".param_3", pr.scope, st_global)); - def_initialized (get_def (&type_param, ".param_4", pr.scope, st_global)); - def_initialized (get_def (&type_param, ".param_5", pr.scope, st_global)); - def_initialized (get_def (&type_param, ".param_6", pr.scope, st_global)); - def_initialized (get_def (&type_param, ".param_7", pr.scope, st_global)); + size_t i; + def_t *def; + static struct { + const char *name; + type_t *type; + } defs[] = { + {".zero", &type_zero}, + {".return", &type_param}, + {".param_0", &type_param}, + {".param_1", &type_param}, + {".param_2", &type_param}, + {".param_3", &type_param}, + {".param_4", &type_param}, + {".param_5", &type_param}, + {".param_6", &type_param}, + {".param_7", &type_param}, + }; + + for (i = 0; i < sizeof (defs) / sizeof (defs[0]); i++) { + def = get_def (defs[i].type, defs[i].name, pr.scope, st_global); + def->nosave = 1; + def_initialized (def); + } } static qboolean diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index ed4caa7d5..36035bc50 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -226,6 +226,7 @@ emit_struct(type_t *strct, const char *name) goto done; ivars_def = get_def (ivar_list, ivars_name->str, pr.scope, st_static); ivars_def->initialized = ivars_def->constant = 1; + ivars_def->nosave = 1; ivars = &G_STRUCT (pr_ivar_list_t, ivars_def->ofs); ivars->ivar_count = count; for (i = 0, field = strct->struct_head; field; field = field->next) {