diff --git a/tools/qfcc/include/flow.h b/tools/qfcc/include/flow.h
index b021549c4..17cc0fc1b 100644
--- a/tools/qfcc/include/flow.h
+++ b/tools/qfcc/include/flow.h
@@ -109,7 +109,9 @@ void flow_del_graph (flowgraph_t *graph);
void flow_data_flow (flowgraph_t *graph);
struct sblock_s *flow_generate (flowgraph_t *graph);
-void print_flowgraph (flowgraph_t *graph, const char *filename);
+void dump_dot_flow (void *g, const char *filename);
+void dump_dot_flow_dags (void *g, const char *filename);
+void dump_dot_flow_live (void *g, const char *filename);
//@}
diff --git a/tools/qfcc/source/dot_flow.c b/tools/qfcc/source/dot_flow.c
index 3a7e8309c..141db49ac 100644
--- a/tools/qfcc/source/dot_flow.c
+++ b/tools/qfcc/source/dot_flow.c
@@ -51,11 +51,131 @@
#include "statements.h"
#include "strpool.h"
+typedef struct {
+ const char *type;
+ void (*print_node) (dstring_t *, flowgraph_t *, flownode_t *, int);
+ void (*print_edge) (dstring_t *, flowgraph_t *, flowedge_t *, int);
+} flow_dot_t;
+
static void
print_flow_node (dstring_t *dstr, flowgraph_t *graph, flownode_t *node,
int level)
{
int indent = level * 2 + 2;
+
+ dasprintf (dstr, "%*s\"fn_%p\" [label=\"%d (%d)\"];\n", indent, "",
+ node, node->id, node->dfn);
+}
+
+static void
+print_flow_edge (dstring_t *dstr, flowgraph_t *graph, flowedge_t *edge,
+ int level)
+{
+ int indent = level * 2 + 2;
+ int edge_num = edge - graph->edges;
+ flownode_t *t, *h;
+ const char *style;
+ const char *dir;
+ int weight;
+
+ t = graph->nodes[edge->tail];
+ h = graph->nodes[edge->head];
+ if (t->dfn >= h->dfn) {
+ flownode_t *temp;
+ temp = h;
+ h = t;
+ t = temp;
+
+ dir = "dir=back,";
+ style = "dashed";
+ weight = 0;
+ } else if (set_is_member (graph->dfst, edge_num)) {
+ dir = "";
+ style = "bold";
+ weight = 10;
+ } else {
+ dir = "";
+ style = "solid";
+ weight = 0;
+ }
+ dasprintf (dstr, "%*s", indent, "");
+ dasprintf (dstr, "fn_%p -> ", t);
+ dasprintf (dstr, "fn_%p [%sstyle=%s,weight=%d", h, dir, style, weight);
+ dasprintf (dstr, "];\n");
+}
+
+static void
+print_flow_node_dag (dstring_t *dstr, flowgraph_t *graph, flownode_t *node,
+ int level)
+{
+ if (node->dag)
+ print_dag (dstr, node->dag, va ("%d (%d)", node->id, node->dfn));
+ else
+ print_flow_node (dstr, graph, node, level);
+}
+
+static void
+print_flow_edge_dag (dstring_t *dstr, flowgraph_t *graph, flowedge_t *edge,
+ int level)
+{
+ int indent = level * 2 + 2;
+ int edge_num = edge - graph->edges;
+ flownode_t *t, *h;
+ const char *tpref;
+ const char *hpref;
+ const char *style;
+ const char *dir;
+ int weight;
+
+ t = graph->nodes[edge->tail];
+ h = graph->nodes[edge->head];
+ if (t->dfn >= h->dfn) {
+ flownode_t *temp;
+ temp = h;
+ h = t;
+ t = temp;
+
+ tpref = "enter";
+ hpref = "leave";
+ dir = "dir=back,";
+ style = "dashed";
+ weight = 0;
+ } else if (set_is_member (graph->dfst, edge_num)) {
+ tpref = "leave";
+ hpref = "enter";
+ dir = "";
+ style = "bold";
+ weight = 10;
+ } else {
+ tpref = "leave";
+ hpref = "enter";
+ dir = "";
+ style = "solid";
+ weight = 0;
+ }
+ dasprintf (dstr, "%*s", indent, "");
+ if (t->dag)
+ dasprintf (dstr, "dag_%s_%p -> ", tpref, t->dag);
+ else
+ dasprintf (dstr, "fn_%p -> ", t);
+ if (h->dag)
+ dasprintf (dstr, "dag_%s_%p [%sstyle=%s,weight=%d",
+ hpref, h->dag, dir, style, weight);
+ else
+ dasprintf (dstr, "fn_%p [%sstyle=%s,weight=%d",
+ h, dir, style, weight);
+ if (t->dag)
+ dasprintf (dstr, ",ltail=cluster_dag_%p", t->dag);
+ if (h->dag)
+ dasprintf (dstr, ",lhead=cluster_dag_%p", h->dag);
+ dasprintf (dstr, "];\n");
+}
+
+static void
+print_flow_node_live (dstring_t *dstr, flowgraph_t *graph, flownode_t *node,
+ int level)
+{
+ int indent = level * 2 + 2;
set_iter_t *var_iter;
flowvar_t *var;
int live;
@@ -63,21 +183,11 @@ print_flow_node (dstring_t *dstr, flowgraph_t *graph, flownode_t *node,
live = node->live_vars.out && !set_is_empty (node->live_vars.out);
if (live) {
- dasprintf (dstr, "%*ssubgraph sub_%p {\n", indent, "", node);
- //dasprintf (dstr, "%*s rank=same;\n", indent, "");
- indent += 2;
- }
- if (node->dag) {
- print_dag (dstr, node->dag, va ("%d (%d)", node->id, node->dfn));
- } else {
- dasprintf (dstr, "%*s\"fn_%p\" [label=\"%d (%d)\"];\n", indent, "",
- node, node->id, node->dfn);
- }
- if (live) {
- dasprintf (dstr, "%*slv_%p [shape=none,label=<\n", indent, "", node);
+ dasprintf (dstr, "%*sfn_%p [shape=none,label=<\n", indent, "", node);
dasprintf (dstr, "%*s
\n", indent + 2, "");
- dasprintf (dstr, "%*sLive Vars |
\n", indent + 4, "");
+ dasprintf (dstr, "%*s%d (%d) |
\n", indent + 4, "",
+ node->id, node->dfn);
for (var_iter = set_first (node->live_vars.out); var_iter;
var_iter = set_next (var_iter)) {
var = graph->func->vars[var_iter->member];
@@ -85,97 +195,34 @@ print_flow_node (dstring_t *dstr, flowgraph_t *graph, flownode_t *node,
var->number, html_string(operand_string (var->op)));
}
dasprintf (dstr, "%*s
>];\n", indent + 2, "");
- if (node->dag) {
- dasprintf (dstr, "%*sdag_enter_%p -> lv_%p "
- //"[constraint=false,style=dashed,weight=10];\n",
- "[style=dashed,weight=10,ltail=cluster_dag_%p];\n",
- indent, "", node->dag, node, node->dag);
- } else {
- dasprintf (dstr, "%*sfn_%p -> lv_%p "
- //"[constraint=false,style=dashed,weight=10];\n",
- "[style=dashed,weight=10];\n",
- indent, "", node, node);
- }
- indent -= 2;
- dasprintf (dstr, "%*s}\n", indent, "");
+ } else {
+ print_flow_node (dstr, graph, node, level);
}
}
+static flow_dot_t flow_dot_methods[] = {
+ {"", print_flow_node, print_flow_edge},
+ {"dag", print_flow_node_dag, print_flow_edge_dag},
+ {"live", print_flow_node_live, print_flow_edge},
+};
+
static void
-print_flow_edges (dstring_t *dstr, flowgraph_t *graph, int level)
-{
- int indent = level * 2 + 2;
- int i;
- flowedge_t *edge;
- flownode_t *t, *h;
- const char *tpref;
- const char *hpref;
- const char *style;
- const char *dir;
- int weight;
-
- for (i = 0; i < graph->num_edges; i++) {
- edge = &graph->edges[i];
- t = graph->nodes[edge->tail];
- h = graph->nodes[edge->head];
- if (t->dfn >= h->dfn) {
- flownode_t *temp;
- temp = h;
- h = t;
- t = temp;
-
- tpref = "enter";
- hpref = "leave";
- dir = "dir=back,";
- style = "dashed";
- weight = 0;
- } else if (set_is_member (graph->dfst, i)) {
- tpref = "leave";
- hpref = "enter";
- dir = "";
- style = "bold";
- weight = 10;
- } else {
- tpref = "leave";
- hpref = "enter";
- dir = "";
- style = "solid";
- weight = 0;
- }
- dasprintf (dstr, "%*s", indent, "");
- if (t->dag)
- dasprintf (dstr, "dag_%s_%p -> ", tpref, t->dag);
- else
- dasprintf (dstr, "fn_%p -> ", t);
- if (h->dag)
- dasprintf (dstr, "dag_%s_%p [%sstyle=%s,weight=%d",
- hpref, h->dag, dir, style, weight);
- else
- dasprintf (dstr, "fn_%p [%sstyle=%s,weight=%d",
- h, dir, style, weight);
- if (t->dag)
- dasprintf (dstr, ",ltail=cluster_dag_%p", t->dag);
- if (h->dag)
- dasprintf (dstr, ",lhead=cluster_dag_%p", h->dag);
- dasprintf (dstr, "];\n");
- }
-}
-
-void
-print_flowgraph (flowgraph_t *graph, const char *filename)
+print_flowgraph (flow_dot_t *method, flowgraph_t *graph, const char *filename)
{
int i;
dstring_t *dstr = dstring_newstr();
- dasprintf (dstr, "digraph flowgraph_%p {\n", graph);
+ dasprintf (dstr, "digraph flowgraph_%s_%p {\n", method->type, graph);
dasprintf (dstr, " layout=dot;\n");
dasprintf (dstr, " clusterrank=local;\n");
dasprintf (dstr, " rankdir=TB;\n");
dasprintf (dstr, " compound=true;\n");
for (i = 0; i < graph->num_nodes; i++) {
- print_flow_node (dstr, graph, graph->nodes[i], 0);
+ method->print_node (dstr, graph, graph->nodes[i], 0);
+ }
+ for (i = 0; i < graph->num_edges; i++) {
+ method->print_edge (dstr, graph, &graph->edges[i], 0);
}
- print_flow_edges (dstr, graph, 0);
dasprintf (dstr, "}\n");
if (filename) {
@@ -189,3 +236,21 @@ print_flowgraph (flowgraph_t *graph, const char *filename)
}
dstring_delete (dstr);
}
+
+void
+dump_dot_flow (void *g, const char *filename)
+{
+ print_flowgraph (&flow_dot_methods[0], (flowgraph_t *) g, filename);
+}
+
+void
+dump_dot_flow_dags (void *g, const char *filename)
+{
+ print_flowgraph (&flow_dot_methods[1], (flowgraph_t *) g, filename);
+}
+
+void
+dump_dot_flow_live (void *g, const char *filename)
+{
+ print_flowgraph (&flow_dot_methods[2], (flowgraph_t *) g, filename);
+}
diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c
index b1a024e78..6bbd44705 100644
--- a/tools/qfcc/source/flow.c
+++ b/tools/qfcc/source/flow.c
@@ -76,12 +76,6 @@ static struct {
};
static const int num_flow_params = sizeof(flow_params)/sizeof(flow_params[0]);
-static void
-dump_dot_flow (void *data, const char *fname)
-{
- print_flowgraph ((flowgraph_t *) data, fname);
-}
-
static flowvar_t *
new_flowvar (void)
{
@@ -575,7 +569,7 @@ flow_build_dags (flowgraph_t *graph)
node->dag = dag_create (node);
}
//if (options.block_dot.dags)
- // dump_dot ("dags", graph, dump_dot_flow);
+ // dump_dot ("dags", graph, dump_dot_flow_dags);
}
void