2.95.2 argument-passing bug on PowerPC (LinuxPPC)

Franz Sirl Franz.Sirl-kernel@lauterbach.com
Sun Nov 7 09:10:00 GMT 1999


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)



More information about the Gcc-patches mailing list