This is the mail archive of the gcc-patches@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]

[PATCH, i386]: Partially fix PR 38151


Hello!

There is a problem with x86_64 merged argument passing when agregates are involved. The problem is, that we don't account for cases, where argument register crosses argument register boundary, i.e. when merging 32bit and 64bit values.

classify_argument () function should return classes for both parts since the second value is now passed in two registers.

2008-11-19 Uros Bizjak <ubizjak@gmail.com>

   PR target/38151
   * config/i386/i386.c (classify_argument) [integer mode size <= 64bit]:
   Handle cases when integer argument crosses argument register boundary.

testsuite/ChangeLog:

2008-11-19 Uros Bizjak <ubizjak@gmail.com>

   PR target/38151
   * gcc.target/i386/pr38151-1.c: New test.

Attached patch was bootstrapped and regression tested on x86_64-pc-linux-gnu {,-m32}. The patch is however not enough to fully fix the PR, since the problem remains for va_arg arguments. Will look tomorrow.

Uros.
Index: testsuite/gcc.target/i386/pr38151-1.c
===================================================================
--- testsuite/gcc.target/i386/pr38151-1.c	(revision 0)
+++ testsuite/gcc.target/i386/pr38151-1.c	(revision 0)
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+void abort (void);
+
+struct S2848
+{
+  unsigned int a;
+  _Complex int b;
+};
+
+struct S2848 s2848;
+
+void __attribute__((noinline))
+check2848 (struct S2848 arg0)
+{
+  if (arg0.b != s2848.b)
+    abort ();
+}
+
+int main()
+{
+  s2848.a = 4027477739U;
+  s2848.b = (723419448 + -218144346 * __extension__ 1i);
+
+  check2848 (s2848);
+
+  return 0;
+}
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 142014)
+++ config/i386/i386.c	(working copy)
@@ -5029,11 +5029,33 @@ classify_argument (enum machine_mode mod
     case CSImode:
     case CHImode:
     case CQImode:
-      if (bit_offset + GET_MODE_BITSIZE (mode) <= 32)
-	classes[0] = X86_64_INTEGERSI_CLASS;
-      else
-	classes[0] = X86_64_INTEGER_CLASS;
-      return 1;
+      {
+	int size = (bit_offset % 64)+ (int) GET_MODE_BITSIZE (mode);
+
+	if (size <= 32)
+	  {
+	    classes[0] = X86_64_INTEGERSI_CLASS;
+	    return 1;
+	  }
+	else if (size <= 64)
+	  {
+	    classes[0] = X86_64_INTEGER_CLASS;
+	    return 1;
+	  }
+	else if (size <= 64+32)
+	  {
+	    classes[0] = X86_64_INTEGER_CLASS;
+	    classes[1] = X86_64_INTEGERSI_CLASS;
+	    return 2;
+	  }
+	else if (size <= 64+64)
+	  {
+	    classes[0] = classes[1] = X86_64_INTEGER_CLASS;
+	    return 2;
+	  }
+	else
+	  gcc_unreachable ();
+      }
     case CDImode:
     case TImode:
       classes[0] = classes[1] = X86_64_INTEGER_CLASS;

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