Handle jumpb statements in dot_sblock and flow graphs.

This commit is contained in:
Bill Currie 2012-11-03 18:59:15 +09:00
parent ffa08a99c2
commit acde6ca0a0
3 changed files with 57 additions and 4 deletions

View file

@ -76,8 +76,10 @@ typedef struct flowgraph_s {
int flow_is_cond (struct statement_s *s); int flow_is_cond (struct statement_s *s);
int flow_is_goto (struct statement_s *s); int flow_is_goto (struct statement_s *s);
int flow_is_jumpb (struct statement_s *s);
int flow_is_return (struct statement_s *s); int flow_is_return (struct statement_s *s);
struct sblock_s *flow_get_target (struct statement_s *s); struct sblock_s *flow_get_target (struct statement_s *s);
struct sblock_s **flow_get_targetlist (struct statement_s *s);
void flow_build_vars (struct function_s *func); void flow_build_vars (struct function_s *func);
flowgraph_t *flow_build_graph (struct sblock_s *func); flowgraph_t *flow_build_graph (struct sblock_s *func);
void flow_del_graph (flowgraph_t *graph); void flow_del_graph (flowgraph_t *graph);

View file

@ -66,7 +66,8 @@ static void
flow_sblock (dstring_t *dstr, sblock_t *sblock, int blockno) flow_sblock (dstring_t *dstr, sblock_t *sblock, int blockno)
{ {
statement_t *s; statement_t *s;
sblock_t *target; sblock_t **target;
sblock_t **target_list;
ex_label_t *l; ex_label_t *l;
if (sblock->dag) { if (sblock->dag) {
@ -94,11 +95,15 @@ flow_sblock (dstring_t *dstr, sblock_t *sblock, int blockno)
dasprintf (dstr, " </tr>\n"); dasprintf (dstr, " </tr>\n");
dasprintf (dstr, " </table>>];\n"); dasprintf (dstr, " </table>>];\n");
if (sblock->next && !flow_is_goto ((statement_t *) sblock->tail) if (sblock->next && !flow_is_goto ((statement_t *) sblock->tail)
&& !flow_is_jumpb ((statement_t *) sblock->tail)
&& !flow_is_return ((statement_t *) sblock->tail)) && !flow_is_return ((statement_t *) sblock->tail))
dasprintf (dstr, " sb_%p:e -> sb_%p:s;\n", sblock, sblock->next); dasprintf (dstr, " sb_%p:e -> sb_%p:s;\n", sblock, sblock->next);
if ((target = flow_get_target ((statement_t *) sblock->tail))) if ((target_list = flow_get_targetlist ((statement_t *) sblock->tail))) {
dasprintf (dstr, " sb_%p:e -> sb_%p:s [label=\"%s\"];\n", sblock, for (target = target_list; *target; target++)
target, ((statement_t *) sblock->tail)->opcode); dasprintf (dstr, " sb_%p:e -> sb_%p:s [label=\"%s\"];\n", sblock,
*target, ((statement_t *) sblock->tail)->opcode);
free (target_list);
}
dasprintf (dstr, "\n"); dasprintf (dstr, "\n");
} }

View file

@ -42,12 +42,14 @@
#include "QF/dstring.h" #include "QF/dstring.h"
#include "dags.h" #include "dags.h"
#include "def.h"
#include "flow.h" #include "flow.h"
#include "function.h" #include "function.h"
#include "qfcc.h" #include "qfcc.h"
#include "set.h" #include "set.h"
#include "statements.h" #include "statements.h"
#include "symtab.h" #include "symtab.h"
#include "type.h"
static flowloop_t *free_loops; static flowloop_t *free_loops;
static flownode_t *free_nodes; static flownode_t *free_nodes;
@ -229,6 +231,14 @@ flow_is_goto (statement_t *s)
return !strcmp (s->opcode, "<GOTO>"); return !strcmp (s->opcode, "<GOTO>");
} }
int
flow_is_jumpb (statement_t *s)
{
if (!s)
return 0;
return !strcmp (s->opcode, "<JUMPB>");
}
int int
flow_is_return (statement_t *s) flow_is_return (statement_t *s)
{ {
@ -247,6 +257,36 @@ flow_get_target (statement_t *s)
return 0; return 0;
} }
sblock_t **
flow_get_targetlist (statement_t *s)
{
sblock_t **target_list;
int count, i;
def_t *table = 0;
expr_t *e;
if (flow_is_cond (s)) {
count = 1;
} else if (flow_is_goto (s)) {
count = 1;
} else if (flow_is_jumpb (s)) {
table = s->opa->o.alias->o.symbol->s.def; //FIXME check!!!
count = table->type->t.array.size;
}
target_list = malloc ((count + 1) * sizeof (sblock_t *));
target_list[count] = 0;
if (flow_is_cond (s)) {
target_list[0] = flow_get_target (s);
} else if (flow_is_goto (s)) {
target_list[0] = flow_get_target (s);
} else if (flow_is_jumpb (s)) {
e = table->initializer->e.block.head; //FIXME check!!!
for (i = 0; i < count; e = e->next, i++)
target_list[i] = e->e.labelref.label->dest;
}
return target_list;
}
static void static void
flow_find_predecessors (flowgraph_t *graph) flow_find_predecessors (flowgraph_t *graph)
{ {
@ -413,6 +453,7 @@ flow_build_graph (sblock_t *sblock)
flowgraph_t *graph; flowgraph_t *graph;
flownode_t *node; flownode_t *node;
sblock_t *sb; sblock_t *sb;
sblock_t **target_list, **target;
statement_t *st; statement_t *st;
set_iter_t *succ; set_iter_t *succ;
int i, j; int i, j;
@ -445,6 +486,11 @@ flow_build_graph (sblock_t *sblock)
if (flow_is_goto (st)) { if (flow_is_goto (st)) {
// sb's next is never followed. // sb's next is never followed.
set_add (node->successors, flow_get_target (st)->number); set_add (node->successors, flow_get_target (st)->number);
} else if (flow_is_jumpb (st)) {
target_list = flow_get_targetlist (st);
for (target = target_list; *target; target++)
set_add (node->successors, (*target)->number);
free (target_list);
} else if (flow_is_cond (st)) { } else if (flow_is_cond (st)) {
// branch: either sb's next or the conditional statment's // branch: either sb's next or the conditional statment's
// target will be followed. // target will be followed.