This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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); }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]