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:
Richard Biener 2013-01-14 14:59:20 +00:00 committed by Richard Biener
parent 30b2fc65b9
commit 7bb0199604
2 changed files with 105 additions and 1 deletions

View File

@ -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

View File

@ -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);
}