diff options
author | Jeffrey A Law <law@cygnus.com> | 1999-02-24 16:29:36 +0000 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 1999-02-24 09:29:36 -0700 |
commit | cc0b1adcce51d1d605ab5615160b6e64438b1a10 (patch) | |
tree | f87ae99a30be3d490d78e0fe431e2bbdffdf283d /gcc/calls.c | |
parent | 1de558ee81d8ce1ffa6662e6fc0a940306c816d9 (diff) | |
download | gcc-cc0b1adcce51d1d605ab5615160b6e64438b1a10.zip gcc-cc0b1adcce51d1d605ab5615160b6e64438b1a10.tar.gz gcc-cc0b1adcce51d1d605ab5615160b6e64438b1a10.tar.bz2 |
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
Diffstat (limited to 'gcc/calls.c')
-rw-r--r-- | gcc/calls.c | 123 |
1 files changed, 78 insertions, 45 deletions
diff --git a/gcc/calls.c b/gcc/calls.c index f7e5eb2..bfc71e7 100644 --- a/gcc/calls.c +++ b/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. */ |