[qfcc] Rewrite operand_address to be much simpler

It now creates a pointer value and returns that rather than generating
an address statement.
This commit is contained in:
Bill Currie 2020-03-16 12:21:38 +09:00
parent a0c28a5ac5
commit b58deb5680

View file

@ -658,39 +658,42 @@ expr_address (sblock_t *sblock, expr_t *e, operand_t **op)
return sblock; return sblock;
} }
static sblock_t * static operand_t *
operand_address (sblock_t *sblock, operand_t *reference, operand_t **op, operand_address (operand_t *reference, expr_t *e)
expr_t *e)
{ {
statement_t *s; def_t *def;
type_t *type; type_t *type;
int offset = 0;
type = reference->type;
switch (reference->op_type) { switch (reference->op_type) {
case op_def: case op_def:
case op_temp: // assumes aliasing is only one level deep which should be the
case op_alias: // case
// build an address expression so dags can extract the correct def = reference->o.def;
// type. address_expr cannot be used because reference might not if (def->alias) {
// be something it likes offset = def->offset;
e = expr_file_line (new_unary_expr ('&', e), e); def = def->alias;
type = pointer_type (reference->type);
e->e.expr.type = type;
s = new_statement (st_expr, "&", e);
s->opa = reference;
s->opc = temp_operand (type, e);
sblock_add_statement (sblock, s);
if (op) {
*(op) = s->opc;
} }
return sblock; return value_operand (new_pointer_val (offset, type, def, 0), e);
case op_temp:
// assumes aliasing is only one level deep which should be the
// case
if (reference->o.tempop.alias) {
offset = reference->o.tempop.offset;
reference = reference->o.tempop.alias;
}
return value_operand (new_pointer_val (offset, type, 0,
&reference->o.tempop), e);
case op_alias:
//op_alias comes only from alias_operand and that is called
// by dags, so not expected
case op_value: case op_value:
case op_label: case op_label:
case op_nil: case op_nil:
break; break;
} }
internal_error ((*op)->expr, internal_error (e, "invalid operand type for operand address: %s",
"invalid operand type for operand address: %s",
op_type_names[reference->op_type]); op_type_names[reference->op_type]);
} }
@ -763,7 +766,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src)
*op = src; *op = src;
} }
if (is_indirect (dst_expr) || is_indirect (src_expr)) { if (is_indirect (dst_expr) || is_indirect (src_expr)) {
sblock = operand_address (sblock, src, &src, src_expr); src = operand_address (src, src_expr);
goto dereference_dst; goto dereference_dst;
} }
} }