From patchwork Mon Jul 12 13:41:58 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Fix complex argument passing on Solaris 8/9 x86 Date: Mon, 12 Jul 2010 03:41:58 -0000 From: Rainer Orth X-Patchwork-Id: 58612 Message-Id: To: gcc-patches@gcc.gnu.org Cc: Uros Bizjak All complex execution tests were failing on Solaris 8 and 9/x86. There's a mismatch between caller and callee when passing complex values. The following testcase shows the problem: s8 $ cat complex.c #include int main (void) { _Complex double cd = 1 + 2 * (__extension__ 1.0iF); _Complex double ce = 2 + 3 * (__extension__ 1.0iF); _Complex double cr; printf ("__real__ cd = %g __imag__ cd = %g\n", __real__ cd, __imag__ cd); printf ("__real__ ce = %g __imag__ ce = %g\n", __real__ ce, __imag__ ce); cr = cd * ce; printf ("__real__ cr = %g __imag__ cr = %g\n", __real__ cr, __imag__ cr); return 0; } s8 $ gcc -o complex complex.c s8 $ ./complex __real__ cd = 1 __imag__ cd = 2 __real__ ce = 2 __imag__ ce = 3 __real__ cr = -8.12265e+152 __imag__ cr = 1.36845e-310 s11 $ gcc -o complex complex.c s11 $ ./complex __real__ cd = 1 __imag__ cd = 2 __real__ ce = 2 __imag__ ce = 3 __real__ cr = -4 __imag__ cr = 7 Running complex under gdb reveals that __muldc3 expects its first argument at 0x8(%ebp) while it actually is at 0xc(%ebp): S8: 0x080507a1 <__muldc3+1>: mov %esp,%ebp 0x080507a3 <__muldc3+3>: push %ebx 0x080507a4 <__muldc3+4>: sub $0x3c,%esp 0x080507a7 <__muldc3+7>: fldl 0x8(%ebp) 0x080507aa <__muldc3+10>: fldl 0x10(%ebp) 0x080507ad <__muldc3+13>: fldl 0x18(%ebp) 0x080507b0 <__muldc3+16>: fldl 0x20(%ebp) S11: 0x08050da0 <__muldc3+0>: sub $0x3c,%esp 0x08050da3 <__muldc3+3>: fldl 0x44(%esp) 0x08050da7 <__muldc3+7>: fldl 0x4c(%esp) 0x08050dab <__muldc3+11>: fldl 0x54(%esp) 0x08050daf <__muldc3+15>: fldl 0x5c(%esp) This is due to the fact that while Solaris 10+ uses ix86_sol10_return_in_memory, Solaris 8 and 9 use the default return_in_memory_32. At least if I use the S10 function on Solaris 8/9, too, everything is fine, and I cannot at all imagine that the Solaris 2/x86 32-bit ABI should have changed incompatibly between Solaris 9 and 10. To be honest, I don't really understand how this can cause the observed caller/callee mismatch, but obviously it does. Right now, return_in_memory_32 and ix86_sol10_return_in_memory are inconsistent in other areas (like no AVX support, cf. PR target/44452), so I plan to address this by merging the two functions to avoid such discrepancies in the future. Bootstrapped without regressions on Solaris 8 to 11/x86, ok for mainline (and the 4.4 and 4.5 branches after testing)? Thanks. Rainer 2010-06-19 Rainer Orth * config/i386/i386.c (ix86_sol10_return_in_memory): Rename to ix86_solaris_return_in_memory. * config/i386-protos.h: Reflect this. * config/i386/vx-common.h (SUBTARGET_RETURN_IN_MEMORY): Likewise. * config/i386/sol2-10.h (SUBTARGET_RETURN_IN_MEMORY): Likewise. Move ... * config/i386/sol2.h (SUBTARGET_RETURN_IN_MEMORY): ... here. diff -r 2bb0d54482e5 gcc/config/i386/i386-protos.h --- a/gcc/config/i386/i386-protos.h Fri Jul 09 12:46:32 2010 +0200 +++ b/gcc/config/i386/i386-protos.h Fri Jul 09 12:51:21 2010 +0200 @@ -141,7 +141,7 @@ extern bool ix86_function_arg_regno_p (int); extern void ix86_asm_output_function_label (FILE *, const char *, tree); extern int ix86_function_arg_boundary (enum machine_mode, tree); -extern bool ix86_sol10_return_in_memory (const_tree,const_tree); +extern bool ix86_solaris_return_in_memory (const_tree,const_tree); extern rtx ix86_force_to_memory (enum machine_mode, rtx); extern void ix86_free_from_memory (enum machine_mode); extern enum calling_abi ix86_cfun_abi (void); diff -r 2bb0d54482e5 gcc/config/i386/i386.c --- a/gcc/config/i386/i386.c Fri Jul 09 12:46:32 2010 +0200 +++ b/gcc/config/i386/i386.c Fri Jul 09 12:51:21 2010 +0200 @@ -6871,12 +6871,12 @@ } /* Return false iff TYPE is returned in memory. This version is used - on Solaris 10. It is similar to the generic ix86_return_in_memory, + on Solaris 2. It is similar to the generic ix86_return_in_memory, but differs notably in that when MMX is available, 8-byte vectors are returned in memory, rather than in MMX registers. */ bool -ix86_sol10_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) +ix86_solaris_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) { int size; enum machine_mode mode = type_natural_mode (type, NULL); diff -r 2bb0d54482e5 gcc/config/i386/sol2-10.h --- a/gcc/config/i386/sol2-10.h Fri Jul 09 12:46:32 2010 +0200 +++ b/gcc/config/i386/sol2-10.h Fri Jul 09 12:51:21 2010 +0200 @@ -145,7 +145,3 @@ #undef TARGET_ASM_NAMED_SECTION #define TARGET_ASM_NAMED_SECTION i386_solaris_elf_named_section - -#undef SUBTARGET_RETURN_IN_MEMORY -#define SUBTARGET_RETURN_IN_MEMORY(TYPE, FNTYPE) \ - ix86_sol10_return_in_memory (TYPE, FNTYPE) diff -r 2bb0d54482e5 gcc/config/i386/sol2.h --- a/gcc/config/i386/sol2.h Fri Jul 09 12:46:32 2010 +0200 +++ b/gcc/config/i386/sol2.h Fri Jul 09 12:51:21 2010 +0200 @@ -140,6 +140,10 @@ /* Register the Solaris-specific #pragma directives. */ #define REGISTER_SUBTARGET_PRAGMAS() solaris_register_pragmas () +#undef SUBTARGET_RETURN_IN_MEMORY +#define SUBTARGET_RETURN_IN_MEMORY(TYPE, FNTYPE) \ + ix86_solaris_return_in_memory (TYPE, FNTYPE) + /* Output a simple call for .init/.fini. */ #define ASM_OUTPUT_CALL(FILE, FN) \ do \ diff -r 2bb0d54482e5 gcc/config/i386/vx-common.h --- a/gcc/config/i386/vx-common.h Fri Jul 09 12:46:32 2010 +0200 +++ b/gcc/config/i386/vx-common.h Fri Jul 09 12:51:21 2010 +0200 @@ -1,5 +1,5 @@ /* IA32 VxWorks and VxWorks AE target definitions. - Copyright (C) 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -20,7 +20,7 @@ #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN) -/* VxWorks uses the same ABI as Solaris 10. */ +/* VxWorks uses the same ABI as Solaris 2. */ #define SUBTARGET_RETURN_IN_MEMORY(TYPE, FNTYPE) \ - ix86_sol10_return_in_memory (TYPE, FNTYPE) + ix86_solaris_return_in_memory (TYPE, FNTYPE)