This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
MIPS patch: fix execute/20020412-1.c
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 24 Sep 2003 21:15:50 +0100
- Subject: 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);