From: Richard Sandiford Date: Sun, 14 Sep 2003 10:07:51 +0000 (+0000) Subject: function.c (STACK_BYTES): Move definition to head of file. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=975f381876699c55c3802e2d102eb0d9e1dcd6b3;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 92fc97db56e..9c4ae39a385 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2003-09-14 Richard Sandiford + + * 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 * objc/objc-act.c: Convert to ISO C90 prototypes. diff --git a/gcc/function.c b/gcc/function.c index 8227139d256..29c84222071 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -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, - ¤t_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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4d0d6fe916d..b2f7a2fefc2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-09-14 Richard Sandiford + + * gcc.c-torture/execute/20030914-[12].c: New tests. + 2003-09-11 Nathan Sidwell PR c++/11788 diff --git a/gcc/testsuite/gcc.c-torture/execute/20030914-1.c b/gcc/testsuite/gcc.c-torture/execute/20030914-1.c new file mode 100644 index 00000000000..ab1c1541df0 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20030914-1.c @@ -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); +} diff --git a/gcc/testsuite/gcc.c-torture/execute/20030914-2.c b/gcc/testsuite/gcc.c-torture/execute/20030914-2.c new file mode 100644 index 00000000000..38a81982ff2 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20030914-2.c @@ -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); +}