mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 08:30:28 +08:00
tree-cfg.c (verify_expr_location, [...]): New functions.
2013-01-14 Richard Biener <rguenther@suse.de> * tree-cfg.c (verify_expr_location, verify_expr_location_1, verify_location, collect_subblocks): New functions. (verify_gimple_in_cfg): Verify that locations only reference BLOCKs in the functions BLOCK tree. From-SVN: r195147
This commit is contained in:
parent
30b2fc65b9
commit
7bb0199604
@ -1,3 +1,10 @@
|
||||
2013-01-14 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* tree-cfg.c (verify_expr_location, verify_expr_location_1,
|
||||
verify_location, collect_subblocks): New functions.
|
||||
(verify_gimple_in_cfg): Verify that locations only reference
|
||||
BLOCKs in the functions BLOCK tree.
|
||||
|
||||
2013-01-14 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* tree-cfgcleanup.c (remove_forwarder_block): Unshare propagated
|
||||
|
@ -4499,6 +4499,63 @@ verify_eh_throw_stmt_node (void **slot, void *data)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Verify if the location LOCs block is in BLOCKS. */
|
||||
|
||||
static bool
|
||||
verify_location (pointer_set_t *blocks, location_t loc)
|
||||
{
|
||||
tree block = LOCATION_BLOCK (loc);
|
||||
if (block != NULL_TREE
|
||||
&& !pointer_set_contains (blocks, block))
|
||||
{
|
||||
error ("location references block not in block tree");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Called via walk_tree. Verify locations of expressions. */
|
||||
|
||||
static tree
|
||||
verify_expr_location_1 (tree *tp, int *walk_subtrees, void *data)
|
||||
{
|
||||
struct pointer_set_t *blocks = (struct pointer_set_t *) data;
|
||||
|
||||
if (!EXPR_P (*tp))
|
||||
{
|
||||
*walk_subtrees = false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
location_t loc = EXPR_LOCATION (*tp);
|
||||
if (verify_location (blocks, loc))
|
||||
return *tp;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Called via walk_gimple_op. Verify locations of expressions. */
|
||||
|
||||
static tree
|
||||
verify_expr_location (tree *tp, int *walk_subtrees, void *data)
|
||||
{
|
||||
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
|
||||
return verify_expr_location_1 (tp, walk_subtrees, wi->info);
|
||||
}
|
||||
|
||||
/* Insert all subblocks of BLOCK into BLOCKS and recurse. */
|
||||
|
||||
static void
|
||||
collect_subblocks (pointer_set_t *blocks, tree block)
|
||||
{
|
||||
tree t;
|
||||
for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
|
||||
{
|
||||
pointer_set_insert (blocks, t);
|
||||
collect_subblocks (blocks, t);
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify the GIMPLE statements in the CFG of FN. */
|
||||
|
||||
DEBUG_FUNCTION void
|
||||
@ -4506,12 +4563,20 @@ verify_gimple_in_cfg (struct function *fn)
|
||||
{
|
||||
basic_block bb;
|
||||
bool err = false;
|
||||
struct pointer_set_t *visited, *visited_stmts;
|
||||
struct pointer_set_t *visited, *visited_stmts, *blocks;
|
||||
|
||||
timevar_push (TV_TREE_STMT_VERIFY);
|
||||
visited = pointer_set_create ();
|
||||
visited_stmts = pointer_set_create ();
|
||||
|
||||
/* Collect all BLOCKs referenced by the BLOCK tree of FN. */
|
||||
blocks = pointer_set_create ();
|
||||
if (DECL_INITIAL (fn->decl))
|
||||
{
|
||||
pointer_set_insert (blocks, DECL_INITIAL (fn->decl));
|
||||
collect_subblocks (blocks, DECL_INITIAL (fn->decl));
|
||||
}
|
||||
|
||||
FOR_EACH_BB_FN (bb, fn)
|
||||
{
|
||||
gimple_stmt_iterator gsi;
|
||||
@ -4532,6 +4597,13 @@ verify_gimple_in_cfg (struct function *fn)
|
||||
|
||||
err2 |= verify_gimple_phi (phi);
|
||||
|
||||
/* Only PHI arguments have locations. */
|
||||
if (gimple_location (phi) != UNKNOWN_LOCATION)
|
||||
{
|
||||
error ("PHI node with location");
|
||||
err2 = true;
|
||||
}
|
||||
|
||||
for (i = 0; i < gimple_phi_num_args (phi); i++)
|
||||
{
|
||||
tree arg = gimple_phi_arg_def (phi, i);
|
||||
@ -4543,6 +4615,20 @@ verify_gimple_in_cfg (struct function *fn)
|
||||
debug_generic_expr (addr);
|
||||
err2 |= true;
|
||||
}
|
||||
location_t loc = gimple_phi_arg_location (phi, i);
|
||||
if (virtual_operand_p (gimple_phi_result (phi))
|
||||
&& loc != UNKNOWN_LOCATION)
|
||||
{
|
||||
error ("virtual PHI with argument locations");
|
||||
err2 = true;
|
||||
}
|
||||
addr = walk_tree (&arg, verify_expr_location_1, blocks, NULL);
|
||||
if (addr)
|
||||
{
|
||||
debug_generic_expr (addr);
|
||||
err2 = true;
|
||||
}
|
||||
err2 |= verify_location (blocks, loc);
|
||||
}
|
||||
|
||||
if (err2)
|
||||
@ -4567,6 +4653,7 @@ verify_gimple_in_cfg (struct function *fn)
|
||||
}
|
||||
|
||||
err2 |= verify_gimple_stmt (stmt);
|
||||
err2 |= verify_location (blocks, gimple_location (stmt));
|
||||
|
||||
memset (&wi, 0, sizeof (wi));
|
||||
wi.info = (void *) visited;
|
||||
@ -4578,6 +4665,15 @@ verify_gimple_in_cfg (struct function *fn)
|
||||
err2 |= true;
|
||||
}
|
||||
|
||||
memset (&wi, 0, sizeof (wi));
|
||||
wi.info = (void *) blocks;
|
||||
addr = walk_gimple_op (stmt, verify_expr_location, &wi);
|
||||
if (addr)
|
||||
{
|
||||
debug_generic_expr (addr);
|
||||
err2 |= true;
|
||||
}
|
||||
|
||||
/* ??? Instead of not checking these stmts at all the walker
|
||||
should know its context via wi. */
|
||||
if (!is_gimple_debug (stmt)
|
||||
@ -4632,6 +4728,7 @@ verify_gimple_in_cfg (struct function *fn)
|
||||
|
||||
pointer_set_destroy (visited);
|
||||
pointer_set_destroy (visited_stmts);
|
||||
pointer_set_destroy (blocks);
|
||||
verify_histograms ();
|
||||
timevar_pop (TV_TREE_STMT_VERIFY);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user