aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-eh.c
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2005-04-14 18:44:09 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2005-04-14 18:44:09 +0000
commitdd58eb5a7279bf7328afa905b55623b15a8577b0 (patch)
treecc72442cfa0549c9f53a4dec4cd687aa95223624 /gcc/tree-eh.c
parentb67af20b5b1cf35ed61242540ac7608485852578 (diff)
downloadgcc-dd58eb5a7279bf7328afa905b55623b15a8577b0.zip
gcc-dd58eb5a7279bf7328afa905b55623b15a8577b0.tar.gz
gcc-dd58eb5a7279bf7328afa905b55623b15a8577b0.tar.bz2
tree-eh.c (lower_try_finally_copy): Generate new code in response to goto_queue entries as if...
* tree-eh.c (lower_try_finally_copy): Generate new code in response to goto_queue entries as if the queue was sorted by index, not pointers. (lower_try_finally_switch): Likewise. From-SVN: r98149
Diffstat (limited to 'gcc/tree-eh.c')
-rw-r--r--gcc/tree-eh.c109
1 files changed, 75 insertions, 34 deletions
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 3dbcfa8..90f9061 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -1038,47 +1038,72 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
{
struct goto_queue_node *q, *qe;
tree return_val = NULL;
- int return_index;
- tree *labels;
+ int return_index, index;
+ struct
+ {
+ struct goto_queue_node *q;
+ tree label;
+ } *labels;
if (tf->dest_array)
return_index = VARRAY_ACTIVE_SIZE (tf->dest_array);
else
return_index = 0;
- labels = xcalloc (sizeof (tree), return_index + 1);
+ labels = xcalloc (sizeof (*labels), return_index + 1);
q = tf->goto_queue;
qe = q + tf->goto_queue_active;
for (; q < qe; q++)
{
- int index = q->index < 0 ? return_index : q->index;
- tree lab = labels[index];
- bool build_p = false;
+ index = q->index < 0 ? return_index : q->index;
- if (!lab)
- {
- labels[index] = lab = create_artificial_label ();
- build_p = true;
- }
+ if (!labels[index].q)
+ labels[index].q = q;
+ }
+
+ for (index = 0; index < return_index + 1; index++)
+ {
+ tree lab;
+
+ q = labels[index].q;
+ if (! q)
+ continue;
+
+ lab = labels[index].label = create_artificial_label ();
if (index == return_index)
do_return_redirection (q, lab, NULL, &return_val);
else
do_goto_redirection (q, lab, NULL);
- if (build_p)
- {
- x = build1 (LABEL_EXPR, void_type_node, lab);
- append_to_statement_list (x, &new_stmt);
+ x = build1 (LABEL_EXPR, void_type_node, lab);
+ append_to_statement_list (x, &new_stmt);
- x = lower_try_finally_dup_block (finally, state);
- lower_eh_constructs_1 (state, &x);
- append_to_statement_list (x, &new_stmt);
+ x = lower_try_finally_dup_block (finally, state);
+ lower_eh_constructs_1 (state, &x);
+ append_to_statement_list (x, &new_stmt);
- append_to_statement_list (q->cont_stmt, &new_stmt);
- maybe_record_in_goto_queue (state, q->cont_stmt);
- }
+ append_to_statement_list (q->cont_stmt, &new_stmt);
+ maybe_record_in_goto_queue (state, q->cont_stmt);
+ }
+
+ for (q = tf->goto_queue; q < qe; q++)
+ {
+ tree lab;
+
+ index = q->index < 0 ? return_index : q->index;
+
+ if (labels[index].q == q)
+ continue;
+
+ lab = labels[index].label;
+
+ if (index == return_index)
+ do_return_redirection (q, lab, NULL, &return_val);
+ else
+ do_goto_redirection (q, lab, NULL);
}
+
replace_goto_queue (tf);
free (labels);
}
@@ -1194,7 +1219,6 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
q = tf->goto_queue;
qe = q + tf->goto_queue_active;
j = last_case_index + tf->may_return;
- last_case_index += nlabels;
for (; q < qe; ++q)
{
tree mod;
@@ -1217,20 +1241,37 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
case_index = j + q->index;
if (!TREE_VEC_ELT (case_label_vec, case_index))
- {
- last_case = build (CASE_LABEL_EXPR, void_type_node,
- build_int_cst (NULL_TREE, switch_id), NULL,
- create_artificial_label ());
- TREE_VEC_ELT (case_label_vec, case_index) = last_case;
-
- x = build (LABEL_EXPR, void_type_node, CASE_LABEL (last_case));
- append_to_statement_list (x, &switch_body);
- append_to_statement_list (q->cont_stmt, &switch_body);
- maybe_record_in_goto_queue (state, q->cont_stmt);
- }
+ TREE_VEC_ELT (case_label_vec, case_index)
+ = build (CASE_LABEL_EXPR, void_type_node,
+ build_int_cst (NULL_TREE, switch_id), NULL,
+ /* We store the cont_stmt in the
+ CASE_LABEL, 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. */
+ q->cont_stmt);
+ }
+ for (j = last_case_index; j < last_case_index + nlabels; j++)
+ {
+ tree label;
+ tree cont_stmt;
+
+ last_case = TREE_VEC_ELT (case_label_vec, j);
+
+ gcc_assert (last_case);
+
+ cont_stmt = CASE_LABEL (last_case);
+
+ label = create_artificial_label ();
+ CASE_LABEL (last_case) = label;
+
+ x = build (LABEL_EXPR, void_type_node, label);
+ append_to_statement_list (x, &switch_body);
+ append_to_statement_list (cont_stmt, &switch_body);
+ maybe_record_in_goto_queue (state, cont_stmt);
}
replace_goto_queue (tf);
- last_case_index += nlabels;
/* Make sure that the last case is the default label, as one is required.
Then sort the labels, which is also required in GIMPLE. */