This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: bootstrap compare failure in ada/targparm.o on i686-pc-linux-gnu?
On Apr 12, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:
> On Apr 12, 2005, Alexandre Oliva <aoliva@redhat.com> 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 <aoliva@redhat.com>
* 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 aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist oliva@{lsd.ic.unicamp.br, gnu.org}