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]

MIPS patch: fix execute/20020412-1.c


This patch fixes execute/20020412-1.c for mips targets.  It was failing
for all ABIs except EABI.[*]

The test case passes some variable-sized structures to a variadic function:

    void foo (int size, ...);

    int main (void)
    {
      int z = 5;
      struct { char a[z]; } x, y;
      [...]
      foo (z, x, y);

Since the structures have a variable size, we pass them on the stack,
skipping over any remaining register arguments.  The problem was that
mips_va_arg didn't account for this and tried to find "x" in the
register save area.

mips_va_arg already aligns the valist before passing it on to the generic
code.  This patch adds a maximum operation as well.

Tested on mips-sgi-irix6.5{,o32}, mips64{,el}-linxu-gnu etc.  OK to install?

Richard

[*] This doesn't trigger for EABI since we pass the structures
    by reference instead.


	* config/mips/mips.c (mips_va_arg): Handle arguments that must be
	passed on the stack.

Common subdirectories: config/mips.abi/CVS and config/mips/CVS
diff -cpd config/mips.abi/mips.c config/mips/mips.c
*** config/mips.abi/mips.c	Wed Sep 10 02:01:47 2003
--- config/mips/mips.c	Sun Sep 21 08:02:13 2003
*************** mips_va_arg (tree valist, tree type)
*** 4285,4290 ****
--- 4285,4291 ----
      {
        /* Not EABI.  */
        int align;
+       HOST_WIDE_INT min_offset;
  
        /* ??? The original va-mips.h did always align, despite the fact
  	 that alignments <= UNITS_PER_WORD are preserved by the va_arg
*************** mips_va_arg (tree valist, tree type)
*** 4303,4308 ****
--- 4304,4327 ----
        t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
  		 build_int_2 (align - 1, 0));
        t = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
+ 
+       /* If arguments of type TYPE must be passed on the stack,
+ 	 set MIN_OFFSET to the offset of the first stack parameter.  */
+       if (!MUST_PASS_IN_STACK (TYPE_MODE (type), type))
+ 	min_offset = 0;
+       else if (TARGET_NEWABI)
+ 	min_offset = current_function_pretend_args_size;
+       else
+ 	min_offset = REG_PARM_STACK_SPACE (current_function_decl);
+ 
+       /* Make sure the new address is at least MIN_OFFSET bytes from
+ 	 the incoming argument pointer.  */
+       if (min_offset > 0)
+ 	t = build (MAX_EXPR, TREE_TYPE (valist), t,
+ 		   make_tree (TREE_TYPE (valist),
+ 			      plus_constant (virtual_incoming_args_rtx,
+ 					     min_offset)));
+ 
        t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
        expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  


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