Rewrite dags to use sets.

While things are quite broken now (very incorrect code is being generated),
the dag is much easier to work with. The dag is now stored in an array of
nodes (the children pointers are still used for dagnode operands), and sets
are used for marking node parents, attached identifiers and (when done,
extra edges).
This commit is contained in:
Bill Currie 2012-11-17 21:14:42 +09:00
parent 0bb2fc1891
commit 12133bc02f
5 changed files with 241 additions and 249 deletions

View file

@ -43,11 +43,8 @@ struct dstring_s;
struct flownode_s; struct flownode_s;
typedef struct daglabel_s { typedef struct daglabel_s {
/// \name attached identifer linked list
//@{
struct daglabel_s *next; struct daglabel_s *next;
struct daglabel_s **prev; int number; ///< index into array of labels in dag_t
//@}
struct daglabel_s *daglabel_chain; ///< all labels created for a dag struct daglabel_s *daglabel_chain; ///< all labels created for a dag
const char *opcode; ///< not if op const char *opcode; ///< not if op
struct operand_s *op; ///< not if opcode; struct operand_s *op; ///< not if opcode;
@ -57,29 +54,41 @@ typedef struct daglabel_s {
typedef struct dagnode_s { typedef struct dagnode_s {
struct dagnode_s *next; struct dagnode_s *next;
int print_count; ///< used to avoid double printing nodes int number; ///< index into array of nodes in dag_t
int is_child; ///< true if a child node struct set_s *parents; ///< empty if root 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) 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;
/// \name child nodes /// \name child nodes
/// All three child nodes will be null if this node is a leaf /// if \a children[0] is null, the rest must be null as well. Similar for
/// If \a a is null, both \a b and \a c must also be null. If \a is not /// \a children[1].
/// null, either \a b or \a c or even both may be non-null. Both \a b and ///
/// \a c being non-null is reserved for the few opcodes that take three /// \a edges is the set of all nodes upon which this node depends. ie,
/// inputs (rcall2+, 3 op state, indirect move, indexed pointer assignment) /// they must be evaluated before this node is evaluted. So while nodes
/// \a b and \a c are used to help keep track of the original statement /// in \a edges may not be true children of this node, they are effective
/// operands /// children in the DAG. That is, \a edges is for producing a correct
/// topological sort of the DAG.
//@{ //@{
struct dagnode_s *a, *b, *c; struct dagnode_s *children[3];
etype_t ta, tb, tc; ///< desired type of each operand (to alias) etype_t types[3]; ///< desired type of each operand (to alias)
struct set_s *edges; ///< includes nodes pointed to by \a children
//@} //@}
daglabel_t *identifiers; ///< list of identifiers with value of this node struct set_s *identifiers; ///< set of identifiers attached to this node
} dagnode_t; } dagnode_t;
typedef struct dag_s {
struct dag_s *next;
dagnode_t **nodes; ///< array of all dagnodes in this dag
int num_nodes;
daglabel_t **labels; ///< array of all daglabels in this dag
int num_labels;;
struct set_s *roots; ///< set of root nodes
struct flownode_s *flownode;///< flow node this dag represents
} dag_t;
const char *daglabel_string (daglabel_t *label); const char *daglabel_string (daglabel_t *label);
void print_dag (struct dstring_s *dstr, dagnode_t *node); void print_dag (struct dstring_s *dstr, dag_t *dag);
/** Make a dag for a single basic block. /** Make a dag for a single basic block.
@ -88,9 +97,9 @@ void print_dag (struct dstring_s *dstr, dagnode_t *node);
variable information already computed. variable information already computed.
\return The dag representing the basic block. \return The dag representing the basic block.
*/ */
dagnode_t *dag_create (const struct flownode_s *flownode); dag_t *dag_create (const struct flownode_s *flownode);
void dag_generate (sblock_t *block, const struct flownode_s *flownode); void dag_generate (dag_t *dag, sblock_t *block);
//@} //@}

View file

@ -76,7 +76,7 @@ typedef struct flownode_s {
struct set_s *out; struct set_s *out;
} live_vars; } live_vars;
struct sblock_s *sblock; ///< original statement block struct sblock_s *sblock; ///< original statement block
struct dagnode_s *dag; ///< dag for this node struct dag_s *dag; ///< dag for this node
} flownode_t; } flownode_t;
typedef struct flowgraph_s { typedef struct flowgraph_s {

View file

@ -53,6 +53,7 @@
static daglabel_t *free_labels; static daglabel_t *free_labels;
static dagnode_t *free_nodes; static dagnode_t *free_nodes;
static dag_t *free_dags;
static daglabel_t *daglabel_chain; static daglabel_t *daglabel_chain;
@ -80,6 +81,14 @@ flush_daglabels (void)
} }
} }
static dag_t *
new_dag (void)
{
dag_t *dag;
ALLOC (256, dag_t, dags, dag);
return dag;
}
static daglabel_t * static daglabel_t *
new_label (void) new_label (void)
{ {
@ -87,6 +96,7 @@ new_label (void)
ALLOC (256, daglabel_t, labels, label); ALLOC (256, daglabel_t, labels, label);
label->daglabel_chain = daglabel_chain; label->daglabel_chain = daglabel_chain;
daglabel_chain = label; daglabel_chain = label;
label->number = -1;
return label; return label;
} }
@ -95,6 +105,9 @@ new_node (void)
{ {
dagnode_t *node; dagnode_t *node;
ALLOC (256, dagnode_t, nodes, node); ALLOC (256, dagnode_t, nodes, node);
node->parents = set_new ();
node->edges = set_new ();
node->identifiers = set_new ();
return node; return node;
} }
@ -210,22 +223,19 @@ node (operand_t *op)
static int static int
dagnode_match (const dagnode_t *n, const daglabel_t *op, dagnode_match (const dagnode_t *n, const daglabel_t *op,
const dagnode_t *y, const dagnode_t *z, const dagnode_t *w) dagnode_t *operands[3])
{ {
int i;
if (n->label->opcode != op->opcode) if (n->label->opcode != op->opcode)
return 0; return 0;
if (n->a && y && n->a->label->op != y->label->op) for (i = 0; i < 3; i++) {
return 0; if (n->children[i] && operands[i]
if (n->b && z && n->b->label->op != z->label->op) && n->children[i]->label->op != operands[i]->label->op )
return 0; return 0;
if (n->c && w && n->c->label->op != w->label->op) if ((!n->children[i]) ^ (!operands[i]))
return 0; return 0;
if ((!n->a) ^ (!y)) }
return 0;
if ((!n->c) ^ (!z))
return 0;
if ((!n->b) ^ (!w))
return 0;
return 1; return 1;
} }
@ -254,165 +264,153 @@ dagnode_attach_label (dagnode_t *n, daglabel_t *l)
if (!op_is_identifer (l->op)) if (!op_is_identifer (l->op))
internal_error (0, "attempt to attach non-identifer label to dagnode " internal_error (0, "attempt to attach non-identifer label to dagnode "
"identifers"); "identifers");
if (n->identifiers) if (l->dagnode)
n->identifiers->prev = &l->next; set_remove (l->dagnode->identifiers, l->number);
l->next = n->identifiers;
l->prev = &n->identifiers;
l->dagnode = n; l->dagnode = n;
n->identifiers = l; set_add (n->identifiers, l->number);
} }
static void dag_t *
daglabel_detatch (daglabel_t *l)
{
if (l->next)
l->next->prev = l->prev;
*l->prev = l->next;
l->dagnode = 0;
}
static statement_t *
build_statement (const char *opcode, operand_t *a, operand_t *b, operand_t *c,
expr_t *expr)
{
statement_t *st = new_statement (st_none, opcode, expr);
st->opa = a;
st->opb = b;
st->opc = c;
return st;
}
dagnode_t *
dag_create (const flownode_t *flownode) dag_create (const flownode_t *flownode)
{ {
sblock_t *block = flownode->sblock; dag_t *dag;
sblock_t *block = flownode->sblock;
statement_t *s; statement_t *s;
dagnode_t *dagnodes = 0; dagnode_t **nodes;
dagnode_t **dagtail = &dagnodes; daglabel_t **labels;
dagnode_t *d; int num_statements = 0;
int num_nodes = 0;
int num_labels = 0;
int i;
flush_daglabels (); flush_daglabels ();
for (s = block->statements; s; s = s->next)
num_statements++;
// at most 4 per statement
nodes = alloca (num_statements * 4 * sizeof (dagnode_t));
// at most 3 per statement
labels = alloca (num_statements * 3 * sizeof (daglabel_t));
for (s = block->statements; s; s = s->next) { for (s = block->statements; s; s = s->next) {
operand_t *operands[4]; operand_t *operands[4];
dagnode_t *n = 0, *ny, *nz, *nw; dagnode_t *n = 0, *children[3] = {0, 0, 0};
daglabel_t *op, *lx; daglabel_t *op, *lx;
int i;
flow_analyze_statement (s, 0, 0, 0, operands); flow_analyze_statement (s, 0, 0, 0, operands);
if (!(ny = node (operands[1]))) { for (i = 0; i < 3; i++) {
ny = leaf_node (operands[1], s->expr); if (!(children[i] = node (operands[i + 1]))) {
if (s->type == st_assign) { children[i] = leaf_node (operands[i + 1], s->expr);
*dagtail = ny; if (children[i]) {
dagtail = &ny->next; children[i]->number = num_nodes;
nodes[num_nodes++] = children[i];
if (children[i]->label->number == -1) {
children[i]->label->number = num_labels;
labels[num_labels++] = children[i]->label;
}
}
} }
} }
if (!(nz = node (operands[2])))
nz = leaf_node (operands[2], s->expr);
if (!(nw = node (operands[3])))
nw = leaf_node (operands[3], s->expr);
op = opcode_label (s->opcode, s->expr); op = opcode_label (s->opcode, s->expr);
op->number = num_labels;
labels[num_labels++] = op;
if (s->type == st_assign) { if (s->type == st_assign) {
n = ny; n = children[0];
} else { } else {
for (n = dagnodes; n; n = n->next) n = 0;
if (dagnode_match (n, op, ny, nz, nw)) for (i = 0; i < num_nodes; i++) {
if (dagnode_match (nodes[i], op, children)) {
n = nodes[i];
break; break;
}
}
} }
if (!n) { if (!n) {
n = new_node (); n = new_node ();
n->type = s->type; n->type = s->type;
n->label = op; n->label = op;
n->a = ny; n->number = num_nodes;
n->b = nz; nodes[num_nodes++] = n;
n->c = nw; for (i = 0; i < 3; i++) {
if (ny) { n->children[i] = children[i];
ny->is_child = 1; if (n->children[i]) {
n->ta = operands[1]->type; set_add (n->children[i]->parents, n->number);
n->types[i] = operands[i + 1]->type;
}
} }
if (nz) {
nz->is_child = 1;
n->tb = operands[2]->type;
}
if (nw) {
nw->is_child = 1;
n->tc = operands[3]->type;
}
*dagtail = n;
dagtail = &n->next;
} }
lx = operand_label (operands[0]); lx = operand_label (operands[0]);
if (lx) { if (lx) {
if (lx->prev) flowvar_t *var = flow_get_var (lx->op);
daglabel_detatch (lx);
lx->expr = s->expr; lx->expr = s->expr;
dagnode_attach_label (n, lx); if (lx->number == -1) {
lx->number = num_labels;
labels[num_labels++] = lx;
}
if (set_is_member (flownode->live_vars.out, var->number))
dagnode_attach_label (n, lx);
} }
} }
for (d = dagnodes; d; d = d->next) { dag = new_dag ();
daglabel_t **l = &d->identifiers; dag->nodes = malloc (num_nodes * sizeof (dagnode_t *));
memcpy (dag->nodes, nodes, num_nodes * sizeof (dagnode_t *));
while (*l) { dag->num_nodes = num_nodes;
if ((*l)->op->op_type == op_temp dag->labels = malloc (num_labels * sizeof (daglabel_t *));
&& !set_is_member (flownode->live_vars.out, memcpy (dag->labels, labels, num_labels * sizeof (daglabel_t *));
flow_get_var ((*l)->op)->number)) dag->num_labels = num_labels;
daglabel_detatch (*l); dag->roots = set_new ();
else for (i = 0; i < num_nodes; i++) {
l = &(*l)->next; if (set_is_empty (dag->nodes[i]->parents))
} set_add (dag->roots, dag->nodes[i]->number);
} }
while (dagnodes->is_child) { return dag;
dagnode_t *n = dagnodes->next;
dagnodes->next = 0;
dagnodes = n;
}
for (d = dagnodes; d && d->next; d = d->next) {
while (d->next && d->next->is_child) {
dagnode_t *n = d->next->next;
d->next->next = 0;
d->next = n;
}
}
return dagnodes;
} }
static statement_t *
build_statement (const char *opcode, operand_t **operands, expr_t *expr)
{
statement_t *st = new_statement (st_none, opcode, expr);
st->opa = operands[0];
st->opb = operands[1];
st->opc = operands[2];
return st;
}
#if 0
static void static void
dag_calc_node_costs (dagnode_t *dagnode) dag_calc_node_costs (dagnode_t *dagnode)
{ {
if ((!dagnode->a && (dagnode->b || dagnode->c)) int i;
|| (dagnode->a && !dagnode->b && dagnode->c))
internal_error (0, "bad dag node");
if (dagnode->a) for (i = 0; i < 3; i++)
dag_calc_node_costs (dagnode->a); if (dagnode->children[i])
if (dagnode->b) dag_calc_node_costs (dagnode->children[i]);
dag_calc_node_costs (dagnode->b);
if (dagnode->c)
dag_calc_node_costs (dagnode->c);
// if dagnode->a is null, then this is a leaf (as b and c are guaranted to // if dagnode->a is null, then this is a leaf (as b and c are guaranted to
// be null) // be null)
if (!dagnode->a) { if (!dagnode->children[0]) {
// Because qc vm statements don't mix source and destination operands, // Because qc vm statements don't mix source and destination operands,
// leaves never need temporary variables. // leaves never need temporary variables.
dagnode->cost = 0; dagnode->cost = 0;
} else { } else {
int different = 0; int different = 0;
// a non-leaf is guaranteed to have a valid "a" // a non-leaf is guaranteed to have a valid first child
dagnode->cost = dagnode->a->cost; dagnode->cost = dagnode->children[0]->cost;
if (dagnode->b && dagnode->b->cost != dagnode->cost) { for (i = 1; i < 3; i++) {
dagnode->cost = max (dagnode->cost, dagnode->b->cost); if (dagnode->children[i]
different = 1; && dagnode->children[i]->cost != dagnode->cost) {
} dagnode->cost = max (dagnode->cost,
if (dagnode->c && (different || dagnode->c->cost != dagnode->cost)) { dagnode->children[i]->cost);
dagnode->cost = max (dagnode->cost, dagnode->c->cost); different = 1;
different = 1; }
} }
if (!different) if (!different)
dagnode->cost += 1; dagnode->cost += 1;
} }
} }
#endif
static operand_t * static operand_t *
fix_op_type (operand_t *op, etype_t type) fix_op_type (operand_t *op, etype_t type)
{ {
@ -422,93 +420,103 @@ fix_op_type (operand_t *op, etype_t type)
} }
static operand_t * static operand_t *
generate_assignments (sblock_t *block, operand_t *src, daglabel_t *var) generate_assignments (dag_t *dag, sblock_t *block, operand_t *src,
set_iter_t *var_iter)
{ {
statement_t *st; statement_t *st;
operand_t *dst = 0; operand_t *dst = 0;
operand_t *operands[3] = {src, 0, 0};
daglabel_t *var;
while (var) { for ( ; var_iter; var_iter = set_next (var_iter)) {
operand_t *vop = fix_op_type (var->op, src->type); var = dag->labels[var_iter->member];
operands[1] = fix_op_type (var->op, src->type);
if (!dst) { if (!dst) {
dst = vop; dst = operands[1];
while (dst->op_type == op_alias) while (dst->op_type == op_alias)
dst = dst->o.alias; dst = dst->o.alias;
} }
st = build_statement ("=", src, vop, 0, var->expr);
st = build_statement ("=", operands, var->expr);
sblock_add_statement (block, st); sblock_add_statement (block, st);
var = var->next;
} }
return dst; return dst;
} }
static operand_t *dag_gencode (dag_t *dag, sblock_t *block,
const dagnode_t *dagnode);
static operand_t * static operand_t *
dag_gencode (sblock_t *block, const dagnode_t *dagnode) make_operand (dag_t *dag, sblock_t *block, const dagnode_t *dagnode, int index)
{ {
operand_t *opa = 0, *opb = 0, *opc = 0; operand_t *op;
op = dag_gencode (dag, block, dagnode->children[index]);
op = fix_op_type (op, dagnode->types[index]);
return op;
}
static operand_t *
dag_gencode (dag_t *dag, sblock_t *block, const dagnode_t *dagnode)
{
operand_t *operands[3] = {0, 0, 0};
operand_t *dst = 0; operand_t *dst = 0;
statement_t *st; statement_t *st;
daglabel_t *var; set_iter_t *var_iter;
int i;
switch (dagnode->type) { switch (dagnode->type) {
case st_none: case st_none:
if (!dagnode->label->op) if (!dagnode->label->op)
internal_error (0, "non-leaf label in leaf node"); internal_error (0, "non-leaf label in leaf node");
dst = dagnode->label->op; dst = dagnode->label->op;
if (dagnode->identifiers) if ((var_iter = set_first (dagnode->identifiers)))
dst = generate_assignments (block, dst, dagnode->identifiers); dst = generate_assignments (dag, block, dst, var_iter);
break; break;
case st_expr: case st_expr:
opa = fix_op_type (dag_gencode (block, dagnode->a), dagnode->ta); operands[0] = make_operand (dag, block, dagnode, 0);
if (dagnode->b) if (dagnode->children[1])
opb = fix_op_type (dag_gencode (block, dagnode->b), operands[1] = make_operand (dag, block, dagnode, 1);
dagnode->tb); if (!(var_iter = set_first (dagnode->identifiers))) {
if (!(var = dagnode->identifiers)) { operands[2] = temp_operand (get_type (dagnode->label->expr));
opc = temp_operand (get_type (dagnode->label->expr));
} else { } else {
opc = fix_op_type (var->op, daglabel_t *var = dag->labels[var_iter->member];
extract_type (dagnode->label->expr)); etype_t type = extract_type (dagnode->label->expr);
var = var->next; operands[2] = fix_op_type (var->op, type);
var_iter = set_next (var_iter);
} }
dst = opc; dst = operands[2];
st = build_statement (dagnode->label->opcode, opa, opb, opc, st = build_statement (dagnode->label->opcode, operands,
dagnode->label->expr); dagnode->label->expr);
sblock_add_statement (block, st); sblock_add_statement (block, st);
generate_assignments (block, opc, var); generate_assignments (dag, block, operands[2], var_iter);
break; break;
case st_assign: case st_assign:
internal_error (0, "unexpected assignment node"); internal_error (0, "unexpected assignment node");
case st_ptrassign: case st_ptrassign:
opa = fix_op_type (dag_gencode (block, dagnode->a), dagnode->ta); operands[0] = make_operand (dag, block, dagnode, 0);
opb = fix_op_type (dag_gencode (block, dagnode->b), dagnode->tb); operands[1] = make_operand (dag, block, dagnode, 1);
if (dagnode->c) if (dagnode->children[2])
opc = fix_op_type (dag_gencode (block, dagnode->c), operands[2] = make_operand (dag, block, dagnode, 2);
dagnode->tc); st = build_statement (dagnode->label->opcode, operands,
st = build_statement (dagnode->label->opcode, opa, opb, opc,
dagnode->label->expr); dagnode->label->expr);
sblock_add_statement (block, st); sblock_add_statement (block, st);
break; break;
case st_move: case st_move:
case st_state: case st_state:
case st_func: case st_func:
if (dagnode->a) for (i = 0; i < 3; i++)
opa = fix_op_type (dag_gencode (block, dagnode->a), if (dagnode->children[i])
dagnode->ta); operands[i] = make_operand (dag, block, dagnode, i);
if (dagnode->b) st = build_statement (dagnode->label->opcode, operands,
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->label->expr); dagnode->label->expr);
sblock_add_statement (block, st); sblock_add_statement (block, st);
break; break;
case st_flow: case st_flow:
opa = fix_op_type (dag_gencode (block, dagnode->a), dagnode->ta); operands[0] = make_operand (dag, block, dagnode, 0);
if (dagnode->b) if (dagnode->children[1])
opb = fix_op_type (dag_gencode (block, dagnode->b), operands[1] = make_operand (dag, block, dagnode, 1);
dagnode->tb); st = build_statement (dagnode->label->opcode, operands,
st = build_statement (dagnode->label->opcode, opa, opb, 0,
dagnode->label->expr); dagnode->label->expr);
sblock_add_statement (block, st); sblock_add_statement (block, st);
break; break;
@ -517,14 +525,11 @@ dag_gencode (sblock_t *block, const dagnode_t *dagnode)
} }
void void
dag_generate (sblock_t *block, const flownode_t *flownode) dag_generate (dag_t *dag, sblock_t *block)
{ {
const dagnode_t *dag; set_iter_t *node_iter;
dag_calc_node_costs (flownode->dag); for (node_iter = set_first (dag->roots); node_iter;
for (dag = flownode->dag; dag; dag = dag->next) { node_iter = set_next (node_iter))
//if (!dag->a || (strcmp (dag->label->opcode, ".=") && !dag->identifiers)) dag_gencode (dag, block, dag->nodes[node_iter->member]);
// continue;
dag_gencode (block, dag);
}
} }

View file

@ -44,83 +44,58 @@
#include <QF/va.h> #include <QF/va.h>
#include "dags.h" #include "dags.h"
#include "set.h"
#include "statements.h" #include "statements.h"
#include "symtab.h" #include "symtab.h"
#include "type.h" #include "type.h"
static int print_count;
static void static void
print_node_def (dstring_t *dstr, dagnode_t *node, int recurse) print_node_def (dstring_t *dstr, dagnode_t *node)
{ {
if (!node->a && (node->b || node->c)) {
dasprintf (dstr, " \"dagnode_%p\" [label=\"bad node\"];\n", node);
return;
}
dasprintf (dstr, " \"dagnode_%p\" [%slabel=\"%s\"];\n", node, dasprintf (dstr, " \"dagnode_%p\" [%slabel=\"%s\"];\n", node,
node->type != st_none ? "" : "shape=none,", node->type != st_none ? "" : "shape=none,",
daglabel_string (node->label)); daglabel_string (node->label));
if (recurse) {
if (node->a)
print_node_def (dstr, node->a, 1);
if (node->b)
print_node_def (dstr, node->b, 1);
if (node->c)
print_node_def (dstr, node->c, 1);
}
} }
static void static void
print_root_nodes (dstring_t *dstr, dagnode_t *dag) print_root_nodes (dstring_t *dstr, dag_t *dag)
{ {
set_iter_t *node_iter;
dasprintf (dstr, " subgraph roots_%p {", dag); dasprintf (dstr, " subgraph roots_%p {", dag);
dasprintf (dstr, " rank=same;"); dasprintf (dstr, " rank=same;");
for (; dag; dag = dag->next) for (node_iter = set_first (dag->roots); node_iter;
print_node_def (dstr, dag, 0); node_iter = set_next (node_iter))
print_node_def (dstr, dag->nodes[node_iter->member]);
dasprintf (dstr, " }\n"); dasprintf (dstr, " }\n");
} }
static void static void
print_child_nodes (dstring_t *dstr, dagnode_t *dag) print_child_nodes (dstring_t *dstr, dag_t *dag)
{ {
for (; dag; dag = dag->next) { int i;
if (!dag->a && (dag->b || dag->c)) dagnode_t *node;
continue;
if (dag->a) for (i = 0; i < dag->num_nodes; i++) {
print_node_def (dstr, dag->a, 1); node = dag->nodes[i];
if (dag->b) if (!set_is_empty (node->parents))
print_node_def (dstr, dag->b, 1); print_node_def (dstr, node);
if (dag->c)
print_node_def (dstr, dag->c, 1);
} }
} }
static void static void
print_node (dstring_t *dstr, dagnode_t *node) print_node (dstring_t *dstr, dag_t *dag, dagnode_t *node)
{ {
if (node->print_count == print_count) int i;
return;
node->print_count = print_count; for (i = 0; i < 3; i++) {
if (node->a) { if (node->children[i]) {
dasprintf (dstr, " \"dagnode_%p\" -> \"dagnode_%p\" [label=a];\n", dasprintf (dstr,
node, node->a); " \"dagnode_%p\" -> \"dagnode_%p\" [label=%c];\n",
print_node (dstr, node->a); node, node->children[i], i + 'a');
}
} }
if (node->b) { if (!set_is_empty (node->identifiers)) {
dasprintf (dstr, " \"dagnode_%p\" -> \"dagnode_%p\" [label=b];\n", set_iter_t *id_iter;
node, node->b);
print_node (dstr, node->b);
}
if (node->c) {
dasprintf (dstr, " \"dagnode_%p\" -> \"dagnode_%p\" [label=c];\n",
node, node->c);
print_node (dstr, node->c);
}
if (node->next)
dasprintf (dstr,
" \"dagnode_%p\" -> \"dagnode_%p\" [style=dashed];\n",
node, node->next);
if (node->identifiers) {
daglabel_t *id; daglabel_t *id;
dasprintf (dstr, " \"dagnode_%p\" -> \"dagid_%p\" " dasprintf (dstr, " \"dagnode_%p\" -> \"dagid_%p\" "
@ -130,8 +105,11 @@ print_node (dstring_t *dstr, dagnode_t *node)
"cellspacing=\"0\">\n"); "cellspacing=\"0\">\n");
dasprintf (dstr, " <tr>\n"); dasprintf (dstr, " <tr>\n");
dasprintf (dstr, " <td>"); dasprintf (dstr, " <td>");
for (id = node->identifiers; id; id = id->next) for (id_iter = set_first (node->identifiers); id_iter;
dasprintf (dstr, "%s%s", daglabel_string(id), id->next ? " " : ""); id_iter = set_next (id_iter)) {
id = dag->labels[id_iter->member];
dasprintf (dstr, " %s", daglabel_string(id));
}
dasprintf (dstr, " </td>"); dasprintf (dstr, " </td>");
dasprintf (dstr, " </tr>\n"); dasprintf (dstr, " </tr>\n");
dasprintf (dstr, " </table>>];\n"); dasprintf (dstr, " </table>>];\n");
@ -139,13 +117,13 @@ print_node (dstring_t *dstr, dagnode_t *node)
} }
void void
print_dag (dstring_t *dstr, dagnode_t *dag) print_dag (dstring_t *dstr, dag_t *dag)
{ {
int i;
dasprintf (dstr, " subgraph cluster_dag_%p {", dag); dasprintf (dstr, " subgraph cluster_dag_%p {", dag);
print_count++;
print_root_nodes (dstr, dag); print_root_nodes (dstr, dag);
print_child_nodes (dstr, dag); print_child_nodes (dstr, dag);
for (; dag; dag = dag->next) for (i = 0; i < dag->num_nodes; i++)
print_node (dstr, dag); print_node (dstr, dag, dag->nodes[i]);
dasprintf (dstr, " }\n"); dasprintf (dstr, " }\n");
} }

View file

@ -433,7 +433,7 @@ flow_generate (flowgraph_t *graph)
label->dest = block; label->dest = block;
} }
// generate new statements from the dag; // generate new statements from the dag;
dag_generate (block, node); dag_generate (node->dag, block);
} }
//dump_dot ("post", code, dump_dot_sblock); //dump_dot ("post", code, dump_dot_sblock);
return code; return code;