mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-23 04:42:32 +00:00
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:
parent
0bb2fc1891
commit
12133bc02f
5 changed files with 241 additions and 249 deletions
|
@ -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);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue