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:
parent
872b13616d
commit
43d77900d5
|
@ -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);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue