PATCH: PR target/39082: union with long double doesn't follow x86-64 psABI
H.J. Lu
hjl.tools@gmail.com
Tue Feb 10 19:15:00 GMT 2009
On Tue, Feb 10, 2009 at 9:43 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Tue, Feb 10, 2009 at 7:17 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>> On Thu, Feb 05, 2009 at 12:56:06PM -0800, H.J. Lu wrote:
>>> --Wunused-value -Wunused-variable @gol
>>> +-Wunused-value -Wunused-variable -Wunion-with-long-double @gol
>>
>> I think inventing a new -W* option for this is a bad idea, I'd prefer
>> the warning to be covered by -Wabi (I know it is ATM C++/ObjC++ only,
>> but it could be easily changed to be a common warning).
>
> -Wabi is off by default. Don't we want this warning on by default?
>
>>> --- testsuite/gcc.dg/compat/struct-layout-1_generate.c (revision 5181)
>>> +++ testsuite/gcc.dg/compat/struct-layout-1_generate.c (working copy)
>>> @@ -44,7 +44,7 @@ along with GCC; see the file COPYING3.
>>>
>>> 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-union-with-long-double\" { 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",
>>
>> The i?86/x86_64 darwin dg-options should use the same -W* option as other
>> i?86/x86_64 targets.
>>
>>> --- testsuite/g++.dg/compat/struct-layout-1_generate.c (revision 5181)
>>> +++ testsuite/g++.dg/compat/struct-layout-1_generate.c (working copy)
>>
>> Likewise.
>>
>
> I will make those changes.
>
Here is the updated patch. I added an undocumented -Wpsabi so that
psABI changes can be turned on by default when -Wabi/-Wno-abi isn't
used. OK for trunk?
Thanks.
--
H.J.
---
gcc/
2009-02-10 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-10 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/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.
-------------- next part --------------
gcc/
2009-02-10 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-10 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/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.
diff -x LAST_UPDATED -x REVISION -x gcc_update -x .svn \
-x "ChangeLog.*" \
-uprN ../gcc/gcc gcc
diff -x LAST_UPDATED -x REVISION -x gcc_update -x .svn -x 'ChangeLog.*' -uprN ../gcc/gcc/gcc/config/i386/i386.c gcc/gcc/config/i386/i386.c
--- ../gcc/gcc/gcc/config/i386/i386.c 2009-02-10 08:31:01.000000000 -0800
+++ gcc/gcc/config/i386/i386.c 2009-02-10 10:02:48.000000000 -0800
@@ -5001,10 +5001,24 @@ classify_argument (enum machine_mode mod
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 -x LAST_UPDATED -x REVISION -x gcc_update -x .svn -x 'ChangeLog.*' -uprN ../gcc/gcc/gcc/c.opt gcc/gcc/c.opt
--- ../gcc/gcc/gcc/c.opt 2009-02-02 11:38:56.000000000 -0800
+++ gcc/gcc/c.opt 2009-02-10 09:47:56.000000000 -0800
@@ -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 -x LAST_UPDATED -x REVISION -x gcc_update -x .svn -x 'ChangeLog.*' -uprN ../gcc/gcc/gcc/c-opts.c gcc/gcc/c-opts.c
--- ../gcc/gcc/gcc/c-opts.c 2009-02-02 11:38:56.000000000 -0800
+++ gcc/gcc/c-opts.c 2009-02-10 09:50:51.000000000 -0800
@@ -978,6 +978,10 @@ c_common_handle_option (size_t scode, co
case OPT_v:
verbose = true;
break;
+
+ case OPT_Wabi:
+ warn_psabi = value;
+ break;
}
return result;
diff -x LAST_UPDATED -x REVISION -x gcc_update -x .svn -x 'ChangeLog.*' -uprN ../gcc/gcc/gcc/doc/invoke.texi gcc/gcc/doc/invoke.texi
--- ../gcc/gcc/gcc/doc/invoke.texi 2009-02-02 11:38:48.000000000 -0800
+++ gcc/gcc/doc/invoke.texi 2009-02-10 10:14:11.000000000 -0800
@@ -1966,7 +1966,7 @@ Do not assume @samp{inline} for function
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
@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 -x LAST_UPDATED -x REVISION -x gcc_update -x .svn -x 'ChangeLog.*' -uprN ../gcc/gcc/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c gcc/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c
--- ../gcc/gcc/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c 2009-01-22 14:28:55.000000000 -0800
+++ gcc/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c 2009-02-10 10:08:47.000000000 -0800
@@ -44,9 +44,9 @@ along with GCC; see the file COPYING3.
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 -x LAST_UPDATED -x REVISION -x gcc_update -x .svn -x 'ChangeLog.*' -uprN ../gcc/gcc/gcc/testsuite/gcc.target/i386/pr39082-1.c gcc/gcc/testsuite/gcc.target/i386/pr39082-1.c
--- ../gcc/gcc/gcc/testsuite/gcc.target/i386/pr39082-1.c 1969-12-31 16:00:00.000000000 -0800
+++ gcc/gcc/testsuite/gcc.target/i386/pr39082-1.c 2009-02-05 07:43:01.000000000 -0800
@@ -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 -x LAST_UPDATED -x REVISION -x gcc_update -x .svn -x 'ChangeLog.*' -uprN ../gcc/gcc/gcc/testsuite/gcc.target/x86_64/abi/abi-x86_64.exp gcc/gcc/testsuite/gcc.target/x86_64/abi/abi-x86_64.exp
--- ../gcc/gcc/gcc/testsuite/gcc.target/x86_64/abi/abi-x86_64.exp 2009-02-10 08:30:59.000000000 -0800
+++ gcc/gcc/testsuite/gcc.target/x86_64/abi/abi-x86_64.exp 2009-02-10 10:08:15.000000000 -0800
@@ -29,7 +29,7 @@ if { (![istarget x86_64-*-*] && ![istarg
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 -x LAST_UPDATED -x REVISION -x gcc_update -x .svn -x 'ChangeLog.*' -uprN ../gcc/gcc/gcc/testsuite/gcc.target/x86_64/abi/args.h gcc/gcc/testsuite/gcc.target/x86_64/abi/args.h
--- ../gcc/gcc/gcc/testsuite/gcc.target/x86_64/abi/args.h 2007-11-28 17:54:11.000000000 -0800
+++ gcc/gcc/testsuite/gcc.target/x86_64/abi/args.h 2009-02-03 14:23:07.000000000 -0800
@@ -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 -x LAST_UPDATED -x REVISION -x gcc_update -x .svn -x 'ChangeLog.*' -uprN ../gcc/gcc/gcc/testsuite/gcc.target/x86_64/abi/defines.h gcc/gcc/testsuite/gcc.target/x86_64/abi/defines.h
--- ../gcc/gcc/gcc/testsuite/gcc.target/x86_64/abi/defines.h 2007-11-28 17:54:11.000000000 -0800
+++ gcc/gcc/testsuite/gcc.target/x86_64/abi/defines.h 2009-02-03 18:24:31.000000000 -0800
@@ -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 -x LAST_UPDATED -x REVISION -x gcc_update -x .svn -x 'ChangeLog.*' -uprN ../gcc/gcc/gcc/testsuite/gcc.target/x86_64/abi/test_m64m128_returning.c gcc/gcc/testsuite/gcc.target/x86_64/abi/test_m64m128_returning.c
--- ../gcc/gcc/gcc/testsuite/gcc.target/x86_64/abi/test_m64m128_returning.c 1969-12-31 16:00:00.000000000 -0800
+++ gcc/gcc/testsuite/gcc.target/x86_64/abi/test_m64m128_returning.c 2009-02-03 12:34:20.000000000 -0800
@@ -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 -x LAST_UPDATED -x REVISION -x gcc_update -x .svn -x 'ChangeLog.*' -uprN ../gcc/gcc/gcc/testsuite/gcc.target/x86_64/abi/test_passing_m64m128.c gcc/gcc/testsuite/gcc.target/x86_64/abi/test_passing_m64m128.c
--- ../gcc/gcc/gcc/testsuite/gcc.target/x86_64/abi/test_passing_m64m128.c 1969-12-31 16:00:00.000000000 -0800
+++ gcc/gcc/testsuite/gcc.target/x86_64/abi/test_passing_m64m128.c 2009-02-03 13:37:15.000000000 -0800
@@ -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 -x LAST_UPDATED -x REVISION -x gcc_update -x .svn -x 'ChangeLog.*' -uprN ../gcc/gcc/gcc/testsuite/gcc.target/x86_64/abi/test_passing_structs.c gcc/gcc/testsuite/gcc.target/x86_64/abi/test_passing_structs.c
--- ../gcc/gcc/gcc/testsuite/gcc.target/x86_64/abi/test_passing_structs.c 2007-11-28 17:54:11.000000000 -0800
+++ gcc/gcc/testsuite/gcc.target/x86_64/abi/test_passing_structs.c 2009-02-05 07:05:49.000000000 -0800
@@ -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_stru
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 -x LAST_UPDATED -x REVISION -x gcc_update -x .svn -x 'ChangeLog.*' -uprN ../gcc/gcc/gcc/testsuite/gcc.target/x86_64/abi/test_passing_unions.c gcc/gcc/testsuite/gcc.target/x86_64/abi/test_passing_unions.c
--- ../gcc/gcc/gcc/testsuite/gcc.target/x86_64/abi/test_passing_unions.c 2007-11-28 17:54:11.000000000 -0800
+++ gcc/gcc/testsuite/gcc.target/x86_64/abi/test_passing_unions.c 2009-02-05 07:10:47.000000000 -0800
@@ -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 ATTRIBU
}
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 ATTRIBU
#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;
}
diff -x LAST_UPDATED -x REVISION -x gcc_update -x .svn -x 'ChangeLog.*' -uprN ../gcc/gcc/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c gcc/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c
--- ../gcc/gcc/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c 2009-01-22 14:28:57.000000000 -0800
+++ gcc/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c 2009-02-10 10:09:10.000000000 -0800
@@ -44,9 +44,9 @@ along with GCC; see the file COPYING3.
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]))
More information about the Gcc-patches
mailing list