From d717a0b3f2403d1ab0effe2d163b9e75647cbde1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Dec 2012 13:56:26 +0900 Subject: [PATCH] Add dummy nodes at the beginning and end of the graph. The dummy nodes are for detectining uninitialized variables (entry dummy) and making globals live at function exit (exit dummy). The reaching defs and live vars code currently seg because neither node has had its sets initialized. --- tools/qfcc/include/flow.h | 2 +- tools/qfcc/source/dot_flow.c | 3 ++ tools/qfcc/source/flow.c | 66 ++++++++++++++++++++++++++---------- 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/tools/qfcc/include/flow.h b/tools/qfcc/include/flow.h index 5ffd2d238..0a17e1978 100644 --- a/tools/qfcc/include/flow.h +++ b/tools/qfcc/include/flow.h @@ -96,7 +96,7 @@ typedef struct flowgraph_s { struct flowgraph_s *next; ///< for ALLOC struct function_s *func; ///< function to which this graph is attached flownode_t **nodes; ///< array of nodes in the graph - int num_nodes; + int num_nodes; ///< number of real nodes in the graph flowedge_t *edges; ///< array of all edges in the graph int num_edges; struct set_s *dfst; ///< edges in the depth-first search tree diff --git a/tools/qfcc/source/dot_flow.c b/tools/qfcc/source/dot_flow.c index 5337fdb12..1ae35b9dc 100644 --- a/tools/qfcc/source/dot_flow.c +++ b/tools/qfcc/source/dot_flow.c @@ -246,6 +246,9 @@ print_flowgraph (flow_dot_t *method, flowgraph_t *graph, const char *filename) method->print_node (dstr, graph, graph->nodes[i], 0); } for (i = 0; i < graph->num_edges; i++) { + if ((int) graph->edges[i].head >= graph->num_nodes + || (int) graph->edges[i].tail >= graph->num_nodes) + continue; // dummy node method->print_edge (dstr, graph, &graph->edges[i], 0); } dasprintf (dstr, "}\n"); diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index f1e0bf581..7adc82d06 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -854,7 +854,7 @@ flow_find_predecessors (flowgraph_t *graph) flownode_t *node; set_iter_t *succ; - for (i = 0; i < graph->num_nodes; i++) { + for (i = 0; i < graph->num_nodes + 2; i++) { node = graph->nodes[i]; for (succ = set_first (node->successors); succ; succ = set_next (succ)) { @@ -1005,6 +1005,10 @@ flow_build_dfst (flowgraph_t *graph) set_t *visited = set_new (); int i; + // mark the dummy nodes as visited to keep them out of the dfst + set_add (visited, graph->num_nodes); + set_add (visited, graph->num_nodes + 1); + graph->dfo = malloc (graph->num_nodes * sizeof (unsigned)); graph->dfst = set_new (); i = graph->num_nodes; @@ -1012,6 +1016,22 @@ flow_build_dfst (flowgraph_t *graph) set_delete (visited); } +static flownode_t * +flow_make_node (sblock_t *sblock, int id, function_t *func) +{ + flownode_t *node; + + node = new_node (); + node->predecessors = set_new (); + node->successors = set_new (); + node->edges = set_new (); + node->dom = set_new (); + node->global_vars = func->global_vars; + node->id = id; + node->sblock = sblock; + return node; +} + static flowgraph_t * flow_build_graph (function_t *func) { @@ -1028,18 +1048,16 @@ flow_build_graph (function_t *func) graph->func = func; for (sb = sblock; sb; sb = sb->next) sb->number = graph->num_nodes++; - graph->nodes = malloc (graph->num_nodes * sizeof (flownode_t *)); - for (sb = sblock; sb; sb = sb->next) { - node = new_node (); - node->predecessors = set_new (); - node->successors = set_new (); - node->edges = set_new (); - node->dom = set_new (); - node->global_vars = func->global_vars; - node->id = sb->number; - node->sblock = sb; - graph->nodes[node->id] = node; - } + // + 2 for the uninitialized dummy head block and the live dummy end block + graph->nodes = malloc ((graph->num_nodes + 2) * sizeof (flownode_t *)); + for (sb = sblock; sb; sb = sb->next) + graph->nodes[sb->number] = flow_make_node (sb, sb->number, func); + // Create the dummy node for detecting uninitialized variables + node = flow_make_node (0, graph->num_nodes, func); + graph->nodes[graph->num_nodes] = node; + // Create the dummy node for making global vars live at function exit + node = flow_make_node (0, graph->num_nodes + 1, func); + graph->nodes[graph->num_nodes + 1] = node; // "convert" the basic blocks connections to flow-graph connections for (i = 0; i < graph->num_nodes; i++) { @@ -1066,15 +1084,29 @@ flow_build_graph (function_t *func) set_add (node->successors, statement_get_target (st)->number); } else if (statement_is_return (st)) { // exit from function (dead end) + // however, make the exit dummy block the node's successor + set_add (node->successors, graph->num_nodes + 1); } else { // there is no flow-control statement in sb, so sb's next // must be followed - set_add (node->successors, sb->next->number); + if (sb->next) { + set_add (node->successors, sb->next->number); + } else { + bug (0, "code drops off the end of the function"); + // this shouldn't happen + // however, make the exit dummy block the node's successor + set_add (node->successors, graph->num_nodes + 1); + } } graph->num_edges += set_size (node->successors); } + // set the successor for the entry dummy node to the real entry node + node = graph->nodes[graph->num_nodes]; + set_add (node->successors, 0); + graph->num_edges += set_size (node->successors); + graph->edges = malloc (graph->num_edges * sizeof (flowedge_t *)); - for (j = 0, i = 0; i < graph->num_nodes; i++) { + for (j = 0, i = 0; i < graph->num_nodes + 2; i++) { node = graph->nodes[i]; for (succ = set_first (node->successors); succ; succ = set_next (succ), j++) { @@ -1098,6 +1130,8 @@ flow_data_flow (function_t *func) flow_build_statements (func); flow_build_vars (func); graph = flow_build_graph (func); + if (options.block_dot.flow) + dump_dot ("flow", graph, dump_dot_flow); func->graph = graph; flow_reaching_defs (graph); if (options.block_dot.reaching) @@ -1105,7 +1139,5 @@ flow_data_flow (function_t *func) flow_live_vars (graph); flow_uninitialized (graph); flow_build_dags (graph); - if (options.block_dot.flow) - dump_dot ("flow", graph, dump_dot_flow); func->sblock = flow_generate (graph); }