diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 732610d94..ee1bcf713 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -397,6 +397,8 @@ extern int pr_error_count; void PR_NewLine (void); def_t *PR_GetDef (type_t *type, const char *name, def_t *scope, qboolean allocate); def_t *PR_NewDef (type_t *type, const char *name, def_t *scope); +def_t *PR_GetTempDef (type_t *type); +void PR_FreeTempDefs (); void PR_FlushScope (def_t *scope); void PR_PrintDefs (void); diff --git a/tools/qfcc/source/pr_comp.c b/tools/qfcc/source/pr_comp.c index 79ee63035..b2986381a 100644 --- a/tools/qfcc/source/pr_comp.c +++ b/tools/qfcc/source/pr_comp.c @@ -335,85 +335,88 @@ PR_ParseStatement (void) def_t *e; dstatement_t *patch1, *patch2; - if (PR_Check (tt_punct, "{")) { - do { - PR_ParseStatement (); - } while (!PR_Check (tt_punct, "}")); - return; - } - - if (PR_Check (tt_name, "return")) { - if (PR_Check (tt_punct, ";")) { - PR_Statement (op_return, 0, 0); - return; + do { + if (PR_Check (tt_punct, "{")) { + do { + PR_ParseStatement (); + } while (!PR_Check (tt_punct, "}")); + break; } - e = PR_Expression (TOP_PRIORITY); + if (PR_Check (tt_name, "return")) { + if (PR_Check (tt_punct, ";")) { + PR_Statement (op_return, 0, 0); + break; + } - PR_Expect (tt_punct, ";"); - PR_Statement (op_return, e, 0); + e = PR_Expression (TOP_PRIORITY); - return; - } + PR_Expect (tt_punct, ";"); + PR_Statement (op_return, e, 0); - if (PR_Check (tt_name, "while")) { - PR_Expect (tt_punct, "("); - patch2 = &statements[numstatements]; - e = PR_Expression (TOP_PRIORITY); - PR_Expect (tt_punct, ")"); - patch1 = &statements[numstatements]; - PR_Statement (op_ifnot, e, 0); - PR_ParseStatement (); - junkdef.ofs = patch2 - &statements[numstatements]; - PR_Statement (op_goto, &junkdef, 0); - patch1->b = &statements[numstatements] - patch1; - return; - } + break; + } - if (PR_Check (tt_name, "do")) { - patch1 = &statements[numstatements]; - PR_ParseStatement (); - PR_Expect (tt_name, "while"); - PR_Expect (tt_punct, "("); - e = PR_Expression (TOP_PRIORITY); - PR_Expect (tt_punct, ")"); - PR_Expect (tt_punct, ";"); - junkdef.ofs = patch1 - &statements[numstatements]; - PR_Statement (op_if, e, &junkdef); - return; - } - - if (PR_Check (tt_name, "local")) { - PR_ParseDefs (); - locals_end = numpr_globals; - return; - } - - if (PR_Check (tt_name, "if")) { - PR_Expect (tt_punct, "("); - e = PR_Expression (TOP_PRIORITY); - PR_Expect (tt_punct, ")"); - - patch1 = &statements[numstatements]; - PR_Statement (op_ifnot, e, 0); - - PR_ParseStatement (); - - if (PR_Check (tt_name, "else")) { + if (PR_Check (tt_name, "while")) { + PR_Expect (tt_punct, "("); patch2 = &statements[numstatements]; - PR_Statement (op_goto, 0, 0); - patch1->b = &statements[numstatements] - patch1; + e = PR_Expression (TOP_PRIORITY); + PR_Expect (tt_punct, ")"); + patch1 = &statements[numstatements]; + PR_Statement (op_ifnot, e, 0); PR_ParseStatement (); - patch2->a = &statements[numstatements] - patch2; - } else { + junkdef.ofs = patch2 - &statements[numstatements]; + PR_Statement (op_goto, &junkdef, 0); patch1->b = &statements[numstatements] - patch1; + break; } - return; - } + if (PR_Check (tt_name, "do")) { + patch1 = &statements[numstatements]; + PR_ParseStatement (); + PR_Expect (tt_name, "while"); + PR_Expect (tt_punct, "("); + e = PR_Expression (TOP_PRIORITY); + PR_Expect (tt_punct, ")"); + PR_Expect (tt_punct, ";"); + junkdef.ofs = patch1 - &statements[numstatements]; + PR_Statement (op_if, e, &junkdef); + break; + } - PR_Expression (TOP_PRIORITY); - PR_Expect (tt_punct, ";"); + if (PR_Check (tt_name, "local")) { + PR_ParseDefs (); + locals_end = numpr_globals; + break; + } + + if (PR_Check (tt_name, "if")) { + PR_Expect (tt_punct, "("); + e = PR_Expression (TOP_PRIORITY); + PR_Expect (tt_punct, ")"); + + patch1 = &statements[numstatements]; + PR_Statement (op_ifnot, e, 0); + + PR_ParseStatement (); + + if (PR_Check (tt_name, "else")) { + patch2 = &statements[numstatements]; + PR_Statement (op_goto, 0, 0); + patch1->b = &statements[numstatements] - patch1; + PR_ParseStatement (); + patch2->a = &statements[numstatements] - patch2; + } else { + patch1->b = &statements[numstatements] - patch1; + } + + break; + } + + PR_Expression (TOP_PRIORITY); + PR_Expect (tt_punct, ";"); + } while (0); + PR_FreeTempDefs (); } diff --git a/tools/qfcc/source/pr_def.c b/tools/qfcc/source/pr_def.c index 57686f5df..81d5804a5 100644 --- a/tools/qfcc/source/pr_def.c +++ b/tools/qfcc/source/pr_def.c @@ -27,6 +27,8 @@ def_t *pr_global_defs[MAX_REGS]; // to find def for a global variable int pr_edict_size; +static def_t *free_temps[ev_type_count]; +static def_t temp_scope; static hashtab_t *defs_by_name; @@ -143,6 +145,38 @@ PR_NewDef (type_t *type, const char *name, def_t *scope) return def; } +def_t * +PR_GetTempDef (type_t *type) +{ + int t = type->type; + def_t *d; + if (free_temps[t]) { + d = free_temps[t]; + free_temps[t] = d->next; + } else { + d = PR_NewDef (type, 0, 0); + d->ofs = numpr_globals; + numpr_globals += type_size[t]; + } + d->scope_next = temp_scope.scope_next; + temp_scope.scope_next = d; + return d; +} + +void +PR_FreeTempDefs (void) +{ + def_t *def; + etype_t type; + + for (def = temp_scope.scope_next; def; def = def->scope_next) { + type = def->type->type; + def->next = free_temps[type]; + free_temps[type] = def; + } + temp_scope.scope_next = 0; +} + void PR_FlushScope (def_t *scope) { diff --git a/tools/qfcc/source/pr_opcode.c b/tools/qfcc/source/pr_opcode.c index 4fabe64c3..810580192 100644 --- a/tools/qfcc/source/pr_opcode.c +++ b/tools/qfcc/source/pr_opcode.c @@ -154,11 +154,8 @@ PR_Statement (opcode_t * op, def_t * var_a, def_t * var_b) var_c = NULL; statement->c = 0; } else { // allocate result space - var_c = PR_NewDef (op->type_c->type, 0, 0); - var_c->ofs = numpr_globals; - - statement->c = numpr_globals; - numpr_globals += type_size[op->type_c->type->type]; + var_c = PR_GetTempDef (op->type_c->type); + statement->c = var_c->ofs; } if (op->right_associative)