diff options
author | Jan Hubicka <jh@suse.cz> | 2000-03-29 13:10:44 +0000 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2000-03-29 13:10:44 +0000 |
commit | f73ad30e011e5fa64e634e576bd6297b667f9364 (patch) | |
tree | f907c433c28df15d0d9341afb54624130db44220 /gcc/calls.c | |
parent | db8cb48e64684efc2956b1229e9b1fbac558229a (diff) | |
download | gcc-f73ad30e011e5fa64e634e576bd6297b667f9364.zip gcc-f73ad30e011e5fa64e634e576bd6297b667f9364.tar.gz gcc-f73ad30e011e5fa64e634e576bd6297b667f9364.tar.bz2 |
Convert ACCUMULATE_OUTGOING_ARGS to an expression.
* calls.c (PUSH_ARGS_REVERSED) Change to expression.
(ACCUMULATE_OUTGOING_ARGS, PUSH_ARGS): Provide default value.
(struct arg_data): Remove #ifdef ACCUMULATE_OUTGOING_ARGS.
(save_fixed_argument_area, restore_fixed_argument_area):
conditionize by #ifdef REG_PARM_STACK_SPACE only.
(emit_call): Change #ifdefs on ACCUMULATE_OUTGOING_ARGS
to conditions, handle RETURN_POPS_ARGS on ACCUMULATE_OUTGOING_ARGS.
(precompute_register_parameters): Avoid #ifdefs on
ACCUMULATE_OUTGOING_ARGS and PUSH_ARGS_REVERSED.
(stire_one_args): Likewise.
(expand_call): Likewise; conditionize PUSH_ROUNDING code by PUSH_ARGS.
(emit_library_call_value_1): Likewise.
(compute_argument_block_size): Align to STACK_BOUNDARY only for
ACCUMULATE_OUTGOING_ARGS.
* combine.c (ACCUMULATE_OUTGOING_ARGS, PUSH_ARGS): Provide default
value.
(nonzero_bits): Conditionize PUSH_ROUNDING code by USE_PUSH.
(use_crosses_set_p): Likewise.
* all targets (ACCUMULATE_OUTGOING_ARGS define): Change to
#define ACCUMULATE_OUTGOING_ARGS 1.
* i386.c (ix86_compute_frame_size): Handle ACCUMULATE_OUTGOING_ARGS
frames.
* i386.h (MASK_NO_PUSH_ARGS, MASK_ACCUMULATE_OUTGOING_ARGS): New
constants.
(TARGET_PUSH_ARGS, TARGET_ACCUMULATE_OUTGOING_ARGS): New macros.
(TARGET_SWITCHES): Add push-args, no-push-args,
accumulate-outgoing-args and no-accumulate-outgoing-args.
(ACCUMULATE_OUTGOING_ARGS, PUSH_ARGS): New macro.
* expr.c (ACCUMULATE_OUTGONG_ARGS, PUSH_ARGS): Provide default.
(push_block): Avoid ifdefs on ACCUMULATE_OUTGONG_ARGS
and PUSH_ROUNDING.
(emit_push_insn): Likewise.
* final.c (ACCUMULATE_OUTGOING_ARGS): Provide default.
(final_scan_insn): Avoid ifdefs on ACCUMULATE_OUTGOING_ARGS.
* function.c (ACCUMULATE_OUTGOING_ARGS): Provide default.
(STACK_DYNAMIC_OFFSET): Define correctly for both
ACCUMULATE_OUTGOING_ARGS and normal mode.
* invoke.texi (-mpush_args, -maccumulate-outgoing-args): Document.
* tm.texi (PUSH_ARGS): Document.
(ACCUMULATE_OUTGOING_ARGS, PUSH_ROUNDING): Update documentation.
From-SVN: r32803
Diffstat (limited to 'gcc/calls.c')
-rw-r--r-- | gcc/calls.c | 956 |
1 files changed, 483 insertions, 473 deletions
diff --git a/gcc/calls.c b/gcc/calls.c index a978dd4..b0a65f1 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -32,6 +32,19 @@ Boston, MA 02111-1307, USA. */ #include "output.h" #include "tm_p.h" +#ifndef ACCUMULATE_OUTGOING_ARGS +#define ACCUMULATE_OUTGOING_ARGS 0 +#endif + +/* Supply a default definition for PUSH_ARGS. */ +#ifndef PUSH_ARGS +#ifdef PUSH_ROUNDING +#define PUSH_ARGS !ACCUMULATE_OUTGOING_ARGS +#else +#define PUSH_ARGS 0 +#endif +#endif + #if !defined FUNCTION_OK_FOR_SIBCALL #define FUNCTION_OK_FOR_SIBCALL(DECL) 1 #endif @@ -49,11 +62,15 @@ Boston, MA 02111-1307, USA. */ #ifdef PUSH_ROUNDING #if defined (STACK_GROWS_DOWNWARD) != defined (ARGS_GROW_DOWNWARD) -#define PUSH_ARGS_REVERSED /* If it's last to first */ +#define PUSH_ARGS_REVERSED PUSH_ARGS #endif #endif +#ifndef PUSH_ARGS_REVERSED +#define PUSH_ARGS_REVERSED 0 +#endif + /* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits. */ #define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) @@ -101,10 +118,8 @@ struct arg_data differ from STACK if this arg pads downward. This location is known to be aligned to FUNCTION_ARG_BOUNDARY. */ rtx stack_slot; -#ifdef ACCUMULATE_OUTGOING_ARGS /* Place that this stack area has been saved, if needed. */ rtx save_area; -#endif /* If an argument's alignment does not permit direct copying into registers, copy in smaller-sized pieces into pseudos. These are stored in a block pointed to by this field. The next field says how many @@ -116,7 +131,6 @@ struct arg_data struct args_size alignment_pad; }; -#ifdef ACCUMULATE_OUTGOING_ARGS /* A vector of one char per byte of stack space. A byte if non-zero if the corresponding stack location has been used. This vector is used to prevent a function call within an argument from @@ -132,7 +146,6 @@ static int highest_outgoing_arg_in_use; to make sure the object being constructed does not overlap the argument list for the constructor call. */ int stack_arg_under_construction; -#endif static int calls_function PARAMS ((tree, int)); static int calls_function_1 PARAMS ((tree, int)); @@ -176,7 +189,7 @@ static rtx emit_library_call_value_1 PARAMS ((int, rtx, rtx, int, enum machine_mode, int, va_list)); -#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE) +#ifdef REG_PARM_STACK_SPACE static rtx save_fixed_argument_area PARAMS ((int, rtx, int *, int *)); static void restore_fixed_argument_area PARAMS ((rtx, rtx, int, int)); #endif @@ -413,10 +426,8 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size, rtx struct_value_size_rtx = GEN_INT (struct_value_size); #endif rtx call_insn; -#ifndef ACCUMULATE_OUTGOING_ARGS int already_popped = 0; HOST_WIDE_INT n_popped = RETURN_POPS_ARGS (fndecl, funtype, stack_size); -#endif /* Ensure address is valid. SYMBOL_REF is already valid, so no need, and we don't want to load it into a register as an optimization, @@ -424,7 +435,6 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size, if (GET_CODE (funexp) != SYMBOL_REF) funexp = memory_address (FUNCTION_MODE, funexp); -#ifndef ACCUMULATE_OUTGOING_ARGS #if defined (HAVE_sibcall_pop) && defined (HAVE_sibcall_value_pop) if ((ecf_flags & ECF_SIBCALL) && HAVE_sibcall_pop && HAVE_sibcall_value_pop @@ -459,7 +469,7 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size, even if the call has no arguments to pop. */ #if defined (HAVE_call) && defined (HAVE_call_value) if (HAVE_call && HAVE_call_value && HAVE_call_pop && HAVE_call_value_pop - && n_popped > 0) + && n_popped > 0) #else if (HAVE_call_pop && HAVE_call_value_pop) #endif @@ -483,7 +493,6 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size, } else #endif -#endif #if defined (HAVE_sibcall) && defined (HAVE_sibcall_value) if ((ecf_flags & ECF_SIBCALL) @@ -559,18 +568,6 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size, if the context of the call as a whole permits. */ inhibit_defer_pop = old_inhibit_defer_pop; -#ifndef ACCUMULATE_OUTGOING_ARGS - /* If returning from the subroutine does not automatically pop the args, - we need an instruction to pop them sooner or later. - Perhaps do it now; perhaps just record how much space to pop later. - - If returning from the subroutine does pop the args, indicate that the - stack pointer will be changed. */ - - /* The space for the args is no longer waiting for the call; either it - was popped by the call, or it'll be popped below. */ - arg_space_so_far -= rounded_stack_size; - if (n_popped > 0) { if (!already_popped) @@ -582,15 +579,41 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size, rounded_stack_size_rtx = GEN_INT (rounded_stack_size); } - if (rounded_stack_size != 0) + if (!ACCUMULATE_OUTGOING_ARGS) { - if (flag_defer_pop && inhibit_defer_pop == 0 - && !(ecf_flags & ECF_IS_CONST)) - pending_stack_adjust += rounded_stack_size; - else - adjust_stack (rounded_stack_size_rtx); + /* If returning from the subroutine does not automatically pop the args, + we need an instruction to pop them sooner or later. + Perhaps do it now; perhaps just record how much space to pop later. + + If returning from the subroutine does pop the args, indicate that the + stack pointer will be changed. */ + + /* The space for the args is no longer waiting for the call; either it + was popped by the call, or it'll be popped below. */ + arg_space_so_far -= rounded_stack_size - n_popped; + + if (rounded_stack_size != 0) + { + if (flag_defer_pop && inhibit_defer_pop == 0 + && !(ecf_flags & ECF_IS_CONST)) + pending_stack_adjust += rounded_stack_size; + else + adjust_stack (rounded_stack_size_rtx); + } } -#endif + /* When we accumulate outgoing args, we must avoid any stack manipulations. + Restore the stack pointer to its original value now. Usually + ACCUMULATE_OUTGOING_ARGS targets don't get here, but there are exceptions. + On i386 ACCUMULATE_OUTGOING_ARGS can be enabled on demand, and + popping variants of functions exist as well. + + ??? We may optimize similar to defer_pop above, but it is + probably not worthwhile. + + ??? It will be worthwhile to enable combine_stack_adjustments even for + such machines. */ + else if (n_popped) + anti_adjust_stack (GEN_INT (n_popped)); } /* Determine if the function identified by NAME and FNDECL is one with @@ -774,7 +797,7 @@ precompute_register_parameters (num_actuals, args, reg_parm_seen) } } -#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE) +#ifdef REG_PARM_STACK_SPACE /* The argument list is the property of the called routine and it may clobber it. If the fixed area has been used for previous @@ -1013,13 +1036,16 @@ initialize_argument_information (num_actuals, args, args_size, n_named_args, We fill up ARGS from the front or from the back if necessary so that in any case the first arg to be pushed ends up at the front. */ -#ifdef PUSH_ARGS_REVERSED - i = num_actuals - 1, inc = -1; - /* In this case, must reverse order of args - so that we compute and push the last arg first. */ -#else - i = 0, inc = 1; -#endif + if (PUSH_ARGS_REVERSED) + { + i = num_actuals - 1, inc = -1; + /* In this case, must reverse order of args + so that we compute and push the last arg first. */ + } + else + { + i = 0, inc = 1; + } /* I counts args in order (to be) pushed; ARGPOS counts in order written. */ for (p = actparms, argpos = 0; p; p = TREE_CHAIN (p), i += inc, argpos++) @@ -1262,6 +1288,14 @@ compute_argument_block_size (reg_parm_stack_space, args_size, { int unadjusted_args_size = args_size->constant; + /* For accumulate outgoing args mode we don't need to align, since the frame + will be already aligned. Align to STACK_BOUNDARY in order to prevent + backends from generating missaligned frame sizes. */ +#ifdef STACK_BOUNDARY + if (ACCUMULATE_OUTGOING_ARGS && preferred_stack_boundary > STACK_BOUNDARY) + preferred_stack_boundary = STACK_BOUNDARY; +#endif + /* Compute the actual size of the argument block required. The variable and constant sizes must be combined, the size may have to be rounded, and there may be a minimum required size. */ @@ -1692,9 +1726,7 @@ expand_call (exp, target, ignore) or 0 if the function is computed (not known by name). */ tree fndecl = 0; char *name = 0; -#ifdef ACCUMULATE_OUTGOING_ARGS rtx before_call; -#endif rtx insn; int try_tail_call; int pass; @@ -1744,11 +1776,7 @@ expand_call (exp, target, ignore) So the entire argument block must then be preallocated (i.e., we ignore PUSH_ROUNDING in that case). */ -#ifdef PUSH_ROUNDING - int must_preallocate = 0; -#else - int must_preallocate = 1; -#endif + int must_preallocate = !PUSH_ARGS; /* Size of the stack reserved for parameter registers. */ int reg_parm_stack_space = 0; @@ -1777,18 +1805,16 @@ expand_call (exp, target, ignore) int is_volatile = 0; /* Nonzero if this is a call to a function that won't throw an exception. */ int nothrow = TREE_NOTHROW (exp); -#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE) +#ifdef REG_PARM_STACK_SPACE /* Define the boundary of the register parm stack space that needs to be save, if any. */ int low_to_save = -1, high_to_save; rtx save_area = 0; /* Place that it is saved */ #endif -#ifdef ACCUMULATE_OUTGOING_ARGS int initial_highest_arg_in_use = highest_outgoing_arg_in_use; char *initial_stack_usage_map = stack_usage_map; int old_stack_arg_under_construction = 0; -#endif rtx old_stack_level = 0; int old_pending_adj = 0; @@ -1866,8 +1892,8 @@ expand_call (exp, target, ignore) #endif #endif -#if defined(PUSH_ROUNDING) && ! defined(OUTGOING_REG_PARM_STACK_SPACE) - if (reg_parm_stack_space > 0) +#ifndef OUTGOING_REG_PARM_STACK_SPACE + if (reg_parm_stack_space > 0 && PUSH_ARGS) must_preallocate = 1; #endif @@ -1935,9 +1961,7 @@ expand_call (exp, target, ignore) { rtx temp; -#ifdef ACCUMULATE_OUTGOING_ARGS before_call = get_last_insn (); -#endif temp = expand_inline_function (fndecl, actparms, target, ignore, TREE_TYPE (exp), @@ -1946,64 +1970,65 @@ expand_call (exp, target, ignore) /* If inlining succeeded, return. */ if (temp != (rtx) (HOST_WIDE_INT) -1) { -#ifdef ACCUMULATE_OUTGOING_ARGS - /* If the outgoing argument list must be preserved, push - the stack before executing the inlined function if it - makes any calls. */ + if (ACCUMULATE_OUTGOING_ARGS) + { + /* If the outgoing argument list must be preserved, push + the stack before executing the inlined function if it + makes any calls. */ - for (i = reg_parm_stack_space - 1; i >= 0; i--) - if (i < highest_outgoing_arg_in_use && stack_usage_map[i] != 0) - break; + for (i = reg_parm_stack_space - 1; i >= 0; i--) + if (i < highest_outgoing_arg_in_use && stack_usage_map[i] != 0) + break; - if (stack_arg_under_construction || i >= 0) - { - rtx first_insn - = before_call ? NEXT_INSN (before_call) : get_insns (); - rtx insn = NULL_RTX, seq; + if (stack_arg_under_construction || i >= 0) + { + rtx first_insn + = before_call ? NEXT_INSN (before_call) : get_insns (); + rtx insn = NULL_RTX, seq; - /* Look for a call in the inline function code. - If DECL_SAVED_INSNS (fndecl)->outgoing_args_size is - nonzero then there is a call and it is not necessary - to scan the insns. */ + /* Look for a call in the inline function code. + If DECL_SAVED_INSNS (fndecl)->outgoing_args_size is + nonzero then there is a call and it is not necessary + to scan the insns. */ - if (DECL_SAVED_INSNS (fndecl)->outgoing_args_size == 0) - for (insn = first_insn; insn; insn = NEXT_INSN (insn)) - if (GET_CODE (insn) == CALL_INSN) - break; + if (DECL_SAVED_INSNS (fndecl)->outgoing_args_size == 0) + for (insn = first_insn; insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == CALL_INSN) + break; - if (insn) - { - /* Reserve enough stack space so that the largest - argument list of any function call in the inline - function does not overlap the argument list being - evaluated. This is usually an overestimate because - allocate_dynamic_stack_space reserves space for an - outgoing argument list in addition to the requested - space, but there is no way to ask for stack space such - that an argument list of a certain length can be - safely constructed. - - Add the stack space reserved for register arguments, if - any, in the inline function. What is really needed is the - largest value of reg_parm_stack_space in the inline - function, but that is not available. Using the current - value of reg_parm_stack_space is wrong, but gives - correct results on all supported machines. */ - - int adjust = (DECL_SAVED_INSNS (fndecl)->outgoing_args_size - + reg_parm_stack_space); - - start_sequence (); - emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX); - allocate_dynamic_stack_space (GEN_INT (adjust), - NULL_RTX, BITS_PER_UNIT); - seq = get_insns (); - end_sequence (); - emit_insns_before (seq, first_insn); - emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX); + if (insn) + { + /* Reserve enough stack space so that the largest + argument list of any function call in the inline + function does not overlap the argument list being + evaluated. This is usually an overestimate because + allocate_dynamic_stack_space reserves space for an + outgoing argument list in addition to the requested + space, but there is no way to ask for stack space such + that an argument list of a certain length can be + safely constructed. + + Add the stack space reserved for register arguments, if + any, in the inline function. What is really needed is the + largest value of reg_parm_stack_space in the inline + function, but that is not available. Using the current + value of reg_parm_stack_space is wrong, but gives + correct results on all supported machines. */ + + int adjust = (DECL_SAVED_INSNS (fndecl)->outgoing_args_size + + reg_parm_stack_space); + + start_sequence (); + emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX); + allocate_dynamic_stack_space (GEN_INT (adjust), + NULL_RTX, BITS_PER_UNIT); + seq = get_insns (); + end_sequence (); + emit_insns_before (seq, first_insn); + emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX); + } } } -#endif /* If the result is equivalent to TARGET, return TARGET to simplify checks in store_expr. They can be equivalent but not equal in the @@ -2260,10 +2285,9 @@ expand_call (exp, target, ignore) If it is virtual_outgoing_args_rtx, we must copy it to another register in some cases. */ rtx temp = (GET_CODE (structure_value_addr) != REG -#ifdef ACCUMULATE_OUTGOING_ARGS - || (stack_arg_under_construction + || (ACCUMULATE_OUTGOING_ARGS + && stack_arg_under_construction && structure_value_addr == virtual_outgoing_args_rtx) -#endif ? copy_addr_to_reg (structure_value_addr) : structure_value_addr); @@ -2380,9 +2404,7 @@ expand_call (exp, target, ignore) || reg_mentioned_p (virtual_outgoing_args_rtx, structure_value_addr)) && (args_size.var -#ifndef ACCUMULATE_OUTGOING_ARGS - || args_size.constant -#endif + || (!ACCUMULATE_OUTGOING_ARGS && args_size.constant) )) structure_value_addr = copy_to_reg (structure_value_addr); @@ -2405,13 +2427,11 @@ expand_call (exp, target, ignore) emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX); old_pending_adj = pending_stack_adjust; pending_stack_adjust = 0; -#ifdef ACCUMULATE_OUTGOING_ARGS /* stack_arg_under_construction says whether a stack arg is being constructed at the old stack level. Pushing the stack gets a clean outgoing argument block. */ old_stack_arg_under_construction = stack_arg_under_construction; stack_arg_under_construction = 0; -#endif } argblock = push_block (ARGS_SIZE_RTX (args_size), 0, 0); } @@ -2433,85 +2453,87 @@ expand_call (exp, target, ignore) if (must_preallocate) { -#ifdef ACCUMULATE_OUTGOING_ARGS - /* Since the stack pointer will never be pushed, it is possible - for the evaluation of a parm to clobber something we have - already written to the stack. Since most function calls on - RISC machines do not use the stack, this is uncommon, but - must work correctly. + if (ACCUMULATE_OUTGOING_ARGS) + { + /* Since the stack pointer will never be pushed, it is possible + for the evaluation of a parm to clobber something we have + already written to the stack. Since most function calls on + RISC machines do not use the stack, this is uncommon, but + must work correctly. - Therefore, we save any area of the stack that was already - written and that we are using. Here we set up to do this by - making a new stack usage map from the old one. The actual - save will be done by store_one_arg. + Therefore, we save any area of the stack that was already + written and that we are using. Here we set up to do this by + making a new stack usage map from the old one. The actual + save will be done by store_one_arg. - Another approach might be to try to reorder the argument - evaluations to avoid this conflicting stack usage. */ + Another approach might be to try to reorder the argument + evaluations to avoid this conflicting stack usage. */ #ifndef OUTGOING_REG_PARM_STACK_SPACE - /* Since we will be writing into the entire argument area, the - map must be allocated for its entire size, not just the part - that is the responsibility of the caller. */ - needed += reg_parm_stack_space; + /* Since we will be writing into the entire argument area, the + map must be allocated for its entire size, not just the part + that is the responsibility of the caller. */ + needed += reg_parm_stack_space; #endif #ifdef ARGS_GROW_DOWNWARD - highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, - needed + 1); + highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, + needed + 1); #else - highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, - needed); + highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, + needed); #endif - stack_usage_map = (char *) alloca (highest_outgoing_arg_in_use); + stack_usage_map = (char *) alloca (highest_outgoing_arg_in_use); - if (initial_highest_arg_in_use) - bcopy (initial_stack_usage_map, stack_usage_map, - initial_highest_arg_in_use); + if (initial_highest_arg_in_use) + bcopy (initial_stack_usage_map, stack_usage_map, + initial_highest_arg_in_use); - if (initial_highest_arg_in_use != highest_outgoing_arg_in_use) - bzero (&stack_usage_map[initial_highest_arg_in_use], - (highest_outgoing_arg_in_use - - initial_highest_arg_in_use)); - needed = 0; + if (initial_highest_arg_in_use != highest_outgoing_arg_in_use) + bzero (&stack_usage_map[initial_highest_arg_in_use], + (highest_outgoing_arg_in_use + - initial_highest_arg_in_use)); + needed = 0; - /* The address of the outgoing argument list must not be copied - to a register here, because argblock would be left pointing - to the wrong place after the call to - allocate_dynamic_stack_space below. */ + /* The address of the outgoing argument list must not be copied + to a register here, because argblock would be left pointing + to the wrong place after the call to + allocate_dynamic_stack_space below. */ - argblock = virtual_outgoing_args_rtx; - -#else /* not ACCUMULATE_OUTGOING_ARGS */ - if (inhibit_defer_pop == 0) + argblock = virtual_outgoing_args_rtx; + } + else { - /* Try to reuse some or all of the pending_stack_adjust - to get this space. Maybe we can avoid any pushing. */ - if (needed > pending_stack_adjust) + if (inhibit_defer_pop == 0) { - needed -= pending_stack_adjust; - pending_stack_adjust = 0; + /* Try to reuse some or all of the pending_stack_adjust + to get this space. Maybe we can avoid any pushing. */ + if (needed > pending_stack_adjust) + { + needed -= pending_stack_adjust; + pending_stack_adjust = 0; + } + else + { + pending_stack_adjust -= needed; + needed = 0; + } } + /* Special case this because overhead of `push_block' in this + case is non-trivial. */ + if (needed == 0) + argblock = virtual_outgoing_args_rtx; else - { - pending_stack_adjust -= needed; - needed = 0; - } + argblock = push_block (GEN_INT (needed), 0, 0); + + /* We only really need to call `copy_to_reg' in the case where + push insns are going to be used to pass ARGBLOCK to a function + call in ARGS. In that case, the stack pointer changes value + from the allocation point to the call point, and hence + the value of VIRTUAL_OUTGOING_ARGS_RTX changes as well. + But might as well always do it. */ + argblock = copy_to_reg (argblock); } - /* Special case this because overhead of `push_block' in this - case is non-trivial. */ - if (needed == 0) - argblock = virtual_outgoing_args_rtx; - else - argblock = push_block (GEN_INT (needed), 0, 0); - - /* We only really need to call `copy_to_reg' in the case where - push insns are going to be used to pass ARGBLOCK to a function - call in ARGS. In that case, the stack pointer changes value - from the allocation point to the call point, and hence - the value of VIRTUAL_OUTGOING_ARGS_RTX changes as well. - But might as well always do it. */ - argblock = copy_to_reg (argblock); -#endif /* not ACCUMULATE_OUTGOING_ARGS */ } } @@ -2524,51 +2546,52 @@ expand_call (exp, target, ignore) argblock = force_reg (Pmode, force_operand (temp, NULL_RTX)); } -#ifdef ACCUMULATE_OUTGOING_ARGS - /* The save/restore code in store_one_arg handles all cases except one: - a constructor call (including a C function returning a BLKmode struct) - to initialize an argument. */ - if (stack_arg_under_construction) + if (ACCUMULATE_OUTGOING_ARGS) { + /* The save/restore code in store_one_arg handles all cases except one: + a constructor call (including a C function returning a BLKmode struct) + to initialize an argument. */ + if (stack_arg_under_construction) + { #ifndef OUTGOING_REG_PARM_STACK_SPACE - rtx push_size = GEN_INT (reg_parm_stack_space + args_size.constant); + rtx push_size = GEN_INT (reg_parm_stack_space + args_size.constant); #else - rtx push_size = GEN_INT (args_size.constant); + rtx push_size = GEN_INT (args_size.constant); #endif - if (old_stack_level == 0) - { - emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX); - old_pending_adj = pending_stack_adjust; - pending_stack_adjust = 0; - /* stack_arg_under_construction says whether a stack arg is - being constructed at the old stack level. Pushing the stack - gets a clean outgoing argument block. */ - old_stack_arg_under_construction = stack_arg_under_construction; - stack_arg_under_construction = 0; - /* Make a new map for the new argument list. */ - stack_usage_map = (char *)alloca (highest_outgoing_arg_in_use); - bzero (stack_usage_map, highest_outgoing_arg_in_use); - highest_outgoing_arg_in_use = 0; + if (old_stack_level == 0) + { + emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX); + old_pending_adj = pending_stack_adjust; + pending_stack_adjust = 0; + /* stack_arg_under_construction says whether a stack arg is + being constructed at the old stack level. Pushing the stack + gets a clean outgoing argument block. */ + old_stack_arg_under_construction = stack_arg_under_construction; + stack_arg_under_construction = 0; + /* Make a new map for the new argument list. */ + stack_usage_map = (char *)alloca (highest_outgoing_arg_in_use); + bzero (stack_usage_map, highest_outgoing_arg_in_use); + highest_outgoing_arg_in_use = 0; + } + allocate_dynamic_stack_space (push_size, NULL_RTX, BITS_PER_UNIT); } - allocate_dynamic_stack_space (push_size, NULL_RTX, BITS_PER_UNIT); + /* If argument evaluation might modify the stack pointer, copy the + address of the argument list to a register. */ + for (i = 0; i < num_actuals; i++) + if (args[i].pass_on_stack) + { + argblock = copy_addr_to_reg (argblock); + break; + } } - /* If argument evaluation might modify the stack pointer, copy the - address of the argument list to a register. */ - for (i = 0; i < num_actuals; i++) - if (args[i].pass_on_stack) - { - argblock = copy_addr_to_reg (argblock); - break; - } -#endif compute_argument_addresses (args, argblock, num_actuals); -#ifdef PUSH_ARGS_REVERSED #ifdef PREFERRED_STACK_BOUNDARY /* If we push args individually in reverse order, perform stack alignment before the first push (the last arg). */ - if (args_size.constant != unadjusted_args_size) + if (PUSH_ARGS_REVERSED && argblock == 0 + && args_size.constant != unadjusted_args_size) { /* When the stack adjustment is pending, we get better code by combining the adjustments. */ @@ -2596,7 +2619,6 @@ expand_call (exp, target, ignore) NO_DEFER_POP; } #endif -#endif /* Don't try to defer pops if preallocating, not even from the first arg, since ARGBLOCK probably refers to the SP. */ @@ -2621,11 +2643,12 @@ expand_call (exp, target, ignore) once we have started filling any specific hard regs. */ precompute_register_parameters (num_actuals, args, ®_parm_seen); -#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE) +#ifdef REG_PARM_STACK_SPACE /* Save the fixed argument area if it's part of the caller's frame and is clobbered by argument setup for this call. */ - save_area = save_fixed_argument_area (reg_parm_stack_space, argblock, - &low_to_save, &high_to_save); + if (ACCUMULATE_OUTGOING_ARGS) + save_area = save_fixed_argument_area (reg_parm_stack_space, argblock, + &low_to_save, &high_to_save); #endif /* Now store (and compute if necessary) all non-register parms. @@ -2654,22 +2677,21 @@ expand_call (exp, target, ignore) store_one_arg (&args[i], argblock, may_be_alloca, args_size.var != 0, reg_parm_stack_space); -#ifndef PUSH_ARGS_REVERSED #ifdef PREFERRED_STACK_BOUNDARY /* If we pushed args in forward order, perform stack alignment after pushing the last arg. */ /* ??? Fix for arg_space_so_far. */ - if (argblock == 0) + if (!PUSH_ARGS_REVERSED && argblock == 0) anti_adjust_stack (GEN_INT (args_size.constant - unadjusted_args_size)); #endif -#endif /* If register arguments require space on the stack and stack space was not preallocated, allocate stack space here for arguments passed in registers. */ -#if ! defined(ACCUMULATE_OUTGOING_ARGS) && defined(OUTGOING_REG_PARM_STACK_SPACE) - if (must_preallocate == 0 && reg_parm_stack_space > 0) +#ifdef OUTGOING_REG_PARM_STACK_SPACE + if (!ACCUMULATE_OUTGOING_ARGS + must_preallocate == 0 && reg_parm_stack_space > 0) anti_adjust_stack (GEN_INT (reg_parm_stack_space)); #endif @@ -2749,13 +2771,12 @@ expand_call (exp, target, ignore) /* Construct an "equal form" for the value which mentions all the arguments in order as well as the function name. */ -#ifdef PUSH_ARGS_REVERSED - for (i = 0; i < num_actuals; i++) - note = gen_rtx_EXPR_LIST (VOIDmode, args[i].initial_value, note); -#else - for (i = num_actuals - 1; i >= 0; i--) - note = gen_rtx_EXPR_LIST (VOIDmode, args[i].initial_value, note); -#endif + if (PUSH_ARGS_REVERSED) + for (i = 0; i < num_actuals; i++) + note = gen_rtx_EXPR_LIST (VOIDmode, args[i].initial_value, note); + else + for (i = num_actuals - 1; i >= 0; i--) + note = gen_rtx_EXPR_LIST (VOIDmode, args[i].initial_value, note); note = gen_rtx_EXPR_LIST (VOIDmode, funexp, note); insns = get_insns (); @@ -2939,15 +2960,12 @@ expand_call (exp, target, ignore) { emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX); pending_stack_adjust = old_pending_adj; -#ifdef ACCUMULATE_OUTGOING_ARGS stack_arg_under_construction = old_stack_arg_under_construction; highest_outgoing_arg_in_use = initial_highest_arg_in_use; stack_usage_map = initial_stack_usage_map; -#endif sibcall_failure = 1; } -#ifdef ACCUMULATE_OUTGOING_ARGS - else + else if (ACCUMULATE_OUTGOING_ARGS) { #ifdef REG_PARM_STACK_SPACE if (save_area) @@ -2981,7 +2999,6 @@ expand_call (exp, target, ignore) highest_outgoing_arg_in_use = initial_highest_arg_in_use; stack_usage_map = initial_stack_usage_map; } -#endif /* If this was alloca, record the new stack level for nonlocal gotos. Check for the handler slots since we might not have a save area @@ -3125,22 +3142,18 @@ emit_library_call_value_1 (retval, orgfun, value, no_queue, outmode, nargs, p) int is_const; int reg_parm_stack_space = 0; int nothrow; -#ifdef ACCUMULATE_OUTGOING_ARGS int needed; -#endif -#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE) +#ifdef REG_PARM_STACK_SPACE /* Define the boundary of the register parm stack space that needs to be save, if any. */ int low_to_save = -1, high_to_save = 0; rtx save_area = 0; /* Place that it is saved */ #endif -#ifdef ACCUMULATE_OUTGOING_ARGS /* Size of the stack reserved for parameter registers. */ int initial_highest_arg_in_use = highest_outgoing_arg_in_use; char *initial_stack_usage_map = stack_usage_map; -#endif #ifdef REG_PARM_STACK_SPACE #ifdef MAYBE_REG_PARM_STACK_SPACE @@ -3336,133 +3349,139 @@ emit_library_call_value_1 (retval, orgfun, value, no_queue, outmode, nargs, p) if (args_size.constant > current_function_outgoing_args_size) current_function_outgoing_args_size = args_size.constant; -#ifdef ACCUMULATE_OUTGOING_ARGS - /* Since the stack pointer will never be pushed, it is possible for - the evaluation of a parm to clobber something we have already - written to the stack. Since most function calls on RISC machines - do not use the stack, this is uncommon, but must work correctly. + if (ACCUMULATE_OUTGOING_ARGS) + { + /* Since the stack pointer will never be pushed, it is possible for + the evaluation of a parm to clobber something we have already + written to the stack. Since most function calls on RISC machines + do not use the stack, this is uncommon, but must work correctly. - Therefore, we save any area of the stack that was already written - and that we are using. Here we set up to do this by making a new - stack usage map from the old one. + Therefore, we save any area of the stack that was already written + and that we are using. Here we set up to do this by making a new + stack usage map from the old one. - Another approach might be to try to reorder the argument - evaluations to avoid this conflicting stack usage. */ + Another approach might be to try to reorder the argument + evaluations to avoid this conflicting stack usage. */ - needed = args_size.constant; + needed = args_size.constant; #ifndef OUTGOING_REG_PARM_STACK_SPACE - /* Since we will be writing into the entire argument area, the - map must be allocated for its entire size, not just the part that - is the responsibility of the caller. */ - needed += reg_parm_stack_space; + /* Since we will be writing into the entire argument area, the + map must be allocated for its entire size, not just the part that + is the responsibility of the caller. */ + needed += reg_parm_stack_space; #endif #ifdef ARGS_GROW_DOWNWARD - highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, - needed + 1); + highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, + needed + 1); #else - highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, - needed); -#endif - stack_usage_map = (char *) alloca (highest_outgoing_arg_in_use); - - if (initial_highest_arg_in_use) - bcopy (initial_stack_usage_map, stack_usage_map, - initial_highest_arg_in_use); - - if (initial_highest_arg_in_use != highest_outgoing_arg_in_use) - bzero (&stack_usage_map[initial_highest_arg_in_use], - highest_outgoing_arg_in_use - initial_highest_arg_in_use); - needed = 0; - - /* The address of the outgoing argument list must not be copied to a - register here, because argblock would be left pointing to the - wrong place after the call to allocate_dynamic_stack_space below. - */ - - argblock = virtual_outgoing_args_rtx; -#else /* not ACCUMULATE_OUTGOING_ARGS */ -#ifndef PUSH_ROUNDING - argblock = push_block (GEN_INT (args_size.constant), 0, 0); -#endif + highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, + needed); #endif + stack_usage_map = (char *) alloca (highest_outgoing_arg_in_use); + + if (initial_highest_arg_in_use) + bcopy (initial_stack_usage_map, stack_usage_map, + initial_highest_arg_in_use); + + if (initial_highest_arg_in_use != highest_outgoing_arg_in_use) + bzero (&stack_usage_map[initial_highest_arg_in_use], + highest_outgoing_arg_in_use - initial_highest_arg_in_use); + needed = 0; + + /* The address of the outgoing argument list must not be copied to a + register here, because argblock would be left pointing to the + wrong place after the call to allocate_dynamic_stack_space below. + */ + + argblock = virtual_outgoing_args_rtx; + } + else + { + if (!PUSH_ARGS) + argblock = push_block (GEN_INT (args_size.constant), 0, 0); + } -#ifdef PUSH_ARGS_REVERSED #ifdef PREFERRED_STACK_BOUNDARY /* If we push args individually in reverse order, perform stack alignment before the first push (the last arg). */ - if (argblock == 0) + if (argblock == 0 && PUSH_ARGS_REVERSED) anti_adjust_stack (GEN_INT (args_size.constant - original_args_size.constant)); #endif -#endif -#ifdef PUSH_ARGS_REVERSED - inc = -1; - argnum = nargs - 1; -#else - inc = 1; - argnum = 0; -#endif + if (PUSH_ARGS_REVERSED) + { + inc = -1; + argnum = nargs - 1; + } + else + { + inc = 1; + argnum = 0; + } -#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE) - /* The argument list is the property of the called routine and it - may clobber it. If the fixed area has been used for previous - parameters, we must save and restore it. +#ifdef REG_PARM_STACK_SPACE + if (ACCUMULATE_OUTGOING_ARGS) + { + /* The argument list is the property of the called routine and it + may clobber it. If the fixed area has been used for previous + parameters, we must save and restore it. - Here we compute the boundary of the that needs to be saved, if any. */ + Here we compute the boundary of the that needs to be saved, if any. */ #ifdef ARGS_GROW_DOWNWARD - for (count = 0; count < reg_parm_stack_space + 1; count++) + for (count = 0; count < reg_parm_stack_space + 1; count++) #else - for (count = 0; count < reg_parm_stack_space; count++) + for (count = 0; count < reg_parm_stack_space; count++) #endif - { - if (count >= highest_outgoing_arg_in_use - || stack_usage_map[count] == 0) - continue; + { + if (count >= highest_outgoing_arg_in_use + || stack_usage_map[count] == 0) + continue; - if (low_to_save == -1) - low_to_save = count; + if (low_to_save == -1) + low_to_save = count; - high_to_save = count; - } + high_to_save = count; + } - if (low_to_save >= 0) - { - int num_to_save = high_to_save - low_to_save + 1; - enum machine_mode save_mode - = mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1); - rtx stack_area; + if (low_to_save >= 0) + { + int num_to_save = high_to_save - low_to_save + 1; + enum machine_mode save_mode + = mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1); + rtx stack_area; - /* If we don't have the required alignment, must do this in BLKmode. */ - if ((low_to_save & (MIN (GET_MODE_SIZE (save_mode), - BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1))) - save_mode = BLKmode; + /* If we don't have the required alignment, must do this in BLKmode. */ + if ((low_to_save & (MIN (GET_MODE_SIZE (save_mode), + BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1))) + save_mode = BLKmode; #ifdef ARGS_GROW_DOWNWARD - stack_area = gen_rtx_MEM (save_mode, - memory_address (save_mode, - plus_constant (argblock, - - high_to_save))); + stack_area = gen_rtx_MEM (save_mode, + memory_address (save_mode, + plus_constant (argblock, + - high_to_save))); #else - stack_area = gen_rtx_MEM (save_mode, - memory_address (save_mode, - plus_constant (argblock, - low_to_save))); + stack_area = gen_rtx_MEM (save_mode, + memory_address (save_mode, + plus_constant (argblock, + low_to_save))); #endif - if (save_mode == BLKmode) - { - save_area = assign_stack_temp (BLKmode, num_to_save, 0); - emit_block_move (validize_mem (save_area), stack_area, - GEN_INT (num_to_save), - PARM_BOUNDARY / BITS_PER_UNIT); - } - else - { - save_area = gen_reg_rtx (save_mode); - emit_move_insn (save_area, stack_area); + if (save_mode == BLKmode) + { + save_area = assign_stack_temp (BLKmode, num_to_save, 0); + emit_block_move (validize_mem (save_area), stack_area, + GEN_INT (num_to_save), + PARM_BOUNDARY / BITS_PER_UNIT); + } + else + { + save_area = gen_reg_rtx (save_mode); + emit_move_insn (save_area, stack_area); + } } } #endif @@ -3477,80 +3496,75 @@ emit_library_call_value_1 (retval, orgfun, value, no_queue, outmode, nargs, p) register rtx val = argvec[argnum].value; rtx reg = argvec[argnum].reg; int partial = argvec[argnum].partial; -#ifdef ACCUMULATE_OUTGOING_ARGS - int lower_bound, upper_bound, i; -#endif + int lower_bound = 0, upper_bound = 0, i; if (! (reg != 0 && partial == 0)) { -#ifdef ACCUMULATE_OUTGOING_ARGS - /* If this is being stored into a pre-allocated, fixed-size, stack - area, save any previous data at that location. */ + if (ACCUMULATE_OUTGOING_ARGS) + { + /* If this is being stored into a pre-allocated, fixed-size, stack + area, save any previous data at that location. */ #ifdef ARGS_GROW_DOWNWARD - /* stack_slot is negative, but we want to index stack_usage_map - with positive values. */ - upper_bound = -argvec[argnum].offset.constant + 1; - lower_bound = upper_bound - argvec[argnum].size.constant; + /* stack_slot is negative, but we want to index stack_usage_map + with positive values. */ + upper_bound = -argvec[argnum].offset.constant + 1; + lower_bound = upper_bound - argvec[argnum].size.constant; #else - lower_bound = argvec[argnum].offset.constant; - upper_bound = lower_bound + argvec[argnum].size.constant; + lower_bound = argvec[argnum].offset.constant; + upper_bound = lower_bound + argvec[argnum].size.constant; #endif - for (i = lower_bound; i < upper_bound; i++) - if (stack_usage_map[i] - /* Don't store things in the fixed argument area at this point; - it has already been saved. */ - && i > reg_parm_stack_space) - break; + for (i = lower_bound; i < upper_bound; i++) + if (stack_usage_map[i] + /* Don't store things in the fixed argument area at this point; + it has already been saved. */ + && i > reg_parm_stack_space) + break; - if (i != upper_bound) - { - /* We need to make a save area. See what mode we can make it. */ - enum machine_mode save_mode - = mode_for_size (argvec[argnum].size.constant * BITS_PER_UNIT, - MODE_INT, 1); - rtx stack_area - = gen_rtx_MEM - (save_mode, - memory_address - (save_mode, - plus_constant (argblock, - argvec[argnum].offset.constant))); - argvec[argnum].save_area = gen_reg_rtx (save_mode); - - emit_move_insn (argvec[argnum].save_area, stack_area); + if (i != upper_bound) + { + /* We need to make a save area. See what mode we can make it. */ + enum machine_mode save_mode + = mode_for_size (argvec[argnum].size.constant * BITS_PER_UNIT, + MODE_INT, 1); + rtx stack_area + = gen_rtx_MEM + (save_mode, + memory_address + (save_mode, + plus_constant (argblock, + argvec[argnum].offset.constant))); + argvec[argnum].save_area = gen_reg_rtx (save_mode); + + emit_move_insn (argvec[argnum].save_area, stack_area); + } } -#endif emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0, argblock, GEN_INT (argvec[argnum].offset.constant), reg_parm_stack_space, ARGS_SIZE_RTX (alignment_pad)); -#ifdef ACCUMULATE_OUTGOING_ARGS /* Now mark the segment we just used. */ - for (i = lower_bound; i < upper_bound; i++) - stack_usage_map[i] = 1; -#endif + if (ACCUMULATE_OUTGOING_ARGS) + for (i = lower_bound; i < upper_bound; i++) + stack_usage_map[i] = 1; NO_DEFER_POP; } } -#ifndef PUSH_ARGS_REVERSED #ifdef PREFERRED_STACK_BOUNDARY /* If we pushed args in forward order, perform stack alignment after pushing the last arg. */ - if (argblock == 0) + if (argblock == 0 && !PUSH_ARGS_REVERSED) anti_adjust_stack (GEN_INT (args_size.constant - original_args_size.constant)); #endif -#endif -#ifdef PUSH_ARGS_REVERSED - argnum = nargs - 1; -#else - argnum = 0; -#endif + if (PUSH_ARGS_REVERSED) + argnum = nargs - 1; + else + argnum = 0; fun = prepare_call_address (fun, NULL_TREE, &call_fusage, 0); @@ -3647,50 +3661,51 @@ emit_library_call_value_1 (retval, orgfun, value, no_queue, outmode, nargs, p) value = hard_libcall_value (outmode); } -#ifdef ACCUMULATE_OUTGOING_ARGS -#ifdef REG_PARM_STACK_SPACE - if (save_area) + if (ACCUMULATE_OUTGOING_ARGS) { - enum machine_mode save_mode = GET_MODE (save_area); +#ifdef REG_PARM_STACK_SPACE + if (save_area) + { + enum machine_mode save_mode = GET_MODE (save_area); #ifdef ARGS_GROW_DOWNWARD - rtx stack_area - = gen_rtx_MEM (save_mode, - memory_address (save_mode, - plus_constant (argblock, - - high_to_save))); + rtx stack_area + = gen_rtx_MEM (save_mode, + memory_address (save_mode, + plus_constant (argblock, + - high_to_save))); #else - rtx stack_area - = gen_rtx_MEM (save_mode, - memory_address (save_mode, - plus_constant (argblock, low_to_save))); + rtx stack_area + = gen_rtx_MEM (save_mode, + memory_address (save_mode, + plus_constant (argblock, low_to_save))); #endif - if (save_mode != BLKmode) - emit_move_insn (stack_area, save_area); - else - emit_block_move (stack_area, validize_mem (save_area), - GEN_INT (high_to_save - low_to_save + 1), - PARM_BOUNDARY / BITS_PER_UNIT); - } + if (save_mode != BLKmode) + emit_move_insn (stack_area, save_area); + else + emit_block_move (stack_area, validize_mem (save_area), + GEN_INT (high_to_save - low_to_save + 1), + PARM_BOUNDARY / BITS_PER_UNIT); + } #endif - - /* If we saved any argument areas, restore them. */ - for (count = 0; count < nargs; count++) - if (argvec[count].save_area) - { - enum machine_mode save_mode = GET_MODE (argvec[count].save_area); - rtx stack_area - = gen_rtx_MEM (save_mode, - memory_address - (save_mode, - plus_constant (argblock, - argvec[count].offset.constant))); - - emit_move_insn (stack_area, argvec[count].save_area); - } + + /* If we saved any argument areas, restore them. */ + for (count = 0; count < nargs; count++) + if (argvec[count].save_area) + { + enum machine_mode save_mode = GET_MODE (argvec[count].save_area); + rtx stack_area + = gen_rtx_MEM (save_mode, + memory_address + (save_mode, + plus_constant (argblock, + argvec[count].offset.constant))); + + emit_move_insn (stack_area, argvec[count].save_area); + } - highest_outgoing_arg_in_use = initial_highest_arg_in_use; - stack_usage_map = initial_stack_usage_map; -#endif + highest_outgoing_arg_in_use = initial_highest_arg_in_use; + stack_usage_map = initial_stack_usage_map; + } return value; @@ -3847,9 +3862,7 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, rtx reg = 0; int partial = 0; int used = 0; -#ifdef ACCUMULATE_OUTGOING_ARGS int i, lower_bound = 0, upper_bound = 0; -#endif if (TREE_CODE (pval) == ERROR_MARK) return; @@ -3858,75 +3871,75 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, this argument. */ push_temp_slots (); -#ifdef ACCUMULATE_OUTGOING_ARGS - /* If this is being stored into a pre-allocated, fixed-size, stack area, - save any previous data at that location. */ - if (argblock && ! variable_size && arg->stack) + if (ACCUMULATE_OUTGOING_ARGS) { + /* If this is being stored into a pre-allocated, fixed-size, stack area, + save any previous data at that location. */ + if (argblock && ! variable_size && arg->stack) + { #ifdef ARGS_GROW_DOWNWARD - /* stack_slot is negative, but we want to index stack_usage_map - with positive values. */ - if (GET_CODE (XEXP (arg->stack_slot, 0)) == PLUS) - upper_bound = -INTVAL (XEXP (XEXP (arg->stack_slot, 0), 1)) + 1; - else - upper_bound = 0; + /* stack_slot is negative, but we want to index stack_usage_map + with positive values. */ + if (GET_CODE (XEXP (arg->stack_slot, 0)) == PLUS) + upper_bound = -INTVAL (XEXP (XEXP (arg->stack_slot, 0), 1)) + 1; + else + upper_bound = 0; - lower_bound = upper_bound - arg->size.constant; + lower_bound = upper_bound - arg->size.constant; #else - if (GET_CODE (XEXP (arg->stack_slot, 0)) == PLUS) - lower_bound = INTVAL (XEXP (XEXP (arg->stack_slot, 0), 1)); - else - lower_bound = 0; + if (GET_CODE (XEXP (arg->stack_slot, 0)) == PLUS) + lower_bound = INTVAL (XEXP (XEXP (arg->stack_slot, 0), 1)); + else + lower_bound = 0; - upper_bound = lower_bound + arg->size.constant; + upper_bound = lower_bound + arg->size.constant; #endif - for (i = lower_bound; i < upper_bound; i++) - if (stack_usage_map[i] - /* Don't store things in the fixed argument area at this point; - it has already been saved. */ - && i > reg_parm_stack_space) - break; - - if (i != upper_bound) - { - /* We need to make a save area. See what mode we can make it. */ - enum machine_mode save_mode - = mode_for_size (arg->size.constant * BITS_PER_UNIT, MODE_INT, 1); - rtx stack_area - = gen_rtx_MEM (save_mode, - memory_address (save_mode, - XEXP (arg->stack_slot, 0))); + for (i = lower_bound; i < upper_bound; i++) + if (stack_usage_map[i] + /* Don't store things in the fixed argument area at this point; + it has already been saved. */ + && i > reg_parm_stack_space) + break; - if (save_mode == BLKmode) - { - arg->save_area = assign_stack_temp (BLKmode, - arg->size.constant, 0); - MEM_SET_IN_STRUCT_P (arg->save_area, - AGGREGATE_TYPE_P (TREE_TYPE - (arg->tree_value))); - preserve_temp_slots (arg->save_area); - emit_block_move (validize_mem (arg->save_area), stack_area, - GEN_INT (arg->size.constant), - PARM_BOUNDARY / BITS_PER_UNIT); - } - else + if (i != upper_bound) { - arg->save_area = gen_reg_rtx (save_mode); - emit_move_insn (arg->save_area, stack_area); + /* We need to make a save area. See what mode we can make it. */ + enum machine_mode save_mode + = mode_for_size (arg->size.constant * BITS_PER_UNIT, MODE_INT, 1); + rtx stack_area + = gen_rtx_MEM (save_mode, + memory_address (save_mode, + XEXP (arg->stack_slot, 0))); + + if (save_mode == BLKmode) + { + arg->save_area = assign_stack_temp (BLKmode, + arg->size.constant, 0); + MEM_SET_IN_STRUCT_P (arg->save_area, + AGGREGATE_TYPE_P (TREE_TYPE + (arg->tree_value))); + preserve_temp_slots (arg->save_area); + emit_block_move (validize_mem (arg->save_area), stack_area, + GEN_INT (arg->size.constant), + PARM_BOUNDARY / BITS_PER_UNIT); + } + else + { + arg->save_area = gen_reg_rtx (save_mode); + emit_move_insn (arg->save_area, stack_area); + } } } + /* Now that we have saved any slots that will be overwritten by this + store, mark all slots this store will use. We must do this before + we actually expand the argument since the expansion itself may + trigger library calls which might need to use the same stack slot. */ + if (argblock && ! variable_size && arg->stack) + for (i = lower_bound; i < upper_bound; i++) + stack_usage_map[i] = 1; } - /* Now that we have saved any slots that will be overwritten by this - store, mark all slots this store will use. We must do this before - we actually expand the argument since the expansion itself may - trigger library calls which might need to use the same stack slot. */ - if (argblock && ! variable_size && arg->stack) - for (i = lower_bound; i < upper_bound; i++) - stack_usage_map[i] = 1; -#endif - /* If this isn't going to be placed on both the stack and in registers, set up the register and number of words. */ if (! arg->pass_on_stack) @@ -3946,7 +3959,6 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, it directly into its stack slot. Otherwise, we can. */ if (arg->value == 0) { -#ifdef ACCUMULATE_OUTGOING_ARGS /* stack_arg_under_construction is nonzero if a function argument is being evaluated directly into the outgoing argument list and expand_call must take special action to preserve the argument list @@ -3967,7 +3979,7 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, if (arg->pass_on_stack) stack_arg_under_construction++; -#endif + arg->value = expand_expr (pval, (partial || TYPE_MODE (TREE_TYPE (pval)) != arg->mode) @@ -3981,10 +3993,8 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, arg->value = convert_modes (arg->mode, TYPE_MODE (TREE_TYPE (pval)), arg->value, arg->unsignedp); -#ifdef ACCUMULATE_OUTGOING_ARGS if (arg->pass_on_stack) stack_arg_under_construction--; -#endif } /* Don't allow anything left on stack from computation |