diff options
author | H.J. Lu <hongjiu.lu@intel.com> | 2009-02-18 02:16:03 +0000 |
---|---|---|
committer | H.J. Lu <hjl@gcc.gnu.org> | 2009-02-17 18:16:03 -0800 |
commit | bce08d5003e0cb1f63cbe92895be8cbcc5c48547 (patch) | |
tree | 69c176a033d12f090d8e12d52fe61b4ace95034f | |
parent | 5600f233ef5f740908f0480b76936e503b1d4cda (diff) | |
download | gcc-bce08d5003e0cb1f63cbe92895be8cbcc5c48547.zip gcc-bce08d5003e0cb1f63cbe92895be8cbcc5c48547.tar.gz gcc-bce08d5003e0cb1f63cbe92895be8cbcc5c48547.tar.bz2 |
re PR target/39082 (union with long double doesn't follow x86-64 psABI)
gcc/
2009-02-17 H.J. Lu <hongjiu.lu@intel.com>
PR target/39082
* c.opt (Wabi): Support C and ObjC.
(Wpsabi): New.
* c-opts.c (c_common_handle_option): Handle OPT_Wabi.
* config/i386/i386.c (classify_argument): Warn once about the ABI
change when passing union with long double.
* doc/invoke.texi: Update -Wabi for warning psABI changes.
gcc/testsuite/
2009-02-17 H.J. Lu <hongjiu.lu@intel.com>
PR target/39082
* g++.dg/compat/struct-layout-1_generate.c (dg_options): Add
-Wno-abi for x86.
* gcc.dg/compat/struct-layout-1_generate.c (dg_options): Likewise.
* gcc.target/i386/pr39082-1.c: New.
* gcc.target/x86_64/abi/abi-x86_64.exp (additional_flags): Add
-Wno-abi.
* gcc.target/x86_64/abi/args.h (XMM_T): Add _m64 and _m128 if
CHECK_M64_M128 is defined.
(check_f_arguments): Add "do".
(check_vector_arguments): New.
(check_m64_arguments): Likewise.
(check_m128_arguments): Likewise.
* gcc.target/x86_64/abi/defines.h: Include <xmmintrin.h>.
(CHECK_M64_M128): Define.
* gcc.target/x86_64/abi/test_m64m128_returning.c: New. Based
on abitest.
* gcc.target/x86_64/abi/test_passing_m64m128.c: Likewise.
* gcc.target/x86_64/abi/test_passing_structs.c: Define __m128
tests only if CHECK_M64_M128 is defined.
* gcc.target/x86_64/abi/test_passing_structs.c (m128_struct): New.
(m128_2_struct): Likewise.
(check_struct_passing5): Likewise.
(check_struct_passing6): Likewise.
(main): Test struct with __m128 if CHECK_M64_M128 is defined.
* gcc.target/x86_64/abi/test_passing_unions.c (un4): New.
(un5): Likewise.
(check_union_passing4): Likewise.
(main): Test union with __m128 if CHECK_M64_M128 is defined.
From-SVN: r144257
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/c-opts.c | 4 | ||||
-rw-r--r-- | gcc/c.opt | 5 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 20 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 23 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 40 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr39082-1.c | 35 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/x86_64/abi/abi-x86_64.exp | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/x86_64/abi/args.h | 44 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/x86_64/abi/defines.h | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/x86_64/abi/test_m64m128_returning.c | 54 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/x86_64/abi/test_passing_m64m128.c | 249 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/x86_64/abi/test_passing_structs.c | 58 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/x86_64/abi/test_passing_unions.c | 89 |
16 files changed, 634 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 17869d7..780468f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2009-02-17 H.J. Lu <hongjiu.lu@intel.com> + + PR target/39082 + * c.opt (Wabi): Support C and ObjC. + (Wpsabi): New. + + * c-opts.c (c_common_handle_option): Handle OPT_Wabi. + + * config/i386/i386.c (classify_argument): Warn once about the ABI + change when passing union with long double. + + * doc/invoke.texi: Update -Wabi for warning psABI changes. + 2009-02-18 Joseph Myers <joseph@codesourcery.com> PR c/35447 diff --git a/gcc/c-opts.c b/gcc/c-opts.c index a7ff6cc..28bdc31 100644 --- a/gcc/c-opts.c +++ b/gcc/c-opts.c @@ -978,6 +978,10 @@ c_common_handle_option (size_t scode, const char *arg, int value) case OPT_v: verbose = true; break; + + case OPT_Wabi: + warn_psabi = value; + break; } return result; @@ -112,9 +112,12 @@ C ObjC C++ ObjC++ Joined Separate -U<macro> Undefine <macro> Wabi -C++ ObjC++ Var(warn_abi) Warning +C ObjC C++ ObjC++ Var(warn_abi) Warning Warn about things that will change when compiling with an ABI-compliant compiler +Wpsabi +C ObjC C++ ObjC++ Var(warn_psabi) Init(1) Undocumented + Waddress C ObjC C++ ObjC++ Var(warn_address) Warning Warn about suspicious uses of memory addresses diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 582a9dc..da36f17 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -5022,10 +5022,24 @@ classify_argument (enum machine_mode mode, const_tree type, classes[i] = X86_64_SSE_CLASS; } - /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */ + /* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS, + everything should be passed in memory. */ if (classes[i] == X86_64_X87UP_CLASS - && (i == 0 || classes[i - 1] != X86_64_X87_CLASS)) - classes[i] = X86_64_SSE_CLASS; + && (classes[i - 1] != X86_64_X87_CLASS)) + { + static bool warned; + + /* The first one should never be X86_64_X87UP_CLASS. */ + gcc_assert (i != 0); + if (!warned && warn_psabi) + { + warned = true; + inform (input_location, + "The ABI of passing union with long double" + " has changed in GCC 4.4"); + } + return 0; + } } return words; } diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 6d36794..f52b643 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1966,7 +1966,7 @@ Do not assume @samp{inline} for functions defined inside a class scope. functions will have linkage like inline functions; they just won't be inlined by default. -@item -Wabi @r{(C++ and Objective-C++ only)} +@item -Wabi @r{(C, Objective-C, C++ and Objective-C++ only)} @opindex Wabi @opindex Wno-abi Warn when G++ generates code that is probably not compatible with the @@ -2066,6 +2066,27 @@ Instantiations of these templates may be mangled incorrectly. @end itemize +It also warns psABI related changes. The known psABI changes at this +point include: + +@itemize @bullet + +@item +For SYSV/x86-64, when passing union with long double, it is changed to +pass in memory as specified in psABI. For example: + +@smallexample +union U @{ + long double ld; + int i; +@}; +@end smallexample + +@noindent +@code{union U} will always be passed in memory. + +@end itemize + @item -Wctor-dtor-privacy @r{(C++ and Objective-C++ only)} @opindex Wctor-dtor-privacy @opindex Wno-ctor-dtor-privacy diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 055c2b1..ca72b02 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,43 @@ +2009-02-17 H.J. Lu <hongjiu.lu@intel.com> + + PR target/39082 + * g++.dg/compat/struct-layout-1_generate.c (dg_options): Add + -Wno-abi for x86. + * gcc.dg/compat/struct-layout-1_generate.c (dg_options): Likewise. + + * gcc.target/i386/pr39082-1.c: New. + + * gcc.target/x86_64/abi/abi-x86_64.exp (additional_flags): Add + -Wno-abi. + + * gcc.target/x86_64/abi/args.h (XMM_T): Add _m64 and _m128 if + CHECK_M64_M128 is defined. + (check_f_arguments): Add "do". + (check_vector_arguments): New. + (check_m64_arguments): Likewise. + (check_m128_arguments): Likewise. + + * gcc.target/x86_64/abi/defines.h: Include <xmmintrin.h>. + (CHECK_M64_M128): Define. + + * gcc.target/x86_64/abi/test_m64m128_returning.c: New. Based + on abitest. + * gcc.target/x86_64/abi/test_passing_m64m128.c: Likewise. + + * gcc.target/x86_64/abi/test_passing_structs.c: Define __m128 + tests only if CHECK_M64_M128 is defined. + + * gcc.target/x86_64/abi/test_passing_structs.c (m128_struct): New. + (m128_2_struct): Likewise. + (check_struct_passing5): Likewise. + (check_struct_passing6): Likewise. + (main): Test struct with __m128 if CHECK_M64_M128 is defined. + + * gcc.target/x86_64/abi/test_passing_unions.c (un4): New. + (un5): Likewise. + (check_union_passing4): Likewise. + (main): Test union with __m128 if CHECK_M64_M128 is defined. + 2009-02-18 Joseph Myers <joseph@codesourcery.com> PR c/35447 diff --git a/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c b/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c index 575ad61..93700d2 100644 --- a/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c +++ b/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c @@ -44,9 +44,9 @@ along with GCC; see the file COPYING3. If not see const char *dg_options[] = { "/* { dg-options \"%s-I%s\" } */\n", -"/* { dg-options \"%s-I%s -mno-mmx\" { target i?86-*-* x86_64-*-* } } */\n", +"/* { dg-options \"%s-I%s -mno-mmx -Wno-abi\" { target i?86-*-* x86_64-*-* } } */\n", "/* { dg-options \"%s-I%s -fno-common\" { target hppa*-*-hpux* powerpc*-*-darwin* *-*-mingw32* *-*-cygwin* } } */\n", -"/* { dg-options \"%s-I%s -mno-mmx -fno-common\" { target i?86-*-darwin* x86_64-*-darwin* } } */\n", +"/* { dg-options \"%s-I%s -mno-mmx -fno-common -Wno-abi\" { target i?86-*-darwin* x86_64-*-darwin* } } */\n", "/* { dg-options \"%s-I%s -mno-base-addresses\" { target mmix-*-* } } */\n", "/* { dg-options \"%s-I%s -mlongcalls -mtext-section-literals\" { target xtensa*-*-* } } */\n" #define NDG_OPTIONS (sizeof (dg_options) / sizeof (dg_options[0])) diff --git a/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c b/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c index a162dee..c080147 100644 --- a/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c +++ b/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c @@ -44,9 +44,9 @@ along with GCC; see the file COPYING3. If not see const char *dg_options[] = { "/* { dg-options \"%s-I%s\" } */\n", -"/* { dg-options \"%s-I%s -mno-mmx\" { target i?86-*-* x86_64-*-* } } */\n", +"/* { dg-options \"%s-I%s -mno-mmx -Wno-abi\" { target i?86-*-* x86_64-*-* } } */\n", "/* { dg-options \"%s-I%s -fno-common\" { target hppa*-*-hpux* powerpc*-*-darwin* *-*-mingw32* *-*-cygwin* } } */\n", -"/* { dg-options \"%s-I%s -mno-mmx -fno-common\" { target i?86-*-darwin* x86_64-*-darwin* } } */\n", +"/* { dg-options \"%s-I%s -mno-mmx -fno-common -Wno-abi\" { target i?86-*-darwin* x86_64-*-darwin* } } */\n", "/* { dg-options \"%s-I%s -mno-base-addresses\" { target mmix-*-* } } */\n", "/* { dg-options \"%s-I%s -mlongcalls -mtext-section-literals\" { target xtensa*-*-* } } */\n" #define NDG_OPTIONS (sizeof (dg_options) / sizeof (dg_options[0])) diff --git a/gcc/testsuite/gcc.target/i386/pr39082-1.c b/gcc/testsuite/gcc.target/i386/pr39082-1.c new file mode 100644 index 0000000..4c4e254 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr39082-1.c @@ -0,0 +1,35 @@ +/* PR target/39082 */ +/* { dg-do compile } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-O2" } */ + +union un +{ + long double x; + int i; +}; + +extern int bar1 (union un); +extern union un bar2 (int); + +int +foo1 (union un u) /* { dg-message "note: The ABI of passing union with long double has changed in GCC 4.4" } */ +{ + bar1 (u); + return u.i; +} + +int +foo2 (void) +{ + union un u; + u.i = 1; + return foo1 (u) + bar1 (u); +} + +int +foo3 (int x) +{ + union un u = bar2 (x); + return u.i; +} diff --git a/gcc/testsuite/gcc.target/x86_64/abi/abi-x86_64.exp b/gcc/testsuite/gcc.target/x86_64/abi/abi-x86_64.exp index 97a33e5..57ffc52 100644 --- a/gcc/testsuite/gcc.target/x86_64/abi/abi-x86_64.exp +++ b/gcc/testsuite/gcc.target/x86_64/abi/abi-x86_64.exp @@ -29,7 +29,7 @@ if { (![istarget x86_64-*-*] && ![istarget i?86-*-*]) torture-init set-torture-options $C_TORTURE_OPTIONS -set additional_flags "-W -Wall" +set additional_flags "-W -Wall -Wno-abi" foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] { if {[runtest_file_p $runtests $src]} { diff --git a/gcc/testsuite/gcc.target/x86_64/abi/args.h b/gcc/testsuite/gcc.target/x86_64/abi/args.h index db54268..99d7b76 100644 --- a/gcc/testsuite/gcc.target/x86_64/abi/args.h +++ b/gcc/testsuite/gcc.target/x86_64/abi/args.h @@ -25,6 +25,10 @@ typedef union { long _long[2]; int _int[4]; unsigned long _ulong[2]; +#ifdef CHECK_M64_M128 + __m64 _m64[2]; + __m128 _m128[1]; +#endif } XMM_T; typedef union { @@ -111,7 +115,7 @@ extern unsigned int num_iregs, num_fregs; clear_int_hardware_registers /* TODO: Do the checking. */ -#define check_f_arguments(T) { \ +#define check_f_arguments(T) do { \ assert (num_fregs <= 0 || fregs.xmm0._ ## T [0] == xmm_regs[0]._ ## T [0]); \ assert (num_fregs <= 1 || fregs.xmm1._ ## T [0] == xmm_regs[1]._ ## T [0]); \ assert (num_fregs <= 2 || fregs.xmm2._ ## T [0] == xmm_regs[2]._ ## T [0]); \ @@ -125,6 +129,44 @@ extern unsigned int num_iregs, num_fregs; #define check_float_arguments check_f_arguments(float) #define check_double_arguments check_f_arguments(double) +#define check_vector_arguments(T,O) do { \ + assert (num_fregs <= 0 \ + || memcmp (((char *) &fregs.xmm0) + (O), \ + &xmm_regs[0], \ + sizeof (__ ## T) - (O)) == 0); \ + assert (num_fregs <= 1 \ + || memcmp (((char *) &fregs.xmm1) + (O), \ + &xmm_regs[1], \ + sizeof (__ ## T) - (O)) == 0); \ + assert (num_fregs <= 2 \ + || memcmp (((char *) &fregs.xmm2) + (O), \ + &xmm_regs[2], \ + sizeof (__ ## T) - (O)) == 0); \ + assert (num_fregs <= 3 \ + || memcmp (((char *) &fregs.xmm3) + (O), \ + &xmm_regs[3], \ + sizeof (__ ## T) - (O)) == 0); \ + assert (num_fregs <= 4 \ + || memcmp (((char *) &fregs.xmm4) + (O), \ + &xmm_regs[4], \ + sizeof (__ ## T) - (O)) == 0); \ + assert (num_fregs <= 5 \ + || memcmp (((char *) &fregs.xmm5) + (O), \ + &xmm_regs[5], \ + sizeof (__ ## T) - (O)) == 0); \ + assert (num_fregs <= 6 \ + || memcmp (((char *) &fregs.xmm6) + (O), \ + &xmm_regs[6], \ + sizeof (__ ## T) - (O)) == 0); \ + assert (num_fregs <= 7 \ + || memcmp (((char *) &fregs.xmm7) + (O), \ + &xmm_regs[7], \ + sizeof (__ ## T) - (O)) == 0); \ + } while (0) + +#define check_m64_arguments check_vector_arguments(m64, 0) +#define check_m128_arguments check_vector_arguments(m128, 0) + /* ldoubles are not passed in registers */ #define check_ldouble_arguments diff --git a/gcc/testsuite/gcc.target/x86_64/abi/defines.h b/gcc/testsuite/gcc.target/x86_64/abi/defines.h index 34707a8..a32daf6 100644 --- a/gcc/testsuite/gcc.target/x86_64/abi/defines.h +++ b/gcc/testsuite/gcc.target/x86_64/abi/defines.h @@ -1,6 +1,9 @@ #ifndef DEFINED_DEFINES_H #define DEFINED_DEFINES_H +/* Get __m64 and __m128. */ +#include <xmmintrin.h> + typedef unsigned long ulong; typedef long double ldouble; @@ -18,7 +21,7 @@ typedef long double ldouble; /* #define CHECK_FLOAT128 */ /* Scalar types __m64 and __m128. */ -/* #define CHECK_M64_M128 */ +#define CHECK_M64_M128 /* Returning of complex type. */ #define CHECK_COMPLEX diff --git a/gcc/testsuite/gcc.target/x86_64/abi/test_m64m128_returning.c b/gcc/testsuite/gcc.target/x86_64/abi/test_m64m128_returning.c new file mode 100644 index 0000000..cde0346 --- /dev/null +++ b/gcc/testsuite/gcc.target/x86_64/abi/test_m64m128_returning.c @@ -0,0 +1,54 @@ +#include <stdio.h> +#include "defines.h" +#include "macros.h" +#include "args.h" + +struct IntegerRegisters iregs; +struct FloatRegisters fregs; +unsigned int num_iregs, num_fregs; + +__m64 +fun_test_returning___m64 (void) +{ + volatile_var++; + return (__m64){72,0}; +} + +__m128 +fun_test_returning___m128 (void) +{ + volatile_var++; + return (__m128){73,0,0,0}; +} + +__m64 test_64; +__m128 test_128; + +int +main (void) +{ + unsigned failed = 0; + XMM_T xmmt1, xmmt2; + + /* We jump through hoops to compare the results as gcc 3.3 does throw + an ICE when trying to generate a compare for a == b, when a and b + are of __m64 or __m128 type :-( */ + clear_struct_registers; + test_64 = (__m64){72,0}; + xmmt1._m64[0] = test_64; + xmmt2._m64[0] = WRAP_RET (fun_test_returning___m64)(); + if (xmmt1._long[0] != xmmt2._long[0] + || xmmt1._long[0] != xmm_regs[0]._long[0]) + printf ("fail m64\n"), failed++; + + clear_struct_registers; + test_128 = (__m128){73,0}; + xmmt1._m128[0] = test_128; + xmmt2._m128[0] = WRAP_RET (fun_test_returning___m128)(); + if (xmmt1._long[0] != xmmt2._long[0] + || xmmt1._long[0] != xmm_regs[0]._long[0]) + printf ("fail m128\n"), failed++; + if (failed) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/x86_64/abi/test_passing_m64m128.c b/gcc/testsuite/gcc.target/x86_64/abi/test_passing_m64m128.c new file mode 100644 index 0000000..237435c --- /dev/null +++ b/gcc/testsuite/gcc.target/x86_64/abi/test_passing_m64m128.c @@ -0,0 +1,249 @@ +#include <stdio.h> +#include "defines.h" +#include "macros.h" +#include "args.h" + +struct IntegerRegisters iregs; +struct FloatRegisters fregs; +unsigned int num_iregs, num_fregs; + +/* This struct holds values for argument checking. */ +struct +{ + XMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23; +} values; + +char *pass; +int failed = 0; + +#undef assert +#define assert(c) do { \ + if (!(c)) {failed++; printf ("failed %s\n", pass); } \ +} while (0) + +#define compare(X1,X2,T) do { \ + assert (memcmp (&X1, &X2, sizeof (T)) == 0); \ +} while (0) + +void +fun_check_passing_m64_8_values (__m64 i0 ATTRIBUTE_UNUSED, __m64 i1 ATTRIBUTE_UNUSED, __m64 i2 ATTRIBUTE_UNUSED, __m64 i3 ATTRIBUTE_UNUSED, __m64 i4 ATTRIBUTE_UNUSED, __m64 i5 ATTRIBUTE_UNUSED, __m64 i6 ATTRIBUTE_UNUSED, __m64 i7 ATTRIBUTE_UNUSED) +{ + /* Check argument values. */ + compare (values.i0, i0, __m64); + compare (values.i1, i1, __m64); + compare (values.i2, i2, __m64); + compare (values.i3, i3, __m64); + compare (values.i4, i4, __m64); + compare (values.i5, i5, __m64); + compare (values.i6, i6, __m64); + compare (values.i7, i7, __m64); +} + +void +fun_check_passing_m64_8_regs (__m64 i0 ATTRIBUTE_UNUSED, __m64 i1 ATTRIBUTE_UNUSED, __m64 i2 ATTRIBUTE_UNUSED, __m64 i3 ATTRIBUTE_UNUSED, __m64 i4 ATTRIBUTE_UNUSED, __m64 i5 ATTRIBUTE_UNUSED, __m64 i6 ATTRIBUTE_UNUSED, __m64 i7 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m64_arguments; +} + +void +fun_check_passing_m64_20_values (__m64 i0 ATTRIBUTE_UNUSED, __m64 i1 ATTRIBUTE_UNUSED, __m64 i2 ATTRIBUTE_UNUSED, __m64 i3 ATTRIBUTE_UNUSED, __m64 i4 ATTRIBUTE_UNUSED, __m64 i5 ATTRIBUTE_UNUSED, __m64 i6 ATTRIBUTE_UNUSED, __m64 i7 ATTRIBUTE_UNUSED, __m64 i8 ATTRIBUTE_UNUSED, __m64 i9 ATTRIBUTE_UNUSED, __m64 i10 ATTRIBUTE_UNUSED, __m64 i11 ATTRIBUTE_UNUSED, __m64 i12 ATTRIBUTE_UNUSED, __m64 i13 ATTRIBUTE_UNUSED, __m64 i14 ATTRIBUTE_UNUSED, __m64 i15 ATTRIBUTE_UNUSED, __m64 i16 ATTRIBUTE_UNUSED, __m64 i17 ATTRIBUTE_UNUSED, __m64 i18 ATTRIBUTE_UNUSED, __m64 i19 ATTRIBUTE_UNUSED) +{ + /* Check argument values. */ + compare (values.i0 , i0, __m64); + compare (values.i1 , i1, __m64); + compare (values.i2 , i2, __m64); + compare (values.i3 , i3, __m64); + compare (values.i4 , i4, __m64); + compare (values.i5 , i5, __m64); + compare (values.i6 , i6, __m64); + compare (values.i7 , i7, __m64); + compare (values.i8 , i8, __m64); + compare (values.i9 , i9, __m64); + compare (values.i10 , i10, __m64); + compare (values.i11 , i11, __m64); + compare (values.i12 , i12, __m64); + compare (values.i13 , i13, __m64); + compare (values.i14 , i14, __m64); + compare (values.i15 , i15, __m64); + compare (values.i16 , i16, __m64); + compare (values.i17 , i17, __m64); + compare (values.i18 , i18, __m64); + compare (values.i19 , i19, __m64); +} + +void +fun_check_passing_m64_20_regs (__m64 i0 ATTRIBUTE_UNUSED, __m64 i1 ATTRIBUTE_UNUSED, __m64 i2 ATTRIBUTE_UNUSED, __m64 i3 ATTRIBUTE_UNUSED, __m64 i4 ATTRIBUTE_UNUSED, __m64 i5 ATTRIBUTE_UNUSED, __m64 i6 ATTRIBUTE_UNUSED, __m64 i7 ATTRIBUTE_UNUSED, __m64 i8 ATTRIBUTE_UNUSED, __m64 i9 ATTRIBUTE_UNUSED, __m64 i10 ATTRIBUTE_UNUSED, __m64 i11 ATTRIBUTE_UNUSED, __m64 i12 ATTRIBUTE_UNUSED, __m64 i13 ATTRIBUTE_UNUSED, __m64 i14 ATTRIBUTE_UNUSED, __m64 i15 ATTRIBUTE_UNUSED, __m64 i16 ATTRIBUTE_UNUSED, __m64 i17 ATTRIBUTE_UNUSED, __m64 i18 ATTRIBUTE_UNUSED, __m64 i19 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m64_arguments; +} + +void +fun_check_passing_m128_8_values (__m128 i0 ATTRIBUTE_UNUSED, __m128 i1 ATTRIBUTE_UNUSED, __m128 i2 ATTRIBUTE_UNUSED, __m128 i3 ATTRIBUTE_UNUSED, __m128 i4 ATTRIBUTE_UNUSED, __m128 i5 ATTRIBUTE_UNUSED, __m128 i6 ATTRIBUTE_UNUSED, __m128 i7 ATTRIBUTE_UNUSED) +{ + /* Check argument values. */ + compare (values.i0, i0, __m128); + compare (values.i1, i1, __m128); + compare (values.i2, i2, __m128); + compare (values.i3, i3, __m128); + compare (values.i4, i4, __m128); + compare (values.i5, i5, __m128); + compare (values.i6, i6, __m128); + compare (values.i7, i7, __m128); +} + +void +fun_check_passing_m128_8_regs (__m128 i0 ATTRIBUTE_UNUSED, __m128 i1 ATTRIBUTE_UNUSED, __m128 i2 ATTRIBUTE_UNUSED, __m128 i3 ATTRIBUTE_UNUSED, __m128 i4 ATTRIBUTE_UNUSED, __m128 i5 ATTRIBUTE_UNUSED, __m128 i6 ATTRIBUTE_UNUSED, __m128 i7 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m128_arguments; +} + +void +fun_check_passing_m128_20_values (__m128 i0 ATTRIBUTE_UNUSED, __m128 i1 ATTRIBUTE_UNUSED, __m128 i2 ATTRIBUTE_UNUSED, __m128 i3 ATTRIBUTE_UNUSED, __m128 i4 ATTRIBUTE_UNUSED, __m128 i5 ATTRIBUTE_UNUSED, __m128 i6 ATTRIBUTE_UNUSED, __m128 i7 ATTRIBUTE_UNUSED, __m128 i8 ATTRIBUTE_UNUSED, __m128 i9 ATTRIBUTE_UNUSED, __m128 i10 ATTRIBUTE_UNUSED, __m128 i11 ATTRIBUTE_UNUSED, __m128 i12 ATTRIBUTE_UNUSED, __m128 i13 ATTRIBUTE_UNUSED, __m128 i14 ATTRIBUTE_UNUSED, __m128 i15 ATTRIBUTE_UNUSED, __m128 i16 ATTRIBUTE_UNUSED, __m128 i17 ATTRIBUTE_UNUSED, __m128 i18 ATTRIBUTE_UNUSED, __m128 i19 ATTRIBUTE_UNUSED) +{ + /* Check argument values. */ + compare (values.i0 , i0, __m128); + compare (values.i1 , i1, __m128); + compare (values.i2 , i2, __m128); + compare (values.i3 , i3, __m128); + compare (values.i4 , i4, __m128); + compare (values.i5 , i5, __m128); + compare (values.i6 , i6, __m128); + compare (values.i7 , i7, __m128); + compare (values.i8 , i8, __m128); + compare (values.i9 , i9, __m128); + compare (values.i10 , i10, __m128); + compare (values.i11 , i11, __m128); + compare (values.i12 , i12, __m128); + compare (values.i13 , i13, __m128); + compare (values.i14 , i14, __m128); + compare (values.i15 , i15, __m128); + compare (values.i16 , i16, __m128); + compare (values.i17 , i17, __m128); + compare (values.i18 , i18, __m128); + compare (values.i19 , i19, __m128); +} + +void +fun_check_passing_m128_20_regs (__m128 i0 ATTRIBUTE_UNUSED, __m128 i1 ATTRIBUTE_UNUSED, __m128 i2 ATTRIBUTE_UNUSED, __m128 i3 ATTRIBUTE_UNUSED, __m128 i4 ATTRIBUTE_UNUSED, __m128 i5 ATTRIBUTE_UNUSED, __m128 i6 ATTRIBUTE_UNUSED, __m128 i7 ATTRIBUTE_UNUSED, __m128 i8 ATTRIBUTE_UNUSED, __m128 i9 ATTRIBUTE_UNUSED, __m128 i10 ATTRIBUTE_UNUSED, __m128 i11 ATTRIBUTE_UNUSED, __m128 i12 ATTRIBUTE_UNUSED, __m128 i13 ATTRIBUTE_UNUSED, __m128 i14 ATTRIBUTE_UNUSED, __m128 i15 ATTRIBUTE_UNUSED, __m128 i16 ATTRIBUTE_UNUSED, __m128 i17 ATTRIBUTE_UNUSED, __m128 i18 ATTRIBUTE_UNUSED, __m128 i19 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m128_arguments; +} + + +#define def_check_int_passing8(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _func1, _func2, TYPE) \ + values.i0.TYPE[0] = _i0; \ + values.i1.TYPE[0] = _i1; \ + values.i2.TYPE[0] = _i2; \ + values.i3.TYPE[0] = _i3; \ + values.i4.TYPE[0] = _i4; \ + values.i5.TYPE[0] = _i5; \ + values.i6.TYPE[0] = _i6; \ + values.i7.TYPE[0] = _i7; \ + WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7); \ + \ + clear_float_registers; \ + fregs.F0.TYPE[0] = _i0; \ + fregs.F1.TYPE[0] = _i1; \ + fregs.F2.TYPE[0] = _i2; \ + fregs.F3.TYPE[0] = _i3; \ + fregs.F4.TYPE[0] = _i4; \ + fregs.F5.TYPE[0] = _i5; \ + fregs.F6.TYPE[0] = _i6; \ + fregs.F7.TYPE[0] = _i7; \ + num_fregs = 8; \ + WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7); + +#define def_check_int_passing20(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, _i18, _i19, _func1, _func2, TYPE) \ + values.i0.TYPE[0] = _i0; \ + values.i1.TYPE[0] = _i1; \ + values.i2.TYPE[0] = _i2; \ + values.i3.TYPE[0] = _i3; \ + values.i4.TYPE[0] = _i4; \ + values.i5.TYPE[0] = _i5; \ + values.i6.TYPE[0] = _i6; \ + values.i7.TYPE[0] = _i7; \ + values.i8.TYPE[0] = _i8; \ + values.i9.TYPE[0] = _i9; \ + values.i10.TYPE[0] = _i10; \ + values.i11.TYPE[0] = _i11; \ + values.i12.TYPE[0] = _i12; \ + values.i13.TYPE[0] = _i13; \ + values.i14.TYPE[0] = _i14; \ + values.i15.TYPE[0] = _i15; \ + values.i16.TYPE[0] = _i16; \ + values.i17.TYPE[0] = _i17; \ + values.i18.TYPE[0] = _i18; \ + values.i19.TYPE[0] = _i19; \ + WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, _i18, _i19); \ + \ + clear_float_registers; \ + fregs.F0.TYPE[0] = _i0; \ + fregs.F1.TYPE[0] = _i1; \ + fregs.F2.TYPE[0] = _i2; \ + fregs.F3.TYPE[0] = _i3; \ + fregs.F4.TYPE[0] = _i4; \ + fregs.F5.TYPE[0] = _i5; \ + fregs.F6.TYPE[0] = _i6; \ + fregs.F7.TYPE[0] = _i7; \ + num_fregs = 8; \ + WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, _i18, _i19); + +void +test_m64_on_stack () +{ + __m64 x[8]; + int i; + for (i = 0; i < 8; i++) + x[i] = (__m64){32+i, 0}; + pass = "m64-8"; + def_check_int_passing8(x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], fun_check_passing_m64_8_values, fun_check_passing_m64_8_regs, _m64); +} + +void +test_too_many_m64 () +{ + __m64 x[20]; + int i; + for (i = 0; i < 20; i++) + x[i] = (__m64){32+i, 0}; + pass = "m64-20"; + def_check_int_passing20(x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15], x[16], x[17], x[18], x[19], fun_check_passing_m64_20_values, fun_check_passing_m64_20_regs, _m64); +} + +void +test_m128_on_stack () +{ + __m128 x[8]; + int i; + for (i = 0; i < 8; i++) + x[i] = (__m128){32+i, 0, 0, 0}; + pass = "m128-8"; + def_check_int_passing8(x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], fun_check_passing_m128_8_values, fun_check_passing_m128_8_regs, _m128); +} + +void +test_too_many_m128 () +{ + __m128 x[20]; + int i; + for (i = 0; i < 20; i++) + x[i] = (__m128){32+i, 0, 0, 0}; + pass = "m128-20"; + def_check_int_passing20(x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15], x[16], x[17], x[18], x[19], fun_check_passing_m128_20_values, fun_check_passing_m128_20_regs, _m128); +} + +int +main (void) +{ + test_m64_on_stack (); + test_too_many_m64 (); + test_m128_on_stack (); + test_too_many_m128 (); + if (failed) + abort (); + return 0; +} 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 211c700..3ce0db1 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 @@ -1,4 +1,4 @@ -/* This tests passing of structs. Only integers are tested. */ +/* This tests passing of structs. */ #include "defines.h" #include "args.h" @@ -57,6 +57,40 @@ check_struct_passing4 (struct long3_struct ls ATTRIBUTE_UNUSED) assert ((unsigned long)&ls.l3 == rsp+24); } +#ifdef CHECK_M64_M128 +struct m128_struct +{ + __m128 x; +}; + +struct m128_2_struct +{ + __m128 x1, x2; +}; + +/* Check that the struct is passed as the individual members in fregs. */ +void +check_struct_passing5 (struct m128_struct ms1 ATTRIBUTE_UNUSED, + struct m128_struct ms2 ATTRIBUTE_UNUSED, + struct m128_struct ms3 ATTRIBUTE_UNUSED, + struct m128_struct ms4 ATTRIBUTE_UNUSED, + struct m128_struct ms5 ATTRIBUTE_UNUSED, + struct m128_struct ms6 ATTRIBUTE_UNUSED, + struct m128_struct ms7 ATTRIBUTE_UNUSED, + struct m128_struct ms8 ATTRIBUTE_UNUSED) +{ + check_m128_arguments; +} + +void +check_struct_passing6 (struct m128_2_struct ms ATTRIBUTE_UNUSED) +{ + /* Check the passing on the stack by comparing the address of the + stack elements to the expected place on the stack. */ + assert ((unsigned long)&ms.x1 == rsp+8); + assert ((unsigned long)&ms.x2 == rsp+24); +} +#endif int main (void) @@ -67,6 +101,14 @@ main (void) struct long2_struct l2s = { 50, 51 }; struct long3_struct l3s = { 52, 53, 54 }; #endif +#ifdef CHECK_M64_M128 + struct m128_struct m128s[8]; + struct m128_2_struct m128_2s = { + { 48.394, 39.3, -397.9, 3484.9 }, + { -8.394, -93.3, 7.9, 84.94 } + }; + int i; +#endif clear_struct_registers; iregs.I0 = is.i; @@ -90,5 +132,19 @@ main (void) WRAP_CALL (check_struct_passing4)(l3s); #endif +#ifdef CHECK_M64_M128 + clear_struct_registers; + for (i = 0; i < 8; i++) + { + m128s[i].x = (__m128){32+i, 0, i, 0}; + fregs.xmm0._m128[i] = m128s[i].x; + } + num_fregs = 8; + clear_float_hardware_registers; + WRAP_CALL (check_struct_passing5)(m128s[0], m128s[1], m128s[2], m128s[3], + m128s[4], m128s[5], m128s[6], m128s[7]); + WRAP_CALL (check_struct_passing6)(m128_2s); +#endif + return 0; } diff --git a/gcc/testsuite/gcc.target/x86_64/abi/test_passing_unions.c b/gcc/testsuite/gcc.target/x86_64/abi/test_passing_unions.c index 0b60704..1e3e85f 100644 --- a/gcc/testsuite/gcc.target/x86_64/abi/test_passing_unions.c +++ b/gcc/testsuite/gcc.target/x86_64/abi/test_passing_unions.c @@ -1,4 +1,4 @@ -/* This tests passing of structs. Only integers are tested. */ +/* This tests passing of structs. */ #include "defines.h" #include "args.h" @@ -45,7 +45,7 @@ check_union_passing1(union un1 u ATTRIBUTE_UNUSED) } void -check_union_passing2(union un2 u ATTRIBUTE_UNUSED) +check_union_passing2(union un2 u1 ATTRIBUTE_UNUSED) { check_int_arguments; } @@ -60,6 +60,61 @@ check_union_passing3(union un3 u ATTRIBUTE_UNUSED) #define check_union_passing2 WRAP_CALL(check_union_passing2) #define check_union_passing3 WRAP_CALL(check_union_passing3) +#ifdef CHECK_M64_M128 +union un4 +{ + __m128 x; + float f; +}; + +union un5 +{ + __m128 x; + long i; +}; + +void +check_union_passing4(union un4 u1 ATTRIBUTE_UNUSED, + union un4 u2 ATTRIBUTE_UNUSED, + union un4 u3 ATTRIBUTE_UNUSED, + union un4 u4 ATTRIBUTE_UNUSED, + union un4 u5 ATTRIBUTE_UNUSED, + union un4 u6 ATTRIBUTE_UNUSED, + union un4 u7 ATTRIBUTE_UNUSED, + union un4 u8 ATTRIBUTE_UNUSED) +{ + check_m128_arguments; +} + +void +check_union_passing5(union un5 u ATTRIBUTE_UNUSED) +{ + check_int_arguments; + check_vector_arguments(m128, 8); +} + +#define check_union_passing4 WRAP_CALL(check_union_passing4) +#define check_union_passing5 WRAP_CALL(check_union_passing5) +#endif + +union un6 +{ + long double ld; + int i; +}; + + +void +check_union_passing6(union un6 u ATTRIBUTE_UNUSED) +{ + /* Check the passing on the stack by comparing the address of the + stack elements to the expected place on the stack. */ + assert ((unsigned long)&u.ld == rsp+8); + assert ((unsigned long)&u.i == rsp+8); +} + +#define check_union_passing6 WRAP_CALL(check_union_passing6) + int main (void) { @@ -70,6 +125,12 @@ main (void) struct int_struct is; struct long_struct ls; #endif /* CHECK_LARGER_UNION_PASSING */ +#ifdef CHECK_M64_M128 + union un4 u4[8]; + union un5 u5 = { { 48.394, 39.3, -397.9, 3484.9 } }; + int i; +#endif + union un6 u6; /* Check a union with char, int. */ clear_struct_registers; @@ -140,5 +201,29 @@ main (void) check_union_passing3(u3); #endif /* CHECK_LARGER_UNION_PASSING */ +#ifdef CHECK_M64_M128 + clear_struct_registers; + for (i = 0; i < 8; i++) + { + u4[i].x = (__m128){32+i, 0, i, 0}; + fregs.xmm0._m128[i] = u4[i].x; + } + num_fregs = 8; + clear_float_hardware_registers; + check_union_passing4(u4[0], u4[1], u4[2], u4[3], + u4[4], u4[5], u4[6], u4[7]); + + clear_struct_registers; + fregs.xmm0._m128[0] = u5.x; + num_fregs = 1; + num_iregs = 1; + iregs.I0 = u5.i; + clear_float_hardware_registers; + check_union_passing5(u5); +#endif + + u6.i = 2; + check_union_passing6(u6); + return 0; } |