calls.c (compute_argument_addresses): New function.

* calls.c (compute_argument_addresses): New function.
        (rtx_for_function_call): New function.
        (expand_call): Use them.

From-SVN: r25653
This commit is contained in:
Jeffrey A Law 1999-03-09 14:05:13 +00:00 committed by Jeff Law
parent 91e1a7f5aa
commit a45bdd02f5
2 changed files with 110 additions and 71 deletions

View File

@ -11,6 +11,10 @@ Tue Mar 9 09:33:16 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
Tue Mar 9 02:08:17 1999 Jeffrey A Law (law@cygnus.com) Tue Mar 9 02:08:17 1999 Jeffrey A Law (law@cygnus.com)
* calls.c (compute_argument_addresses): New function.
(rtx_for_function_call): New function.
(expand_call): Use them.
* i386.md (zero_extendhisi2): Split into an expander and anonymous * i386.md (zero_extendhisi2): Split into an expander and anonymous
pattern. Add new anonymous pattern for use when optimizing for pattern. Add new anonymous pattern for use when optimizing for
size or for the PPro. size or for the PPro.

View File

@ -152,7 +152,10 @@ static void initialize_argument_information PROTO ((int,
CUMULATIVE_ARGS *, CUMULATIVE_ARGS *,
int, rtx *, int *, int, rtx *, int *,
int *, int *)); int *, int *));
static void compute_argument_addresses PROTO ((struct arg_data *,
rtx, int));
static rtx rtx_for_function_call PROTO ((tree, tree));
#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE) #if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
static rtx save_fixed_argument_area PROTO ((int, rtx, int *, int *)); static rtx save_fixed_argument_area PROTO ((int, rtx, int *, int *));
static void restore_fixed_argument_area PROTO ((rtx, rtx, int, int)); static void restore_fixed_argument_area PROTO ((rtx, rtx, int, int));
@ -1313,6 +1316,106 @@ finalize_must_preallocate (must_preallocate, num_actuals, args, args_size)
return must_preallocate; return must_preallocate;
} }
/* If we preallocated stack space, compute the address of each argument
and store it into the ARGS array.
We need not ensure it is a valid memory address here; it will be
validized when it is used.
ARGBLOCK is an rtx for the address of the outgoing arguments. */
static void
compute_argument_addresses (args, argblock, num_actuals)
struct arg_data *args;
rtx argblock;
int num_actuals;
{
if (argblock)
{
rtx arg_reg = argblock;
int i, arg_offset = 0;
if (GET_CODE (argblock) == PLUS)
arg_reg = XEXP (argblock, 0), arg_offset = INTVAL (XEXP (argblock, 1));
for (i = 0; i < num_actuals; i++)
{
rtx offset = ARGS_SIZE_RTX (args[i].offset);
rtx slot_offset = ARGS_SIZE_RTX (args[i].slot_offset);
rtx addr;
/* Skip this parm if it will not be passed on the stack. */
if (! args[i].pass_on_stack && args[i].reg != 0)
continue;
if (GET_CODE (offset) == CONST_INT)
addr = plus_constant (arg_reg, INTVAL (offset));
else
addr = gen_rtx_PLUS (Pmode, arg_reg, offset);
addr = plus_constant (addr, arg_offset);
args[i].stack = gen_rtx_MEM (args[i].mode, addr);
MEM_SET_IN_STRUCT_P
(args[i].stack,
AGGREGATE_TYPE_P (TREE_TYPE (args[i].tree_value)));
if (GET_CODE (slot_offset) == CONST_INT)
addr = plus_constant (arg_reg, INTVAL (slot_offset));
else
addr = gen_rtx_PLUS (Pmode, arg_reg, slot_offset);
addr = plus_constant (addr, arg_offset);
args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr);
}
}
}
/* Given a FNDECL and EXP, return an rtx suitable for use as a target address
in a call instruction.
FNDECL is the tree node for the target function. For an indirect call
FNDECL will be NULL_TREE.
EXP is the CALL_EXPR for this call. */
static rtx
rtx_for_function_call (fndecl, exp)
tree fndecl;
tree exp;
{
rtx funexp;
/* Get the function to call, in the form of RTL. */
if (fndecl)
{
/* If this is the first use of the function, see if we need to
make an external definition for it. */
if (! TREE_USED (fndecl))
{
assemble_external (fndecl);
TREE_USED (fndecl) = 1;
}
/* Get a SYMBOL_REF rtx for the function address. */
funexp = XEXP (DECL_RTL (fndecl), 0);
}
else
/* Generate an rtx (probably a pseudo-register) for the address. */
{
push_temp_slots ();
funexp = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
pop_temp_slots (); /* FUNEXP can't be BLKmode */
/* Check the function is executable. */
if (current_function_check_memory_usage)
emit_library_call (chkr_check_exec_libfunc, 1,
VOIDmode, 1,
funexp, ptr_mode);
emit_queue ();
}
return funexp;
}
/* Generate all the code for a function call /* Generate all the code for a function call
and return an rtx for its value. and return an rtx for its value.
Store the value in TARGET (specified as an rtx) if convenient. Store the value in TARGET (specified as an rtx) if convenient.
@ -1971,49 +2074,8 @@ expand_call (exp, target, ignore)
} }
#endif #endif
compute_argument_addresses (args, argblock, num_actuals);
/* If we preallocated stack space, compute the address of each argument.
We need not ensure it is a valid memory address here; it will be
validized when it is used. */
if (argblock)
{
rtx arg_reg = argblock;
int arg_offset = 0;
if (GET_CODE (argblock) == PLUS)
arg_reg = XEXP (argblock, 0), arg_offset = INTVAL (XEXP (argblock, 1));
for (i = 0; i < num_actuals; i++)
{
rtx offset = ARGS_SIZE_RTX (args[i].offset);
rtx slot_offset = ARGS_SIZE_RTX (args[i].slot_offset);
rtx addr;
/* Skip this parm if it will not be passed on the stack. */
if (! args[i].pass_on_stack && args[i].reg != 0)
continue;
if (GET_CODE (offset) == CONST_INT)
addr = plus_constant (arg_reg, INTVAL (offset));
else
addr = gen_rtx_PLUS (Pmode, arg_reg, offset);
addr = plus_constant (addr, arg_offset);
args[i].stack = gen_rtx_MEM (args[i].mode, addr);
MEM_SET_IN_STRUCT_P
(args[i].stack,
AGGREGATE_TYPE_P (TREE_TYPE (args[i].tree_value)));
if (GET_CODE (slot_offset) == CONST_INT)
addr = plus_constant (arg_reg, INTVAL (slot_offset));
else
addr = gen_rtx_PLUS (Pmode, arg_reg, slot_offset);
addr = plus_constant (addr, arg_offset);
args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr);
}
}
#ifdef PUSH_ARGS_REVERSED #ifdef PUSH_ARGS_REVERSED
#ifdef PREFERRED_STACK_BOUNDARY #ifdef PREFERRED_STACK_BOUNDARY
/* If we push args individually in reverse order, perform stack alignment /* If we push args individually in reverse order, perform stack alignment
@ -2028,34 +2090,7 @@ expand_call (exp, target, ignore)
if (argblock) if (argblock)
NO_DEFER_POP; NO_DEFER_POP;
/* Get the function to call, in the form of RTL. */ funexp = rtx_for_function_call (fndecl, exp);
if (fndecl)
{
/* If this is the first use of the function, see if we need to
make an external definition for it. */
if (! TREE_USED (fndecl))
{
assemble_external (fndecl);
TREE_USED (fndecl) = 1;
}
/* Get a SYMBOL_REF rtx for the function address. */
funexp = XEXP (DECL_RTL (fndecl), 0);
}
else
/* Generate an rtx (probably a pseudo-register) for the address. */
{
push_temp_slots ();
funexp = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
pop_temp_slots (); /* FUNEXP can't be BLKmode */
/* Check the function is executable. */
if (current_function_check_memory_usage)
emit_library_call (chkr_check_exec_libfunc, 1,
VOIDmode, 1,
funexp, ptr_mode);
emit_queue ();
}
/* Figure out the register where the value, if any, will come back. */ /* Figure out the register where the value, if any, will come back. */
valreg = 0; valreg = 0;