diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 109f81282ea..7db2bc046ee 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2000-04-28 Richard Henderson + Jan Hubicka + + * calls.c (combine_pending_stack_adjustment_and_call): Return the + adjustment; don't do the stack adjust. + (expand_call): Call compute_argument_block_size right before + allocating the block; update comment; don't do alignment sanity + checking for sibling call; use args_size instead of + unadjusted_args_size before args_size is adjusted. Use + combine_pending_stack_adjustment_and_call to compute stack adjust + for must_preallocate case. + + * expr.c (push_block): Remove shadow `temp' in inner scope. + 2000-04-28 Jason Merrill * toplev.c (rest_of_compilation): Call diff --git a/gcc/calls.c b/gcc/calls.c index 56e18f8f231..eff0042422f 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -210,7 +210,7 @@ static int special_function_p PARAMS ((tree, int)); static int flags_from_decl_or_type PARAMS ((tree)); static rtx try_to_integrate PARAMS ((tree, tree, rtx, int, tree, rtx)); -static void combine_pending_stack_adjustment_and_call +static int combine_pending_stack_adjustment_and_call PARAMS ((int, struct args_size *, int)); #ifdef REG_PARM_STACK_SPACE @@ -1860,13 +1860,13 @@ try_to_integrate (fndecl, actparms, target, ignore, type, structure_value_addr) /* We need to pop PENDING_STACK_ADJUST bytes. But, if the arguments wouldn't fill up an even multiple of PREFERRED_UNIT_STACK_BOUNDARY bytes, then we would need to push some additional bytes to pad the - arguments. So, we adjust the stack pointer by an amount that will - leave the stack under-aligned by UNADJUSTED_ARGS_SIZE bytes. Then, - when the arguments are pushed the stack will be perfectly aligned. - ARGS_SIZE->CONSTANT is set to the number of bytes that should be - popped after the call. */ + arguments. So, we compute an adjust to the stack pointer for an + amount that will leave the stack under-aligned by UNADJUSTED_ARGS_SIZE + bytes. Then, when the arguments are pushed the stack will be perfectly + aligned. ARGS_SIZE->CONSTANT is set to the number of bytes that should + be popped after the call. Returns the adjustment. */ -static void +static int combine_pending_stack_adjustment_and_call (unadjusted_args_size, args_size, preferred_unit_stack_boundary) @@ -1910,9 +1910,7 @@ combine_pending_stack_adjustment_and_call (unadjusted_args_size, args_size->constant = pending_stack_adjust - adjustment + unadjusted_args_size; - /* Push the right number of bytes. */ - pending_stack_adjust = adjustment; - do_pending_stack_adjust (); + return adjustment; } /* Generate all the code for a function call @@ -2504,19 +2502,9 @@ expand_call (exp, target, ignore) sibcall_failure = 1; } - /* 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. When generating a sibcall - pattern, do not round up, since we'll be re-using whatever space our - caller provided. */ - unadjusted_args_size - = compute_argument_block_size (reg_parm_stack_space, &args_size, - (pass == 0 ? 0 - : preferred_stack_boundary)); - /* If the callee pops its own arguments, then it must pop exactly the same number of arguments as the current function. */ - if (RETURN_POPS_ARGS (fndecl, funtype, unadjusted_args_size) + if (RETURN_POPS_ARGS (fndecl, funtype, args_size.constant) != RETURN_POPS_ARGS (current_function_decl, TREE_TYPE (current_function_decl), current_function_args_size)) @@ -2548,14 +2536,25 @@ expand_call (exp, target, ignore) if (flags & (ECF_CONST | ECF_PURE | ECF_MALLOC)) start_sequence (); + /* 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. When generating a sibcall + pattern, do not round up, since we'll be re-using whatever space our + caller provided. */ + unadjusted_args_size + = compute_argument_block_size (reg_parm_stack_space, &args_size, + (pass == 0 ? 0 + : preferred_stack_boundary)); + old_stack_allocated = stack_pointer_delta - pending_stack_adjust; + /* The argument block when performing a sibling call is the incoming argument block. */ if (pass == 0) argblock = virtual_incoming_args_rtx; + /* If we have no actual push instructions, or shouldn't use them, make space for all args right now. */ - else if (args_size.var != 0) { if (old_stack_level == 0) @@ -2644,20 +2643,36 @@ expand_call (exp, target, ignore) if (inhibit_defer_pop == 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) + to get this space. */ + needed + = (combine_pending_stack_adjustment_and_call + (unadjusted_args_size, + &args_size, + preferred_unit_stack_boundary)); + + /* combine_pending_stack_adjustment_and_call computes + an adjustment before the arguments are allocated. + Account for them and see whether or not the stack + needs to go up or down. */ + needed = unadjusted_args_size - needed; + + if (needed < 0) { - needed -= pending_stack_adjust; - pending_stack_adjust = 0; - } - else - { - pending_stack_adjust -= needed; + /* We're releasing stack space. */ + /* ??? We can avoid any adjustment at all if we're + already aligned. FIXME. */ + pending_stack_adjust = -needed; + do_pending_stack_adjust (); needed = 0; } + else + /* We need to allocate space. We'll do that in + push_block below. */ + pending_stack_adjust = 0; } - /* Special case this because overhead of `push_block' in this - case is non-trivial. */ + + /* Special case this because overhead of `push_block' in + this case is non-trivial. */ if (needed == 0) argblock = virtual_outgoing_args_rtx; else @@ -2673,35 +2688,41 @@ expand_call (exp, target, ignore) argblock = copy_to_reg (argblock); /* 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. */ + 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); #endif if (old_stack_level == 0) { - emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX); + 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 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); + 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. */ + /* 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) { @@ -2725,10 +2746,14 @@ expand_call (exp, target, ignore) if (pending_stack_adjust && ! (flags & (ECF_CONST | ECF_PURE)) && ! inhibit_defer_pop) - combine_pending_stack_adjustment_and_call - (unadjusted_args_size, - &args_size, - preferred_unit_stack_boundary); + { + pending_stack_adjust + = (combine_pending_stack_adjustment_and_call + (unadjusted_args_size, + &args_size, + preferred_unit_stack_boundary)); + do_pending_stack_adjust (); + } else if (argblock == 0) anti_adjust_stack (GEN_INT (args_size.constant - unadjusted_args_size)); @@ -2862,8 +2887,8 @@ expand_call (exp, target, ignore) now! */ #ifdef PREFERRED_STACK_BOUNDARY - /* Stack must to be properly aligned now. */ - if (stack_pointer_delta & (preferred_stack_boundary / BITS_PER_UNIT - 1)) + /* Stack must be properly aligned now. */ + if (pass && stack_pointer_delta % preferred_unit_stack_boundary) abort(); #endif @@ -3767,7 +3792,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) ? hard_libcall_value (outmode) : NULL_RTX); #ifdef PREFERRED_STACK_BOUNDARY - /* Stack must to be properly aligned now. */ + /* Stack must be properly aligned now. */ if (stack_pointer_delta & (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT - 1)) abort(); #endif diff --git a/gcc/expr.c b/gcc/expr.c index a0b8465cab8..bc1bbf4bfdd 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -2840,7 +2840,7 @@ push_block (size, extra, below) anti_adjust_stack (size); else { - rtx temp = copy_to_mode_reg (Pmode, size); + temp = copy_to_mode_reg (Pmode, size); if (extra != 0) temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra), temp, 0, OPTAB_LIB_WIDEN); @@ -2857,7 +2857,6 @@ push_block (size, extra, below) if (1) #endif { - /* Return the lowest stack address when STACK or ARGS grow downward and we are not aaccumulating outgoing arguments (the c4x port uses such conventions). */