Add support for binary alias expressions

Doesn't quite work yet.
This commit is contained in:
Bill Currie 2019-06-10 23:48:58 +09:00
parent 913b9f52e0
commit ee1f5f9478
4 changed files with 70 additions and 45 deletions

View file

@ -42,6 +42,7 @@ typedef enum {
typedef struct {
struct def_s *def;
int offset;
struct type_s *type;
struct flowvar_s *flowvar;
struct daglabel_s *daglabel;

View file

@ -320,8 +320,16 @@ print_subexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"r\"];\n", indent, "", e,
e->e.expr.e2);
}
dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e,
get_op_string (e->e.expr.op), e->line);
if (e->e.expr.op == 'A') {
dstring_t *typestr = dstring_newstr();
print_type_str (typestr, e->e.expr.type);
dasprintf (dstr, "%*se_%p [label=\"%s (%s)\\n%d\"];\n", indent, "", e,
get_op_string (e->e.expr.op), typestr->str, e->line);
dstring_delete (typestr);
} else {
dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e,
get_op_string (e->e.expr.op), e->line);
}
}
static void

View file

@ -109,6 +109,9 @@ check_valid_lvalue (expr_t *expr)
if (expr->e.expr.op == '.') {
return 0;
}
if (expr->e.expr.op == 'A') {
return check_valid_lvalue (expr->e.expr.e1);
}
break;
case ex_uexpr:
if (expr->e.expr.op == '.') {

View file

@ -804,6 +804,59 @@ expr_block (sblock_t *sblock, expr_t *e, operand_t **op)
return sblock;
}
static sblock_t *
expr_alias (sblock_t *sblock, expr_t *e, operand_t **op)
{
operand_t *aop = 0;
operand_t *top;
etype_t type;
def_t *def;
int offset = 0;
if (e->type == ex_expr) {
offset = expr_integer (e->e.expr.e2);
}
type = low_level_type (e->e.expr.type);
sblock = statement_subexpr (sblock, e->e.expr.e1, &aop);
if (aop->type == type) {
if (offset) {
internal_error (e, "offset alias of same type");
}
*op = aop;
return sblock;
}
if (aop->op_type == op_temp) {
while (aop->o.tempop.alias) {
aop = aop->o.tempop.alias;
if (aop->op_type != op_temp)
internal_error (e, "temp alias of non-temp var");
}
for (top = aop->o.tempop.alias_ops; top; top = top->next) {
if (top->type == type && top->o.tempop.offset == offset) {
break;
}
}
if (!top) {
top = new_operand (op_temp);
top->type = type;
top->o.tempop.alias = aop;
top->o.tempop.offset = offset;
top->next = aop->o.tempop.alias_ops;
aop->o.tempop.alias_ops = top;
}
*op = top;
} else if (aop->op_type == op_def) {
def = aop->o.def;
while (def->alias)
def = def->alias;
*op = def_operand (alias_def (def, ev_types[type], offset), 0);
} else {
internal_error (e, "invalid alias target: %s: %s",
optype_str (aop->op_type), operand_string (aop));
}
return sblock;
}
static sblock_t *
expr_expr (sblock_t *sblock, expr_t *e, operand_t **op)
{
@ -822,6 +875,9 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op)
case 'M':
sblock = expr_move (sblock, e, op);
break;
case 'A':
sblock = expr_alias (sblock, e, op);
break;
default:
opcode = convert_op (e->e.expr.op);
if (!opcode)
@ -838,49 +894,6 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op)
return sblock;
}
static sblock_t *
expr_alias (sblock_t *sblock, expr_t *e, operand_t **op)
{
operand_t *aop = 0;
operand_t *top;
etype_t type;
def_t *def;
type = low_level_type (e->e.expr.type);
sblock = statement_subexpr (sblock, e->e.expr.e1, &aop);
if (aop->type == type) {
*op = aop;
return sblock;
}
if (aop->op_type == op_temp) {
while (aop->o.tempop.alias) {
aop = aop->o.tempop.alias;
if (aop->op_type != op_temp)
internal_error (e, "temp alias of non-temp var");
}
for (top = aop->o.tempop.alias_ops; top; top = top->next)
if (top->type == type)
break;
if (!top) {
top = new_operand (op_temp);
top->type = type;
top->o.tempop.alias = aop;
top->next = aop->o.tempop.alias_ops;
aop->o.tempop.alias_ops = top;
}
*op = top;
} else if (aop->op_type == op_def) {
def = aop->o.def;
while (def->alias)
def = def->alias;
*op = def_operand (alias_def (def, ev_types[type], 0), 0);
} else {
internal_error (e, "invalid alias target: %s: %s",
optype_str (aop->op_type), operand_string (aop));
}
return sblock;
}
static sblock_t *
expr_cast (sblock_t *sblock, expr_t *e, operand_t **op)
{