Give labels a usage count to detect unused labels.

This commit is contained in:
Bill Currie 2011-03-03 15:28:49 +09:00
parent 90640614ef
commit c5ecc170b6
5 changed files with 41 additions and 17 deletions

View file

@ -74,6 +74,7 @@ typedef struct ex_label_s {
struct reloc_s *refs; ///< relocations associated with this label
struct sblock_s *dest; ///< the location of this label if known
const char *name; ///< the name of this label
int used; ///< label is used as a target
} ex_label_t;
typedef struct {
@ -548,6 +549,8 @@ expr_t *build_function_call (expr_t *fexpr, struct type_s *ftype,
expr_t *params);
expr_t *function_expr (expr_t *e1, expr_t *e2);
struct function_s;
expr_t *branch_expr (int op, expr_t *test, expr_t *label);
expr_t *goto_expr (expr_t *label);
expr_t *return_expr (struct function_s *f, expr_t *e);
expr_t *conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2);
expr_t *incop_expr (int op, expr_t *e, int postop);

View file

@ -1081,15 +1081,15 @@ convert_bool (expr_t *e, int block)
if (e->type == ex_error)
return e;
if (is_integer_val (e)) {
b = new_unary_expr ('g', 0);
b = goto_expr (0);
if (expr_integer (e))
e = new_bool_expr (make_list (b), 0, b);
else
e = new_bool_expr (0, make_list (b), b);
} else {
b = new_block_expr ();
append_expr (b, new_binary_expr ('i', e, 0));
append_expr (b, new_unary_expr ('g', 0));
append_expr (b, branch_expr ('i', e, 0));
append_expr (b, goto_expr (0));
e = new_bool_expr (make_list (b->e.block.head),
make_list (b->e.block.head->next), b);
}
@ -1818,6 +1818,26 @@ function_expr (expr_t *fexpr, expr_t *params)
return build_function_call (fexpr, ftype, params);
}
expr_t *
branch_expr (int op, expr_t *test, expr_t *label)
{
if (label && label->type != ex_label)
internal_error (label, "not a label");
if (label)
label->e.label.used++;
return new_binary_expr (op, test, label);
}
expr_t *
goto_expr (expr_t *label)
{
if (label && label->type != ex_label)
internal_error (label, "not a label");
if (label)
label->e.label.used++;
return new_unary_expr ('g', label);
}
expr_t *
return_expr (function_t *f, expr_t *e)
{
@ -1913,7 +1933,7 @@ conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2)
append_expr (block, assign_expr (block->e.block.result, e2));
else
append_expr (block, e2);
append_expr (block, new_unary_expr ('g', elabel));
append_expr (block, goto_expr (elabel));
append_expr (block, tlabel);
if (block->e.block.result)
append_expr (block, assign_expr (block->e.block.result, e1));
@ -2124,7 +2144,7 @@ build_if_statement (expr_t *test, expr_t *s1, expr_t *s2)
if (s2) {
expr_t *nl = new_label_expr ();
append_expr (if_expr, new_unary_expr ('g', nl));
append_expr (if_expr, goto_expr (nl));
append_expr (if_expr, fl);
append_expr (if_expr, s2);
@ -2154,7 +2174,7 @@ build_while_statement (expr_t *test, expr_t *statement,
while_expr = new_block_expr ();
append_expr (while_expr, new_unary_expr ('g', continue_label));
append_expr (while_expr, goto_expr (continue_label));
append_expr (while_expr, l1);
append_expr (while_expr, statement);
append_expr (while_expr, continue_label);
@ -2234,7 +2254,7 @@ build_for_statement (expr_t *init, expr_t *test, expr_t *next,
append_expr (for_expr, init);
if (test) {
l1 = new_label_expr ();
append_expr (for_expr, new_unary_expr ('g', l1));
append_expr (for_expr, goto_expr (l1));
}
append_expr (for_expr, tl);
append_expr (for_expr, statement);
@ -2250,7 +2270,7 @@ build_for_statement (expr_t *init, expr_t *test, expr_t *next,
append_expr (for_expr, test);
}
} else {
append_expr (for_expr, new_unary_expr ('g', tl));
append_expr (for_expr, goto_expr (tl));
append_expr (for_expr, fl);
}

View file

@ -1000,7 +1000,7 @@ statement
{
$$ = 0;
if (break_label)
$$ = new_unary_expr ('g', break_label);
$$ = goto_expr (break_label);
else
error (0, "break outside of loop or switch");
}
@ -1008,7 +1008,7 @@ statement
{
$$ = 0;
if (continue_label)
$$ = new_unary_expr ('g', continue_label);
$$ = goto_expr (continue_label);
else
error (0, "continue outside of loop");
}

View file

@ -1054,6 +1054,7 @@ make_statements (expr_t *e)
statement_slist (sblock, e);
// print_flow (sblock);
remove_dead_blocks (sblock);
// print_flow (sblock);
check_final_block (sblock);
// print_flow (sblock);
return sblock;

View file

@ -271,7 +271,7 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val,
expr_t *low_label = default_label;
if (!tree) {
branch = new_unary_expr ('g', default_label);
branch = goto_expr (default_label);
append_expr (sw, branch);
return;
}
@ -289,7 +289,7 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val,
append_expr (sw, test);
if (tree->low == tree->high) {
branch = new_binary_expr ('n', temp, tree->labels[0]);
branch = branch_expr ('n', temp, tree->labels[0]);
append_expr (sw, branch);
if (tree->left) {
@ -326,7 +326,7 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val,
}
//FIXME unsigned int
test = binary_expr (GT, cast_expr (&type_integer, temp), range);
branch = new_binary_expr ('i', test, high_label);
branch = branch_expr ('i', test, high_label);
append_expr (sw, branch);
branch = new_binary_expr ('g', table, temp);
append_expr (sw, branch);
@ -342,6 +342,7 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val,
def_t loc;
loc.space = sym->s.def->space;
loc.offset = sym->s.def->offset + i;
tree->labels[i]->e.label.used++;
reloc_def_op (&tree->labels[i]->e.label, &loc);
}
}
@ -373,7 +374,7 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label,
default_label = &_default_label;
default_label->label = break_label;
}
default_expr = new_unary_expr ('g', default_label->label);
default_expr = goto_expr (default_label->label);
append_expr (sw, assign_expr (sw_val, switch_block->test));
@ -385,9 +386,8 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label,
|| num_labels < 8) {
for (l = labels; *l; l++) {
expr_t *cmp = binary_expr (EQ, sw_val, (*l)->value);
expr_t *test = new_binary_expr ('i',
test_expr (cmp),
(*l)->label);
expr_t *test = branch_expr ('i', test_expr (cmp),
(*l)->label);
append_expr (sw, test);
}