function.c (STACK_BYTES): Move definition to head of file.

* function.c (STACK_BYTES): Move definition to head of file.
	(assign_parms): Don't pass current_function_pretend_args_size
	directly to SETUP_INCOMING_VARARGS.  For partial register arguments,
	round current_function_pretend_args_size up to STACK_BYTES.  Skip any
	excess before laying out the argument.

From-SVN: r71372
This commit is contained in:
Richard Sandiford 2003-09-14 10:07:51 +00:00 committed by Richard Sandiford
parent 011d50d946
commit 975f381876
5 changed files with 109 additions and 21 deletions

View File

@ -1,3 +1,11 @@
2003-09-14 Richard Sandiford <rsandifo@redhat.com>
* function.c (STACK_BYTES): Move definition to head of file.
(assign_parms): Don't pass current_function_pretend_args_size
directly to SETUP_INCOMING_VARARGS. For partial register arguments,
round current_function_pretend_args_size up to STACK_BYTES. Skip any
excess before laying out the argument.
2003-09-14 Andreas Jaeger <aj@suse.de>
* objc/objc-act.c: Convert to ISO C90 prototypes.

View File

@ -76,6 +76,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define STACK_ALIGNMENT_NEEDED 1
#endif
#define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
/* Some systems use __main in a way incompatible with its use in gcc, in these
cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
give the same symbol without quotes for an alternative entry point. You
@ -4339,6 +4341,7 @@ assign_parms (tree fndecl)
int last_named = 0, named_arg;
int in_regs;
int partial = 0;
int pretend_bytes = 0;
/* Set LAST_NAMED if this is last named arg before last
anonymous args. */
@ -4453,10 +4456,17 @@ assign_parms (tree fndecl)
Also, indicate when RTL generation is to be suppressed. */
if (last_named && !varargs_setup)
{
int varargs_pretend_bytes = 0;
targetm.calls.setup_incoming_varargs (&args_so_far, promoted_mode,
passed_type,
&current_function_pretend_args_size, 0);
passed_type,
&varargs_pretend_bytes, 0);
varargs_setup = 1;
/* If the back-end has requested extra stack space, record how
much is needed. Do not change pretend_args_size otherwise
since it may be nonzero from an earlier partial argument. */
if (varargs_pretend_bytes > 0)
current_function_pretend_args_size = varargs_pretend_bytes;
}
/* Determine parm's home in the stack,
@ -4500,8 +4510,43 @@ assign_parms (tree fndecl)
#ifdef FUNCTION_ARG_PARTIAL_NREGS
if (entry_parm)
partial = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, promoted_mode,
passed_type, named_arg);
{
partial = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, promoted_mode,
passed_type, named_arg);
if (partial
#ifndef MAYBE_REG_PARM_STACK_SPACE
/* The caller might already have allocated stack space
for the register parameters. */
&& reg_parm_stack_space == 0
#endif
)
{
/* Part of this argument is passed in registers and part
is passed on the stack. Ask the prologue code to extend
the stack part so that we can recreate the full value.
PRETEND_BYTES is the size of the registers we need to store.
CURRENT_FUNCTION_PRETEND_ARGS_SIZE is the amount of extra
stack space that the prologue should allocate.
Internally, gcc assumes that the argument pointer is
aligned to STACK_BOUNDARY bits. This is used both for
alignment optimisations (see init_emit) and to locate
arguments that are aligned to more than PARM_BOUNDARY
bits. We must preserve this invariant by rounding
CURRENT_FUNCTION_PRETEND_ARGS_SIZE up to a stack
boundary. */
pretend_bytes = partial * UNITS_PER_WORD;
current_function_pretend_args_size
= CEIL_ROUND (pretend_bytes, STACK_BYTES);
/* If PRETEND_BYTES != CURRENT_FUNCTION_PRETEND_ARGS_SIZE,
insert the padding before the start of the first pretend
argument. */
stack_args_size.constant
= (current_function_pretend_args_size - pretend_bytes);
}
}
#endif
memset (&locate, 0, sizeof (locate));
@ -4546,17 +4591,6 @@ assign_parms (tree fndecl)
if (partial)
{
#ifndef MAYBE_REG_PARM_STACK_SPACE
/* When REG_PARM_STACK_SPACE is nonzero, stack space for
split parameters was allocated by our caller, so we
won't be pushing it in the prolog. */
if (reg_parm_stack_space == 0)
#endif
current_function_pretend_args_size
= (((partial * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
/ (PARM_BOUNDARY / BITS_PER_UNIT)
* (PARM_BOUNDARY / BITS_PER_UNIT));
/* Handle calls that pass values in multiple non-contiguous
locations. The Irix 6 ABI has examples of this. */
if (GET_CODE (entry_parm) == PARALLEL)
@ -4600,10 +4634,7 @@ assign_parms (tree fndecl)
#endif
)
{
stack_args_size.constant += locate.size.constant;
/* locate.size doesn't include the part in regs. */
if (partial)
stack_args_size.constant += current_function_pretend_args_size;
stack_args_size.constant += pretend_bytes + locate.size.constant;
if (locate.size.var)
ADD_PARM_SIZE (stack_args_size, locate.size.var);
}
@ -5175,8 +5206,6 @@ assign_parms (tree fndecl)
#endif
#endif
#define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
current_function_args_size
= ((current_function_args_size + STACK_BYTES - 1)
/ STACK_BYTES) * STACK_BYTES;

View File

@ -1,3 +1,7 @@
2003-09-14 Richard Sandiford <rsandifo@redhat.com>
* gcc.c-torture/execute/20030914-[12].c: New tests.
2003-09-11 Nathan Sidwell <nathan@codesourcery.com>
PR c++/11788

View File

@ -0,0 +1,26 @@
/* On IRIX 6, PB is passed partially in registers and partially on the
stack, with an odd number of words in the register part. Check that
the long double stack argument (PC) is still accessed properly. */
struct s { int val[16]; };
long double f (int pa, struct s pb, long double pc)
{
int i;
for (i = 0; i < 16; i++)
pc += pb.val[i];
return pc;
}
int main ()
{
struct s x;
int i;
for (i = 0; i < 16; i++)
x.val[i] = i + 1;
if (f (1, x, 10000.0L) != 10136.0L)
abort ();
exit (0);
}

View File

@ -0,0 +1,21 @@
/* On IRIX 6, PA is passed partially in registers and partially on the
stack. We therefore have two potential uses of pretend_args_size:
one for the partial argument and one for the varargs save area.
Make sure that these uses don't conflict. */
struct s { int i[18]; };
int f (struct s pa, int pb, ...)
{
return pb;
}
struct s gs;
int main ()
{
if (f (gs, 0x1234) != 0x1234)
abort ();
exit (0);
}