Resurrect alias operands.

It turns out they are necessary for the code output from dags. This fixes
the ice for *to = *from++;
This commit is contained in:
Bill Currie 2012-12-11 15:52:37 +09:00
parent 8452f69a21
commit 7607c7d649
5 changed files with 45 additions and 6 deletions

View file

@ -37,6 +37,7 @@ typedef enum {
op_value,
op_label,
op_temp,
op_alias,
} op_type_e;
typedef struct {
@ -59,6 +60,7 @@ typedef struct operand_s {
struct ex_value_s *value;
struct ex_label_s *label;
tempop_t tempop;
struct operand_s *alias;
} o;
} operand_t;
@ -111,6 +113,7 @@ struct dstring_s;
const char *optype_str (op_type_e type);
operand_t *temp_operand (struct type_s *type);
operand_t *alias_operand (etype_t type, operand_t *op);
sblock_t *new_sblock (void);
statement_t *new_statement (st_type_t type, const char *opcode,
struct expr_s *expr);

View file

@ -560,6 +560,8 @@ build_statement (const char *opcode, operand_t **operands, expr_t *expr)
for (i = 0; i < 3; i++) {
if ((op = operands[i])) {
while (op->op_type == op_alias)
op = op->o.alias;
if (op->op_type == op_temp) {
while (op->o.tempop.alias)
op = op->o.tempop.alias;
@ -606,6 +608,13 @@ dag_calc_node_costs (dagnode_t *dagnode)
}
}
#endif
static operand_t *
fix_op_type (operand_t *op, etype_t type)
{
if (op && op->op_type != op_label && op->type != type)
op = alias_operand (type, op);
return op;
}
static operand_t *
generate_assignments (dag_t *dag, sblock_t *block, operand_t *src,
@ -616,10 +625,10 @@ generate_assignments (dag_t *dag, sblock_t *block, operand_t *src,
operand_t *operands[3] = {0, 0, 0};
daglabel_t *var;
operands[0] = src;
operands[0] = fix_op_type (src, type);
for ( ; var_iter; var_iter = set_next (var_iter)) {
var = dag->labels[var_iter->value];
operands[1] = var->op;
operands[1] = fix_op_type (var->op, type);
if (!dst)
dst = operands[1];
@ -635,6 +644,7 @@ make_operand (dag_t *dag, sblock_t *block, const dagnode_t *dagnode, int index)
operand_t *op;
op = dagnode->children[index]->value;
op = fix_op_type (op, dagnode->types[index]);
return op;
}
@ -655,9 +665,6 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode)
dst = dagnode->label->op;
if ((var_iter = set_first (dagnode->identifiers))) {
type = dst->type;
//if (dst->op_type == op_def
// && !strcmp (dst->o.def->name, ".return"))
// type = dag->flownode->return_type.in;
dst = generate_assignments (dag, block, dst, var_iter, type);
}
break;
@ -671,7 +678,7 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode)
} else {
daglabel_t *var = dag->labels[var_iter->value];
operands[2] = var->op;
operands[2] = fix_op_type (var->op, type);
var_iter = set_next (var_iter);
}
dst = operands[2];

View file

@ -96,6 +96,8 @@ get_operand_def (expr_t *expr, operand_t *op)
if (!op->o.tempop.def)
op->o.tempop.def = temp_def (op->type, op->size);
return op->o.tempop.def;
case op_alias:
return get_operand_def (expr, op->o.alias);
}
return 0;
}

View file

@ -166,6 +166,8 @@ flowvar_get_def (flowvar_t *var)
return 0;
case op_temp:
return op->o.tempop.def;
case op_alias:
internal_error (0, "unexpected alias operand");
}
internal_error (0, "oops, blue pill");
return 0;

View file

@ -127,6 +127,13 @@ operand_string (operand_t *op)
op->o.tempop.alias,
op->o.tempop.alias->o.tempop.users);
return va ("<tmp %p:%d>", op, op->o.tempop.users);
case op_alias:
{
const char *alias = operand_string (op->o.alias);
char *buf = alloca (strlen (alias) + 1);
strcpy (buf, alias);
return va ("alias(%s,%s)", pr_type_name[op->type], buf);
}
}
return ("??");
}
@ -192,6 +199,10 @@ print_operand (operand_t *op)
if (op->o.tempop.def)
printf (" %s", op->o.tempop.def->name);
break;
case op_alias:
printf ("alias(%s,", pr_type_name[op->type]);
print_operand (op->o.alias);
printf (")");
}
}
@ -292,6 +303,20 @@ temp_operand (type_t *type)
return op;
}
operand_t *
alias_operand (etype_t type, operand_t *op)
{
operand_t *aop;
if (pr_type_size[type] != pr_type_size[op->type])
internal_error (0, "aliasing operand with type of diffent size");
aop = new_operand (op_alias);
aop->o.alias = op;
aop->type = type;
aop->size = pr_type_size[type];
return aop;
}
static operand_t *
short_operand (short short_val)
{