This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tuples] Fix EH lowering (part 1)
- From: Diego Novillo <dnovillo at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 04 Mar 2008 07:09:45 -0800
- Subject: [tuples] Fix EH lowering (part 1)
This fixes about 200 testsuite failures related to EH lowering. It
still doesn't fix all the problems, we cannot get libstdc++ compiled. I
will be posting a patch for that shortly.
Tested on x86_64 and ppc64.
Diego.
2008-03-03 Diego Novillo <dnovillo@google.com>
* expr.c (expand_expr_real): Call lookup_expr_eh_region.
* tree-eh.c (lookup_stmt_eh_region_fn):
(lookup_stmt_eh_region): Fix comment.
(lookup_expr_eh_region): Handle missing cfun and missing
EH table.
(record_in_finally_tree): Fix comment.
(collect_finally_tree_1): Remove handler for
GIMPLE_SWITCH.
(maybe_record_in_goto_queue): Remove local variable
NEW_IS_LABEL.
Record GIMPLE_GOTOs instead of their label.
(verify_norecord_switch_expr): Retrieve the CASE_LABEL
from the case label expression.
(do_return_redirection): Change sign of assertion.
(lower_try_finally_onedest): Assert that
TF->GOTO_QUEUE[0] contains a GIMPLE statement.
(lower_try_finally_copy): Assert that Q contains a GIMPLE
statement.
(lower_try_finally_switch): Build a new GIMPLE label for
CONT_STMT.
(mark_eh_edge): Tuplify.
(verify_eh_edges): Tuplify.
(tree_can_throw_external): Remove unused function.
(optimize_double_finally): Remove #if 0.
* gimple-pretty-print.c (GIMPLE_NIY): Tidy.
(dump_gimple_resx): Fix format string for
dump_gimple_fmt.
* gimplify.c (gimplify_cleanup_point_expr): Initialize
BODY_SEQUENCE.
* calls.c (emit_call_1): Remove ATTRIBUTE_UNUSED markers.
* cfgexpand.c (gimple_to_tree) <GIMPLE_NOP>: Assign new
expression to T.
<GIMPLE_RESX>: Handle.
Always assign the value from lookup_stmt_eh_region to
ANN->RN.
* tree-cfg.c (start_recording_case_labels):
(recording_case_labels_p): Re-enable.
(get_cases_for_edge): Likewise.
(gimple_verify_flow_info): Re-enable call to
verify_eh_edges.
(gimple_redirect_edge_and_branch): Re-enable handling of
GIMPLE_SWITCH.
(gimple_block_ends_with_call_p): Tuplify.
(struct gimple_cfg_hooks): Enable block_ends_with_call_p
callback.
2008-03-03 Diego Novillo <dnovillo@google.com>
* expr.c (expand_expr_real): Call lookup_expr_eh_region.
* tree-eh.c (lookup_stmt_eh_region_fn):
(lookup_stmt_eh_region): Fix comment.
(lookup_expr_eh_region): Handle missing cfun and missing
EH table.
(record_in_finally_tree): Fix comment.
(collect_finally_tree_1): Remove handler for
GIMPLE_SWITCH.
(maybe_record_in_goto_queue): Remove local variable
NEW_IS_LABEL.
Record GIMPLE_GOTOs instead of their label.
(verify_norecord_switch_expr): Retrieve the CASE_LABEL
from the case label expression.
(do_return_redirection): Change sign of assertion.
(lower_try_finally_onedest): Assert that
TF->GOTO_QUEUE[0] contains a GIMPLE statement.
(lower_try_finally_copy): Assert that Q contains a GIMPLE
statement.
(lower_try_finally_switch): Build a new GIMPLE label for
CONT_STMT.
(mark_eh_edge): Tuplify.
(verify_eh_edges): Tuplify.
(tree_can_throw_external): Remove unused function.
(optimize_double_finally): Remove #if 0.
* gimple-pretty-print.c (GIMPLE_NIY): Tidy.
(dump_gimple_resx): Fix format string for
dump_gimple_fmt.
* gimplify.c (gimplify_cleanup_point_expr): Initialize
BODY_SEQUENCE.
* calls.c (emit_call_1): Remove ATTRIBUTE_UNUSED markers.
* cfgexpand.c (gimple_to_tree) <GIMPLE_NOP>: Assign new
expression to T.
<GIMPLE_RESX>: Handle.
Always assign the value from lookup_stmt_eh_region to
ANN->RN.
* tree-cfg.c (start_recording_case_labels):
(recording_case_labels_p): Re-enable.
(get_cases_for_edge): Likewise.
(gimple_verify_flow_info): Re-enable call to
verify_eh_edges.
(gimple_redirect_edge_and_branch): Re-enable handling of
GIMPLE_SWITCH.
(gimple_block_ends_with_call_p): Tuplify.
(struct gimple_cfg_hooks): Enable block_ends_with_call_p
callback.
Index: expr.c
===================================================================
--- expr.c (revision 132841)
+++ expr.c (working copy)
@@ -7061,11 +7061,7 @@ expand_expr_real (tree exp, rtx target,
if (flag_non_call_exceptions)
{
-#if 0
- rn = lookup_stmt_eh_region (exp);
-#else
rn = lookup_expr_eh_region (exp);
-#endif
/* If rn < 0, then either (1) tree-ssa not used or (2) doesn't throw. */
if (rn >= 0)
Index: tree-eh.c
===================================================================
--- tree-eh.c (revision 132841)
+++ tree-eh.c (working copy)
@@ -185,8 +185,8 @@ lookup_stmt_eh_region_fn (struct functio
/* Determine if statement T is inside an EH region in the current
function (cfun). Return the EH region number if found, return -2
- if IFUN does not have an EH table and -1 if T could not be found in
- IFUN's EH region table. */
+ if cfun does not have an EH table and -1 if T could not be found in
+ cfun's EH region table. */
int
lookup_stmt_eh_region (gimple t)
@@ -199,6 +199,7 @@ lookup_stmt_eh_region (gimple t)
return lookup_stmt_eh_region_fn (cfun, t);
}
+
/* Determine if expression T is inside an EH region in the current
function (cfun). Return the EH region number if found, return -2
if IFUN does not have an EH table and -1 if T could not be found in
@@ -210,7 +211,15 @@ lookup_stmt_eh_region (gimple t)
int
lookup_expr_eh_region (tree t)
{
- if (EXPR_P (t))
+ /* We can get called from initialized data when -fnon-call-exceptions
+ is on; prevent crash. */
+ if (!cfun)
+ return -1;
+
+ if (!get_eh_throw_stmt_table (cfun))
+ return -2;
+
+ if (t && EXPR_P (t))
{
tree_ann_common_t ann = get_tree_common_ann (t);
return (int) ann->rn;
@@ -255,7 +264,7 @@ record_in_finally_tree (treemple child,
static void
collect_finally_tree (gimple stmt, gimple region);
-/* Go through the gimple sequence. Works with collect_finally_tree() to
+/* Go through the gimple sequence. Works with collect_finally_tree to
record all GIMPLE_LABEL and GIMPLE_TRY statements. */
static void
@@ -270,22 +279,10 @@ collect_finally_tree_1 (gimple_seq seq,
static void
collect_finally_tree (gimple stmt, gimple region)
{
- size_t i, n;
treemple temp;
switch (gimple_code (stmt))
{
- /* FIXME tuples: Why is GIMPLE_SWITCH necessary? */
- case GIMPLE_SWITCH:
- n = gimple_switch_num_labels (stmt);
- for (i = 0; i < n; i++)
- {
- tree lab = gimple_switch_label (stmt, i);
- temp.t = lab;
- record_in_finally_tree (temp, region);
- }
- break;
-
case GIMPLE_LABEL:
temp.t = gimple_label_label (stmt);
record_in_finally_tree (temp, region);
@@ -585,7 +582,6 @@ maybe_record_in_goto_queue (struct leh_s
struct leh_tf_state *tf = state->tf;
struct goto_queue_node *q;
treemple new_stmt;
- int new_is_label;
size_t active, size;
int index;
@@ -629,8 +625,7 @@ maybe_record_in_goto_queue (struct leh_s
/* In the case of a GOTO we want to record the destination label,
since with a GIMPLE_COND we have an easy access to the then/else
labels. */
- new_stmt.t = lab;
- new_is_label = 1;
+ new_stmt.g = stmt;
}
break;
@@ -638,7 +633,6 @@ maybe_record_in_goto_queue (struct leh_s
tf->may_return = true;
index = -1;
new_stmt.g = stmt;
- new_is_label = 0;
break;
default:
@@ -662,7 +656,6 @@ maybe_record_in_goto_queue (struct leh_s
memset (q, 0, sizeof (*q));
q->stmt = new_stmt;
- q->is_label = new_is_label;
q->index = index;
}
@@ -684,8 +677,8 @@ verify_norecord_switch_expr (struct leh_
for (i = 0; i < n; ++i)
{
- tree lab = gimple_switch_label (switch_expr, i);
treemple temp;
+ tree lab = CASE_LABEL (gimple_switch_label (switch_expr, i));
temp.t = lab;
gcc_assert (!outside_finally_tree (temp, tf->try_finally_expr));
}
@@ -707,7 +700,7 @@ do_return_redirection (struct goto_queue
gimple x;
/* In the case of a return, the queue node must be a gimple statement. */
- gcc_assert (q->is_label);
+ gcc_assert (!q->is_label);
ret_expr = gimple_return_retval (q->stmt.g);
@@ -1149,6 +1142,7 @@ lower_try_finally_onedest (struct leh_st
/* Reset the locus of the goto since we're moving
goto to a different block which might be on a different line. */
+ gcc_assert (!tf->goto_queue[0].is_label);
gimple_set_locus (tf->goto_queue[0].cont_stmt.g, 0);
gimple_seq_add_stmt (&tf->top_p_seq, tf->goto_queue[0].cont_stmt.g);
maybe_record_in_goto_queue (state, tf->goto_queue[0].cont_stmt.g);
@@ -1241,6 +1235,7 @@ lower_try_finally_copy (struct leh_state
lower_eh_constructs_1 (state, seq);
gimple_seq_add_seq (&new_stmt, seq);
+ gcc_assert (!q->is_label);
gimple_seq_add_stmt (&new_stmt, q->cont_stmt.g);
maybe_record_in_goto_queue (state, q->cont_stmt.g);
}
@@ -1429,7 +1424,7 @@ lower_try_finally_switch (struct leh_sta
/* As the comment above suggests, CASE_LABEL (last_case) was just a
placeholder, it does not store an actual label, yet. */
- cont_stmt.t = CASE_LABEL (last_case);
+ cont_stmt.g = gimple_build_label (CASE_LABEL (last_case));
label = create_artificial_label ();
CASE_LABEL (last_case) = label;
@@ -1914,20 +1909,20 @@ make_eh_edges (gimple stmt)
foreach_reachable_handler (region_nr, is_resx, make_eh_edge, stmt);
}
-/* FIXME tuples. */
-#if 0
static bool mark_eh_edge_found_error;
/* Mark edge make_eh_edge would create for given region by setting it aux
field, output error if something goes wrong. */
+
static void
mark_eh_edge (struct eh_region *region, void *data)
{
- tree stmt, lab;
+ gimple stmt;
+ tree lab;
basic_block src, dst;
edge e;
- stmt = (tree) data;
+ stmt = (gimple) data;
lab = get_eh_region_tree_label (region);
src = gimple_bb (stmt);
@@ -1954,10 +1949,11 @@ mark_eh_edge (struct eh_region *region,
e->aux = (void *)1;
}
-/* Verify that BB containing stmt as last stmt has precisely the edges
- make_eh_edges would create. */
+/* Verify that BB containing STMT as the last statement, has precisely the
+ edges that make_eh_edges would create. */
+
bool
-verify_eh_edges (tree stmt)
+verify_eh_edges (gimple stmt)
{
int region_nr;
bool is_resx;
@@ -1968,9 +1964,9 @@ verify_eh_edges (tree stmt)
FOR_EACH_EDGE (e, ei, bb->succs)
gcc_assert (!e->aux);
mark_eh_edge_found_error = false;
- if (TREE_CODE (stmt) == RESX_EXPR)
+ if (gimple_code (stmt) == GIMPLE_RESX)
{
- region_nr = TREE_INT_CST_LOW (TREE_OPERAND (stmt, 0));
+ region_nr = gimple_resx_region (stmt);
is_resx = true;
}
else
@@ -1986,7 +1982,7 @@ verify_eh_edges (tree stmt)
}
return false;
}
- if (!tree_could_throw_p (stmt))
+ if (!stmt_could_throw_p (stmt))
{
error ("BB %i last statement has incorrectly set region", bb->index);
return true;
@@ -2008,7 +2004,6 @@ verify_eh_edges (tree stmt)
return mark_eh_edge_found_error;
}
-#endif
/* Return true if operation OP may trap. FP_OPERATION is true if OP is applied
@@ -2396,32 +2391,6 @@ stmt_can_throw_internal (gimple stmt)
}
-/* Return true if STMT can throw an exception that is visible outside
- the current function (CFUN). */
-
-bool
-tree_can_throw_external (tree stmt ATTRIBUTE_UNUSED)
-{
- /* FIXME tuples. */
-#if 0
- int region_nr;
- bool is_resx = false;
-
- if (TREE_CODE (stmt) == RESX_EXPR)
- region_nr = TREE_INT_CST_LOW (TREE_OPERAND (stmt, 0)), is_resx = true;
- else
- region_nr = lookup_stmt_eh_region (stmt);
- if (region_nr < 0)
- return tree_could_throw_p (stmt);
- else
- return can_throw_external_1 (region_nr, is_resx);
-#else
- gimple_unreachable ();
- return false;
-#endif
-}
-
-
/* Given a statement OLD_STMT and a new statement NEW_STMT that has replaced
OLD_STMT in the function, remove OLD_STMT from the EH table and put NEW_STMT
in the table if it should be in there. Return TRUE if a replacement was
@@ -2520,12 +2489,7 @@ optimize_double_finally (tree one, tree
TREE_SET_CODE (one, TRY_CATCH_EXPR);
i = tsi_start (TREE_OPERAND (two, 0));
- /* FIXME tuples. */
-#if 0
tsi_link_before (&i, unsave_expr_now (b), TSI_SAME_STMT);
-#else
- gimple_unreachable ();
-#endif
}
}
Index: gimple-pretty-print.c
===================================================================
--- gimple-pretty-print.c (revision 132841)
+++ gimple-pretty-print.c (working copy)
@@ -40,7 +40,7 @@ Software Foundation, 51 Franklin Street,
static pretty_printer buffer;
static bool initialized = false;
-#define GIMPLE_NIY do_niy(buffer,gs)
+#define GIMPLE_NIY do_niy (buffer,gs)
/* Try to print on BUFFER a default message for the unrecognized
gimple statement GS. */
@@ -632,8 +632,7 @@ dump_gimple_resx (pretty_printer *buffer
dump_gimple_fmt (buffer, spc, flags, "%G <%d>", gs,
gimple_resx_region (gs));
else
- dump_gimple_fmt (buffer, spc, flags, "resx %T", gimple_resx_region (gs));
- GIMPLE_NIY;
+ dump_gimple_fmt (buffer, spc, flags, "resx %d", gimple_resx_region (gs));
}
/* Dump a GIMPLE_OMP_FOR tuple on the pretty_printer BUFFER. */
Index: gimplify.c
===================================================================
--- gimplify.c (revision 132841)
+++ gimplify.c (working copy)
@@ -4500,7 +4500,7 @@ static enum gimplify_status
gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
{
gimple_stmt_iterator iter;
- gimple_seq body_sequence;
+ gimple_seq body_sequence = NULL;
tree temp = voidify_wrapper_expr (*expr_p, NULL);
Index: calls.c
===================================================================
--- calls.c (revision 132841)
+++ calls.c (working copy)
@@ -238,7 +238,7 @@ prepare_call_address (rtx funexp, rtx st
denote registers used by the called function. */
static void
-emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNUSED,
+emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED,
tree funtype ATTRIBUTE_UNUSED,
HOST_WIDE_INT stack_size ATTRIBUTE_UNUSED,
HOST_WIDE_INT rounded_stack_size,
Index: cfgexpand.c
===================================================================
--- cfgexpand.c (revision 132841)
+++ cfgexpand.c (working copy)
@@ -208,7 +208,12 @@ gimple_to_tree (gimple stmt)
break;
case GIMPLE_NOP:
- return build1 (NOP_EXPR, void_type_node, size_zero_node);
+ t = build1 (NOP_EXPR, void_type_node, size_zero_node);
+ break;
+
+ case GIMPLE_RESX:
+ t = build_resx (gimple_resx_region (stmt));
+ break;
default:
error ("Unrecognized GIMPLE statement during RTL expansion");
@@ -221,8 +226,7 @@ gimple_to_tree (gimple stmt)
{
int rn = lookup_stmt_eh_region (stmt);
tree_ann_common_t ann = get_tree_common_ann (t);
- if (rn >= 0)
- ann->rn = rn;
+ ann->rn = rn;
}
SET_EXPR_LOCATION (t, gimple_locus (stmt));
Index: tree-flow.h
===================================================================
--- tree-flow.h (revision 132841)
+++ tree-flow.h (working copy)
@@ -1049,7 +1049,6 @@ extern bool operation_could_trap_p (enum
extern bool stmt_could_throw_p (gimple);
extern bool tree_could_throw_p (tree);
extern bool stmt_can_throw_internal (gimple);
-extern bool tree_can_throw_external (tree);
extern void add_stmt_to_eh_region (gimple, int);
extern bool remove_stmt_from_eh_region (gimple);
extern bool maybe_clean_or_replace_eh_stmt (gimple, gimple);
@@ -1058,7 +1057,7 @@ extern bool remove_stmt_from_eh_region_f
extern int lookup_stmt_eh_region_fn (struct function *, gimple);
extern int lookup_expr_eh_region (tree);
extern int lookup_stmt_eh_region (gimple);
-extern bool verify_eh_edges (tree);
+extern bool verify_eh_edges (gimple);
/* In tree-ssa-pre.c */
Index: tree-cfg.c
===================================================================
--- tree-cfg.c (revision 132841)
+++ tree-cfg.c (working copy)
@@ -700,8 +700,6 @@ start_recording_case_labels (void)
edge_to_cases = pointer_map_create ();
}
-/* FIXME tuples. */
-#if 0
/* Return nonzero if we are recording information for case labels. */
static bool
@@ -709,7 +707,6 @@ recording_case_labels_p (void)
{
return (edge_to_cases != NULL);
}
-#endif
/* Stop recording information mapping edges to case labels and
remove any information we have recorded. */
@@ -721,8 +718,6 @@ end_recording_case_labels (void)
edge_to_cases = NULL;
}
-/* FIXME tuples. */
-#if 0
/* If we are inside a {start,end}_recording_cases block, then return
a chain of CASE_LABEL_EXPRs from T which reference E.
@@ -764,7 +759,6 @@ get_cases_for_edge (edge e, gimple t)
return (tree) *pointer_map_contains (edge_to_cases, e);
}
-#endif
/* Create the edges for a GIMPLE_SWITCH starting at block BB. */
@@ -4159,10 +4153,7 @@ gimple_verify_flow_info (void)
stmt = gsi_stmt (gsi);
- /* FIXME tuples. */
-#if 0
err |= verify_eh_edges (stmt);
-#endif
if (is_ctrl_stmt (stmt))
{
@@ -4498,8 +4489,6 @@ gimple_redirect_edge_and_branch (edge e,
case GIMPLE_SWITCH:
{
tree label = gimple_block_label (dest);
-/* FIXME tuples. */
-#if 0
tree cases = get_cases_for_edge (e, stmt);
/* If we have a list of cases associated with E, then use it
@@ -4528,7 +4517,6 @@ gimple_redirect_edge_and_branch (edge e,
}
}
else
-#endif
{
size_t i, n = gimple_switch_num_labels (stmt);
@@ -6065,15 +6053,12 @@ debug_loop_num (unsigned num, int verbos
instructions that must stay with the call. Return false,
otherwise. */
-/* FIXME tuples. */
-#if 0
static bool
gimple_block_ends_with_call_p (basic_block bb)
{
- gimple_stmt_iterator gsi = gsi_last (bb);
- return get_call_expr_in (gsi_stmt (gsi)) != NULL;
+ gimple_stmt_iterator gsi = gsi_last_bb (bb);
+ return gimple_code (gsi_stmt (gsi)) == GIMPLE_CALL;
}
-#endif
/* Return true if BB ends with a conditional branch. Return false,
@@ -6563,7 +6548,7 @@ struct cfg_hooks gimple_cfg_hooks = {
gimple_split_edge, /* split_edge */
gimple_make_forwarder_block, /* make_forward_block */
NULL, /* tidy_fallthru_edge */
- 0 /* FIXME tuples gimple_block_ends_with_call_p */, /* block_ends_with_call_p */
+ gimple_block_ends_with_call_p,/* block_ends_with_call_p */
0 /* FIXME tuples gimple_block_ends_with_condjump_p */, /* block_ends_with_condjump_p */
0 /* FIXME tuples gimple_flow_call_edges_add */, /* flow_call_edges_add */
gimple_execute_on_growing_pred, /* execute_on_growing_pred */