On Apr 12, 2005, Alexandre Oliva <[EMAIL PROTECTED]> wrote: > On Apr 12, 2005, Alexandre Oliva <[EMAIL PROTECTED]> wrote: >> It looks like it wouldn't be too hard to overcome this problem by >> generating the artificial labels in case_index order, instead of in >> goto_queue order, but it's not obvious to me that the potential >> randomness from sorting of stmt addresses in the goto_queue that have >> the same index couldn't possibly affect the outcome.
> This is what I had in mind with the paragraph above. Does it feel > like a reasonable approach? (Note that the two sets of > last_case_index were dead, so the patch removes them) The patch I posted before wasn't enough to fix the problem, there was another portion of code that walked the goto queue in order. This one fixes the problem, and enables GCC mainline as of a week ago or so to bootstrap on i686-pc-linux-gnu (Fedora Core devel, with exec-shield mmap randomization enabled). I haven't used a newer tree to test this because I've been unable to bootstrap it for other reasons. Ok to install?
Index: gcc/ChangeLog from Alexandre Oliva <[EMAIL PROTECTED]> * 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. Index: gcc/tree-eh.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-eh.c,v retrieving revision 2.28 diff -u -p -r2.28 tree-eh.c --- gcc/tree-eh.c 1 Apr 2005 03:42:44 -0000 2.28 +++ gcc/tree-eh.c 14 Apr 2005 01:15:45 -0000 @@ -1038,47 +1038,72 @@ lower_try_finally_copy (struct leh_state { 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_sta 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_sta 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. */
-- Alexandre Oliva http://www.ic.unicamp.br/~oliva/ Red Hat Compiler Engineer [EMAIL PROTECTED], gcc.gnu.org} Free Software Evangelist [EMAIL PROTECTED], gnu.org}