This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: 2.95.2 argument-passing bug on PowerPC (LinuxPPC)
- To: stevenj at gil-galad dot mit dot edu,gcc-bugs at gcc dot gnu dot org,gcc-patches at gcc dot gnu dot org
- Subject: Re: 2.95.2 argument-passing bug on PowerPC (LinuxPPC)
- From: Franz Sirl <Franz dot Sirl-kernel at lauterbach dot com>
- Date: Sun, 7 Nov 1999 19:51:19 +0100
- References: <Pine.LNX.4.10.9911041510260.686-100000@gil-galad.mit.edu>
Am Don, 04 Nov 1999 schrieb stevenj@gil-galad.mit.edu:
>Dear gcc folks,
>
>I have encountered a bug in the argument-passing of gcc-2.95.2 on the
>PowerPC--in at least one case, when you pass some arguments to a
>subroutine, the arguments the subroutine actually receives are garbled. A
>short test program exhibiting the bug is attached below.
>
>Compiler version: gcc 2.95.2
>Machine: 1999 Apple PowerBook G3
>OS: LinuxPPC 1999 Q3, kernel 2.2.12
>Compiler command: gcc bug.c -o bug
>
>The test program, attached below, just calls a subroutine bug() from
>main(), printing out the argument list before and during the call. These
>two lists should match, but instead they don't; here is the output:
>
>args: A, B, 1, 2, 3, 4, 2147482552, 5, 2147482560, 6, 7, 2147482568, 8
>args: A, B, 1, 2, 3, 4, 2147482552, 5, 2147482560, 6, 7, 8, 8
>
>The second-to-last argument (a pointer) is garbled (8 instead of
>2147482568). (Slight changes to the program cause the last argument to be
>garbled instead. More changes cause no argument to be garbled.)
>
>Since the program is so short, I've also attached the assembly-language
>output on my machine. Thanks for any confirmation, help, patches, or
>pointers!
>
>Cordially,
>Steven G. Johnson
>
>--------------------------------------------------------------------
>
>extern int printf(const char *, ...);
>
>void bug(char transa, char transb, int m, int n, int k,
> double a, double *A, int fdA, double *B, int fdB,
> double b, double *C, int fdC)
>{
> printf("args: %c, %c, %d, %d, %d, %g, %ld, %d, %ld, %d, %g, %ld, %d\n",
> transa, transb, m, n, k, a, (long)A, fdA, (long)B, fdB, b,
> (long)C, fdC);
>}
>
>int main(void)
>{
> double A[1], B[1], C[1];
>
> printf("args: %c, %c, %d, %d, %d, %g, %ld, %d, %ld, %d, %g, %ld, %d\n",
> 'A', 'B', 1, 2, 3, 4.0, (long)A, 5, (long)B, 6, 7.0, (long)C, 8);
>
> bug('A', 'B', 1, 2, 3, 4.0, A, 5, B, 6, 7.0, C, 8);
>
> return 0;
>}
Hi,
this seems to be a very old platform independent bug. It was triggered on PPC
by the argument passing fixes in gcc >= 2.95.
In function.c/locate_and_pad_parm() initial_offset_ptr was aligned always
instead of offset_ptr only. Other parts of the compiler correctly discard
offset_ptr if the current argument is passed in a register and not on stack.
In the fault case the stack offset in initial_offset_ptr was 4 when a double
was passed in a register, which caused pad_to_arg_alignment() to align it to 8,
even though the argument is passed in a register and no stack alignment is
needed.
The appended patch fixes the testcase for me, I think it should be applied to
both the release and the mainline.
Steven, I'll upload a new RPM to ftp://devel.linuxppc.org/users/fsirl in a few
hours.
Franz.
Index: function.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/function.c,v
retrieving revision 1.90.4.2
diff -u -p -r1.90.4.2 function.c
--- function.c 1999/09/07 07:34:04 1.90.4.2
+++ function.c 1999/11/07 16:39:12
@@ -5274,8 +5274,8 @@ locate_and_pad_parm (passed_mode, type,
- offset_ptr->constant);
}
#else /* !ARGS_GROW_DOWNWARD */
- pad_to_arg_alignment (initial_offset_ptr, boundary);
*offset_ptr = *initial_offset_ptr;
+ pad_to_arg_alignment (offset_ptr, boundary);
#ifdef PUSH_ROUNDING
if (passed_mode != BLKmode)