diff options
author | Richard Sandiford <rsandifo@redhat.com> | 2003-09-14 10:07:51 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2003-09-14 10:07:51 +0000 |
commit | 975f381876699c55c3802e2d102eb0d9e1dcd6b3 (patch) | |
tree | 8d4bc0c5b6278c4ecbb34d3389d0f7d3a7bc36f4 /gcc/function.c | |
parent | 011d50d946a1c854e19d0be0aff69de6f97f6eaf (diff) | |
download | gcc-975f381876699c55c3802e2d102eb0d9e1dcd6b3.zip gcc-975f381876699c55c3802e2d102eb0d9e1dcd6b3.tar.gz gcc-975f381876699c55c3802e2d102eb0d9e1dcd6b3.tar.bz2 |
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
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 71 |
1 files changed, 50 insertions, 21 deletions
diff --git a/gcc/function.c b/gcc/function.c index 8227139..29c8422 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; |