|
|
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 |
+
|