diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 170fc7a50..836ec864d 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -126,6 +126,7 @@ typedef struct ex_pointer_s { int val; struct type_s *type; struct def_s *def; + struct tempop_s *tempop; } ex_pointer_t; typedef struct ex_func_s { diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 7a0b241ed..26904db3d 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -41,7 +41,7 @@ typedef enum { op_nil, } op_type_e; -typedef struct { +typedef struct tempop_s { struct def_s *def; int offset; struct type_s *type; diff --git a/tools/qfcc/include/value.h b/tools/qfcc/include/value.h index b4f22ee60..f2dc7195f 100644 --- a/tools/qfcc/include/value.h +++ b/tools/qfcc/include/value.h @@ -38,6 +38,7 @@ struct def_s; struct ex_value_s; +struct tempop_s; struct type_s; struct ex_value_s *new_string_val (const char *string_val); @@ -49,7 +50,8 @@ struct ex_value_s *new_field_val (int field_val, struct type_s *type, struct def_s *def); struct ex_value_s *new_func_val (int func_val, struct type_s *type); struct ex_value_s *new_pointer_val (int val, struct type_s *type, - struct def_s *def); + struct def_s *def, + struct tempop_s *tempop); struct ex_value_s *new_quaternion_val (const float *quaternion_val); struct ex_value_s *new_integer_val (int integer_val); struct ex_value_s *new_uinteger_val (int uinteger_val); diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index ffaee9be9..6745a7a94 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -884,7 +884,7 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) offset = dstDef->offset; dstDef = dstDef->alias; } - operands[2] = value_operand (new_pointer_val (offset, type, dstDef), + operands[2] = value_operand (new_pointer_val (offset, type, dstDef, 0), operands[1]->expr); st = build_statement ("", operands, var->expr); sblock_add_statement (block, st); diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 0073f3967..f859e4b9f 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -60,16 +60,40 @@ static def_t zero_def; +static def_t *get_operand_def (expr_t *expr, operand_t *op); + static def_t * -get_value_def (ex_value_t *value, type_t *type) +get_tempop_def (expr_t *expr, tempop_t *tempop, type_t *type) +{ + if (tempop->def) { + return tempop->def; + } + if (tempop->alias) { + def_t *tdef = get_operand_def (expr, tempop->alias); + int offset = tempop->offset; + tempop->def = alias_def (tdef, type, offset); + } + if (!tempop->def) { + tempop->def = temp_def (type); + } + return tempop->def; +} + +static def_t * +get_value_def (expr_t *expr, ex_value_t *value, type_t *type) { def_t *def; - if (type == &type_short) { + if (is_short (type)) { def = new_def (0, &type_short, 0, sc_extern); def->offset = value->v.short_val; return def; } + if (is_pointer (type) && value->v.pointer.tempop + && !value->v.pointer.def) { + value->v.pointer.def = get_tempop_def (expr, value->v.pointer.tempop, + type->t.fldptr.type); + } def = emit_value (value, 0); if (type != def->type) return alias_def (def, type, 0); @@ -85,25 +109,13 @@ get_operand_def (expr_t *expr, operand_t *op) case op_def: return op->o.def; case op_value: - return get_value_def (op->o.value, op->type); + return get_value_def (expr, op->o.value, op->type); case op_label: op->type = &type_short; zero_def.type = &type_short; return &zero_def; //FIXME case op_temp: - if (op->o.tempop.def) { - return op->o.tempop.def; - } - if (op->o.tempop.alias) { - def_t *tdef = get_operand_def (expr, op->o.tempop.alias); - int offset = op->o.tempop.offset; - type_t *type = op->type; - op->o.tempop.def = alias_def (tdef, type, offset); - } - if (!op->o.tempop.def) { - op->o.tempop.def = temp_def (op->type); - } - return op->o.tempop.def; + return get_tempop_def (expr, &op->o.tempop, op->type); case op_alias: return get_operand_def (expr, op->o.alias); case op_nil: diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 8a702714d..2cd64dc13 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -800,7 +800,7 @@ new_pointer_expr (int val, type_t *type, def_t *def) { expr_t *e = new_expr (); e->type = ex_value; - e->e.value = new_pointer_val (val, type, def); + e->e.value = new_pointer_val (val, type, def, 0); return e; } @@ -2152,7 +2152,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) if (is_array (type)) { e = e1; e->type = ex_value; - e->e.value = new_pointer_val (0, t, def); + e->e.value = new_pointer_val (0, t, def, 0); } else { e = new_pointer_expr (0, t, def); e->line = e1->line; @@ -2218,7 +2218,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) return e2; if (e->type == ex_value && e->e.value->lltype == ev_pointer && is_short_val (e2)) { - e->e.value = new_pointer_val (e->e.value->v.pointer.val + expr_short (e2), t, e->e.value->v.pointer.def); + e->e.value = new_pointer_val (e->e.value->v.pointer.val + expr_short (e2), t, e->e.value->v.pointer.def, 0); } else { if (!is_short_val (e2) || expr_short (e2)) { if (e->type == ex_expr && e->e.expr.op == '&') { diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 97198268c..424dadce5 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -197,7 +197,8 @@ new_func_val (int func_val, type_t *type) } ex_value_t * -new_pointer_val (int pointer_val, type_t *type, def_t *def) +new_pointer_val (int pointer_val, type_t *type, def_t *def, + struct tempop_s *tempop) { ex_value_t val; if (!type) { @@ -208,6 +209,7 @@ new_pointer_val (int pointer_val, type_t *type, def_t *def) val.v.pointer.val = pointer_val; val.v.pointer.type = type; val.v.pointer.def = def; + val.v.pointer.tempop = tempop; return find_value (&val); } diff --git a/tools/qfcc/test/struct-init-param.r b/tools/qfcc/test/struct-init-param.r index f043cfde3..c3dd5927b 100644 --- a/tools/qfcc/test/struct-init-param.r +++ b/tools/qfcc/test/struct-init-param.r @@ -40,18 +40,20 @@ Rect o = { { 5, 6}, {7, 8} }; int main (void) { int ret = 0; + int ok; + bar(&obj, nil, &o, obj.offset); - printf ("%d %d %d %d\n", o.offset.x, o.offset.y, - o.extent.width, o.extent.height); - if not (o.offset.x == 0 && o.offset.y == 0 - && o.extent.width == 3 && o.extent.height == 4) - ret |= 1; + ok = (o.offset.x == 0 && o.offset.y == 0 + && o.extent.width == 3 && o.extent.height == 4); + ret |= !ok; + printf ("%d %d %d %d %d\n", o.offset.x, o.offset.y, + o.extent.width, o.extent.height, ok); baz(&obj, nil, &o, obj.offset); - printf ("%d %d %d %d\n", o.offset.x, o.offset.y, - o.extent.width, o.extent.height); - if not (o.offset.x == 1 && o.offset.y == 2 - && o.extent.width == 3 && o.extent.height == 4) - ret |= 1; + ok = (o.offset.x == 1 && o.offset.y == 2 + && o.extent.width == 3 && o.extent.height == 4); + ret |= !ok; + printf ("%d %d %d %d %d\n", o.offset.x, o.offset.y, + o.extent.width, o.extent.height, ok); return ret; } diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index 69e660941..934c02cb0 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -138,6 +138,7 @@ init_qf (void) cvar_t *debug = Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "2", 0, 0, 0); + Cvar_Get ("pr_deadbeef_locals", "1", 0, 0, 0); if (options.trace > 1) { Cvar_SetValue (debug, 4);