Blame SOURCES/gcc32-pr18300.patch

6f1b0c
2005-09-07  Jakub Jelinek  <jakub@redhat.com>
6f1b0c
6f1b0c
	PR target/18300
6f1b0c
	* config/i386/i386.c (classify_argument): Only use different
6f1b0c
	iterators for nested loops if nested loops sharing the same
6f1b0c
	iterator would hang.
6f1b0c
6f1b0c
2004-11-13  Zak Kipling  <zak@transversal.com>
6f1b0c
6f1b0c
	PR target/18300
6f1b0c
	* config/i386/i386.c (classify_argument): Fix infinite loop when
6f1b0c
	passing object with 3 or more base classes by value.
6f1b0c
6f1b0c
--- gcc/config/i386/i386.c.jj	2005-07-21 11:01:36.000000000 +0200
6f1b0c
+++ gcc/config/i386/i386.c	2005-09-07 14:22:19.000000000 +0200
6f1b0c
@@ -1784,8 +1784,17 @@ classify_argument (mode, type, classes, 
6f1b0c
 	    {
6f1b0c
 	      tree bases = TYPE_BINFO_BASETYPES (type);
6f1b0c
 	      int n_bases = TREE_VEC_LENGTH (bases);
6f1b0c
-	      int i;
6f1b0c
-
6f1b0c
+	      int i, basenum;
6f1b0c
+	      enum x86_64_reg_class saveclasses[MAX_CLASSES];
6f1b0c
+	      bool seen[MAX_CLASSES];
6f1b0c
+
6f1b0c
+	      /* PR target/18300: The following code mistakenly uses the same
6f1b0c
+		 iterator variable in both nested for loops.  But to preserve
6f1b0c
+		 binary compatibility, do whatever this code used to do before
6f1b0c
+		 unless old GCC would hang in an infinite loop.  In that case
6f1b0c
+		 use whatever GCC 4.0+ does.  */
6f1b0c
+	      memset (seen, 0, sizeof (seen));
6f1b0c
+	      memcpy (saveclasses, classes, sizeof (saveclasses));
6f1b0c
 	      for (i = 0; i < n_bases; ++i)
6f1b0c
 		{
6f1b0c
 		   tree binfo = TREE_VEC_ELT (bases, i);
6f1b0c
@@ -1793,6 +1802,12 @@ classify_argument (mode, type, classes, 
6f1b0c
 		   int offset = tree_low_cst (BINFO_OFFSET (binfo), 0) * 8;
6f1b0c
 		   tree type = BINFO_TYPE (binfo);
6f1b0c
 
6f1b0c
+		   if (i < MAX_CLASSES)
6f1b0c
+		     {
6f1b0c
+		       if (seen[i])
6f1b0c
+			 break;
6f1b0c
+		       seen[i] = true;
6f1b0c
+		     }
6f1b0c
 		   num = classify_argument (TYPE_MODE (type),
6f1b0c
 					    type, subclasses,
6f1b0c
 					    (offset + bit_offset) % 256);
6f1b0c
@@ -1805,6 +1820,32 @@ classify_argument (mode, type, classes, 
6f1b0c
 			 merge_classes (subclasses[i], classes[i + pos]);
6f1b0c
 		     }
6f1b0c
 		}
6f1b0c
+	      if (i < n_bases)
6f1b0c
+		{
6f1b0c
+		  /* Older GCC 3.[0-4].x would hang in the above loop, so
6f1b0c
+		     don't worry about backwards compatibility and
6f1b0c
+		     just DTRT.  */
6f1b0c
+		  memcpy (classes, saveclasses, sizeof (saveclasses));
6f1b0c
+		  for (basenum = 0; basenum < n_bases; ++basenum)
6f1b0c
+		    {
6f1b0c
+		      tree binfo = TREE_VEC_ELT (bases, basenum);
6f1b0c
+		      int num;
6f1b0c
+		      int offset = tree_low_cst (BINFO_OFFSET (binfo), 0) * 8;
6f1b0c
+		      tree type = BINFO_TYPE (binfo);
6f1b0c
+
6f1b0c
+		      num = classify_argument (TYPE_MODE (type),
6f1b0c
+					       type, subclasses,
6f1b0c
+					       (offset + bit_offset) % 256);
6f1b0c
+		      if (!num)
6f1b0c
+			return 0;
6f1b0c
+		      for (i = 0; i < num; i++)
6f1b0c
+			{
6f1b0c
+			  int pos = (offset + (bit_offset % 64)) / 8 / 8;
6f1b0c
+			  classes[i + pos] =
6f1b0c
+			    merge_classes (subclasses[i], classes[i + pos]);
6f1b0c
+			}
6f1b0c
+		    }
6f1b0c
+		}
6f1b0c
 	    }
6f1b0c
 	  /* And now merge the fields of structure.   */
6f1b0c
 	  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
6f1b0c
@@ -1872,8 +1913,17 @@ classify_argument (mode, type, classes, 
6f1b0c
 	    {
6f1b0c
 	      tree bases = TYPE_BINFO_BASETYPES (type);
6f1b0c
 	      int n_bases = TREE_VEC_LENGTH (bases);
6f1b0c
-	      int i;
6f1b0c
-
6f1b0c
+	      int i, basenum;
6f1b0c
+	      enum x86_64_reg_class saveclasses[MAX_CLASSES];
6f1b0c
+	      bool seen[MAX_CLASSES];
6f1b0c
+
6f1b0c
+	      /* PR target/18300: The following code mistakenly uses the same
6f1b0c
+		 iterator variable in both nested for loops.  But to preserve
6f1b0c
+		 binary compatibility, do whatever this code used to do before
6f1b0c
+		 unless old GCC would hang in an infinite loop.  In that case
6f1b0c
+		 use whatever GCC 4.0+ does.  */
6f1b0c
+	      memset (seen, 0, sizeof (seen));
6f1b0c
+	      memcpy (saveclasses, classes, sizeof (saveclasses));
6f1b0c
 	      for (i = 0; i < n_bases; ++i)
6f1b0c
 		{
6f1b0c
 		   tree binfo = TREE_VEC_ELT (bases, i);
6f1b0c
@@ -1881,6 +1931,12 @@ classify_argument (mode, type, classes, 
6f1b0c
 		   int offset = tree_low_cst (BINFO_OFFSET (binfo), 0) * 8;
6f1b0c
 		   tree type = BINFO_TYPE (binfo);
6f1b0c
 
6f1b0c
+		   if (i < MAX_CLASSES)
6f1b0c
+		     {
6f1b0c
+		       if (seen[i])
6f1b0c
+			 break;
6f1b0c
+		       seen[i] = true;
6f1b0c
+		     }
6f1b0c
 		   num = classify_argument (TYPE_MODE (type),
6f1b0c
 					    type, subclasses,
6f1b0c
 					    (offset + (bit_offset % 64)) % 256);
6f1b0c
@@ -1893,6 +1949,32 @@ classify_argument (mode, type, classes, 
6f1b0c
 			 merge_classes (subclasses[i], classes[i + pos]);
6f1b0c
 		     }
6f1b0c
 		}
6f1b0c
+	      if (i < n_bases)
6f1b0c
+		{
6f1b0c
+		  /* Older GCC 3.[0-4].x would hang in the above loop, so
6f1b0c
+		     don't worry about backwards compatibility and
6f1b0c
+		     just DTRT.  */
6f1b0c
+		  memcpy (classes, saveclasses, sizeof (saveclasses));
6f1b0c
+		  for (basenum = 0; basenum < n_bases; ++basenum)
6f1b0c
+		    {
6f1b0c
+		      tree binfo = TREE_VEC_ELT (bases, basenum);
6f1b0c
+		      int num;
6f1b0c
+		      int offset = tree_low_cst (BINFO_OFFSET (binfo), 0) * 8;
6f1b0c
+		      tree type = BINFO_TYPE (binfo);
6f1b0c
+
6f1b0c
+		      num = classify_argument (TYPE_MODE (type),
6f1b0c
+					       type, subclasses,
6f1b0c
+					       (offset + (bit_offset % 64)) % 256);
6f1b0c
+		      if (!num)
6f1b0c
+			return 0;
6f1b0c
+		      for (i = 0; i < num; i++)
6f1b0c
+			{
6f1b0c
+			  int pos = (offset + (bit_offset % 64)) / 8 / 8;
6f1b0c
+			  classes[i + pos] =
6f1b0c
+			    merge_classes (subclasses[i], classes[i + pos]);
6f1b0c
+			}
6f1b0c
+		    }
6f1b0c
+		}
6f1b0c
 	    }
6f1b0c
 	  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
6f1b0c
 	    {
6f1b0c
--- gcc/testsuite/g++.dg/other/infloop-1.C 1 Jan 1970 00:00:00 -0000
6f1b0c
+++ gcc/testsuite/g++.dg/other/infloop-1.C	13 Nov 2004 23:09:08 -0000	1.1
6f1b0c
@@ -0,0 +1,16 @@
6f1b0c
+// PR 18300: This sends old compilers into an infinite loop on x86_64
6f1b0c
+// Testcase and patch contributed by Zak Kipling <zak@transversal.com>
6f1b0c
+
6f1b0c
+struct base1 { };
6f1b0c
+struct base2 { };
6f1b0c
+struct base3 { };
6f1b0c
+
6f1b0c
+struct derived : base1, base2, base3 { };
6f1b0c
+
6f1b0c
+void foo(derived);
6f1b0c
+
6f1b0c
+int main()
6f1b0c
+{
6f1b0c
+  foo(derived());
6f1b0c
+}
6f1b0c
+