From dd58eb5a7279bf7328afa905b55623b15a8577b0 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Thu, 14 Apr 2005 18:44:09 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 ++++ gcc/tree-eh.c | 107 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 81 insertions(+), 33 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ba76cb6a52b..53aa00c82b3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2005-04-14 Alexandre Oliva + + * 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. + 2005-04-14 Richard Henderson * config/i386/i386.c (ix86_expand_sse_cmp): Split out from ... diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 3dbcfa87ef9..90f90611d01 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; + 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; - 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); - } + 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. */