mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-17 01:11:45 +00:00
Move and rename statement related flow_is_* and flow_get_*
They really should have been in statements.[ch] in the first place (actually, they sort of were: is_goto etc, so some redundant code has been removed, too).
This commit is contained in:
parent
086fd0f3c3
commit
93f53605ed
5 changed files with 93 additions and 111 deletions
|
@ -99,12 +99,6 @@ typedef struct flowgraph_s {
|
|||
} flowgraph_t;
|
||||
|
||||
flowvar_t *flow_get_var (struct operand_s *op);
|
||||
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_analyze_statement (struct statement_s *s, struct set_s *use,
|
||||
struct set_s *def, struct set_s *kill,
|
||||
struct operand_s *operands[4]);
|
||||
|
|
|
@ -112,6 +112,12 @@ operand_t *temp_operand (struct type_s *type);
|
|||
sblock_t *new_sblock (void);
|
||||
statement_t *new_statement (st_type_t type, const char *opcode,
|
||||
struct expr_s *expr);
|
||||
int statement_is_cond (statement_t *s);
|
||||
int statement_is_goto (statement_t *s);
|
||||
int statement_is_jumpb (statement_t *s);
|
||||
int statement_is_return (statement_t *s);
|
||||
sblock_t *statement_get_target (statement_t *s);
|
||||
sblock_t **statement_get_targetlist (statement_t *s);
|
||||
void sblock_add_statement (sblock_t *sblock, statement_t *statement);
|
||||
sblock_t *make_statements (struct expr_s *expr);
|
||||
void print_statement (statement_t *s);
|
||||
|
|
|
@ -97,11 +97,11 @@ flow_sblock (dstring_t *dstr, sblock_t *sblock, int blockno)
|
|||
if (sblock->statements) {
|
||||
statement_t *st = (statement_t *) sblock->tail;
|
||||
if (sblock->next
|
||||
&& !flow_is_goto (st)
|
||||
&& !flow_is_jumpb (st)
|
||||
&& !flow_is_return (st))
|
||||
&& !statement_is_goto (st)
|
||||
&& !statement_is_jumpb (st)
|
||||
&& !statement_is_return (st))
|
||||
dasprintf (dstr, " sb_%p:e -> sb_%p:s;\n", sblock, sblock->next);
|
||||
if ((target_list = flow_get_targetlist (st))) {
|
||||
if ((target_list = statement_get_targetlist (st))) {
|
||||
for (target = target_list; *target; target++)
|
||||
dasprintf (dstr, " sb_%p:e -> sb_%p:s [label=\"%s\"];\n",
|
||||
sblock, *target, st->opcode);
|
||||
|
|
|
@ -639,78 +639,6 @@ flow_generate (flowgraph_t *graph)
|
|||
return code;
|
||||
}
|
||||
|
||||
int
|
||||
flow_is_cond (statement_t *s)
|
||||
{
|
||||
if (!s)
|
||||
return 0;
|
||||
return !strncmp (s->opcode, "<IF", 3);
|
||||
}
|
||||
|
||||
int
|
||||
flow_is_goto (statement_t *s)
|
||||
{
|
||||
if (!s)
|
||||
return 0;
|
||||
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)
|
||||
{
|
||||
if (!s)
|
||||
return 0;
|
||||
return !strncmp (s->opcode, "<RETURN", 7);
|
||||
}
|
||||
|
||||
sblock_t *
|
||||
flow_get_target (statement_t *s)
|
||||
{
|
||||
if (flow_is_cond (s))
|
||||
return s->opb->o.label->dest;
|
||||
if (flow_is_goto (s))
|
||||
return s->opa->o.label->dest;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sblock_t **
|
||||
flow_get_targetlist (statement_t *s)
|
||||
{
|
||||
sblock_t **target_list;
|
||||
int count = 0, 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_add_op_var (set_t *set, operand_t *op)
|
||||
{
|
||||
|
@ -1040,23 +968,23 @@ flow_build_graph (sblock_t *sblock, function_t *func)
|
|||
st = 0;
|
||||
if (sb->statements)
|
||||
st = (statement_t *) sb->tail;
|
||||
//NOTE: if st is null (the sblock has no statements), flow_is_* will
|
||||
//return false
|
||||
//NOTE: if st is null (the sblock has no statements), statement_is_*
|
||||
//will return false
|
||||
//FIXME jump/jumpb
|
||||
if (flow_is_goto (st)) {
|
||||
if (statement_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);
|
||||
set_add (node->successors, statement_get_target (st)->number);
|
||||
} else if (statement_is_jumpb (st)) {
|
||||
target_list = statement_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 (statement_is_cond (st)) {
|
||||
// branch: either sb's next or the conditional statment's
|
||||
// target will be followed.
|
||||
set_add (node->successors, sb->next->number);
|
||||
set_add (node->successors, flow_get_target (st)->number);
|
||||
} else if (flow_is_return (st)) {
|
||||
set_add (node->successors, statement_get_target (st)->number);
|
||||
} else if (statement_is_return (st)) {
|
||||
// exit from function (dead end)
|
||||
} else {
|
||||
// there is no flow-control statement in sb, so sb's next
|
||||
|
|
|
@ -368,22 +368,76 @@ convert_op (int op)
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
is_goto (statement_t *s)
|
||||
int
|
||||
statement_is_cond (statement_t *s)
|
||||
{
|
||||
if (!s)
|
||||
return 0;
|
||||
return !strncmp (s->opcode, "<IF", 3);
|
||||
}
|
||||
|
||||
int
|
||||
statement_is_goto (statement_t *s)
|
||||
{
|
||||
if (!s)
|
||||
return 0;
|
||||
return !strcmp (s->opcode, "<GOTO>");
|
||||
}
|
||||
|
||||
static int
|
||||
is_return (statement_t *s)
|
||||
int
|
||||
statement_is_jumpb (statement_t *s)
|
||||
{
|
||||
if (!s)
|
||||
return 0;
|
||||
return !strcmp (s->opcode, "<JUMPB>");
|
||||
}
|
||||
|
||||
int
|
||||
statement_is_return (statement_t *s)
|
||||
{
|
||||
if (!s)
|
||||
return 0;
|
||||
return !strncmp (s->opcode, "<RETURN", 7);
|
||||
}
|
||||
|
||||
static int
|
||||
is_conditional (statement_t *s)
|
||||
sblock_t *
|
||||
statement_get_target (statement_t *s)
|
||||
{
|
||||
return !strncmp (s->opcode, "<IF", 3);
|
||||
if (statement_is_cond (s))
|
||||
return s->opb->o.label->dest;
|
||||
if (statement_is_goto (s))
|
||||
return s->opa->o.label->dest;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sblock_t **
|
||||
statement_get_targetlist (statement_t *s)
|
||||
{
|
||||
sblock_t **target_list;
|
||||
int count = 0, i;
|
||||
def_t *table = 0;
|
||||
expr_t *e;
|
||||
|
||||
if (statement_is_cond (s)) {
|
||||
count = 1;
|
||||
} else if (statement_is_goto (s)) {
|
||||
count = 1;
|
||||
} else if (statement_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 (statement_is_cond (s)) {
|
||||
target_list[0] = statement_get_target (s);
|
||||
} else if (statement_is_goto (s)) {
|
||||
target_list[0] = statement_get_target (s);
|
||||
} else if (statement_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
|
||||
|
@ -1208,14 +1262,14 @@ thread_jumps (sblock_t *blocks)
|
|||
if (!sblock->statements)
|
||||
continue;
|
||||
s = (statement_t *) sblock->tail;
|
||||
if (is_goto (s))
|
||||
if (statement_is_goto (s))
|
||||
label = &s->opa->o.label;
|
||||
else if (is_conditional (s))
|
||||
else if (statement_is_cond (s))
|
||||
label = &s->opb->o.label;
|
||||
else
|
||||
continue;
|
||||
for (l = *label;
|
||||
l->dest->statements && is_goto (l->dest->statements);
|
||||
l->dest->statements && statement_is_goto (l->dest->statements);
|
||||
l = l->dest->statements->opa->o.label) {
|
||||
}
|
||||
if (l != *label) {
|
||||
|
@ -1223,7 +1277,7 @@ thread_jumps (sblock_t *blocks)
|
|||
l->used++;
|
||||
*label = l;
|
||||
}
|
||||
if (is_goto (s) && (*label)->dest == sblock->next) {
|
||||
if (statement_is_goto (s) && (*label)->dest == sblock->next) {
|
||||
statement_t **p;
|
||||
unuse_label (*label);
|
||||
for (p = &sblock->statements; *p != s; p = &(*p)->next)
|
||||
|
@ -1287,7 +1341,7 @@ merge_blocks (sblock_t *blocks)
|
|||
if (!sblock->statements)
|
||||
continue;
|
||||
s = (statement_t *) sblock->tail;
|
||||
if (!is_goto (s))
|
||||
if (!statement_is_goto (s))
|
||||
continue;
|
||||
dest = s->opa->o.label->dest;
|
||||
// The destination block must not be the current block
|
||||
|
@ -1312,7 +1366,7 @@ merge_blocks (sblock_t *blocks)
|
|||
if (!sb->statements)
|
||||
continue;
|
||||
s = (statement_t *) sb->tail;
|
||||
if (!is_goto (s) && !is_return (s))
|
||||
if (!statement_is_goto (s) && !statement_is_return (s))
|
||||
continue;
|
||||
// desination block is reachable only via goto of the current block
|
||||
if (!dest->next)
|
||||
|
@ -1351,8 +1405,8 @@ remove_dead_blocks (sblock_t *blocks)
|
|||
continue;
|
||||
}
|
||||
s = (statement_t *) sblock->tail;
|
||||
if (is_conditional (s)
|
||||
&& sb->statements && is_goto (sb->statements)
|
||||
if (statement_is_cond (s)
|
||||
&& sb->statements && statement_is_goto (sb->statements)
|
||||
&& s->opb->o.label->dest == sb->next) {
|
||||
debug (0, "merging if/goto %p %p", sblock, sb);
|
||||
unuse_label (s->opb->o.label);
|
||||
|
@ -1363,7 +1417,7 @@ remove_dead_blocks (sblock_t *blocks)
|
|||
for (sb = sb->next; sb; sb = sb->next)
|
||||
sb->reachable = 1;
|
||||
break;
|
||||
} else if (!is_goto (s) && !is_return (s)) {
|
||||
} else if (!statement_is_goto (s) && !statement_is_return (s)) {
|
||||
sb->reachable = 1;
|
||||
continue;
|
||||
}
|
||||
|
@ -1379,9 +1433,9 @@ remove_dead_blocks (sblock_t *blocks)
|
|||
|
||||
if (sb->statements) {
|
||||
s = (statement_t *) sb->tail;
|
||||
if (is_goto (s))
|
||||
if (statement_is_goto (s))
|
||||
label = s->opa->o.label;
|
||||
else if (is_conditional (s))
|
||||
else if (statement_is_cond (s))
|
||||
label = s->opb->o.label;
|
||||
}
|
||||
unuse_label (label);
|
||||
|
@ -1408,9 +1462,9 @@ check_final_block (sblock_t *sblock)
|
|||
sblock = sblock->next;
|
||||
if (sblock->statements) {
|
||||
s = (statement_t *) sblock->tail;
|
||||
if (is_goto (s))
|
||||
if (statement_is_goto (s))
|
||||
return; // the end of function is the end of a loop
|
||||
if (is_return (s))
|
||||
if (statement_is_return (s))
|
||||
return;
|
||||
}
|
||||
if (current_func->sym->type->t.func.type != &type_void)
|
||||
|
|
Loading…
Reference in a new issue