This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[3.3] Patch for PR 11084
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: echristo at redhat dot com, mark at codesourcery dot com
- Date: 24 Jun 2003 18:41:25 +0100
- Subject: [3.3] Patch for PR 11084
This patch fixes 11084, a regression on mipsel-linux-gnu.
The bug was caused by an off-by-one error in the o32/o64 stdarg code.
As well as saving the variable arguments to the stack, it would save
the last named register argument as well.
I guess that would normally be harmless, but the code that saves the
registers is in the prologue expander. So if the argument is saved on
the stack after the prologue, the prologue insn will be deleted as dead,
leading to the usual abort.
It's depressingly easy to trigger the bug: see attached test case.
But this doesn't seem to the sort of case that was causing problems
in real code. The tests I've seen were large vararg functions in
which the last named argument gets spilled to the stack. In cases
like those, the bug is sensitive to register allocation and can
trigger in cases where it wouldn't before.
I think the right fix for mainline is to move this code to
setup_incoming_varargs. I'll post that patch soon. For branch, it
seems best to keep the code where it is and just fix the off-by-one
error. The value that we're trying so hard to calculate is already
lying around in the cumulative argument structure.
Tested on mipsel-linux-gnu. OK to install?
Richard
* config/mips/mips.c (mips_expand_prologue): Fix setting of regno
for the end of a variable argument list.
Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.241.2.2
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.241.2.2 mips.c
*** config/mips/mips.c 31 Jan 2003 23:51:23 -0000 1.241.2.2
--- config/mips/mips.c 23 Jun 2003 17:42:17 -0000
*************** mips_expand_prologue ()
*** 7455,7474 ****
break;
}
else
! {
! int words;
!
! if (GET_CODE (entry_parm) != REG)
! abort ();
!
! /* passed in a register, so will get homed automatically */
! if (GET_MODE (entry_parm) == BLKmode)
! words = (int_size_in_bytes (passed_type) + 3) / 4;
! else
! words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4;
!
! regno = REGNO (entry_parm) + words - 1;
! }
}
else
{
--- 7455,7461 ----
break;
}
else
! regno = GP_ARG_FIRST + args_so_far.num_gprs;
}
else
{
*** /dev/null Thu Apr 11 15:25:15 2002
--- testsuite/gcc.c-torture/compile/20030623-1.c Mon Jun 23 18:38:38 2003
***************
*** 0 ****
--- 1 ----
+ void foo (const char *s, ...) { bar (&s); }