This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]