aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-cfg.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2006-09-29 06:32:58 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2006-09-29 06:32:58 +0000
commit4f6c213142e5ce6f5ee17ef5d0f1cb85cd0ff573 (patch)
treec8e2772aad71fdf66dba0112c42b9178748e598f /gcc/tree-cfg.c
parenta40e443fe8ce40cabbedbe4d134a3e7d397ea089 (diff)
downloadgcc-4f6c213142e5ce6f5ee17ef5d0f1cb85cd0ff573.zip
gcc-4f6c213142e5ce6f5ee17ef5d0f1cb85cd0ff573.tar.gz
gcc-4f6c213142e5ce6f5ee17ef5d0f1cb85cd0ff573.tar.bz2
builtins.c (expand_builtin_setjmp): Delete.
* builtins.c (expand_builtin_setjmp): Delete. (expand_builtin) <BUILT_IN_SETJMP>: Mark as unreachable. <BUILT_IN_SETJMP_SETUP>: New case. <BUILT_IN_SETJMP_DISPATCHER>: Likewise. <BUILT_IN_SETJMP_RECEIVER>: Likewise. * builtins.def (BUILT_IN_SETJMP_SETUP): New built-in stub. (BUILT_IN_SETJMP_DISPATCHER): Likewise. (BUILT_IN_SETJMP_RECEIVER): Likewise. * gimple-low.c (struct lower_data): New field calls_builtin_setjmp. (lower_function_body): Initialize it to false. If it is set to true at the end of the processing, emit the setjmp dispatcher. (lower_stmt) <CALL_EXPR>: Invoke lower_builtin_setjmp if the callee is __builtin_setjmp and set calls_builtin_setjmp to true as well. <MODIFY_EXPR>: Fall through to above case if there is a CALL_EXPR on the rhs of the assignment. (lower_builtin_setjmp): New function. * tree.c (build_common_builtin_nodes): Build BUILT_IN_SETJMP_SETUP, BUILT_IN_SETJMP_DISPATCHER and BUILT_IN_SETJMP_RECEIVER nodes. * tree-cfg.c (make_exit_edges) <CALL_EXPR>: Use specific predicate to detect calls that can go to non-local labels. Use specific helper to create the abnormal edges associated with them. <MODIFY_EXPR>: Likewise. (make_abnormal_goto_edges): New function extracted from... (make_goto_expr_edges): ...here. Call it for computed gotos. (simple_goto_p): Minor tweak. (tree_can_make_abnormal_goto): New predicate. (tree_redirect_edge_and_branch): Return zero on all abnormal edges. (tree_purge_dead_abnormal_call_edges): New function. * tree-flow.h (tree_can_make_abnormal_goto): Declare. (tree_purge_dead_abnormal_call_edges): Likewise. (make_abnormal_goto_edges): Likewise. * tree-inline.c (expand_call_inline): Simplify statement frobbing. Purge all dead abnormal edges if the call was in the last statement. * tree-optimize.c (has_abnormal_outgoing_edge_p): New predicate. (execute_fixup_cfg): If there are non-local labels in the function, scan the basic blocks and split them at calls that can go to non-local labels or add missing abnormal call edges. Write down the CFG in the dump file. (pass_fixup_cfg): Remove TODO_dump_func flag. * unwind-sjlj.c: Poison setjmp. * doc/install.texi (enable-sjlj-exceptions): Use more general wording. * doc/tm.texi (DWARF2_UNWIND_INFO): Likewise. (TARGET_UNWIND_TABLES_DEFAULT): Fix typo. (DONT_USE_BUILTIN_SETJMP): Document it. From-SVN: r117298
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r--gcc/tree-cfg.c170
1 files changed, 102 insertions, 68 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 67d0491..46ee1b1 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -489,9 +489,8 @@ make_edges (void)
/* If this function receives a nonlocal goto, then we need to
make edges from this call site to all the nonlocal goto
handlers. */
- if (TREE_SIDE_EFFECTS (last)
- && current_function_has_nonlocal_label)
- make_goto_expr_edges (bb);
+ if (tree_can_make_abnormal_goto (last))
+ make_abnormal_goto_edges (bb, true);
/* If this statement has reachable exception handlers, then
create abnormal edges to them. */
@@ -507,10 +506,8 @@ make_edges (void)
/* A MODIFY_EXPR may have a CALL_EXPR on its RHS and the
CALL_EXPR may have an abnormal edge. Search the RHS for
this case and create any required edges. */
- tree op = get_call_expr_in (last);
- if (op && TREE_SIDE_EFFECTS (op)
- && current_function_has_nonlocal_label)
- make_goto_expr_edges (bb);
+ if (tree_can_make_abnormal_goto (last))
+ make_abnormal_goto_edges (bb, true);
make_eh_edges (last);
}
@@ -836,76 +833,60 @@ label_to_block_fn (struct function *ifun, tree dest)
return VEC_index (basic_block, ifun->cfg->x_label_to_block_map, uid);
}
+/* Create edges for an abnormal goto statement at block BB. If FOR_CALL
+ is true, the source statement is a CALL_EXPR instead of a GOTO_EXPR. */
+
+void
+make_abnormal_goto_edges (basic_block bb, bool for_call)
+{
+ basic_block target_bb;
+ block_stmt_iterator bsi;
+
+ FOR_EACH_BB (target_bb)
+ for (bsi = bsi_start (target_bb); !bsi_end_p (bsi); bsi_next (&bsi))
+ {
+ tree target = bsi_stmt (bsi);
+
+ if (TREE_CODE (target) != LABEL_EXPR)
+ break;
+
+ target = LABEL_EXPR_LABEL (target);
+
+ /* Make an edge to every label block that has been marked as a
+ potential target for a computed goto or a non-local goto. */
+ if ((FORCED_LABEL (target) && !for_call)
+ || (DECL_NONLOCAL (target) && for_call))
+ {
+ make_edge (bb, target_bb, EDGE_ABNORMAL);
+ break;
+ }
+ }
+}
+
/* Create edges for a goto statement at block BB. */
static void
make_goto_expr_edges (basic_block bb)
{
- tree goto_t;
- basic_block target_bb;
- bool for_call;
block_stmt_iterator last = bsi_last (bb);
+ tree goto_t = bsi_stmt (last);
- goto_t = bsi_stmt (last);
-
- /* If the last statement is not a GOTO (i.e., it is a RETURN_EXPR,
- CALL_EXPR or MODIFY_EXPR), then the edge is an abnormal edge resulting
- from a nonlocal goto. */
- if (TREE_CODE (goto_t) != GOTO_EXPR)
- for_call = true;
- else
+ /* A simple GOTO creates normal edges. */
+ if (simple_goto_p (goto_t))
{
tree dest = GOTO_DESTINATION (goto_t);
- for_call = false;
-
- /* A GOTO to a local label creates normal edges. */
- if (simple_goto_p (goto_t))
- {
- edge e = make_edge (bb, label_to_block (dest), EDGE_FALLTHRU);
+ edge e = make_edge (bb, label_to_block (dest), EDGE_FALLTHRU);
#ifdef USE_MAPPED_LOCATION
- e->goto_locus = EXPR_LOCATION (goto_t);
+ e->goto_locus = EXPR_LOCATION (goto_t);
#else
- e->goto_locus = EXPR_LOCUS (goto_t);
+ e->goto_locus = EXPR_LOCUS (goto_t);
#endif
- bsi_remove (&last, true);
- return;
- }
-
- /* Nothing more to do for nonlocal gotos. */
- if (TREE_CODE (dest) == LABEL_DECL)
- return;
-
- /* Computed gotos remain. */
+ bsi_remove (&last, true);
+ return;
}
- /* Look for the block starting with the destination label. In the
- case of a computed goto, make an edge to any label block we find
- in the CFG. */
- FOR_EACH_BB (target_bb)
- {
- block_stmt_iterator bsi;
-
- for (bsi = bsi_start (target_bb); !bsi_end_p (bsi); bsi_next (&bsi))
- {
- tree target = bsi_stmt (bsi);
-
- if (TREE_CODE (target) != LABEL_EXPR)
- break;
-
- if (
- /* Computed GOTOs. Make an edge to every label block that has
- been marked as a potential target for a computed goto. */
- (FORCED_LABEL (LABEL_EXPR_LABEL (target)) && !for_call)
- /* Nonlocal GOTO target. Make an edge to every label block
- that has been marked as a potential target for a nonlocal
- goto. */
- || (DECL_NONLOCAL (LABEL_EXPR_LABEL (target)) && for_call))
- {
- make_edge (bb, target_bb, EDGE_ABNORMAL);
- break;
- }
- }
- }
+ /* A computed GOTO creates abnormal edges. */
+ make_abnormal_goto_edges (bb, false);
}
@@ -2517,13 +2498,31 @@ computed_goto_p (tree t)
}
-/* Checks whether EXPR is a simple local goto. */
+/* Return true if T is a simple local goto. */
+
+bool
+simple_goto_p (tree t)
+{
+ return (TREE_CODE (t) == GOTO_EXPR
+ && TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL);
+}
+
+
+/* Return true if T can make an abnormal transfer of control flow.
+ Transfers of control flow associated with EH are excluded. */
bool
-simple_goto_p (tree expr)
+tree_can_make_abnormal_goto (tree t)
{
- return (TREE_CODE (expr) == GOTO_EXPR
- && TREE_CODE (GOTO_DESTINATION (expr)) == LABEL_DECL);
+ if (computed_goto_p (t))
+ return true;
+ if (TREE_CODE (t) == MODIFY_EXPR)
+ t = TREE_OPERAND (t, 1);
+ if (TREE_CODE (t) == WITH_SIZE_EXPR)
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == CALL_EXPR)
+ return TREE_SIDE_EFFECTS (t) && current_function_has_nonlocal_label;
+ return false;
}
@@ -4072,7 +4071,7 @@ tree_redirect_edge_and_branch (edge e, basic_block dest)
edge ret;
tree label, stmt;
- if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
+ if (e->flags & EDGE_ABNORMAL)
return NULL;
if (e->src != ENTRY_BLOCK_PTR
@@ -5374,6 +5373,41 @@ tree_flow_call_edges_add (sbitmap blocks)
return blocks_split;
}
+/* Purge dead abnormal call edges from basic block BB. */
+
+bool
+tree_purge_dead_abnormal_call_edges (basic_block bb)
+{
+ bool changed = tree_purge_dead_eh_edges (bb);
+
+ if (current_function_has_nonlocal_label)
+ {
+ tree stmt = last_stmt (bb);
+ edge_iterator ei;
+ edge e;
+
+ if (!(stmt && tree_can_make_abnormal_goto (stmt)))
+ for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
+ {
+ if (e->flags & EDGE_ABNORMAL)
+ {
+ remove_edge (e);
+ changed = true;
+ }
+ else
+ ei_next (&ei);
+ }
+
+ /* See tree_purge_dead_eh_edges below. */
+ if (changed)
+ free_dominance_info (CDI_DOMINATORS);
+ }
+
+ return changed;
+}
+
+/* Purge dead EH edges from basic block BB. */
+
bool
tree_purge_dead_eh_edges (basic_block bb)
{