diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 47d162500..43d33bc3b 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -292,6 +292,7 @@ typedef struct def_s { int constant; // 1 when a declaration included "= immediate" statref_t *refs; // for relocations + int freed; // already freed from the scope int removed; // already removed from the symbol table int used; // unused local detection string_t file; // source file diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 40740746d..0b4127e12 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -194,6 +194,29 @@ emit_assign_expr (expr_t *e) return def_b; } +def_t * +emit_bind_expr (expr_t *e1, expr_t *e2) +{ + type_t *t1 = get_type (e1); + type_t *t2 = get_type (e2); + def_t *def; + + if (!e2 || e2->type != ex_temp) { + error (e1, "internal error"); + abort (); + } + def = emit_sub_expr (e1, e2->e.temp.def); + if (t1 != t2) { + def_t *tmp = PR_NewDef (t2, 0, def->scope); + tmp->ofs = def->ofs; + tmp->users = e2->e.temp.users; + tmp->freed = 1; // don't free this offset when freeing def + def = tmp; + } + e2->e.temp.def = def; + return e2->e.temp.def; +} + def_t * emit_sub_expr (expr_t *e, def_t *dest) { @@ -364,11 +387,7 @@ emit_expr (expr_t *e) emit_statement (e->line, op_state, def_a, def_b, 0); break; case 'b': - if (!e->e.expr.e2 || e->e.expr.e2->type != ex_temp) { - error (e, "internal error"); - abort (); - } - e->e.expr.e2->e.temp.def = emit_sub_expr (e->e.expr.e1, e->e.expr.e2->e.temp.def); + emit_bind_expr (e->e.expr.e1, e->e.expr.e2); break; case 'g': def_a = emit_sub_expr (e->e.expr.e1, 0); diff --git a/tools/qfcc/source/pr_def.c b/tools/qfcc/source/pr_def.c index 92d77e2d6..4823a4815 100644 --- a/tools/qfcc/source/pr_def.c +++ b/tools/qfcc/source/pr_def.c @@ -93,6 +93,7 @@ PR_GetArray (type_t *etype, const char *name, int size, def_t *scope, return def; def = PR_NewDef (type, name, scope); def->ofs = *allocate; + def->initialized = def->constant = 1; *allocate += pr_type_size [type->type] * size + 1; pr_global_defs[def->ofs] = def; G_INT (def->ofs) = def->ofs + 1; @@ -281,8 +282,11 @@ PR_FreeTempDefs (void) if (d->expr) d->expr->e.temp.def = 0; - d->next = free_temps[size]; - free_temps[size] = d; + if (!d->freed) { + d->next = free_temps[size]; + free_temps[size] = d; + d->freed = 1; + } } else { def = &(*def)->next; } diff --git a/tools/qfcc/source/pr_imm.c b/tools/qfcc/source/pr_imm.c index 22c4b2019..d7bf39dd4 100644 --- a/tools/qfcc/source/pr_imm.c +++ b/tools/qfcc/source/pr_imm.c @@ -136,7 +136,10 @@ PR_ReuseConstant (expr_t *expr, def_t *def) if (!def || def->type != &type_float) { sprintf (rep, "\001integer:%08X\001", e.e.integer_val); tab = integer_imm_defs; - type = &type_integer; + if (e.type == ex_uinteger) + type = &type_uinteger; + else + type = &type_integer; break; } if (e.type == ex_uinteger) @@ -186,7 +189,12 @@ PR_ReuseConstant (expr_t *expr, def_t *def) // allocate a new one // always share immediates if (def) { - cn = def; + if (def->type != type) { + cn = PR_NewDef (type, ".imm", 0); + cn->ofs = def->ofs; + } else { + cn = def; + } } else { cn = PR_NewDef (type, ".imm", 0); cn->ofs = PR_NewLocation (type); diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 7332ba15f..bb0d7e025 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -255,7 +255,6 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, test->file = sw_val->file; if (tree->low == tree->high) { - printf ("%3d\n", tree->low->e.integer_val); branch = new_binary_expr ('n', test, tree->labels[0]); branch->line = sw_val->line; branch->file = sw_val->file; @@ -284,7 +283,7 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, int i; expr_t *range = binary_expr ('-', tree->high, tree->low); - printf ("%3d %3d\n", low, high); + range->type = ex_uinteger; def = PR_GetArray (&type_uinteger, name, high - low + 1, 0, &numpr_globals); @@ -299,7 +298,6 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, branch->file = sw_val->file; append_expr (sw, branch); } - tree->high->type = ex_uinteger; append_expr (sw, new_binary_expr ('b', temp, utemp)); test = binary_expr (GT, utemp, range); test->line = sw_val->line;