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

View file

@ -183,20 +183,36 @@ static void
emit_statement (statement_t *statement) emit_statement (statement_t *statement)
{ {
const char *opcode = statement->opcode; const char *opcode = statement->opcode;
operand_t *op_a, *op_b, *op_c;
def_t *def_a, *def_b, *def_c; def_t *def_a, *def_b, *def_c;
instruction_t *inst; instruction_t *inst;
dstatement_t *s; 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); 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); 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); 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) { if (!inst) {
print_expr (statement->expr); print_expr (statement->expr);
printf ("%d ", pr.code->size);
print_statement (statement); print_statement (statement);
internal_error (statement->expr, "ice ice baby"); 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_b, s, 1);
add_statement_def_ref (def_c, s, 2); add_statement_def_ref (def_c, s, 2);
add_statement_op_ref (statement->opa, s, 0); add_statement_op_ref (op_a, s, 0);
add_statement_op_ref (statement->opb, s, 1); add_statement_op_ref (op_b, s, 1);
add_statement_op_ref (statement->opc, s, 2); add_statement_op_ref (op_c, s, 2);
} }
void 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]) operand_t *operands[FLOW_OPERANDS])
{ {
int i, start, calln = -1; int i, start, calln = -1;
operand_t *src_op = 0;
operand_t *res_op = 0; operand_t *res_op = 0;
operand_t *aux_op1 = 0; operand_t *aux_op1 = 0;
operand_t *aux_op2 = 0; operand_t *aux_op2 = 0;
operand_t *aux_op3 = 0;
if (use) { if (use) {
set_empty (use); set_empty (use);
@ -1191,11 +1193,11 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill,
} }
break; break;
case st_assign: case st_assign:
flow_add_op_var (def, s->opb, 0); flow_add_op_var (def, s->opa, 0);
flow_add_op_var (use, s->opa, 1); flow_add_op_var (use, s->opc, 1);
if (operands) { if (operands) {
operands[0] = s->opb; operands[0] = s->opa;
operands[1] = s->opa; operands[1] = s->opc;
} }
break; break;
case st_ptrassign: 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: case st_ptrmemset:
flow_add_op_var (use, s->opa, 1); flow_add_op_var (use, s->opa, 1);
flow_add_op_var (use, s->opb, 1); flow_add_op_var (use, s->opb, 1);
aux_op1 = s->opb;
if (!strcmp (s->opcode, "move") if (!strcmp (s->opcode, "move")
|| !strcmp (s->opcode, "memset")) { || !strcmp (s->opcode, "memset")) {
flow_add_op_var (def, s->opc, 0); flow_add_op_var (def, s->opc, 0);
src_op = s->opa;
res_op = s->opc; res_op = s->opc;
} else if (!strcmp (s->opcode, "movep")) { } else if (!strcmp (s->opcode, "movep")) {
flow_add_op_var (use, s->opc, 0); 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); 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")) { } else if (!strcmp (s->opcode, "memsetp")) {
flow_add_op_var (use, s->opc, 0); flow_add_op_var (use, s->opc, 0);
res_op = flow_analyze_pointer_operand (s->opc, def); 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")) { } else if (!strcmp (s->opcode, "store")) {
flow_add_op_var (use, s->opc, 1); flow_add_op_var (use, s->opb, 1);
res_op = flow_analyze_pointer_operand (s->opb, def); res_op = flow_analyze_pointer_operand (s->opa, def);
aux_op1 = s->opc; src_op = s->opc;
aux_op2 = s->opa;
} else { } else {
internal_error (s->expr, "unexpected opcode '%s' for %d", internal_error (s->expr, "unexpected opcode '%s' for %d",
s->opcode, s->type); 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) { if (operands) {
operands[0] = res_op; operands[0] = res_op;
operands[1] = s->opa; operands[1] = src_op;
operands[2] = s->opb; operands[2] = aux_op1;
operands[3] = aux_op1; operands[3] = aux_op2;
operands[4] = aux_op2; operands[4] = aux_op3;
} }
break; break;
case st_state: case st_state:
@ -1296,14 +1303,21 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill,
} }
break; break;
case st_flow: 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); 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) { if (operands) {
operands[1] = s->opa; operands[1] = s->opa;
operands[2] = s->opb; operands[2] = s->opb;
operands[3] = s->opc;
} }
break; break;
} }

View file

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