[qfcc] Switch internal statement format to ruamoko

For the most part, it wasn't too bad as it's just a rotation of the
operands for some instructions (store, assign, branch), but dealing with
all the direct accesses to specific operands was a small pain. I am very
glad I made all those automated tests :)
This commit is contained in:
Bill Currie 2022-01-20 13:05:08 +09:00
parent 875d4dc7cf
commit a5a8017220
4 changed files with 94 additions and 54 deletions

View file

@ -1116,12 +1116,12 @@ generate_assignments (dag_t *dag, sblock_t *block, operand_t *src,
operand_t *operands[3] = {0, 0, 0};
daglabel_t *var;
operands[0] = fix_op_type (src, type);
operands[2] = fix_op_type (src, type);
for ( ; var_iter; var_iter = set_next (var_iter)) {
var = dag->labels[var_iter->element];
operands[1] = fix_op_type (var->op, type);
operands[0] = fix_op_type (var->op, type);
if (!dst)
dst = operands[1];
dst = operands[0];
st = build_statement ("assign", operands, var->expr);
sblock_add_statement (block, st);
@ -1172,15 +1172,15 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode)
case st_assign:
internal_error (0, "unexpected assignment node");
case st_ptrassign:
operands[0] = make_operand (dag, block, dagnode, 0);
operands[1] = make_operand (dag, block, dagnode, 1);
if (dagnode->children[2])
operands[2] = make_operand (dag, block, dagnode, 2);
operands[2] = make_operand (dag, block, dagnode, 0);
operands[0] = make_operand (dag, block, dagnode, 2);
if (dagnode->children[1])
operands[1] = make_operand (dag, block, dagnode, 1);
st = build_statement (dagnode->label->opcode, operands,
dagnode->label->expr);
sblock_add_statement (block, st);
// the source location is suitable for use in other nodes
dst = operands[0];
dst = operands[2];
break;
case st_move:
dst = generate_moves (dag, block, dagnode);
@ -1207,6 +1207,8 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode)
operands[0] = make_operand (dag, block, dagnode, 0);
if (dagnode->children[1])
operands[1] = make_operand (dag, block, dagnode, 1);
if (dagnode->children[2])
operands[2] = make_operand (dag, block, dagnode, 2);
st = build_statement (dagnode->label->opcode, operands,
dagnode->label->expr);
sblock_add_statement (block, st);

View file

@ -183,20 +183,36 @@ static void
emit_statement (statement_t *statement)
{
const char *opcode = statement->opcode;
operand_t *op_a, *op_b, *op_c;
def_t *def_a, *def_b, *def_c;
instruction_t *inst;
dstatement_t *s;
def_a = get_operand_def (statement->expr, statement->opa);
if (options.code.progsversion < PROG_VERSION
&& (strcmp (statement->opcode, "store") == 0
|| strcmp (statement->opcode, "assign") == 0
|| statement_is_cond (statement))) {
// the operands for assign, store and branch instructions are rotated
// when comparing v6/v6p and ruamoko
op_a = statement->opc;
op_b = statement->opa;
op_c = statement->opb;
} else {
op_a = statement->opa;
op_b = statement->opb;
op_c = statement->opc;
}
def_a = get_operand_def (statement->expr, op_a);
use_tempop (statement->opa, statement->expr);
def_b = get_operand_def (statement->expr, statement->opb);
def_b = get_operand_def (statement->expr, op_b);
use_tempop (statement->opb, statement->expr);
def_c = get_operand_def (statement->expr, statement->opc);
def_c = get_operand_def (statement->expr, op_c);
use_tempop (statement->opc, statement->expr);
inst = opcode_find (opcode, statement->opa, statement->opb, statement->opc);
inst = opcode_find (opcode, op_a, op_b, op_c);
if (!inst) {
print_expr (statement->expr);
printf ("%d ", pr.code->size);
print_statement (statement);
internal_error (statement->expr, "ice ice baby");
}
@ -225,9 +241,9 @@ emit_statement (statement_t *statement)
add_statement_def_ref (def_b, s, 1);
add_statement_def_ref (def_c, s, 2);
add_statement_op_ref (statement->opa, s, 0);
add_statement_op_ref (statement->opb, s, 1);
add_statement_op_ref (statement->opc, s, 2);
add_statement_op_ref (op_a, s, 0);
add_statement_op_ref (op_b, s, 1);
add_statement_op_ref (op_c, s, 2);
}
void

View file

@ -1149,9 +1149,11 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill,
operand_t *operands[FLOW_OPERANDS])
{
int i, start, calln = -1;
operand_t *src_op = 0;
operand_t *res_op = 0;
operand_t *aux_op1 = 0;
operand_t *aux_op2 = 0;
operand_t *aux_op3 = 0;
if (use) {
set_empty (use);
@ -1191,11 +1193,11 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill,
}
break;
case st_assign:
flow_add_op_var (def, s->opb, 0);
flow_add_op_var (use, s->opa, 1);
flow_add_op_var (def, s->opa, 0);
flow_add_op_var (use, s->opc, 1);
if (operands) {
operands[0] = s->opb;
operands[1] = s->opa;
operands[0] = s->opa;
operands[1] = s->opc;
}
break;
case st_ptrassign:
@ -1205,23 +1207,28 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill,
case st_ptrmemset:
flow_add_op_var (use, s->opa, 1);
flow_add_op_var (use, s->opb, 1);
aux_op1 = s->opb;
if (!strcmp (s->opcode, "move")
|| !strcmp (s->opcode, "memset")) {
flow_add_op_var (def, s->opc, 0);
src_op = s->opa;
res_op = s->opc;
} else if (!strcmp (s->opcode, "movep")) {
flow_add_op_var (use, s->opc, 0);
aux_op2 = flow_analyze_pointer_operand (s->opa, use);
aux_op3 = flow_analyze_pointer_operand (s->opa, use);
res_op = flow_analyze_pointer_operand (s->opc, def);
aux_op1 = s->opc;
src_op = s->opa;
aux_op2 = s->opc;
} else if (!strcmp (s->opcode, "memsetp")) {
flow_add_op_var (use, s->opc, 0);
res_op = flow_analyze_pointer_operand (s->opc, def);
aux_op1 = s->opc;
src_op = s->opa;
aux_op2 = s->opc;
} else if (!strcmp (s->opcode, "store")) {
flow_add_op_var (use, s->opc, 1);
res_op = flow_analyze_pointer_operand (s->opb, def);
aux_op1 = s->opc;
flow_add_op_var (use, s->opb, 1);
res_op = flow_analyze_pointer_operand (s->opa, def);
src_op = s->opc;
aux_op2 = s->opa;
} else {
internal_error (s->expr, "unexpected opcode '%s' for %d",
s->opcode, s->type);
@ -1231,10 +1238,10 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill,
}
if (operands) {
operands[0] = res_op;
operands[1] = s->opa;
operands[2] = s->opb;
operands[3] = aux_op1;
operands[4] = aux_op2;
operands[1] = src_op;
operands[2] = aux_op1;
operands[3] = aux_op2;
operands[4] = aux_op3;
}
break;
case st_state:
@ -1296,14 +1303,21 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill,
}
break;
case st_flow:
if (strcmp (s->opcode, "jump") != 0) {
if (statement_is_goto (s)) {
// opa is just a label
} else if (statement_is_jumpb (s)) {
flow_add_op_var (use, s->opa, 1);
if (strcmp (s->opcode, "jumpb") == 0)
flow_add_op_var (use, s->opb, 1);
flow_add_op_var (use, s->opb, 1);
} else if (statement_is_cond (s)) {
flow_add_op_var (use, s->opc, 1);
} else {
internal_error (s->expr, "unexpected flow statement: %s",
s->opcode);
}
if (operands) {
operands[1] = s->opa;
operands[2] = s->opb;
operands[3] = s->opc;
}
break;
}

View file

@ -642,14 +642,22 @@ statement_is_return (statement_t *s)
return !strncmp (s->opcode, "return", 6);
}
static ex_label_t **
statement_get_labelref (statement_t *s)
{
if (statement_is_cond (s)
|| statement_is_goto (s)
|| statement_is_jumpb (s)) {
return &s->opa->label;
}
return 0;
}
sblock_t *
statement_get_target (statement_t *s)
{
if (statement_is_cond (s))
return s->opb->label->dest;
if (statement_is_goto (s))
return s->opa->label->dest;
return 0;
ex_label_t **label = statement_get_labelref (s);
return label ? (*label)->dest : 0;
}
sblock_t **
@ -961,9 +969,9 @@ dereference_dst:
ofs = 0;
}
s = new_statement (type, opcode, e);
s->opa = src;
s->opb = dst;
s->opc = ofs;
s->opa = dst;
s->opb = ofs;
s->opc = src;
sblock_add_statement (sblock, s);
return sblock;
}
@ -1038,8 +1046,8 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op)
sblock = statement_subexpr (sblock, a, &arg);
if (arg != p) {
s = new_statement (st_assign, "assign", a);
s->opa = arg;
s->opb = p;
s->opa = p;
s->opc = arg;
sblock_add_statement (sblock, s);
}
}
@ -1086,8 +1094,8 @@ statement_branch (sblock_t *sblock, expr_t *e)
} else {
opcode = opcodes [e->e.branch.type];
s = new_statement (st_flow, opcode, e);
sblock = statement_subexpr (sblock, e->e.branch.test, &s->opa);
s->opb = label_operand (e->e.branch.target);
sblock = statement_subexpr (sblock, e->e.branch.test, &s->opc);
s->opa = label_operand (e->e.branch.target);
}
sblock_add_statement (sblock, s);
@ -1928,14 +1936,15 @@ thread_jumps (sblock_t *blocks)
(*label)->symbol = 0;
}
} else if (statement_is_cond (s)) {
label = &s->opb->label;
label = &s->opa->label;
} else {
continue;
}
for (l = *label;
l->dest && l->dest->statements
&& statement_is_goto (l->dest->statements);
l = l->dest->statements->opa->label) {
l = *statement_get_labelref (l->dest->statements)) {
// empty loop
}
if (l != *label) {
unuse_label (*label);
@ -1988,11 +1997,12 @@ remove_dead_blocks (sblock_t *blocks)
s = (statement_t *) sblock->tail;
if (statement_is_cond (s)
&& sb->statements && statement_is_goto (sb->statements)
&& s->opb->label->dest == sb->next) {
&& statement_get_target (s) == sb->next) {
debug (0, "merging if/goto %p %p", sblock, sb);
unuse_label (s->opb->label);
s->opb->label = sb->statements->opa->label;
s->opb->label->used++;
ex_label_t **labelref = statement_get_labelref(s);
unuse_label (*labelref);
*labelref = *statement_get_labelref (sb->statements);
(*labelref)->used++;
invert_conditional (s);
sb->reachable = 0;
for (sb = sb->next; sb; sb = sb->next)
@ -2014,10 +2024,8 @@ remove_dead_blocks (sblock_t *blocks)
if (sb->statements) {
s = (statement_t *) sb->tail;
if (statement_is_goto (s))
label = s->opa->label;
else if (statement_is_cond (s))
label = s->opb->label;
ex_label_t **labelref = statement_get_labelref (s);
label = labelref ? *labelref : 0;
}
unuse_label (label);
did_something = 1;