This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PATCH: Fix 2 PPC/SYSV varargs problems
- To: Richard Henderson <rth at cygnus dot com>
- Subject: Re: PATCH: Fix 2 PPC/SYSV varargs problems
- From: Franz Sirl <Franz dot Sirl-kernel at lauterbach dot com>
- Date: Sun, 27 Jun 1999 12:59:34 +0200
- Cc: egcs-patches at egcs dot cygnus dot com,meissner at cygnus dot com,David Edelsohn <dje at watson dot ibm dot com>,"Jeffrey A. Law" <law at cygnus dot com>
- References: <19990626210219.A532@cygnus.com>
First, there seems to be a small typo in your patch:
>! else if (sizeof (TYPE) == 8) \
>! { \
>! unsigned long __addr = (unsigned long) (__va_overflow (AP)); \
>! __ptr = (TYPE *)((__addr | 7) & -8); \
I believe you meant to write (__addr + 7). After this change your testcase
works as expected. BTW, the use of rlwinm here simply clears the lowest 3 bits.
>On Mon, May 10, 1999 at 11:14:10PM +0200, Franz Sirl wrote:
>> + else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
>> + cum->sysv_ovf_fwords += RS6000_ARG_SIZE (mode, type, 1);
>> +
>
>This isn't right, as you wind up with doubles not being aligned
>in the argument list. But I also see what lead you to believe
>this might be right -- function_arg_boundary is broken too.
Hmm, I think you missed one purpose of this change. What happens if one or more
integer register are used for varargs passing, but 9 or more floats are earlier
in the argument list? Then the original code in expand_builtin_saveregs()
and elsewhere looses because it only checks words, which includes the float
overflow args. Somehow the use of overflow_arg_area for integer or float
overflow arguments has to be recorded separately. The testcase for this
behaviour is:
#include <stdarg.h>
int i8;
double f9;
void bar(int i1, int i2, int i3, int i4, int i5, int i6, int i7,
double f1, double f2, double f3, double f4, double f5, double f6,
double f7, double f8, ...)
{
va_list args;
va_start(args, f8);
i8 = va_arg(args, int);
f9 = va_arg(args, double);
va_end(args);
}
void foo()
{
bar(1, 2, 3, 4, 5, 6, 7, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
8, 9.0, 9, 10.0);
}
i8 should be passed in register r10 by foo() and bar() thinks it is in
overflow_arg_area. So essentially we have 2 bugs here, the caller doesn't
pass the arguments correctly _and_ expand_builtin_saveregs() doesn't setup
the va_list correctly (you copied this bug from the original va-ppc.h while
implementing expand_builtin_saveregs).
Since you seem to say that words counting is correct as-is, we probably have
to go back to my 1st version of this patch with all the (words -
sysv_ovf_fwords) constructs in there and words and sysv_ovf_fwords incremented
simultaneously. But I thought I had checked all uses of words and my 2nd
version shouldn't change the compiler behaviour in respect to how the code in
rs6000.c uses words.
Franz.