(expand_call, emit_library_call, emit_library_call_value):
Allways adjust current_function_outgoing_args_size, even #ifndef ACCUMULATE_OUTGOING_ARGS. (Useful for stack overflow checking.) From-SVN: r8290
This commit is contained in:
parent
c199879dc7
commit
26a258fee2
133
gcc/calls.c
133
gcc/calls.c
|
@ -1353,98 +1353,103 @@ expand_call (exp, target, ignore)
|
||||||
}
|
}
|
||||||
argblock = push_block (ARGS_SIZE_RTX (args_size), 0, 0);
|
argblock = push_block (ARGS_SIZE_RTX (args_size), 0, 0);
|
||||||
}
|
}
|
||||||
else if (must_preallocate)
|
else
|
||||||
{
|
{
|
||||||
/* Note that we must go through the motions of allocating an argument
|
/* Note that we must go through the motions of allocating an argument
|
||||||
block even if the size is zero because we may be storing args
|
block even if the size is zero because we may be storing args
|
||||||
in the area reserved for register arguments, which may be part of
|
in the area reserved for register arguments, which may be part of
|
||||||
the stack frame. */
|
the stack frame. */
|
||||||
|
|
||||||
int needed = args_size.constant;
|
int needed = args_size.constant;
|
||||||
|
|
||||||
#ifdef ACCUMULATE_OUTGOING_ARGS
|
|
||||||
/* Store the maximum argument space used. It will be pushed by the
|
/* Store the maximum argument space used. It will be pushed by the
|
||||||
prologue.
|
prologue (if ACCUMULATE_OUTGOING_ARGS, or stack overflow checking). */
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
Another approach might be to try to reorder the argument
|
|
||||||
evaluations to avoid this conflicting stack usage. */
|
|
||||||
|
|
||||||
if (needed > current_function_outgoing_args_size)
|
if (needed > current_function_outgoing_args_size)
|
||||||
current_function_outgoing_args_size = needed;
|
current_function_outgoing_args_size = needed;
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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. */
|
||||||
|
|
||||||
#if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
|
#if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
|
||||||
/* Since we will be writing into the entire argument area, the
|
/* Since we will be writing into the entire argument area, the
|
||||||
map must be allocated for its entire size, not just the part that
|
map must be allocated for its entire size, not just the part that
|
||||||
is the responsibility of the caller. */
|
is the responsibility of the caller. */
|
||||||
needed += reg_parm_stack_space;
|
needed += reg_parm_stack_space;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARGS_GROW_DOWNWARD
|
#ifdef ARGS_GROW_DOWNWARD
|
||||||
highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
|
highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
|
||||||
needed + 1);
|
needed + 1);
|
||||||
#else
|
#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
|
#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)
|
if (initial_highest_arg_in_use)
|
||||||
bcopy (initial_stack_usage_map, stack_usage_map,
|
bcopy (initial_stack_usage_map, stack_usage_map,
|
||||||
initial_highest_arg_in_use);
|
initial_highest_arg_in_use);
|
||||||
|
|
||||||
if (initial_highest_arg_in_use != highest_outgoing_arg_in_use)
|
if (initial_highest_arg_in_use != highest_outgoing_arg_in_use)
|
||||||
bzero (&stack_usage_map[initial_highest_arg_in_use],
|
bzero (&stack_usage_map[initial_highest_arg_in_use],
|
||||||
highest_outgoing_arg_in_use - initial_highest_arg_in_use);
|
highest_outgoing_arg_in_use - initial_highest_arg_in_use);
|
||||||
needed = 0;
|
needed = 0;
|
||||||
|
|
||||||
/* The address of the outgoing argument list must not be copied to a
|
/* The address of the outgoing argument list must not be copied to a
|
||||||
register here, because argblock would be left pointing to the
|
register here, because argblock would be left pointing to the
|
||||||
wrong place after the call to allocate_dynamic_stack_space below. */
|
wrong place after the call to allocate_dynamic_stack_space below.
|
||||||
|
*/
|
||||||
|
|
||||||
argblock = virtual_outgoing_args_rtx;
|
argblock = virtual_outgoing_args_rtx;
|
||||||
|
|
||||||
#else /* not ACCUMULATE_OUTGOING_ARGS */
|
#else /* not ACCUMULATE_OUTGOING_ARGS */
|
||||||
if (inhibit_defer_pop == 0)
|
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)
|
|
||||||
{
|
{
|
||||||
needed -= pending_stack_adjust;
|
/* Try to reuse some or all of the pending_stack_adjust
|
||||||
pending_stack_adjust = 0;
|
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
|
else
|
||||||
{
|
argblock = push_block (GEN_INT (needed), 0, 0);
|
||||||
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
|
|
||||||
argblock = push_block (GEN_INT (needed), 0, 0);
|
|
||||||
|
|
||||||
/* We only really need to call `copy_to_reg' in the case where push
|
/* 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
|
insns are going to be used to pass ARGBLOCK to a function
|
||||||
call in ARGS. In that case, the stack pointer changes value
|
call in ARGS. In that case, the stack pointer changes value
|
||||||
from the allocation point to the call point, and hence
|
from the allocation point to the call point, and hence
|
||||||
the value of VIRTUAL_OUTGOING_ARGS_RTX changes as well.
|
the value of VIRTUAL_OUTGOING_ARGS_RTX changes as well.
|
||||||
But might as well always do it. */
|
But might as well always do it. */
|
||||||
argblock = copy_to_reg (argblock);
|
argblock = copy_to_reg (argblock);
|
||||||
#endif /* not ACCUMULATE_OUTGOING_ARGS */
|
#endif /* not ACCUMULATE_OUTGOING_ARGS */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef ACCUMULATE_OUTGOING_ARGS
|
#ifdef ACCUMULATE_OUTGOING_ARGS
|
||||||
/* The save/restore code in store_one_arg handles all cases except one:
|
/* The save/restore code in store_one_arg handles all cases except one:
|
||||||
a constructor call (including a C function returning a BLKmode struct)
|
a constructor call (including a C function returning a BLKmode struct)
|
||||||
|
@ -2276,9 +2281,10 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode,
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ACCUMULATE_OUTGOING_ARGS
|
|
||||||
if (args_size.constant > current_function_outgoing_args_size)
|
if (args_size.constant > current_function_outgoing_args_size)
|
||||||
current_function_outgoing_args_size = args_size.constant;
|
current_function_outgoing_args_size = args_size.constant;
|
||||||
|
|
||||||
|
#ifdef ACCUMULATE_OUTGOING_ARGS
|
||||||
args_size.constant = 0;
|
args_size.constant = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2623,9 +2629,10 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue,
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ACCUMULATE_OUTGOING_ARGS
|
|
||||||
if (args_size.constant > current_function_outgoing_args_size)
|
if (args_size.constant > current_function_outgoing_args_size)
|
||||||
current_function_outgoing_args_size = args_size.constant;
|
current_function_outgoing_args_size = args_size.constant;
|
||||||
|
|
||||||
|
#ifdef ACCUMULATE_OUTGOING_ARGS
|
||||||
args_size.constant = 0;
|
args_size.constant = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue