From 7ef4c2776e66397ac8e70822bea11e43246ea0ab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 8 Jun 2001 06:32:15 +0000 Subject: [PATCH] Immidiate sharing now /works/ (shaved off two pr_globals from CustomTF, too:). Detect assignments to initialized globals and give an error, unless the --cow (copy on write) option is given, and then allocate a new global for the var, clear its initialized flag. Relocate all globals. --- tools/qfcc/include/qfcc.h | 8 ++++++ tools/qfcc/source/pr_comp.c | 16 ++++++++++-- tools/qfcc/source/pr_def.c | 45 ++++++++++++++++++++++++++++++++++ tools/qfcc/source/pr_imm.c | 15 +++++++++--- tools/qfcc/source/qfcc.c | 49 +++++++++++++++++++++++++------------ 5 files changed, 112 insertions(+), 21 deletions(-) diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index e6b58c0a3..b9d83b8d5 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -452,6 +452,8 @@ void PR_NewLine (void); def_t *PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate); def_t *PR_NewDef (type_t *type, const char *name, def_t *scope); +int PR_NewLocation (type_t *type); +void PR_FreeLocation (def_t *def); def_t *PR_GetTempDef (type_t *type, def_t *scope); void PR_FreeTempDefs (); void PR_ResetTempDefs (); @@ -524,3 +526,9 @@ extern int numfiles; int CopyString (const char *str); int ReuseString (const char *str); + +typedef struct { + int cow; // copy on write for constants +} options_t; + +extern options_t options; diff --git a/tools/qfcc/source/pr_comp.c b/tools/qfcc/source/pr_comp.c index 754fa54ae..6aa8c5cb3 100644 --- a/tools/qfcc/source/pr_comp.c +++ b/tools/qfcc/source/pr_comp.c @@ -309,10 +309,22 @@ PR_Expression (int priority) if (e->type->type == ev_pointer && e2->type->type != e->type->aux_type->type) PR_ParseError ("type mismatch for %s", op->name); - if (op->right_associative) + if (op->right_associative) { + if (e->initialized) { + if (options.cow) { + int size = type_size [e->type->type]; + int ofs = PR_NewLocation (e->type); + memcpy (pr_globals + ofs, pr_globals + e->ofs, size); + e->ofs = ofs; + e->initialized = 0; + } else { + PR_ParseError ("assignment to constant: %s", e->name); + } + } e = PR_Statement (op, e2, e); - else + } else { e = PR_Statement (op, e, e2); + } if (var_c.type != &type_void) // field access gets type from field e->type = e2->type->aux_type; diff --git a/tools/qfcc/source/pr_def.c b/tools/qfcc/source/pr_def.c index 6a8fc06ef..267403148 100644 --- a/tools/qfcc/source/pr_def.c +++ b/tools/qfcc/source/pr_def.c @@ -24,11 +24,17 @@ #include "qfcc.h" +typedef struct locref_s { + struct locref_s *next; + int ofs; +} locref_t; def_t *pr_global_defs[MAX_REGS]; // to find def for a global variable int pr_edict_size; static def_t *free_temps[4]; // indexted by type size static def_t temp_scope; +static locref_t *free_locs[4]; // indexted by type size +static locref_t *free_free_locs; static hashtab_t *defs_by_name; @@ -77,6 +83,7 @@ PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate) def = PR_NewDef (type, name, scope); Hash_Add (defs_by_name, def); + //FIXME: need to sort out location re-use def->ofs = *allocate; pr_global_defs[*allocate] = def; @@ -145,6 +152,44 @@ PR_NewDef (type_t *type, const char *name, def_t *scope) return def; } +int +PR_NewLocation (type_t *type) +{ + int size = type_size[type->type]; + locref_t *loc; + + if (free_locs[size]) { + loc = free_locs[size]; + free_locs[size] = loc->next; + + loc->next = free_free_locs; + free_free_locs = loc; + + return loc->ofs; + } + numpr_globals += size; + return numpr_globals - size; +} + +void +PR_FreeLocation (def_t *def) +{ + int size = type_size[def->type->type]; + locref_t *loc; + + if (!free_free_locs) { + free_free_locs = malloc (256 * sizeof (locref_t)); + for (loc = free_free_locs; loc - free_free_locs < 255; loc++) + loc->next = loc + 1; + loc->next = 0; + } + loc = free_free_locs; + free_free_locs = loc->next; + loc->ofs = def->ofs; + loc->next = free_locs[size]; + free_locs[size] = loc; +} + def_t * PR_GetTempDef (type_t *type, def_t *scope) { diff --git a/tools/qfcc/source/pr_imm.c b/tools/qfcc/source/pr_imm.c index 2c1129300..5bd17fe8a 100644 --- a/tools/qfcc/source/pr_imm.c +++ b/tools/qfcc/source/pr_imm.c @@ -71,6 +71,9 @@ PR_ParseImmediate (def_t *def) float_imm_defs = Hash_NewTable (16381, float_imm_get_key, 0, 0); vector_imm_defs = Hash_NewTable (16381, vector_imm_get_key, 0, 0); } + if (def && def->type != pr_immediate_type) { + PR_ParseError ("immediate type missmatch"); + } if (pr_immediate_type == &type_string) { cn = (def_t*) Hash_Find (string_imm_defs, pr_immediate_string); tab = string_imm_defs; @@ -92,8 +95,15 @@ PR_ParseImmediate (def_t *def) PR_ParseError ("weird immediate type"); } if (cn) { - if (cn->type != pr_immediate_type) printf("urk\n"); + if (cn->type != pr_immediate_type) + printf("urk\n"); //printf("found\n"); + if (def) { + PR_FreeLocation (def); + def->ofs = cn->ofs; + def->initialized = 1; + cn = def; + } PR_Lex (); return cn; } @@ -104,9 +114,8 @@ PR_ParseImmediate (def_t *def) cn = def; } else { cn = PR_NewDef (pr_immediate_type, "IMMEDIATE", 0); - cn->ofs = numpr_globals; + cn->ofs = PR_NewLocation (pr_immediate_type); pr_global_defs[cn->ofs] = cn; - numpr_globals += type_size[pr_immediate_type->type]; } cn->initialized = 1; // copy the immediate to the global area diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 8ff99ecf0..5db053cf6 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -37,6 +37,7 @@ #include "qfcc.h" +options_t options; char sourcedir[1024]; char destfile[1024]; @@ -604,6 +605,27 @@ PR_BeginCompilation (void *memory, int memsize) pr_error_count = 0; } +void +PR_RelocateRefs (def_t *def) +{ + statref_t *ref; + for (ref = def->refs; ref; ref = ref->next) { + switch (ref->field) { + case 0: + ref->statement->a = def->ofs; + break; + case 1: + ref->statement->b = def->ofs; + break; + case 2: + ref->statement->c = def->ofs; + break; + default: + abort(); + } + } +} + /* PR_FinishCompilation @@ -617,7 +639,6 @@ PR_FinishCompilation (void) qboolean errors = false; function_t *f; def_t *def; - statref_t *ref; // check to make sure all functions prototyped have code for (d = pr.def_head.next; d; d = d->next) { @@ -634,6 +655,12 @@ PR_FinishCompilation (void) if (errors) return !errors; + for (def = pr.def_head.next; def; def = def->next) { + if (def->scope) + continue; + PR_RelocateRefs (def); + } + for (f = pr_functions; f; f = f->next) { if (f->builtin) continue; @@ -641,22 +668,8 @@ PR_FinishCompilation (void) num_locals = f->def->num_locals; f->dfunc->parm_start = numpr_globals; for (def = f->def->scope_next; def; def = def->scope_next) { - for (ref = def->refs; ref; ref = ref->next) { - switch (ref->field) { - case 0: - ref->statement->a += numpr_globals; - break; - case 1: - ref->statement->b += numpr_globals; - break; - case 2: - ref->statement->c += numpr_globals; - break; - default: - abort(); - } - } def->ofs += numpr_globals; + PR_RelocateRefs (def); } } numpr_globals += num_locals; @@ -856,6 +869,10 @@ Options: \n\ } } + if (CheckParm ("--cow")) { + options.cow = 1; + } + if (strcmp (sourcedir, ".")) { printf ("Source directory: %s\n", sourcedir); }