mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-27 06:34:11 +00:00
Fix loading structs into params via an offset pointer.
For certain values of "fix" :/. The code is ugly, but it does the right thing: calculate the effect address and use the resulting pointer in a move instruction.
This commit is contained in:
parent
352be1f8bd
commit
bcaf3687c5
1 changed files with 35 additions and 8 deletions
|
@ -452,26 +452,53 @@ expr_address (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
}
|
}
|
||||||
|
|
||||||
static sblock_t *
|
static sblock_t *
|
||||||
expr_deref (sblock_t *sblock, expr_t *e, operand_t **op)
|
expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op)
|
||||||
{
|
{
|
||||||
type_t *type = e->e.expr.type;
|
type_t *type = deref->e.expr.type;
|
||||||
|
expr_t *e;
|
||||||
|
|
||||||
e = e->e.expr.e1;
|
e = deref->e.expr.e1;
|
||||||
if (e->type == ex_uexpr && e->e.expr.op == '&'
|
if (e->type == ex_uexpr && e->e.expr.op == '&'
|
||||||
&& e->e.expr.e1->type == ex_symbol) {
|
&& e->e.expr.e1->type == ex_symbol) {
|
||||||
*op = new_operand (op_symbol);
|
*op = new_operand (op_symbol);
|
||||||
(*op)->type = low_level_type (type);
|
(*op)->type = low_level_type (type);
|
||||||
(*op)->o.symbol = e->e.expr.e1->e.symbol;
|
(*op)->o.symbol = e->e.expr.e1->e.symbol;
|
||||||
} else if (e->type == ex_expr && e->e.expr.op == '&') {
|
} else if (e->type == ex_expr && e->e.expr.op == '&') {
|
||||||
statement_t *s = new_statement (".", e);
|
statement_t *s;
|
||||||
sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
|
operand_t *ptr = 0;
|
||||||
sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb);
|
operand_t *offs = 0;
|
||||||
|
sblock = statement_subexpr (sblock, e->e.expr.e1, &ptr);
|
||||||
|
sblock = statement_subexpr (sblock, e->e.expr.e2, &offs);
|
||||||
if (!*op) {
|
if (!*op) {
|
||||||
*op = new_operand (op_temp);
|
*op = new_operand (op_temp);
|
||||||
(*op)->type = low_level_type (type);
|
(*op)->type = low_level_type (type);
|
||||||
}
|
}
|
||||||
s->opc = *op;
|
if (low_level_type (type) == ev_void) {
|
||||||
sblock_add_statement (sblock, s);
|
operand_t *addr;
|
||||||
|
addr = new_operand (op_temp);
|
||||||
|
addr->type = ev_pointer;
|
||||||
|
s = new_statement ("&", e);
|
||||||
|
s->opa = ptr;
|
||||||
|
s->opb = offs;
|
||||||
|
s->opc = addr;
|
||||||
|
sblock_add_statement (sblock, s);
|
||||||
|
s = new_statement ("<MOVE>", deref);
|
||||||
|
s->opa = addr;
|
||||||
|
//FIXME make convenience routines
|
||||||
|
s->opb = new_operand (op_value);
|
||||||
|
s->opb->type = ev_short;
|
||||||
|
s->opb->o.value = calloc (1, sizeof (ex_value_t));
|
||||||
|
s->opb->o.value->type = ev_short;
|
||||||
|
s->opb->o.value->v.short_val = type_size (type);
|
||||||
|
s->opc = *op;
|
||||||
|
sblock_add_statement (sblock, s);
|
||||||
|
} else {
|
||||||
|
s = new_statement (".", deref);
|
||||||
|
s->opa = ptr;
|
||||||
|
s->opb = offs;
|
||||||
|
s->opc = *op;
|
||||||
|
sblock_add_statement (sblock, s);
|
||||||
|
}
|
||||||
} else if (e->type == ex_value && e->e.value.type == ev_pointer) {
|
} else if (e->type == ex_value && e->e.value.type == ev_pointer) {
|
||||||
*op = new_operand (op_pointer);
|
*op = new_operand (op_pointer);
|
||||||
(*op)->type = low_level_type (e->e.value.v.pointer.type);
|
(*op)->type = low_level_type (e->e.value.v.pointer.type);
|
||||||
|
|
Loading…
Reference in a new issue