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_goto (struct statement_s *s);
int flow_is_jumpb (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_targetlist (struct statement_s *s);
void flow_build_vars (struct function_s *func);
flowgraph_t *flow_build_graph (struct sblock_s *func);
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)
{
statement_t *s;
sblock_t *target;
sblock_t **target;
sblock_t **target_list;
ex_label_t *l;
if (sblock->dag) {
@ -94,11 +95,15 @@ flow_sblock (dstring_t *dstr, sblock_t *sblock, int blockno)
dasprintf (dstr, " </tr>\n");
dasprintf (dstr, " </table>>];\n");
if (sblock->next && !flow_is_goto ((statement_t *) sblock->tail)
&& !flow_is_jumpb ((statement_t *) sblock->tail)
&& !flow_is_return ((statement_t *) sblock->tail))
dasprintf (dstr, " sb_%p:e -> sb_%p:s;\n", sblock, sblock->next);
if ((target = flow_get_target ((statement_t *) sblock->tail)))
dasprintf (dstr, " sb_%p:e -> sb_%p:s [label=\"%s\"];\n", sblock,
target, ((statement_t *) sblock->tail)->opcode);
if ((target_list = flow_get_targetlist ((statement_t *) sblock->tail))) {
for (target = target_list; *target; target++)
dasprintf (dstr, " sb_%p:e -> sb_%p:s [label=\"%s\"];\n", sblock,
*target, ((statement_t *) sblock->tail)->opcode);
free (target_list);
}
dasprintf (dstr, "\n");
}

View File

@ -42,12 +42,14 @@
#include "QF/dstring.h"
#include "dags.h"
#include "def.h"
#include "flow.h"
#include "function.h"
#include "qfcc.h"
#include "set.h"
#include "statements.h"
#include "symtab.h"
#include "type.h"
static flowloop_t *free_loops;
static flownode_t *free_nodes;
@ -229,6 +231,14 @@ flow_is_goto (statement_t *s)
return !strcmp (s->opcode, "<GOTO>");
}
int
flow_is_jumpb (statement_t *s)
{
if (!s)
return 0;
return !strcmp (s->opcode, "<JUMPB>");
}
int
flow_is_return (statement_t *s)
{
@ -247,6 +257,36 @@ flow_get_target (statement_t *s)
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
flow_find_predecessors (flowgraph_t *graph)
{
@ -413,6 +453,7 @@ flow_build_graph (sblock_t *sblock)
flowgraph_t *graph;
flownode_t *node;
sblock_t *sb;
sblock_t **target_list, **target;
statement_t *st;
set_iter_t *succ;
int i, j;
@ -445,6 +486,11 @@ flow_build_graph (sblock_t *sblock)
if (flow_is_goto (st)) {
// sb's next is never followed.
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)) {
// branch: either sb's next or the conditional statment's
// target will be followed.