mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-21 08:03:41 +08:00
calls.c (precompute_arguments): New function, extracted from expand_call.
* calls.c (precompute_arguments): New function, extracted from expand_call. (expand_call): Use precompute_arguments. From-SVN: r25409
This commit is contained in:
parent
1de558ee81
commit
cc0b1adcce
@ -1,5 +1,9 @@
|
||||
Wed Feb 24 14:03:54 1999 Jeffrey A Law (law@cygnus.com)
|
||||
|
||||
* calls.c (precompute_arguments): New function, extracted from
|
||||
expand_call.
|
||||
(expand_call): Use precompute_arguments.
|
||||
|
||||
* calls.c (finalize_must_preallocate): New function, extracted from
|
||||
expand_call.
|
||||
(expand_call): Use finalize_must_preallocate.
|
||||
|
123
gcc/calls.c
123
gcc/calls.c
@ -140,6 +140,9 @@ static void store_unaligned_arguments_into_pseudos PROTO ((struct arg_data *,
|
||||
static int finalize_must_preallocate PROTO ((int, int,
|
||||
struct arg_data *,
|
||||
struct args_size *));
|
||||
static void precompute_arguments PROTO ((int, int, int,
|
||||
struct arg_data *,
|
||||
struct args_size *));
|
||||
|
||||
|
||||
#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
|
||||
@ -826,6 +829,78 @@ store_unaligned_arguments_into_pseudos (args, num_actuals)
|
||||
}
|
||||
}
|
||||
|
||||
/* Precompute parameters has needed for a function call.
|
||||
|
||||
IS_CONST indicates the target function is a pure function.
|
||||
|
||||
MUST_PREALLOCATE indicates that we must preallocate stack space for
|
||||
any stack arguments.
|
||||
|
||||
NUM_ACTUALS is the number of arguments.
|
||||
|
||||
ARGS is an array containing information for each argument; this routine
|
||||
fills in the INITIAL_VALUE and VALUE fields for each precomputed argument.
|
||||
|
||||
ARGS_SIZE contains information about the size of the arg list. */
|
||||
|
||||
static void
|
||||
precompute_arguments (is_const, must_preallocate, num_actuals, args, args_size)
|
||||
int is_const;
|
||||
int must_preallocate;
|
||||
int num_actuals;
|
||||
struct arg_data *args;
|
||||
struct args_size *args_size;
|
||||
{
|
||||
int i;
|
||||
|
||||
/* If this function call is cse'able, precompute all the parameters.
|
||||
Note that if the parameter is constructed into a temporary, this will
|
||||
cause an additional copy because the parameter will be constructed
|
||||
into a temporary location and then copied into the outgoing arguments.
|
||||
If a parameter contains a call to alloca and this function uses the
|
||||
stack, precompute the parameter. */
|
||||
|
||||
/* If we preallocated the stack space, and some arguments must be passed
|
||||
on the stack, then we must precompute any parameter which contains a
|
||||
function call which will store arguments on the stack.
|
||||
Otherwise, evaluating the parameter may clobber previous parameters
|
||||
which have already been stored into the stack. */
|
||||
|
||||
for (i = 0; i < num_actuals; i++)
|
||||
if (is_const
|
||||
|| ((args_size->var != 0 || args_size->constant != 0)
|
||||
&& calls_function (args[i].tree_value, 1))
|
||||
|| (must_preallocate
|
||||
&& (args_size->var != 0 || args_size->constant != 0)
|
||||
&& calls_function (args[i].tree_value, 0)))
|
||||
{
|
||||
/* If this is an addressable type, we cannot pre-evaluate it. */
|
||||
if (TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)))
|
||||
abort ();
|
||||
|
||||
push_temp_slots ();
|
||||
|
||||
args[i].initial_value = args[i].value
|
||||
= expand_expr (args[i].tree_value, NULL_RTX, VOIDmode, 0);
|
||||
|
||||
preserve_temp_slots (args[i].value);
|
||||
pop_temp_slots ();
|
||||
|
||||
/* ANSI doesn't require a sequence point here,
|
||||
but PCC has one, so this will avoid some problems. */
|
||||
emit_queue ();
|
||||
|
||||
args[i].initial_value = args[i].value
|
||||
= protect_from_queue (args[i].initial_value, 0);
|
||||
|
||||
if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) != args[i].mode)
|
||||
args[i].value
|
||||
= convert_modes (args[i].mode,
|
||||
TYPE_MODE (TREE_TYPE (args[i].tree_value)),
|
||||
args[i].value, args[i].unsignedp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Given the current state of MUST_PREALLOCATE and information about
|
||||
arguments to a function call in NUM_ACTUALS, ARGS and ARGS_SIZE,
|
||||
compute and return the final value for MUST_PREALLOCATE. */
|
||||
@ -1649,51 +1724,9 @@ expand_call (exp, target, ignore)
|
||||
))
|
||||
structure_value_addr = copy_to_reg (structure_value_addr);
|
||||
|
||||
/* If this function call is cse'able, precompute all the parameters.
|
||||
Note that if the parameter is constructed into a temporary, this will
|
||||
cause an additional copy because the parameter will be constructed
|
||||
into a temporary location and then copied into the outgoing arguments.
|
||||
If a parameter contains a call to alloca and this function uses the
|
||||
stack, precompute the parameter. */
|
||||
|
||||
/* If we preallocated the stack space, and some arguments must be passed
|
||||
on the stack, then we must precompute any parameter which contains a
|
||||
function call which will store arguments on the stack.
|
||||
Otherwise, evaluating the parameter may clobber previous parameters
|
||||
which have already been stored into the stack. */
|
||||
|
||||
for (i = 0; i < num_actuals; i++)
|
||||
if (is_const
|
||||
|| ((args_size.var != 0 || args_size.constant != 0)
|
||||
&& calls_function (args[i].tree_value, 1))
|
||||
|| (must_preallocate && (args_size.var != 0 || args_size.constant != 0)
|
||||
&& calls_function (args[i].tree_value, 0)))
|
||||
{
|
||||
/* If this is an addressable type, we cannot pre-evaluate it. */
|
||||
if (TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)))
|
||||
abort ();
|
||||
|
||||
push_temp_slots ();
|
||||
|
||||
args[i].initial_value = args[i].value
|
||||
= expand_expr (args[i].tree_value, NULL_RTX, VOIDmode, 0);
|
||||
|
||||
preserve_temp_slots (args[i].value);
|
||||
pop_temp_slots ();
|
||||
|
||||
/* ANSI doesn't require a sequence point here,
|
||||
but PCC has one, so this will avoid some problems. */
|
||||
emit_queue ();
|
||||
|
||||
args[i].initial_value = args[i].value
|
||||
= protect_from_queue (args[i].initial_value, 0);
|
||||
|
||||
if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) != args[i].mode)
|
||||
args[i].value
|
||||
= convert_modes (args[i].mode,
|
||||
TYPE_MODE (TREE_TYPE (args[i].tree_value)),
|
||||
args[i].value, args[i].unsignedp);
|
||||
}
|
||||
/* Precompute any arguments as needed. */
|
||||
precompute_arguments (is_const, must_preallocate, num_actuals,
|
||||
args, &args_size);
|
||||
|
||||
/* Now we are about to start emitting insns that can be deleted
|
||||
if a libcall is deleted. */
|
||||
|
Loading…
Reference in New Issue
Block a user