[qfcc] Support pointers to temp operands

This is necessary for correctly taking the address of operands.
This commit is contained in:
Bill Currie 2020-03-16 12:15:55 +09:00
parent 2f07d9a310
commit a0c28a5ac5
9 changed files with 53 additions and 33 deletions

View file

@ -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 {

View file

@ -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;

View file

@ -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);

View file

@ -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 ("<MOVEP>", operands, var->expr);
sblock_add_statement (block, st);

View file

@ -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:

View file

@ -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 == '&') {

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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);