re PR target/39678 (complex type isn't passed correctly)
authorH.J. Lu <hongjiu.lu@intel.com>
Thu, 9 Apr 2009 22:58:51 +0000 (22:58 +0000)
committerH.J. Lu <hjl@gcc.gnu.org>
Thu, 9 Apr 2009 22:58:51 +0000 (15:58 -0700)
gcc/

2009-04-09  H.J. Lu  <hongjiu.lu@intel.com>

PR target/39678
* config/i386/i386.c (classify_argument): Handle SCmode with
(bit_offset % 64) != 0.

gcc/testsuite/

2009-04-09  H.J. Lu  <hongjiu.lu@intel.com>

PR target/39678
* g++.dg/torture/pr39678.C: New.
* gcc.dg/compat/struct-complex-2.h: Likewise.
* gcc.dg/compat/struct-complex-2_main.c: Likewise.
* gcc.dg/compat/struct-complex-2_x.c: Likewise.
* gcc.dg/compat/struct-complex-2_y.c: Likewise.
* gcc.dg/torture/pr39678.c: Likewise.
* gcc.target/i386/pr39678.c: Likewise.

* gcc.dg/compat/struct-complex-1_x.c: Add -Wno-psabi.
* gcc.dg/compat/struct-complex-1_y.c: Likewise.

* gcc.target/x86_64/abi/test_passing_structs.c: Include
<complex.h>.  Add tests for structure with complex float.

From-SVN: r145865

13 files changed:
gcc/ChangeLog
gcc/config/i386/i386.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr39678.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/compat/struct-complex-1_x.c
gcc/testsuite/gcc.dg/compat/struct-complex-1_y.c
gcc/testsuite/gcc.dg/compat/struct-complex-2.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/compat/struct-complex-2_main.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/compat/struct-complex-2_x.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/compat/struct-complex-2_y.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr39678.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr39678.c [new file with mode: 0644]
gcc/testsuite/gcc.target/x86_64/abi/test_passing_structs.c

index 5e4bd00eb7088881028b01a73d0516f615568ec2..1f31df260d4c1c30891861043ce7f3952ca38f3b 100644 (file)
@@ -1,3 +1,9 @@
+2009-04-09  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR target/39678
+       * config/i386/i386.c (classify_argument): Handle SCmode with
+       (bit_offset % 64) != 0.
+
 2009-04-09  Sandra Loosemore  <sandra@codesourcery.com>
 
        * doc/invoke.texi (Optimize Options): Add cross-reference to
index d87e853265f7263d311fb55a94dff607c84c3333..503cc0816e4505cdbde3155b28bf0cb5dd0143c7 100644 (file)
@@ -5273,7 +5273,22 @@ classify_argument (enum machine_mode mode, const_tree type,
       return 2;
     case SCmode:
       classes[0] = X86_64_SSE_CLASS;
-      return 1;
+      if (!(bit_offset % 64))
+       return 1;
+      else
+       {
+         static bool warned;
+
+         if (!warned && warn_psabi)
+           {
+             warned = true;
+             inform (input_location,
+                     "The ABI of passing structure with complex float"
+                     " member has changed in GCC 4.4");
+           }
+         classes[1] = X86_64_SSESF_CLASS;
+         return 2;
+       }
     case DCmode:
       classes[0] = X86_64_SSEDF_CLASS;
       classes[1] = X86_64_SSEDF_CLASS;
index c346b6129dab8ec879437342098fa784261c1627..3c7cab6df09c6011c73f9e2f932ee40cb1205520 100644 (file)
@@ -1,3 +1,20 @@
+2009-04-09  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR target/39678
+       * g++.dg/torture/pr39678.C: New.
+       * gcc.dg/compat/struct-complex-2.h: Likewise.
+       * gcc.dg/compat/struct-complex-2_main.c: Likewise.
+       * gcc.dg/compat/struct-complex-2_x.c: Likewise.
+       * gcc.dg/compat/struct-complex-2_y.c: Likewise.
+       * gcc.dg/torture/pr39678.c: Likewise.
+       * gcc.target/i386/pr39678.c: Likewise.
+
+       * gcc.dg/compat/struct-complex-1_x.c: Add -Wno-psabi.
+       * gcc.dg/compat/struct-complex-1_y.c: Likewise.
+
+       * gcc.target/x86_64/abi/test_passing_structs.c: Include
+       <complex.h>.  Add tests for structure with complex float.
+
 2009-04-10  Ben Elliston  <bje@au.ibm.com>
            Joseph Myers  <joseph@codesourcery.com>
 
diff --git a/gcc/testsuite/g++.dg/torture/pr39678.C b/gcc/testsuite/g++.dg/torture/pr39678.C
new file mode 100644 (file)
index 0000000..a7c120a
--- /dev/null
@@ -0,0 +1,26 @@
+/* PR target/39678 */
+/* { dg-do run } */
+/* { dg-options "-Wno-psabi" } */
+struct Y {};
+struct X {
+  struct Y y;
+  __complex__ float val;
+};
+
+struct X __attribute__((noinline))
+foo (float *p)
+{
+  struct X x;
+  __real x.val = p[0];
+  __imag x.val = p[1];
+  return x;
+}
+extern "C" void abort (void);
+float a[2] = { 3., -2. };
+int main()
+{
+  struct X x = foo(a);
+  if (__real x.val != 3. || __imag x.val != -2.)
+    abort ();
+  return 0;
+}
index c77ba33580fcdd833cc78c4fc6ac2598937eb641..0c6723948705fc3ad199842d057fb8b5f98faa5f 100644 (file)
@@ -1,4 +1,5 @@
-/* { dg-options "-O" } */
+/* { dg-options "-O -Wno-psabi" } */
+
 
 #ifdef __x86_64__
 #include "struct-complex-1.h"
index 9ff450f796c6d64a571fb00fa1bf35b2eedc373a..858e6a9da8b4dbdcfba5666179d8650e3468d10a 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-options "-O" } */
+/* { dg-options "-O -Wno-psabi" } */
 
 #ifdef __x86_64__
 #include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/compat/struct-complex-2.h b/gcc/testsuite/gcc.dg/compat/struct-complex-2.h
new file mode 100644 (file)
index 0000000..1fd1e86
--- /dev/null
@@ -0,0 +1,15 @@
+#include <complex.h>
+
+struct st
+{
+  int s1;
+  float complex x;
+};
+
+typedef struct { float r, i; } _complex;
+
+struct stc
+{
+  int s1;
+  _complex x;
+};
diff --git a/gcc/testsuite/gcc.dg/compat/struct-complex-2_main.c b/gcc/testsuite/gcc.dg/compat/struct-complex-2_main.c
new file mode 100644 (file)
index 0000000..74eae62
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-options "-O" } */
+
+#ifdef __x86_64__
+/* Test function argument passing.  PR target/39678.  */
+
+extern void struct_complex_2_x (void);
+extern void exit (int);
+
+int
+main ()
+{
+  struct_complex_2_x ();
+  exit (0);
+}
+#else
+int
+main ()
+{
+  return 0;
+}
+#endif
diff --git a/gcc/testsuite/gcc.dg/compat/struct-complex-2_x.c b/gcc/testsuite/gcc.dg/compat/struct-complex-2_x.c
new file mode 100644 (file)
index 0000000..2fb9826
--- /dev/null
@@ -0,0 +1,30 @@
+/* { dg-options "-O -Wno-psabi" } */
+
+
+#ifdef __x86_64__
+#include "struct-complex-2.h"
+
+struct st st1;
+struct stc st2;
+
+extern void foo ();
+extern void bar ();
+
+int
+struct_complex_2_x ()
+{
+  st1.s1 = 1;
+  __real__ st1.x = 2;
+  __imag__ st1.x = 4;
+  st2.s1 = 1;
+  st2.x.r = 2;
+  st2.x.i = 4;
+  foo (st1);
+  foo (st2);
+  bar (st1);
+  bar (st2);
+  return 0;
+}
+#else
+int dummy_x;
+#endif
diff --git a/gcc/testsuite/gcc.dg/compat/struct-complex-2_y.c b/gcc/testsuite/gcc.dg/compat/struct-complex-2_y.c
new file mode 100644 (file)
index 0000000..54a72fa
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-options "-O -Wno-psabi" } */
+
+#ifdef __x86_64__
+#include <stdlib.h>
+#include "struct-complex-2.h"
+
+void
+bar(struct st x)
+{
+  if (x.s1 != 1
+      || __real__ x.x != 2 || __imag__ x.x != 4)
+    abort ();
+}
+
+void
+foo(struct stc x)
+{
+  if (x.s1 != 1 || x.x.r != 2 || x.x.i != 4)
+    abort ();
+}
+#else
+int dummy_y;
+#endif
diff --git a/gcc/testsuite/gcc.dg/torture/pr39678.c b/gcc/testsuite/gcc.dg/torture/pr39678.c
new file mode 100644 (file)
index 0000000..42de033
--- /dev/null
@@ -0,0 +1,27 @@
+/* PR target/39678 */
+/* { dg-do run } */
+/* { dg-options "-Wno-psabi" } */
+
+struct X {
+  char c;
+  __complex__ float val;
+};
+
+struct X __attribute__((noinline))
+foo (float *p)
+{
+  struct X x;
+  x.c = -3;
+  __real x.val = p[0];
+  __imag x.val = p[1];
+  return x;
+}
+extern void abort (void);
+float a[2] = { 3., -2. };
+int main()
+{
+  struct X x = foo(a);
+  if (x.c != -3 || __real x.val != a[0] || __imag x.val != a[1])
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr39678.c b/gcc/testsuite/gcc.target/i386/pr39678.c
new file mode 100644 (file)
index 0000000..70e8ff4
--- /dev/null
@@ -0,0 +1,19 @@
+/* PR target/39678 */
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2" } */
+
+struct X {
+  char c;
+  __complex__ float val;
+};
+
+struct X
+foo (float *p)
+{ /* { dg-message "note: The ABI of passing structure with complex float member has changed in GCC 4.4" } */
+  struct X x;
+  x.c = -3;
+  __real x.val = p[0];
+  __imag x.val = p[1];
+  return x;
+}
index 68eca53a2e431952ee443c8eaaef2c6130764bf7..299bc80caba5598259748d616883ef6ca65bed90 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "defines.h"
 #include "args.h"
+#include <complex.h>
 
 struct IntegerRegisters iregs;
 struct FloatRegisters fregs;
@@ -116,6 +117,45 @@ check_struct_passing8 (struct flex2_struct is ATTRIBUTE_UNUSED)
   check_int_arguments;
 }
 
+struct complex1_struct
+{
+  int c;
+  __complex__ float x;
+};
+
+struct complex1a_struct
+{
+  long l;
+  float f;
+};
+
+struct complex2_struct
+{
+  int c;
+  __complex__ float x;
+  float y;
+};
+
+struct complex2a_struct
+{
+  long l;
+  double d;
+};
+
+void
+check_struct_passing9 (struct complex1_struct is ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+  check_float_arguments;
+}
+
+void
+check_struct_passing10 (struct complex2_struct is ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+  check_double_arguments;
+}
+
 static struct flex1_struct f1s = { 60, { } };
 static struct flex2_struct f2s = { 61, { } };
 
@@ -136,6 +176,18 @@ main (void)
   };
   int i;
 #endif
+  struct complex1_struct c1s = { 4, ( -13.4 + 3.5*I ) };
+  union
+    {
+      struct complex1_struct c;
+      struct complex1a_struct u;
+    } c1u;
+  struct complex2_struct c2s = { 4, ( -13.4 + 3.5*I ), -34.5 };
+  union
+    {
+      struct complex2_struct c;
+      struct complex2a_struct u;
+    } c2u;
 
   clear_struct_registers;
   iregs.I0 = is.i;
@@ -185,5 +237,25 @@ main (void)
   clear_int_hardware_registers;
   WRAP_CALL (check_struct_passing8)(f2s);
 
+  clear_struct_registers;
+  c1u.c = c1s;
+  iregs.I0 = c1u.u.l;
+  num_iregs = 1;
+  fregs.xmm0._float [0] = c1u.u.f;
+  num_fregs = 1;
+  clear_int_hardware_registers;
+  clear_float_hardware_registers;
+  WRAP_CALL (check_struct_passing9)(c1s);
+
+  clear_struct_registers;
+  c2u.c = c2s;
+  iregs.I0 = c2u.u.l;
+  num_iregs = 1;
+  fregs.xmm0._double[0] = c2u.u.d;
+  num_fregs = 1;
+  clear_int_hardware_registers;
+  clear_float_hardware_registers;
+  WRAP_CALL (check_struct_passing10)(c2s);
+
   return 0;
 }