From: H.J. Lu Date: Thu, 9 Apr 2009 22:58:51 +0000 (+0000) Subject: re PR target/39678 (complex type isn't passed correctly) X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=805586285dbb8f34cccd4d34295719f59979b649;p=platform%2Fupstream%2Fgcc.git re PR target/39678 (complex type isn't passed correctly) gcc/ 2009-04-09 H.J. Lu PR target/39678 * config/i386/i386.c (classify_argument): Handle SCmode with (bit_offset % 64) != 0. gcc/testsuite/ 2009-04-09 H.J. Lu 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 . Add tests for structure with complex float. From-SVN: r145865 --- 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 + + PR target/39678 + * config/i386/i386.c (classify_argument): Handle SCmode with + (bit_offset % 64) != 0. + 2009-04-09 Sandra Loosemore * 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 + + 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 + . Add tests for structure with complex float. + 2009-04-10 Ben Elliston Joseph Myers 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 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 + +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 +#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 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; }