[qfcc] Rewrite expr_deref to use addressing_mode

This cleans up the generation of load instructions such that they use
ptr+offset addressing instead of lea;load ptr.
This commit is contained in:
Bill Currie 2022-01-28 15:42:06 +09:00
parent e298f0d993
commit d3764c108a
1 changed files with 30 additions and 43 deletions

View File

@ -1432,52 +1432,39 @@ load_statement (operand_t *ptr, operand_t *offs, operand_t *op, expr_t *e)
static sblock_t * static sblock_t *
expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op)
{ {
type_t *type = deref->e.expr.type; type_t *load_type = deref->e.expr.type;
expr_t *e; expr_t *ptr_expr = deref->e.expr.e1;
operand_t *base = 0;
operand_t *offset = 0;
pr_ushort_t mode;
e = deref->e.expr.e1; sblock = addressing_mode (sblock, deref, &base, &offset, &mode);
if (e->type == ex_address && !e->e.address.offset
&& e->e.address.lvalue->type == ex_symbol) {
if (e->e.expr.e1->e.symbol->sy_type != sy_var)
internal_error (e, "address of non-var");
*op = def_operand (e->e.expr.e1->e.symbol->s.def, type, e);
} else if (e->type == ex_address && e->e.address.offset) {
statement_t *s;
operand_t *ptr = 0;
operand_t *offs = 0;
sblock = statement_subexpr (sblock, e->e.address.lvalue, &ptr);
sblock = statement_subexpr (sblock, e->e.address.offset, &offs);
if (!*op)
*op = temp_operand (type, e);
if (low_level_type (type) == ev_void) {
s = lea_statement (ptr, offs, e);
sblock_add_statement (sblock, s);
s = movep_statement (*op, s->opc, type, deref); switch (mode) {
sblock_add_statement (sblock, s); case 1://entity.field
} else { case 2://const indexed pointer
s = load_statement (ptr, offs, *op, deref); case 3://var indexed pointer
sblock_add_statement (sblock, s); break;
} default:
} else if (e->type == ex_value && e->e.value->lltype == ev_ptr) { internal_error (deref, "unexpected addressing mode: %d", mode);
ex_pointer_t *ptr = &e->e.value->v.pointer;
*op = def_operand (alias_def (ptr->def, ptr->type, ptr->val),
ptr->type, e);
} else {
statement_t *s;
operand_t *ptr = 0;
sblock = statement_subexpr (sblock, e, &ptr);
if (!*op)
*op = temp_operand (type, e);
if (low_level_type (type) == ev_void) {
s = movep_statement (*op, ptr, type, deref);
sblock_add_statement (sblock, s);
} else {
s = load_statement (ptr, short_operand (0, e), *op, deref);
sblock_add_statement (sblock, s);
}
} }
if (!*op) {
*op = temp_operand (load_type, deref);
}
statement_t *s;
if (low_level_type (load_type) == ev_void) {
s = lea_statement (base, offset, ptr_expr);
sblock_add_statement (sblock, s);
s = movep_statement (*op, s->opc, load_type, deref);
sblock_add_statement (sblock, s);
} else {
s = load_statement (base, offset, *op, deref);
sblock_add_statement (sblock, s);
}
return sblock; return sblock;
} }