aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2009-04-09 22:58:51 +0000
committerH.J. Lu <hjl@gcc.gnu.org>2009-04-09 15:58:51 -0700
commit805586285dbb8f34cccd4d34295719f59979b649 (patch)
tree46d24cd733f827340cc68bd83323e40748cfbe0a
parent8c70d28b4da7f0d7ed14425ec9ba6c3f99d25742 (diff)
downloadgcc-805586285dbb8f34cccd4d34295719f59979b649.zip
gcc-805586285dbb8f34cccd4d34295719f59979b649.tar.gz
gcc-805586285dbb8f34cccd4d34295719f59979b649.tar.bz2
re PR target/39678 (complex type isn't passed correctly)
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
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/i386/i386.c17
-rw-r--r--gcc/testsuite/ChangeLog17
-rw-r--r--gcc/testsuite/g++.dg/torture/pr39678.C26
-rw-r--r--gcc/testsuite/gcc.dg/compat/struct-complex-1_x.c3
-rw-r--r--gcc/testsuite/gcc.dg/compat/struct-complex-1_y.c2
-rw-r--r--gcc/testsuite/gcc.dg/compat/struct-complex-2.h15
-rw-r--r--gcc/testsuite/gcc.dg/compat/struct-complex-2_main.c21
-rw-r--r--gcc/testsuite/gcc.dg/compat/struct-complex-2_x.c30
-rw-r--r--gcc/testsuite/gcc.dg/compat/struct-complex-2_y.c23
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr39678.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/pr39678.c19
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/test_passing_structs.c72
13 files changed, 275 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5e4bd00..1f31df2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index d87e853..503cc08 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c346b61..3c7cab6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..a7c120a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr39678.C
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.dg/compat/struct-complex-1_x.c b/gcc/testsuite/gcc.dg/compat/struct-complex-1_x.c
index c77ba33..0c67239 100644
--- a/gcc/testsuite/gcc.dg/compat/struct-complex-1_x.c
+++ b/gcc/testsuite/gcc.dg/compat/struct-complex-1_x.c
@@ -1,4 +1,5 @@
-/* { dg-options "-O" } */
+/* { dg-options "-O -Wno-psabi" } */
+
#ifdef __x86_64__
#include "struct-complex-1.h"
diff --git a/gcc/testsuite/gcc.dg/compat/struct-complex-1_y.c b/gcc/testsuite/gcc.dg/compat/struct-complex-1_y.c
index 9ff450f..858e6a9 100644
--- a/gcc/testsuite/gcc.dg/compat/struct-complex-1_y.c
+++ b/gcc/testsuite/gcc.dg/compat/struct-complex-1_y.c
@@ -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
index 0000000..1fd1e86
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/compat/struct-complex-2.h
@@ -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
index 0000000..74eae62
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/compat/struct-complex-2_main.c
@@ -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
index 0000000..2fb9826
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/compat/struct-complex-2_x.c
@@ -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
index 0000000..54a72fa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/compat/struct-complex-2_y.c
@@ -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
index 0000000..42de033
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr39678.c
@@ -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
index 0000000..70e8ff4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr39678.c
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/test_passing_structs.c b/gcc/testsuite/gcc.target/x86_64/abi/test_passing_structs.c
index 68eca53..299bc80 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/test_passing_structs.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/test_passing_structs.c
@@ -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;
}