From 66366b9623d4709c039e2971aaa2c35a8ceeae8f Mon Sep 17 00:00:00 2001 From: rguenth Date: Mon, 14 Jan 2013 14:59:20 +0000 Subject: [PATCH] 2013-01-14 Richard Biener * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@195147 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 +++++ gcc/tree-cfg.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7b316199bdd..93947b6e34f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2013-01-14 Richard Biener + * 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 + * tree-cfgcleanup.c (remove_forwarder_block): Unshare propagated PHI argument. * graphite-sese-to-poly.c (insert_out_of_ssa_copy): Properly diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index e0bf7ac6b3c..83003fb8b44 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -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); } -- 2.11.4.GIT