aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLinus Torvalds <torvalds@ppc970.osdl.org>2004-02-22 18:12:32 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:01:26 -0700
commit60546523cdf5e9e89554b2361a32c83b04a5853a (patch)
tree5feb0cfb520665c9285d2be3b4a346a2510031d8
parenta323e6d3b412a01f6243f1459c556dea0a88e318 (diff)
downloadsparse-dev-60546523cdf5e9e89554b2361a32c83b04a5853a.tar.gz
Add bb "parent" information (ie back-pointers).
This is required for any kind of efficient liveness analysis.
-rw-r--r--linearize.c42
-rw-r--r--symbol.h1
2 files changed, 35 insertions, 8 deletions
diff --git a/linearize.c b/linearize.c
index e86cb799..922867ff 100644
--- a/linearize.c
+++ b/linearize.c
@@ -31,8 +31,15 @@ static struct basic_block *alloc_basic_block(void)
static void show_bb(struct basic_block *bb)
{
struct statement *stmt;
+ struct symbol *owner = bb->this;
- printf("bb: %p%s\n", bb, bb->this ? "" : " UNREACHABLE!!");
+ printf("bb: %p%s\n", bb, owner ? "" : " UNREACHABLE!!");
+ if (owner) {
+ struct basic_block *from;
+ FOR_EACH_PTR(owner->bb_parents, from) {
+ printf(" **from %p**\n", from);
+ } END_FOR_EACH_PTR;
+ }
FOR_EACH_PTR(bb->stmts, stmt) {
show_statement(stmt);
} END_FOR_EACH_PTR;
@@ -85,11 +92,20 @@ static struct basic_block * new_basic_block(struct entrypoint *ep, struct symbol
return bb;
}
+static void add_goto(struct basic_block *bb, struct symbol *sym)
+{
+ if (bb_reachable(bb)) {
+ bb->next = sym;
+ add_bb(&sym->bb_parents, bb);
+ }
+}
+
static void add_label(struct entrypoint *ep, struct symbol *sym)
{
struct basic_block *new_bb = new_basic_block(ep, sym);
+ struct basic_block *bb = ep->active;
- ep->active->next = sym;
+ add_goto(bb, sym);
ep->active = new_bb;
}
@@ -139,6 +155,7 @@ static void add_branch(struct entrypoint *ep, struct statement *stmt, int true,
jump->bb_target = target;
bb->flags |= BB_HASBRANCH;
add_statement(&bb->stmts, jump);
+ add_bb(&target->bb_parents, bb);
}
}
@@ -174,7 +191,7 @@ void linearize_statement(struct entrypoint *ep, struct statement *stmt)
}
case STMT_GOTO: {
- ep->active->next = stmt->goto_label;
+ add_goto(ep->active, stmt->goto_label);
set_unreachable(ep);
break;
}
@@ -218,7 +235,7 @@ void linearize_statement(struct entrypoint *ep, struct statement *stmt)
* with the fallthrough of the never case.
*/
if (bb_reachable(ep->active)) {
- bb->next = create_label(ep, never->pos);
+ add_goto(bb, create_label(ep, never->pos));
break;
}
@@ -239,7 +256,7 @@ void linearize_statement(struct entrypoint *ep, struct statement *stmt)
if (stmt->if_false) {
struct symbol *else_target = alloc_symbol(stmt->pos, SYM_LABEL);
- if_block->next = else_target;
+ add_goto(if_block, else_target);
linearize_statement(ep, stmt->if_false);
add_label(ep, else_target);
}
@@ -247,26 +264,35 @@ void linearize_statement(struct entrypoint *ep, struct statement *stmt)
}
case STMT_SWITCH: {
+ int default_seen;
struct symbol *sym;
struct statement *switch_value;
/* Create the "head node" */
+ if (!bb_reachable(ep->active))
+ break;
+
switch_value = alloc_statement(stmt->pos, STMT_MULTIVALUE);
switch_value->expression = stmt->switch_expression;
linearize_simple_statement(ep, switch_value);
/* Create all the sub-jumps */
+ default_seen = 0;
FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
struct statement *case_stmt = sym->stmt;
struct statement *sw_bb = alloc_statement(case_stmt->pos, STMT_MULTIJMP);
+ if (!case_stmt->case_expression)
+ default_seen = 1;
sw_bb->multi_from = case_stmt->case_expression;
sw_bb->multi_to = case_stmt->case_to;
sw_bb->multi_target = sym;
linearize_simple_statement(ep, sw_bb);
+ add_bb(&sym->bb_parents, ep->active);
} END_FOR_EACH_PTR;
/* Default fall-through case */
- ep->active->next = stmt->switch_break;
+ if (!default_seen)
+ add_goto(ep->active, stmt->switch_break);
set_unreachable(ep);
/* And linearize the actual statement */
@@ -291,7 +317,7 @@ void linearize_statement(struct entrypoint *ep, struct statement *stmt)
if (pre_condition->type == EXPR_VALUE) {
if (!pre_condition->value) {
loop_bottom = alloc_symbol(stmt->pos, SYM_LABEL);
- ep->active->next = loop_bottom;
+ add_goto(ep->active, loop_bottom);
set_unreachable(ep);
}
} else {
@@ -311,7 +337,7 @@ void linearize_statement(struct entrypoint *ep, struct statement *stmt)
linearize_statement(ep, post_statement);
if (!post_condition) {
- ep->active->next = loop_top;
+ add_goto(ep->active, loop_top);
set_unreachable(ep);
} else {
if (post_condition->type != EXPR_VALUE || post_condition->value)
diff --git a/symbol.h b/symbol.h
index 4deec0ac..de6344b7 100644
--- a/symbol.h
+++ b/symbol.h
@@ -95,6 +95,7 @@ struct symbol {
struct symbol_list *symbol_list;
struct expression *initializer;
struct basic_block *bb_target; /* label */
+ struct basic_block_list *bb_parents; /* sources */
long long value; /* Initial value */
};
void *aux; /* Auxiliary info, eg. backend information */