Rewrite dag_gencode to use statement/node types.

It now seems to generate correct code for each node. However, node order is
still incorrect in places (foo++ is being generated as ++foo). quattest.r
actually executes and produces the right output :)
This commit is contained in:
Bill Currie 2012-11-16 22:09:49 +09:00
parent 872b13616d
commit 43d77900d5
3 changed files with 93 additions and 65 deletions

View File

@ -37,9 +37,10 @@
#include "QF/pr_comp.h" #include "QF/pr_comp.h"
#include "statements.h"
struct dstring_s; struct dstring_s;
struct flownode_s; struct flownode_s;
struct sblock_s;
typedef struct daglabel_s { typedef struct daglabel_s {
/// \name attached identifer linked list /// \name attached identifer linked list
@ -58,6 +59,7 @@ typedef struct dagnode_s {
int print_count; ///< used to avoid double printing nodes int print_count; ///< used to avoid double printing nodes
int is_child; ///< true if a child node int is_child; ///< true if a child node
int cost; ///< cost of this node in temp vars int cost; ///< cost of this node in temp vars
st_type_t type; ///< type of node (st_node = leaf)
daglabel_t *label; ///< ident/const if leaf node, or operator daglabel_t *label; ///< ident/const if leaf node, or operator
etype_t tl; etype_t tl;
struct statement_s *statement; ///< statement generating this node struct statement_s *statement; ///< statement generating this node
@ -88,7 +90,7 @@ void print_dag (struct dstring_s *dstr, dagnode_t *node);
*/ */
dagnode_t *dag_create (const struct flownode_s *flownode); dagnode_t *dag_create (const struct flownode_s *flownode);
void dag_generate (struct sblock_s *block, const struct flownode_s *flownode); void dag_generate (sblock_t *block, const struct flownode_s *flownode);
//@} //@}

View File

@ -273,9 +273,7 @@ static statement_t *
build_statement (const char *opcode, operand_t *a, operand_t *b, operand_t *c, build_statement (const char *opcode, operand_t *a, operand_t *b, operand_t *c,
expr_t *expr) expr_t *expr)
{ {
if ((!a && (b || c)) || (a && !b && c)) statement_t *st = new_statement (st_none, opcode, expr);
internal_error (0, "invalid operand combo");
statement_t *st = new_statement (st_none, opcode, expr);//FIXME
st->opa = a; st->opa = a;
st->opb = b; st->opb = b;
st->opc = c; st->opc = c;
@ -321,6 +319,7 @@ dag_create (const flownode_t *flownode)
if (!n) { if (!n) {
n = new_node (); n = new_node ();
n->statement = s; n->statement = s;
n->type = s->type;
n->label = op; n->label = op;
n->a = ny; n->a = ny;
n->b = nz; n->b = nz;
@ -420,73 +419,99 @@ fix_op_type (operand_t *op, etype_t type)
return op; return op;
} }
static operand_t *
generate_assignments (sblock_t *block, operand_t *src, daglabel_t *var)
{
statement_t *st;
operand_t *dst = 0;
while (var) {
operand_t *vop = fix_op_type (var->op, src->type);
if (!dst) {
dst = vop;
while (dst->op_type == op_alias)
dst = dst->o.alias;
}
st = build_statement ("=", src, vop, 0, 0);//FIXME expr
sblock_add_statement (block, st);
var = var->next;
}
return dst;
}
static operand_t * static operand_t *
dag_gencode (sblock_t *block, const dagnode_t *dagnode) dag_gencode (sblock_t *block, const dagnode_t *dagnode)
{ {
if (!dagnode->a) { operand_t *opa = 0, *opb = 0, *opc = 0;
statement_t *st; operand_t *dst = 0;
daglabel_t *var = 0; statement_t *st;
operand_t *op = fix_op_type (dagnode->label->op, dagnode->tl); daglabel_t *var;
if (dagnode->identifiers) { switch (dagnode->type) {
var = dagnode->identifiers; case st_none:
} if (!dagnode->label->op)
for (var = dagnode->identifiers; var; var = var->next) { internal_error (0, "non-leaf label in leaf node");
operand_t *vop = fix_op_type (var->op, op->type); dst = dagnode->label->op;
st = build_statement ("=", op, vop, 0, 0); if (dagnode->identifiers)
sblock_add_statement (block, st); dst = generate_assignments (block, dst, dagnode->identifiers);
} break;
return op; case st_expr:
} else { opa = fix_op_type (dag_gencode (block, dagnode->a), dagnode->ta);
statement_t *st; if (dagnode->b)
daglabel_t *var = 0; opb = fix_op_type (dag_gencode (block, dagnode->b),
operand_t *op_a = 0; dagnode->tb);
operand_t *op_b = 0; if (!(var = dagnode->identifiers)) {
operand_t *op_c = 0; opc = temp_operand (get_type (dagnode->statement->expr));
if (flow_is_cond (dagnode->statement))
op_b = dagnode->statement->opb;
if (dagnode->b && dagnode->c) {
op_a = dag_gencode (block, dagnode->a);
op_b = dag_gencode (block, dagnode->b);
op_c = dag_gencode (block, dagnode->c);
op_c = fix_op_type (op_c, dagnode->tc);
} else if (dagnode->b) {
if (dagnode->a->cost < dagnode->b->cost) {
op_b = dag_gencode (block, dagnode->b);
op_a = dag_gencode (block, dagnode->a);
} else { } else {
op_a = dag_gencode (block, dagnode->a); opc = fix_op_type (var->op,
op_b = dag_gencode (block, dagnode->b); extract_type (dagnode->statement->expr));
var = var->next;
} }
} else { dst = opc;
op_a = dag_gencode (block, dagnode->a); st = build_statement (dagnode->label->opcode, opa, opb, opc,
} dagnode->statement->expr);
if (op_a && op_b && get_type (dagnode->statement->expr)) {
if (dagnode->identifiers) {
op_c = dagnode->identifiers->op;
var = dagnode->identifiers->next;
op_c = fix_op_type (op_c,
extract_type (dagnode->statement->expr));
} else {
op_c = temp_operand (get_type (dagnode->statement->expr));
}
}
op_a = fix_op_type (op_a, dagnode->ta);
op_b = fix_op_type (op_b, dagnode->tb);
st = build_statement (dagnode->label->opcode, op_a, op_b, op_c,
dagnode->statement->expr);
sblock_add_statement (block, st);
while (var) {
operand_t *vop = fix_op_type (var->op, op_c->type);
st = build_statement ("=", op_c, vop, 0, 0);
sblock_add_statement (block, st); sblock_add_statement (block, st);
var = var->next; generate_assignments (block, opc, var);
} break;
return op_c; case st_assign:
internal_error (0, "unexpected assignment node");
case st_ptrassign:
opa = fix_op_type (dag_gencode (block, dagnode->a), dagnode->ta);
opb = fix_op_type (dag_gencode (block, dagnode->b), dagnode->tb);
if (dagnode->c)
opc = fix_op_type (dag_gencode (block, dagnode->c),
dagnode->tc);
st = build_statement (dagnode->label->opcode, opa, opb, opc,
dagnode->statement->expr);
sblock_add_statement (block, st);
break;
case st_move:
case st_state:
case st_func:
if (dagnode->a)
opa = fix_op_type (dag_gencode (block, dagnode->a),
dagnode->ta);
if (dagnode->b)
opb = fix_op_type (dag_gencode (block, dagnode->b),
dagnode->tb);
if (dagnode->c)
opc = fix_op_type (dag_gencode (block, dagnode->c),
dagnode->tc);
st = build_statement (dagnode->label->opcode, opa, opb, opc,
dagnode->statement->expr);
sblock_add_statement (block, st);
break;
case st_flow:
opa = fix_op_type (dag_gencode (block, dagnode->a), dagnode->ta);
if (dagnode->b)
opb = fix_op_type (dag_gencode (block, dagnode->b),
dagnode->tb);
st = build_statement (dagnode->label->opcode, opa, opb, 0,
dagnode->statement->expr);
sblock_add_statement (block, st);
break;
} }
return 0; return dst;
} }
void void

View File

@ -58,7 +58,8 @@ print_node_def (dstring_t *dstr, dagnode_t *node, int recurse)
return; return;
} }
dasprintf (dstr, " \"dagnode_%p\" [%slabel=\"%s\"];\n", node, dasprintf (dstr, " \"dagnode_%p\" [%slabel=\"%s\"];\n", node,
node->a ? "" : "shape=none,", daglabel_string (node->label)); node->type != st_none ? "" : "shape=none,",
daglabel_string (node->label));
if (recurse) { if (recurse) {
if (node->a) if (node->a)
print_node_def (dstr, node->a, 1); print_node_def (dstr, node->a, 1);