/* Exception handling semantics and decomposition for trees.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
{
while (bitmap_set_bit (eh_region_may_contain_throw_map, region->index))
{
+ if (region->type == ERT_MUST_NOT_THROW)
+ break;
region = region->outer;
if (region == NULL)
break;
if (tf->may_fallthru)
{
x = gimple_build_assign (finally_tmp,
- build_int_cst (NULL, fallthru_index));
+ build_int_cst (integer_type_node,
+ fallthru_index));
gimple_seq_add_stmt (&tf->top_p_seq, x);
last_case = build3 (CASE_LABEL_EXPR, void_type_node,
- build_int_cst (NULL, fallthru_index),
+ build_int_cst (integer_type_node, fallthru_index),
NULL, create_artificial_label (tf_loc));
VEC_quick_push (tree, case_label_vec, last_case);
last_case_index++;
emit_post_landing_pad (&eh_seq, tf->region);
x = gimple_build_assign (finally_tmp,
- build_int_cst (NULL, eh_index));
+ build_int_cst (integer_type_node, eh_index));
gimple_seq_add_stmt (&eh_seq, x);
x = gimple_build_goto (finally_label);
gimple_seq_add_stmt (&eh_seq, x);
last_case = build3 (CASE_LABEL_EXPR, void_type_node,
- build_int_cst (NULL, eh_index),
+ build_int_cst (integer_type_node, eh_index),
NULL, create_artificial_label (tf_loc));
VEC_quick_push (tree, case_label_vec, last_case);
last_case_index++;
if (q->index < 0)
{
x = gimple_build_assign (finally_tmp,
- build_int_cst (NULL, return_index));
+ build_int_cst (integer_type_node,
+ return_index));
gimple_seq_add_stmt (&mod, x);
do_return_redirection (q, finally_label, mod, &return_val);
switch_id = return_index;
else
{
x = gimple_build_assign (finally_tmp,
- build_int_cst (NULL, q->index));
+ build_int_cst (integer_type_node, q->index));
gimple_seq_add_stmt (&mod, x);
do_goto_redirection (q, finally_label, mod, tf);
switch_id = q->index;
tree case_lab;
void **slot;
case_lab = build3 (CASE_LABEL_EXPR, void_type_node,
- build_int_cst (NULL, switch_id),
- NULL, NULL);
+ build_int_cst (integer_type_node, switch_id),
+ NULL, create_artificial_label (tf_loc));
/* We store the cont_stmt in the pointer map, so that we can recover
- it in the loop below. We don't create the new label while
- walking the goto_queue because pointers don't offer a stable
- order. */
+ it in the loop below. */
if (!cont_map)
cont_map = pointer_map_create ();
slot = pointer_map_insert (cont_map, case_lab);
}
for (j = last_case_index; j < last_case_index + nlabels; j++)
{
- tree label;
gimple cont_stmt;
void **slot;
gcc_assert (cont_map);
slot = pointer_map_contains (cont_map, last_case);
- /* As the comment above suggests, CASE_LABEL (last_case) was just a
- placeholder, it does not store an actual label, yet. */
gcc_assert (slot);
cont_stmt = *(gimple *) slot;
- label = create_artificial_label (tf_loc);
- CASE_LABEL (last_case) = label;
-
- x = gimple_build_label (label);
+ x = gimple_build_label (CASE_LABEL (last_case));
gimple_seq_add_stmt (&switch_body, x);
gimple_seq_add_stmt (&switch_body, cont_stmt);
maybe_record_in_goto_queue (state, cont_stmt);
}
VEC_free (tree, heap, this_tf.dest_array);
- if (this_tf.goto_queue)
- free (this_tf.goto_queue);
+ free (this_tf.goto_queue);
if (this_tf.goto_queue_map)
pointer_map_destroy (this_tf.goto_queue_map);
this zero argument with the current catch region number. */
if (state->ehp_region)
{
- tree nr = build_int_cst (NULL, state->ehp_region->index);
+ tree nr = build_int_cst (integer_type_node,
+ state->ehp_region->index);
gimple_call_set_arg (stmt, 0, nr);
}
else
|| gimple_call_lhs (twos)
|| gimple_call_chain (ones)
|| gimple_call_chain (twos)
- || !operand_equal_p (gimple_call_fn (ones), gimple_call_fn (twos), 0)
+ || !gimple_call_same_target_p (ones, twos)
|| gimple_call_num_args (ones) != gimple_call_num_args (twos))
return false;
else
{
edge_iterator ei;
- tree dst_nr = build_int_cst (NULL, dst_r->index);
+ tree dst_nr = build_int_cst (integer_type_node, dst_r->index);
fn = implicit_built_in_decls[BUILT_IN_EH_COPY_VALUES];
- src_nr = build_int_cst (NULL, src_r->index);
+ src_nr = build_int_cst (integer_type_node, src_r->index);
x = gimple_build_call (fn, 2, dst_nr, src_nr);
gsi_insert_before (&gsi, x, GSI_SAME_STMT);
else
{
fn = implicit_built_in_decls[BUILT_IN_EH_POINTER];
- src_nr = build_int_cst (NULL, src_r->index);
+ src_nr = build_int_cst (integer_type_node, src_r->index);
x = gimple_build_call (fn, 1, src_nr);
var = create_tmp_var (ptr_type_node, NULL);
var = make_ssa_name (var, x);
else
{
fn = implicit_built_in_decls[BUILT_IN_EH_FILTER];
- x = gimple_build_call (fn, 1, build_int_cst (NULL, region_nr));
+ x = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
+ region_nr));
filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
filter = make_ssa_name (filter, x);
gimple_call_set_lhs (x, filter);
edge f_e = FALLTHRU_EDGE (src);
fn = implicit_built_in_decls[BUILT_IN_EH_FILTER];
- x = gimple_build_call (fn, 1, build_int_cst (NULL, region_nr));
+ x = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
+ region_nr));
filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
filter = make_ssa_name (filter, x);
gimple_call_set_lhs (x, filter);
/* If we did find the corresponding PHI, copy those inputs. */
if (ophi)
{
+ /* If NOP is used somewhere else beyond phis in new_bb, give up. */
+ if (!has_single_use (nop))
+ {
+ imm_use_iterator imm_iter;
+ use_operand_p use_p;
+
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, nop)
+ {
+ if (!gimple_debug_bind_p (USE_STMT (use_p))
+ && (gimple_code (USE_STMT (use_p)) != GIMPLE_PHI
+ || gimple_bb (USE_STMT (use_p)) != new_bb))
+ goto fail;
+ }
+ }
bitmap_set_bit (ophi_handled, SSA_NAME_VERSION (nop));
FOR_EACH_EDGE (e, ei, old_bb->preds)
{
{
gimple_stmt_iterator gsi;
tree lab;
+ edge_iterator ei;
+ edge e;
/* We really ought not have totally lost everything following
a landing pad label. Given that BB is empty, there had better
return false;
}
+ /* The destination block must not be a regular successor for any
+ of the preds of the landing pad. Thus, avoid turning
+ <..>
+ | \ EH
+ | <..>
+ | /
+ <..>
+ into
+ <..>
+ | | EH
+ <..>
+ which CFG verification would choke on. See PR45172. */
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (find_edge (e->src, e_out->dest))
+ return false;
+
/* Attempt to move the PHIs into the successor block. */
if (cleanup_empty_eh_merge_phis (e_out->dest, bb, e_out, false))
{
return false;
}
+/* Return true if edge E_FIRST is part of an empty infinite loop
+ or leads to such a loop through a series of single successor
+ empty bbs. */
+
+static bool
+infinite_empty_loop_p (edge e_first)
+{
+ bool inf_loop = false;
+ edge e;
+
+ if (e_first->dest == e_first->src)
+ return true;
+
+ e_first->src->aux = (void *) 1;
+ for (e = e_first; single_succ_p (e->dest); e = single_succ_edge (e->dest))
+ {
+ gimple_stmt_iterator gsi;
+ if (e->dest->aux)
+ {
+ inf_loop = true;
+ break;
+ }
+ e->dest->aux = (void *) 1;
+ gsi = gsi_after_labels (e->dest);
+ if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
+ gsi_next_nondebug (&gsi);
+ if (!gsi_end_p (gsi))
+ break;
+ }
+ e_first->src->aux = NULL;
+ for (e = e_first; e->dest->aux; e = single_succ_edge (e->dest))
+ e->dest->aux = NULL;
+
+ return inf_loop;
+}
+
/* Examine the block associated with LP to determine if it's an empty
handler for its EH region. If so, attempt to redirect EH edges to
an outer region. Return true the CFG was updated in any way. This
/* If the block is totally empty, look for more unsplitting cases. */
if (gsi_end_p (gsi))
- return cleanup_empty_eh_unsplit (bb, e_out, lp);
+ {
+ /* For the degenerate case of an infinite loop bail out. */
+ if (infinite_empty_loop_p (e_out))
+ return false;
+
+ return cleanup_empty_eh_unsplit (bb, e_out, lp);
+ }
/* The block should consist only of a single RESX statement. */
resx = gsi_stmt (gsi);