parent
f133a43eab
commit
f725a3ec9b
|
@ -1,3 +1,7 @@
|
||||||
|
2000-09-06 Kazu Hirata <kazu@hxi.com>
|
||||||
|
|
||||||
|
* calls.c: Fix formatting.
|
||||||
|
|
||||||
2000-09-06 Graham Stott <grahams@cygnus.co.uk>
|
2000-09-06 Graham Stott <grahams@cygnus.co.uk>
|
||||||
|
|
||||||
* config/i386/i386.h (ADDRESS_COST): Fix typo.
|
* config/i386/i386.h (ADDRESS_COST): Fix typo.
|
||||||
|
|
260
gcc/calls.c
260
gcc/calls.c
|
@ -163,11 +163,11 @@ int stack_arg_under_construction;
|
||||||
static int calls_function PARAMS ((tree, int));
|
static int calls_function PARAMS ((tree, int));
|
||||||
static int calls_function_1 PARAMS ((tree, int));
|
static int calls_function_1 PARAMS ((tree, int));
|
||||||
|
|
||||||
/* Nonzero if this is a call to a `const' function. */
|
/* Nonzero if this is a call to a `const' function. */
|
||||||
#define ECF_CONST 1
|
#define ECF_CONST 1
|
||||||
/* Nonzero if this is a call to a `volatile' function. */
|
/* Nonzero if this is a call to a `volatile' function. */
|
||||||
#define ECF_NORETURN 2
|
#define ECF_NORETURN 2
|
||||||
/* Nonzero if this is a call to malloc or a related function. */
|
/* Nonzero if this is a call to malloc or a related function. */
|
||||||
#define ECF_MALLOC 4
|
#define ECF_MALLOC 4
|
||||||
/* Nonzero if it is plausible that this is a call to alloca. */
|
/* Nonzero if it is plausible that this is a call to alloca. */
|
||||||
#define ECF_MAY_BE_ALLOCA 8
|
#define ECF_MAY_BE_ALLOCA 8
|
||||||
|
@ -203,7 +203,7 @@ static int finalize_must_preallocate PARAMS ((int, int,
|
||||||
struct args_size *));
|
struct args_size *));
|
||||||
static void precompute_arguments PARAMS ((int, int,
|
static void precompute_arguments PARAMS ((int, int,
|
||||||
struct arg_data *));
|
struct arg_data *));
|
||||||
static int compute_argument_block_size PARAMS ((int,
|
static int compute_argument_block_size PARAMS ((int,
|
||||||
struct args_size *,
|
struct args_size *,
|
||||||
int));
|
int));
|
||||||
static void initialize_argument_information PARAMS ((int,
|
static void initialize_argument_information PARAMS ((int,
|
||||||
|
@ -437,7 +437,7 @@ prepare_call_address (funexp, fndecl, call_fusage, reg_parm_seen)
|
||||||
|
|
||||||
CALL_FUSAGE is either empty or an EXPR_LIST of USE expressions that
|
CALL_FUSAGE is either empty or an EXPR_LIST of USE expressions that
|
||||||
denote registers used by the called function. */
|
denote registers used by the called function. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
|
emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
|
||||||
struct_value_size, next_arg_reg, valreg, old_inhibit_defer_pop,
|
struct_value_size, next_arg_reg, valreg, old_inhibit_defer_pop,
|
||||||
|
@ -472,8 +472,8 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
|
||||||
#if defined (HAVE_sibcall_pop) && defined (HAVE_sibcall_value_pop)
|
#if defined (HAVE_sibcall_pop) && defined (HAVE_sibcall_value_pop)
|
||||||
if ((ecf_flags & ECF_SIBCALL)
|
if ((ecf_flags & ECF_SIBCALL)
|
||||||
&& HAVE_sibcall_pop && HAVE_sibcall_value_pop
|
&& HAVE_sibcall_pop && HAVE_sibcall_value_pop
|
||||||
&& (RETURN_POPS_ARGS (fndecl, funtype, stack_size) > 0
|
&& (RETURN_POPS_ARGS (fndecl, funtype, stack_size) > 0
|
||||||
|| stack_size == 0))
|
|| stack_size == 0))
|
||||||
{
|
{
|
||||||
rtx n_pop = GEN_INT (RETURN_POPS_ARGS (fndecl, funtype, stack_size));
|
rtx n_pop = GEN_INT (RETURN_POPS_ARGS (fndecl, funtype, stack_size));
|
||||||
rtx pat;
|
rtx pat;
|
||||||
|
@ -653,7 +653,7 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
|
||||||
|
|
||||||
??? We may optimize similar to defer_pop above, but it is
|
??? We may optimize similar to defer_pop above, but it is
|
||||||
probably not worthwhile.
|
probably not worthwhile.
|
||||||
|
|
||||||
??? It will be worthwhile to enable combine_stack_adjustments even for
|
??? It will be worthwhile to enable combine_stack_adjustments even for
|
||||||
such machines. */
|
such machines. */
|
||||||
else if (n_popped)
|
else if (n_popped)
|
||||||
|
@ -757,7 +757,7 @@ special_function_p (fndecl, flags)
|
||||||
it may return the same address across multiple calls.
|
it may return the same address across multiple calls.
|
||||||
C++ operator new is not suitable because it is not required
|
C++ operator new is not suitable because it is not required
|
||||||
to return a unique pointer; indeed, the standard placement new
|
to return a unique pointer; indeed, the standard placement new
|
||||||
just returns its argument. */
|
just returns its argument. */
|
||||||
else if (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))) == Pmode
|
else if (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))) == Pmode
|
||||||
&& (! strcmp (tname, "malloc")
|
&& (! strcmp (tname, "malloc")
|
||||||
|| ! strcmp (tname, "calloc")
|
|| ! strcmp (tname, "calloc")
|
||||||
|
@ -808,7 +808,6 @@ flags_from_decl_or_type (exp)
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Precompute all register parameters as described by ARGS, storing values
|
/* Precompute all register parameters as described by ARGS, storing values
|
||||||
into fields within the ARGS array.
|
into fields within the ARGS array.
|
||||||
|
|
||||||
|
@ -853,7 +852,7 @@ precompute_register_parameters (num_actuals, args, reg_parm_seen)
|
||||||
TYPE_MODE (TREE_TYPE (args[i].tree_value)),
|
TYPE_MODE (TREE_TYPE (args[i].tree_value)),
|
||||||
args[i].value, args[i].unsignedp);
|
args[i].value, args[i].unsignedp);
|
||||||
|
|
||||||
/* If the value is expensive, and we are inside an appropriately
|
/* If the value is expensive, and we are inside an appropriately
|
||||||
short loop, put the value into a pseudo and then put the pseudo
|
short loop, put the value into a pseudo and then put the pseudo
|
||||||
into the hard reg.
|
into the hard reg.
|
||||||
|
|
||||||
|
@ -915,7 +914,7 @@ save_fixed_argument_area (reg_parm_stack_space, argblock,
|
||||||
|
|
||||||
/* If we don't have the required alignment, must do this in BLKmode. */
|
/* If we don't have the required alignment, must do this in BLKmode. */
|
||||||
if ((*low_to_save & (MIN (GET_MODE_SIZE (save_mode),
|
if ((*low_to_save & (MIN (GET_MODE_SIZE (save_mode),
|
||||||
BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
|
BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
|
||||||
save_mode = BLKmode;
|
save_mode = BLKmode;
|
||||||
|
|
||||||
#ifdef ARGS_GROW_DOWNWARD
|
#ifdef ARGS_GROW_DOWNWARD
|
||||||
|
@ -980,11 +979,11 @@ restore_fixed_argument_area (save_area, argblock, high_to_save, low_to_save)
|
||||||
high_to_save - low_to_save + 1, PARM_BOUNDARY);
|
high_to_save - low_to_save + 1, PARM_BOUNDARY);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If any elements in ARGS refer to parameters that are to be passed in
|
/* If any elements in ARGS refer to parameters that are to be passed in
|
||||||
registers, but not in memory, and whose alignment does not permit a
|
registers, but not in memory, and whose alignment does not permit a
|
||||||
direct copy into registers. Copy the values into a group of pseudos
|
direct copy into registers. Copy the values into a group of pseudos
|
||||||
which we will later copy into the appropriate hard registers.
|
which we will later copy into the appropriate hard registers.
|
||||||
|
|
||||||
Pseudos for each unaligned argument will be stored into the array
|
Pseudos for each unaligned argument will be stored into the array
|
||||||
args[argnum].aligned_regs. The caller is responsible for deallocating
|
args[argnum].aligned_regs. The caller is responsible for deallocating
|
||||||
|
@ -996,7 +995,7 @@ store_unaligned_arguments_into_pseudos (args, num_actuals)
|
||||||
int num_actuals;
|
int num_actuals;
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
for (i = 0; i < num_actuals; i++)
|
for (i = 0; i < num_actuals; i++)
|
||||||
if (args[i].reg != 0 && ! args[i].pass_on_stack
|
if (args[i].reg != 0 && ! args[i].pass_on_stack
|
||||||
&& args[i].mode == BLKmode
|
&& args[i].mode == BLKmode
|
||||||
|
@ -1053,7 +1052,7 @@ store_unaligned_arguments_into_pseudos (args, num_actuals)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill in ARGS_SIZE and ARGS array based on the parameters found in
|
/* Fill in ARGS_SIZE and ARGS array based on the parameters found in
|
||||||
ACTPARMS.
|
ACTPARMS.
|
||||||
|
|
||||||
NUM_ACTUALS is the total number of parameters.
|
NUM_ACTUALS is the total number of parameters.
|
||||||
|
|
||||||
|
@ -1101,7 +1100,7 @@ initialize_argument_information (num_actuals, args, args_size, n_named_args,
|
||||||
struct args_size alignment_pad;
|
struct args_size alignment_pad;
|
||||||
int i;
|
int i;
|
||||||
tree p;
|
tree p;
|
||||||
|
|
||||||
args_size->constant = 0;
|
args_size->constant = 0;
|
||||||
args_size->var = 0;
|
args_size->var = 0;
|
||||||
|
|
||||||
|
@ -1184,8 +1183,8 @@ initialize_argument_information (num_actuals, args, args_size, n_named_args,
|
||||||
but it is safe in the only case where this is a useful
|
but it is safe in the only case where this is a useful
|
||||||
optimization; namely, when the argument is a plain object.
|
optimization; namely, when the argument is a plain object.
|
||||||
In that case, the frontend is just asking the backend to
|
In that case, the frontend is just asking the backend to
|
||||||
make a bitwise copy of the argument. */
|
make a bitwise copy of the argument. */
|
||||||
|
|
||||||
if (TREE_CODE (args[i].tree_value) == TARGET_EXPR
|
if (TREE_CODE (args[i].tree_value) == TARGET_EXPR
|
||||||
&& (DECL_P (TREE_OPERAND (args[i].tree_value, 1)))
|
&& (DECL_P (TREE_OPERAND (args[i].tree_value, 1)))
|
||||||
&& ! REG_P (DECL_RTL (TREE_OPERAND (args[i].tree_value, 1))))
|
&& ! REG_P (DECL_RTL (TREE_OPERAND (args[i].tree_value, 1))))
|
||||||
|
@ -1254,7 +1253,7 @@ initialize_argument_information (num_actuals, args, args_size, n_named_args,
|
||||||
register window has to be unwinded before calling the routine, so
|
register window has to be unwinded before calling the routine, so
|
||||||
arguments have to go into the incoming registers. */
|
arguments have to go into the incoming registers. */
|
||||||
args[i].tail_call_reg = FUNCTION_INCOMING_ARG (*args_so_far, mode, type,
|
args[i].tail_call_reg = FUNCTION_INCOMING_ARG (*args_so_far, mode, type,
|
||||||
argpos < n_named_args);
|
argpos < n_named_args);
|
||||||
#else
|
#else
|
||||||
args[i].tail_call_reg = args[i].reg;
|
args[i].tail_call_reg = args[i].reg;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1314,7 +1313,7 @@ initialize_argument_information (num_actuals, args, args_size, n_named_args,
|
||||||
args[i].size.constant -= ((args[i].partial * UNITS_PER_WORD)
|
args[i].size.constant -= ((args[i].partial * UNITS_PER_WORD)
|
||||||
/ (PARM_BOUNDARY / BITS_PER_UNIT)
|
/ (PARM_BOUNDARY / BITS_PER_UNIT)
|
||||||
* (PARM_BOUNDARY / BITS_PER_UNIT));
|
* (PARM_BOUNDARY / BITS_PER_UNIT));
|
||||||
|
|
||||||
/* Update ARGS_SIZE, the total stack space for args so far. */
|
/* Update ARGS_SIZE, the total stack space for args so far. */
|
||||||
|
|
||||||
args_size->constant += args[i].size.constant;
|
args_size->constant += args[i].size.constant;
|
||||||
|
@ -1349,7 +1348,7 @@ initialize_argument_information (num_actuals, args, args_size, n_named_args,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compute_argument_block_size (reg_parm_stack_space, args_size,
|
compute_argument_block_size (reg_parm_stack_space, args_size,
|
||||||
preferred_stack_boundary)
|
preferred_stack_boundary)
|
||||||
int reg_parm_stack_space;
|
int reg_parm_stack_space;
|
||||||
struct args_size *args_size;
|
struct args_size *args_size;
|
||||||
int preferred_stack_boundary ATTRIBUTE_UNUSED;
|
int preferred_stack_boundary ATTRIBUTE_UNUSED;
|
||||||
|
@ -1378,10 +1377,10 @@ compute_argument_block_size (reg_parm_stack_space, args_size,
|
||||||
if (preferred_stack_boundary > 1)
|
if (preferred_stack_boundary > 1)
|
||||||
{
|
{
|
||||||
/* We don't handle this case yet. To handle it correctly we have
|
/* We don't handle this case yet. To handle it correctly we have
|
||||||
to add the delta, round and substract the delta.
|
to add the delta, round and substract the delta.
|
||||||
Currently no machine description requires this support. */
|
Currently no machine description requires this support. */
|
||||||
if (stack_pointer_delta & (preferred_stack_boundary - 1))
|
if (stack_pointer_delta & (preferred_stack_boundary - 1))
|
||||||
abort();
|
abort ();
|
||||||
args_size->var = round_up (args_size->var, preferred_stack_boundary);
|
args_size->var = round_up (args_size->var, preferred_stack_boundary);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1436,9 +1435,9 @@ compute_argument_block_size (reg_parm_stack_space, args_size,
|
||||||
|
|
||||||
NUM_ACTUALS is the number of arguments.
|
NUM_ACTUALS is the number of arguments.
|
||||||
|
|
||||||
ARGS is an array containing information for each argument; this routine
|
ARGS is an array containing information for each argument; this
|
||||||
fills in the INITIAL_VALUE and VALUE fields for each precomputed argument.
|
routine fills in the INITIAL_VALUE and VALUE fields for each
|
||||||
*/
|
precomputed argument. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
precompute_arguments (flags, num_actuals, args)
|
precompute_arguments (flags, num_actuals, args)
|
||||||
|
@ -1489,7 +1488,7 @@ precompute_arguments (flags, num_actuals, args)
|
||||||
if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) != args[i].mode)
|
if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) != args[i].mode)
|
||||||
{
|
{
|
||||||
args[i].value
|
args[i].value
|
||||||
= convert_modes (args[i].mode,
|
= convert_modes (args[i].mode,
|
||||||
TYPE_MODE (TREE_TYPE (args[i].tree_value)),
|
TYPE_MODE (TREE_TYPE (args[i].tree_value)),
|
||||||
args[i].value, args[i].unsignedp);
|
args[i].value, args[i].unsignedp);
|
||||||
#ifdef PROMOTE_FOR_CALL_ONLY
|
#ifdef PROMOTE_FOR_CALL_ONLY
|
||||||
|
@ -1573,7 +1572,7 @@ finalize_must_preallocate (must_preallocate, num_actuals, args, args_size)
|
||||||
/* If we preallocated stack space, compute the address of each argument
|
/* If we preallocated stack space, compute the address of each argument
|
||||||
and store it into the ARGS array.
|
and store it into the ARGS array.
|
||||||
|
|
||||||
We need not ensure it is a valid memory address here; it will be
|
We need not ensure it is a valid memory address here; it will be
|
||||||
validized when it is used.
|
validized when it is used.
|
||||||
|
|
||||||
ARGBLOCK is an rtx for the address of the outgoing arguments. */
|
ARGBLOCK is an rtx for the address of the outgoing arguments. */
|
||||||
|
@ -1631,7 +1630,7 @@ compute_argument_addresses (args, argblock, num_actuals)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given a FNDECL and EXP, return an rtx suitable for use as a target address
|
/* Given a FNDECL and EXP, return an rtx suitable for use as a target address
|
||||||
in a call instruction.
|
in a call instruction.
|
||||||
|
|
||||||
|
@ -1666,9 +1665,9 @@ rtx_for_function_call (fndecl, exp)
|
||||||
{
|
{
|
||||||
rtx funaddr;
|
rtx funaddr;
|
||||||
push_temp_slots ();
|
push_temp_slots ();
|
||||||
funaddr = funexp =
|
funaddr = funexp =
|
||||||
expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
|
expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
|
||||||
pop_temp_slots (); /* FUNEXP can't be BLKmode */
|
pop_temp_slots (); /* FUNEXP can't be BLKmode. */
|
||||||
|
|
||||||
/* Check the function is executable. */
|
/* Check the function is executable. */
|
||||||
if (current_function_check_memory_usage)
|
if (current_function_check_memory_usage)
|
||||||
|
@ -1676,8 +1675,8 @@ rtx_for_function_call (fndecl, exp)
|
||||||
#ifdef POINTERS_EXTEND_UNSIGNED
|
#ifdef POINTERS_EXTEND_UNSIGNED
|
||||||
/* It might be OK to convert funexp in place, but there's
|
/* It might be OK to convert funexp in place, but there's
|
||||||
a lot going on between here and when it happens naturally
|
a lot going on between here and when it happens naturally
|
||||||
that this seems safer. */
|
that this seems safer. */
|
||||||
funaddr = convert_memory_address (Pmode, funexp);
|
funaddr = convert_memory_address (Pmode, funexp);
|
||||||
#endif
|
#endif
|
||||||
emit_library_call (chkr_check_exec_libfunc, 1,
|
emit_library_call (chkr_check_exec_libfunc, 1,
|
||||||
VOIDmode, 1,
|
VOIDmode, 1,
|
||||||
|
@ -1690,7 +1689,7 @@ rtx_for_function_call (fndecl, exp)
|
||||||
|
|
||||||
/* Do the register loads required for any wholly-register parms or any
|
/* Do the register loads required for any wholly-register parms or any
|
||||||
parms which are passed both on the stack and in a register. Their
|
parms which are passed both on the stack and in a register. Their
|
||||||
expressions were already evaluated.
|
expressions were already evaluated.
|
||||||
|
|
||||||
Mark all register-parms as living through the call, putting these USE
|
Mark all register-parms as living through the call, putting these USE
|
||||||
insns in the CALL_INSN_FUNCTION_USAGE field. */
|
insns in the CALL_INSN_FUNCTION_USAGE field. */
|
||||||
|
@ -1842,7 +1841,7 @@ try_to_integrate (fndecl, actparms, target, ignore, type, structure_value_addr)
|
||||||
outgoing argument list in addition to the requested
|
outgoing argument list in addition to the requested
|
||||||
space, but there is no way to ask for stack space such
|
space, but there is no way to ask for stack space such
|
||||||
that an argument list of a certain length can be
|
that an argument list of a certain length can be
|
||||||
safely constructed.
|
safely constructed.
|
||||||
|
|
||||||
Add the stack space reserved for register arguments, if
|
Add the stack space reserved for register arguments, if
|
||||||
any, in the inline function. What is really needed is the
|
any, in the inline function. What is really needed is the
|
||||||
|
@ -1911,7 +1910,7 @@ combine_pending_stack_adjustment_and_call (unadjusted_args_size,
|
||||||
just pushed the arguments without adjust the stack here. */
|
just pushed the arguments without adjust the stack here. */
|
||||||
HOST_WIDE_INT unadjusted_alignment;
|
HOST_WIDE_INT unadjusted_alignment;
|
||||||
|
|
||||||
unadjusted_alignment
|
unadjusted_alignment
|
||||||
= ((stack_pointer_delta + unadjusted_args_size)
|
= ((stack_pointer_delta + unadjusted_args_size)
|
||||||
% preferred_unit_stack_boundary);
|
% preferred_unit_stack_boundary);
|
||||||
|
|
||||||
|
@ -1922,8 +1921,8 @@ combine_pending_stack_adjustment_and_call (unadjusted_args_size,
|
||||||
-UNADJUSTED_ALIGNMENT modulo the PREFERRED_UNIT_STACK_BOUNDARY. */
|
-UNADJUSTED_ALIGNMENT modulo the PREFERRED_UNIT_STACK_BOUNDARY. */
|
||||||
|
|
||||||
/* Begin by trying to pop all the bytes. */
|
/* Begin by trying to pop all the bytes. */
|
||||||
unadjusted_alignment
|
unadjusted_alignment
|
||||||
= (unadjusted_alignment
|
= (unadjusted_alignment
|
||||||
- (pending_stack_adjust % preferred_unit_stack_boundary));
|
- (pending_stack_adjust % preferred_unit_stack_boundary));
|
||||||
adjustment = pending_stack_adjust;
|
adjustment = pending_stack_adjust;
|
||||||
/* Push enough additional bytes that the stack will be aligned
|
/* Push enough additional bytes that the stack will be aligned
|
||||||
|
@ -1931,16 +1930,16 @@ combine_pending_stack_adjustment_and_call (unadjusted_args_size,
|
||||||
if (preferred_unit_stack_boundary > 1)
|
if (preferred_unit_stack_boundary > 1)
|
||||||
{
|
{
|
||||||
if (unadjusted_alignment >= 0)
|
if (unadjusted_alignment >= 0)
|
||||||
adjustment -= preferred_unit_stack_boundary - unadjusted_alignment;
|
adjustment -= preferred_unit_stack_boundary - unadjusted_alignment;
|
||||||
else
|
else
|
||||||
adjustment += unadjusted_alignment;
|
adjustment += unadjusted_alignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now, sets ARGS_SIZE->CONSTANT so that we pop the right number of
|
/* Now, sets ARGS_SIZE->CONSTANT so that we pop the right number of
|
||||||
bytes after the call. The right number is the entire
|
bytes after the call. The right number is the entire
|
||||||
PENDING_STACK_ADJUST less our ADJUSTMENT plus the amount required
|
PENDING_STACK_ADJUST less our ADJUSTMENT plus the amount required
|
||||||
by the arguments in the first place. */
|
by the arguments in the first place. */
|
||||||
args_size->constant
|
args_size->constant
|
||||||
= pending_stack_adjust - adjustment + unadjusted_args_size;
|
= pending_stack_adjust - adjustment + unadjusted_args_size;
|
||||||
|
|
||||||
return adjustment;
|
return adjustment;
|
||||||
|
@ -1990,24 +1989,23 @@ check_sibcall_argument_overlap_1 (x)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scan all subexpressions. */
|
/* Scan all subexpressions. */
|
||||||
fmt = GET_RTX_FORMAT (code);
|
fmt = GET_RTX_FORMAT (code);
|
||||||
for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
|
for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
|
||||||
{
|
{
|
||||||
if (*fmt == 'e')
|
if (*fmt == 'e')
|
||||||
{
|
{
|
||||||
if (check_sibcall_argument_overlap_1 (XEXP (x, i)))
|
if (check_sibcall_argument_overlap_1 (XEXP (x, i)))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (*fmt == 'E')
|
else if (*fmt == 'E')
|
||||||
{
|
{
|
||||||
for (j = 0; j < XVECLEN (x, i); j++)
|
for (j = 0; j < XVECLEN (x, i); j++)
|
||||||
if (check_sibcall_argument_overlap_1 (XVECEXP (x, i, j)))
|
if (check_sibcall_argument_overlap_1 (XVECEXP (x, i, j)))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scan sequence after INSN if it does not dereference any argument slots
|
/* Scan sequence after INSN if it does not dereference any argument slots
|
||||||
|
@ -2020,7 +2018,7 @@ static int
|
||||||
check_sibcall_argument_overlap (insn, arg)
|
check_sibcall_argument_overlap (insn, arg)
|
||||||
rtx insn;
|
rtx insn;
|
||||||
struct arg_data *arg;
|
struct arg_data *arg;
|
||||||
{
|
{
|
||||||
int low, high;
|
int low, high;
|
||||||
|
|
||||||
if (insn == NULL_RTX)
|
if (insn == NULL_RTX)
|
||||||
|
@ -2029,8 +2027,8 @@ check_sibcall_argument_overlap (insn, arg)
|
||||||
insn = NEXT_INSN (insn);
|
insn = NEXT_INSN (insn);
|
||||||
|
|
||||||
for (; insn; insn = NEXT_INSN (insn))
|
for (; insn; insn = NEXT_INSN (insn))
|
||||||
if (INSN_P (insn) &&
|
if (INSN_P (insn)
|
||||||
check_sibcall_argument_overlap_1 (PATTERN (insn)))
|
&& check_sibcall_argument_overlap_1 (PATTERN (insn)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef ARGS_GROW_DOWNWARD
|
#ifdef ARGS_GROW_DOWNWARD
|
||||||
|
@ -2119,7 +2117,7 @@ expand_call (exp, target, ignore)
|
||||||
int reg_parm_seen;
|
int reg_parm_seen;
|
||||||
/* Nonzero if this is an indirect function call. */
|
/* Nonzero if this is an indirect function call. */
|
||||||
|
|
||||||
/* Nonzero if we must avoid push-insns in the args for this call.
|
/* Nonzero if we must avoid push-insns in the args for this call.
|
||||||
If stack space is allocated for register parameters, but not by the
|
If stack space is allocated for register parameters, but not by the
|
||||||
caller, then it is preallocated in the fixed part of the stack frame.
|
caller, then it is preallocated in the fixed part of the stack frame.
|
||||||
So the entire argument block must then be preallocated (i.e., we
|
So the entire argument block must then be preallocated (i.e., we
|
||||||
|
@ -2203,7 +2201,7 @@ expand_call (exp, target, ignore)
|
||||||
flags |= flags_from_decl_or_type (fndecl);
|
flags |= flags_from_decl_or_type (fndecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we don't have specific function to call, see if we have a
|
/* If we don't have specific function to call, see if we have a
|
||||||
attributes set in the type. */
|
attributes set in the type. */
|
||||||
else
|
else
|
||||||
flags |= flags_from_decl_or_type (TREE_TYPE (TREE_TYPE (p)));
|
flags |= flags_from_decl_or_type (TREE_TYPE (TREE_TYPE (p)));
|
||||||
|
@ -2213,7 +2211,7 @@ expand_call (exp, target, ignore)
|
||||||
&& TYPE_RETURNS_STACK_DEPRESSED (TREE_TYPE (TREE_TYPE (p))))
|
&& TYPE_RETURNS_STACK_DEPRESSED (TREE_TYPE (TREE_TYPE (p))))
|
||||||
{
|
{
|
||||||
flags |= ECF_SP_DEPRESSED;
|
flags |= ECF_SP_DEPRESSED;
|
||||||
flags &= ~ (ECF_PURE | ECF_CONST);
|
flags &= ~(ECF_PURE | ECF_CONST);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef REG_PARM_STACK_SPACE
|
#ifdef REG_PARM_STACK_SPACE
|
||||||
|
@ -2377,10 +2375,8 @@ expand_call (exp, target, ignore)
|
||||||
or not. */
|
or not. */
|
||||||
INIT_CUMULATIVE_ARGS (args_so_far, funtype, NULL_RTX, (fndecl == 0));
|
INIT_CUMULATIVE_ARGS (args_so_far, funtype, NULL_RTX, (fndecl == 0));
|
||||||
|
|
||||||
|
|
||||||
/* Make a vector to hold all the information about each arg. */
|
/* Make a vector to hold all the information about each arg. */
|
||||||
args = (struct arg_data *) alloca (num_actuals
|
args = (struct arg_data *) alloca (num_actuals * sizeof (struct arg_data));
|
||||||
* sizeof (struct arg_data));
|
|
||||||
bzero ((char *) args, num_actuals * sizeof (struct arg_data));
|
bzero ((char *) args, num_actuals * sizeof (struct arg_data));
|
||||||
|
|
||||||
/* Build up entries inthe ARGS array, compute the size of the arguments
|
/* Build up entries inthe ARGS array, compute the size of the arguments
|
||||||
|
@ -2425,7 +2421,7 @@ expand_call (exp, target, ignore)
|
||||||
there's pending loops or cleanups we know there's code to follow
|
there's pending loops or cleanups we know there's code to follow
|
||||||
the call.
|
the call.
|
||||||
|
|
||||||
If rtx_equal_function_value_matters is false, that means we've
|
If rtx_equal_function_value_matters is false, that means we've
|
||||||
finished with regular parsing. Which means that some of the
|
finished with regular parsing. Which means that some of the
|
||||||
machinery we use to generate tail-calls is no longer in place.
|
machinery we use to generate tail-calls is no longer in place.
|
||||||
This is most often true of sjlj-exceptions, which we couldn't
|
This is most often true of sjlj-exceptions, which we couldn't
|
||||||
|
@ -2490,7 +2486,7 @@ expand_call (exp, target, ignore)
|
||||||
(See unsafe_for_reeval commentary for details.)
|
(See unsafe_for_reeval commentary for details.)
|
||||||
|
|
||||||
Generate a new argument list. Pass safe arguments through
|
Generate a new argument list. Pass safe arguments through
|
||||||
unchanged. For the easy badness wrap them in UNSAVE_EXPRs.
|
unchanged. For the easy badness wrap them in UNSAVE_EXPRs.
|
||||||
For hard badness, evaluate them now and put their resulting
|
For hard badness, evaluate them now and put their resulting
|
||||||
rtx in a temporary VAR_DECL.
|
rtx in a temporary VAR_DECL.
|
||||||
|
|
||||||
|
@ -2505,7 +2501,7 @@ expand_call (exp, target, ignore)
|
||||||
end = num_actuals;
|
end = num_actuals;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
inc = -1;
|
inc = -1;
|
||||||
i = num_actuals - 1;
|
i = num_actuals - 1;
|
||||||
end = -1;
|
end = -1;
|
||||||
|
@ -2515,26 +2511,26 @@ expand_call (exp, target, ignore)
|
||||||
{
|
{
|
||||||
switch (unsafe_for_reeval (args[i].tree_value))
|
switch (unsafe_for_reeval (args[i].tree_value))
|
||||||
{
|
{
|
||||||
case 0: /* Safe. */
|
case 0: /* Safe. */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: /* Mildly unsafe. */
|
case 1: /* Mildly unsafe. */
|
||||||
args[i].tree_value = unsave_expr (args[i].tree_value);
|
args[i].tree_value = unsave_expr (args[i].tree_value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: /* Wildly unsafe. */
|
case 2: /* Wildly unsafe. */
|
||||||
{
|
{
|
||||||
tree var = build_decl (VAR_DECL, NULL_TREE,
|
tree var = build_decl (VAR_DECL, NULL_TREE,
|
||||||
TREE_TYPE (args[i].tree_value));
|
TREE_TYPE (args[i].tree_value));
|
||||||
DECL_RTL (var) = expand_expr (args[i].tree_value, NULL_RTX,
|
DECL_RTL (var) = expand_expr (args[i].tree_value, NULL_RTX,
|
||||||
VOIDmode, EXPAND_NORMAL);
|
VOIDmode, EXPAND_NORMAL);
|
||||||
args[i].tree_value = var;
|
args[i].tree_value = var;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
/* We need to build actparms for optimize_tail_recursion. We can
|
/* We need to build actparms for optimize_tail_recursion. We can
|
||||||
safely trash away TREE_PURPOSE, since it is unused by this
|
safely trash away TREE_PURPOSE, since it is unused by this
|
||||||
function. */
|
function. */
|
||||||
|
@ -2648,7 +2644,7 @@ expand_call (exp, target, ignore)
|
||||||
argblock = 0;
|
argblock = 0;
|
||||||
call_fusage = 0;
|
call_fusage = 0;
|
||||||
|
|
||||||
/* Start a new sequence for the normal call case.
|
/* Start a new sequence for the normal call case.
|
||||||
|
|
||||||
From this point on, if the sibling call fails, we want to set
|
From this point on, if the sibling call fails, we want to set
|
||||||
sibcall_failure instead of continuing the loop. */
|
sibcall_failure instead of continuing the loop. */
|
||||||
|
@ -2681,7 +2677,6 @@ expand_call (exp, target, ignore)
|
||||||
temporaries we make. */
|
temporaries we make. */
|
||||||
push_temp_slots ();
|
push_temp_slots ();
|
||||||
|
|
||||||
|
|
||||||
#ifdef FINAL_REG_PARM_STACK_SPACE
|
#ifdef FINAL_REG_PARM_STACK_SPACE
|
||||||
reg_parm_stack_space = FINAL_REG_PARM_STACK_SPACE (args_size.constant,
|
reg_parm_stack_space = FINAL_REG_PARM_STACK_SPACE (args_size.constant,
|
||||||
args_size.var);
|
args_size.var);
|
||||||
|
@ -2702,11 +2697,12 @@ expand_call (exp, target, ignore)
|
||||||
pattern, do not round up, since we'll be re-using whatever space our
|
pattern, do not round up, since we'll be re-using whatever space our
|
||||||
caller provided. */
|
caller provided. */
|
||||||
unadjusted_args_size
|
unadjusted_args_size
|
||||||
= compute_argument_block_size (reg_parm_stack_space, &adjusted_args_size,
|
= compute_argument_block_size (reg_parm_stack_space,
|
||||||
|
&adjusted_args_size,
|
||||||
(pass == 0 ? 0
|
(pass == 0 ? 0
|
||||||
: preferred_stack_boundary));
|
: preferred_stack_boundary));
|
||||||
|
|
||||||
old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
|
old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
|
||||||
|
|
||||||
/* The argument block when performing a sibling call is the
|
/* The argument block when performing a sibling call is the
|
||||||
incoming argument block. */
|
incoming argument block. */
|
||||||
|
@ -2763,7 +2759,7 @@ expand_call (exp, target, ignore)
|
||||||
Therefore, we save any area of the stack that was already
|
Therefore, we save any area of the stack that was already
|
||||||
written and that we are using. Here we set up to do this
|
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
|
by making a new stack usage map from the old one. The
|
||||||
actual save will be done by store_one_arg.
|
actual save will be done by store_one_arg.
|
||||||
|
|
||||||
Another approach might be to try to reorder the argument
|
Another approach might be to try to reorder the argument
|
||||||
evaluations to avoid this conflicting stack usage. */
|
evaluations to avoid this conflicting stack usage. */
|
||||||
|
@ -2798,10 +2794,10 @@ expand_call (exp, target, ignore)
|
||||||
/* The address of the outgoing argument list must not be
|
/* The address of the outgoing argument list must not be
|
||||||
copied to a register here, because argblock would be left
|
copied to a register here, because argblock would be left
|
||||||
pointing to the wrong place after the call to
|
pointing to the wrong place after the call to
|
||||||
allocate_dynamic_stack_space below. */
|
allocate_dynamic_stack_space below. */
|
||||||
|
|
||||||
argblock = virtual_outgoing_args_rtx;
|
argblock = virtual_outgoing_args_rtx;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (inhibit_defer_pop == 0)
|
if (inhibit_defer_pop == 0)
|
||||||
|
@ -2809,7 +2805,7 @@ expand_call (exp, target, ignore)
|
||||||
/* Try to reuse some or all of the pending_stack_adjust
|
/* Try to reuse some or all of the pending_stack_adjust
|
||||||
to get this space. */
|
to get this space. */
|
||||||
needed
|
needed
|
||||||
= (combine_pending_stack_adjustment_and_call
|
= (combine_pending_stack_adjustment_and_call
|
||||||
(unadjusted_args_size,
|
(unadjusted_args_size,
|
||||||
&adjusted_args_size,
|
&adjusted_args_size,
|
||||||
preferred_unit_stack_boundary));
|
preferred_unit_stack_boundary));
|
||||||
|
@ -2829,7 +2825,7 @@ expand_call (exp, target, ignore)
|
||||||
do_pending_stack_adjust ();
|
do_pending_stack_adjust ();
|
||||||
needed = 0;
|
needed = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* We need to allocate space. We'll do that in
|
/* We need to allocate space. We'll do that in
|
||||||
push_block below. */
|
push_block below. */
|
||||||
pending_stack_adjust = 0;
|
pending_stack_adjust = 0;
|
||||||
|
@ -2907,12 +2903,12 @@ expand_call (exp, target, ignore)
|
||||||
{
|
{
|
||||||
/* When the stack adjustment is pending, we get better code
|
/* When the stack adjustment is pending, we get better code
|
||||||
by combining the adjustments. */
|
by combining the adjustments. */
|
||||||
if (pending_stack_adjust
|
if (pending_stack_adjust
|
||||||
&& ! (flags & (ECF_CONST | ECF_PURE))
|
&& ! (flags & (ECF_CONST | ECF_PURE))
|
||||||
&& ! inhibit_defer_pop)
|
&& ! inhibit_defer_pop)
|
||||||
{
|
{
|
||||||
pending_stack_adjust
|
pending_stack_adjust
|
||||||
= (combine_pending_stack_adjustment_and_call
|
= (combine_pending_stack_adjustment_and_call
|
||||||
(unadjusted_args_size,
|
(unadjusted_args_size,
|
||||||
&adjusted_args_size,
|
&adjusted_args_size,
|
||||||
preferred_unit_stack_boundary));
|
preferred_unit_stack_boundary));
|
||||||
|
@ -3015,7 +3011,7 @@ expand_call (exp, target, ignore)
|
||||||
passed in registers. */
|
passed in registers. */
|
||||||
#ifdef OUTGOING_REG_PARM_STACK_SPACE
|
#ifdef OUTGOING_REG_PARM_STACK_SPACE
|
||||||
if (!ACCUMULATE_OUTGOING_ARGS
|
if (!ACCUMULATE_OUTGOING_ARGS
|
||||||
&& must_preallocate == 0 && reg_parm_stack_space > 0)
|
&& must_preallocate == 0 && reg_parm_stack_space > 0)
|
||||||
anti_adjust_stack (GEN_INT (reg_parm_stack_space));
|
anti_adjust_stack (GEN_INT (reg_parm_stack_space));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3032,7 +3028,7 @@ expand_call (exp, target, ignore)
|
||||||
if (current_function_check_memory_usage)
|
if (current_function_check_memory_usage)
|
||||||
emit_library_call (chkr_set_right_libfunc, 1,
|
emit_library_call (chkr_set_right_libfunc, 1,
|
||||||
VOIDmode, 3,
|
VOIDmode, 3,
|
||||||
structure_value_addr, ptr_mode,
|
structure_value_addr, ptr_mode,
|
||||||
GEN_INT (struct_value_size),
|
GEN_INT (struct_value_size),
|
||||||
TYPE_MODE (sizetype),
|
TYPE_MODE (sizetype),
|
||||||
GEN_INT (MEMORY_USE_WO),
|
GEN_INT (MEMORY_USE_WO),
|
||||||
|
@ -3046,7 +3042,7 @@ expand_call (exp, target, ignore)
|
||||||
reg_parm_seen);
|
reg_parm_seen);
|
||||||
|
|
||||||
load_register_parameters (args, num_actuals, &call_fusage, flags);
|
load_register_parameters (args, num_actuals, &call_fusage, flags);
|
||||||
|
|
||||||
/* Perform postincrements before actually calling the function. */
|
/* Perform postincrements before actually calling the function. */
|
||||||
emit_queue ();
|
emit_queue ();
|
||||||
|
|
||||||
|
@ -3082,8 +3078,8 @@ expand_call (exp, target, ignore)
|
||||||
|
|
||||||
/* Verify that we've deallocated all the stack we used. */
|
/* Verify that we've deallocated all the stack we used. */
|
||||||
if (pass
|
if (pass
|
||||||
&& old_stack_allocated != stack_pointer_delta - pending_stack_adjust)
|
&& old_stack_allocated != stack_pointer_delta - pending_stack_adjust)
|
||||||
abort();
|
abort ();
|
||||||
|
|
||||||
/* If call is cse'able, make appropriate pair of reg-notes around it.
|
/* If call is cse'able, make appropriate pair of reg-notes around it.
|
||||||
Test valreg so we don't crash; may safely ignore `const'
|
Test valreg so we don't crash; may safely ignore `const'
|
||||||
|
@ -3117,7 +3113,7 @@ expand_call (exp, target, ignore)
|
||||||
gen_rtx_SCRATCH (VOIDmode))), note);
|
gen_rtx_SCRATCH (VOIDmode))), note);
|
||||||
|
|
||||||
emit_libcall_block (insns, temp, valreg, note);
|
emit_libcall_block (insns, temp, valreg, note);
|
||||||
|
|
||||||
valreg = temp;
|
valreg = temp;
|
||||||
}
|
}
|
||||||
else if (flags & (ECF_CONST | ECF_PURE))
|
else if (flags & (ECF_CONST | ECF_PURE))
|
||||||
|
@ -3133,7 +3129,7 @@ expand_call (exp, target, ignore)
|
||||||
rtx temp = gen_reg_rtx (GET_MODE (valreg));
|
rtx temp = gen_reg_rtx (GET_MODE (valreg));
|
||||||
rtx last, insns;
|
rtx last, insns;
|
||||||
|
|
||||||
/* The return value from a malloc-like function is a pointer. */
|
/* The return value from a malloc-like function is a pointer. */
|
||||||
if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
|
if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
|
||||||
mark_reg_pointer (temp, BIGGEST_ALIGNMENT);
|
mark_reg_pointer (temp, BIGGEST_ALIGNMENT);
|
||||||
|
|
||||||
|
@ -3142,7 +3138,7 @@ expand_call (exp, target, ignore)
|
||||||
/* The return value from a malloc-like function can not alias
|
/* The return value from a malloc-like function can not alias
|
||||||
anything else. */
|
anything else. */
|
||||||
last = get_last_insn ();
|
last = get_last_insn ();
|
||||||
REG_NOTES (last) =
|
REG_NOTES (last) =
|
||||||
gen_rtx_EXPR_LIST (REG_NOALIAS, temp, REG_NOTES (last));
|
gen_rtx_EXPR_LIST (REG_NOALIAS, temp, REG_NOTES (last));
|
||||||
|
|
||||||
/* Write out the sequence. */
|
/* Write out the sequence. */
|
||||||
|
@ -3332,7 +3328,7 @@ expand_call (exp, target, ignore)
|
||||||
stack_usage_map = initial_stack_usage_map;
|
stack_usage_map = initial_stack_usage_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this was alloca, record the new stack level for nonlocal gotos.
|
/* If this was alloca, record the new stack level for nonlocal gotos.
|
||||||
Check for the handler slots since we might not have a save area
|
Check for the handler slots since we might not have a save area
|
||||||
for non-local gotos. */
|
for non-local gotos. */
|
||||||
|
|
||||||
|
@ -3372,7 +3368,7 @@ expand_call (exp, target, ignore)
|
||||||
stack_pointer_delta = save_stack_pointer_delta;
|
stack_pointer_delta = save_stack_pointer_delta;
|
||||||
|
|
||||||
/* Prepare arg structure for next iteration. */
|
/* Prepare arg structure for next iteration. */
|
||||||
for (i = 0 ; i < num_actuals ; i++)
|
for (i = 0; i < num_actuals; i++)
|
||||||
{
|
{
|
||||||
args[i].value = 0;
|
args[i].value = 0;
|
||||||
args[i].aligned_regs = 0;
|
args[i].aligned_regs = 0;
|
||||||
|
@ -3391,7 +3387,7 @@ expand_call (exp, target, ignore)
|
||||||
function who's expansion contains another CALL_PLACEHOLDER.
|
function who's expansion contains another CALL_PLACEHOLDER.
|
||||||
|
|
||||||
If there are any C_Ps in any of these sequences, replace them
|
If there are any C_Ps in any of these sequences, replace them
|
||||||
with their normal call. */
|
with their normal call. */
|
||||||
|
|
||||||
for (insn = normal_call_insns; insn; insn = NEXT_INSN (insn))
|
for (insn = normal_call_insns; insn; insn = NEXT_INSN (insn))
|
||||||
if (GET_CODE (insn) == CALL_INSN
|
if (GET_CODE (insn) == CALL_INSN
|
||||||
|
@ -3462,7 +3458,7 @@ libfunc_nothrow (fun)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output a library call to function FUN (a SYMBOL_REF rtx).
|
/* Output a library call to function FUN (a SYMBOL_REF rtx).
|
||||||
The RETVAL parameter specifies whether return value needs to be saved, other
|
The RETVAL parameter specifies whether return value needs to be saved, other
|
||||||
parameters are documented in the emit_library_call function bellow. */
|
parameters are documented in the emit_library_call function bellow. */
|
||||||
static rtx
|
static rtx
|
||||||
emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||||
|
@ -3485,8 +3481,16 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||||
struct args_size alignment_pad;
|
struct args_size alignment_pad;
|
||||||
rtx argblock = 0;
|
rtx argblock = 0;
|
||||||
CUMULATIVE_ARGS args_so_far;
|
CUMULATIVE_ARGS args_so_far;
|
||||||
struct arg { rtx value; enum machine_mode mode; rtx reg; int partial;
|
struct arg
|
||||||
struct args_size offset; struct args_size size; rtx save_area; };
|
{
|
||||||
|
rtx value;
|
||||||
|
enum machine_mode mode;
|
||||||
|
rtx reg;
|
||||||
|
int partial;
|
||||||
|
struct args_size offset;
|
||||||
|
struct args_size size;
|
||||||
|
rtx save_area;
|
||||||
|
};
|
||||||
struct arg *argvec;
|
struct arg *argvec;
|
||||||
int old_inhibit_defer_pop = inhibit_defer_pop;
|
int old_inhibit_defer_pop = inhibit_defer_pop;
|
||||||
rtx call_fusage = 0;
|
rtx call_fusage = 0;
|
||||||
|
@ -3502,7 +3506,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||||
/* Define the boundary of the register parm stack space that needs to be
|
/* Define the boundary of the register parm stack space that needs to be
|
||||||
save, if any. */
|
save, if any. */
|
||||||
int low_to_save = -1, high_to_save = 0;
|
int low_to_save = -1, high_to_save = 0;
|
||||||
rtx save_area = 0; /* Place that it is saved */
|
rtx save_area = 0; /* Place that it is saved. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Size of the stack reserved for parameter registers. */
|
/* Size of the stack reserved for parameter registers. */
|
||||||
|
@ -3614,7 +3618,6 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||||
NULL_TREE, &args_size, &argvec[count].offset,
|
NULL_TREE, &args_size, &argvec[count].offset,
|
||||||
&argvec[count].size, &alignment_pad);
|
&argvec[count].size, &alignment_pad);
|
||||||
|
|
||||||
|
|
||||||
if (argvec[count].reg == 0 || argvec[count].partial != 0
|
if (argvec[count].reg == 0 || argvec[count].partial != 0
|
||||||
|| reg_parm_stack_space > 0)
|
|| reg_parm_stack_space > 0)
|
||||||
args_size.constant += argvec[count].size.constant;
|
args_size.constant += argvec[count].size.constant;
|
||||||
|
@ -3676,7 +3679,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||||
|
|
||||||
locate_and_pad_parm (mode, NULL_TREE,
|
locate_and_pad_parm (mode, NULL_TREE,
|
||||||
#ifdef STACK_PARMS_IN_REG_PARM_AREA
|
#ifdef STACK_PARMS_IN_REG_PARM_AREA
|
||||||
1,
|
1,
|
||||||
#else
|
#else
|
||||||
argvec[count].reg != 0,
|
argvec[count].reg != 0,
|
||||||
#endif
|
#endif
|
||||||
|
@ -3767,8 +3770,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||||
|
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
@ -3812,7 +3814,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||||
for (count = 0; count < reg_parm_stack_space; count++)
|
for (count = 0; count < reg_parm_stack_space; count++)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (count >= highest_outgoing_arg_in_use
|
if (count >= highest_outgoing_arg_in_use
|
||||||
|| stack_usage_map[count] == 0)
|
|| stack_usage_map[count] == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -3838,7 +3840,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||||
stack_area = gen_rtx_MEM (save_mode,
|
stack_area = gen_rtx_MEM (save_mode,
|
||||||
memory_address (save_mode,
|
memory_address (save_mode,
|
||||||
plus_constant (argblock,
|
plus_constant (argblock,
|
||||||
- high_to_save)));
|
-high_to_save)));
|
||||||
#else
|
#else
|
||||||
stack_area = gen_rtx_MEM (save_mode,
|
stack_area = gen_rtx_MEM (save_mode,
|
||||||
memory_address (save_mode,
|
memory_address (save_mode,
|
||||||
|
@ -3859,7 +3861,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Push the args that need to be pushed. */
|
/* Push the args that need to be pushed. */
|
||||||
|
|
||||||
/* ARGNUM indexes the ARGVEC array in the order in which the arguments
|
/* ARGNUM indexes the ARGVEC array in the order in which the arguments
|
||||||
|
@ -3899,7 +3901,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||||
if (i != upper_bound)
|
if (i != upper_bound)
|
||||||
{
|
{
|
||||||
/* We need to make a save area. See what mode we can make
|
/* We need to make a save area. See what mode we can make
|
||||||
it. */
|
it. */
|
||||||
enum machine_mode save_mode
|
enum machine_mode save_mode
|
||||||
= mode_for_size (argvec[argnum].size.constant
|
= mode_for_size (argvec[argnum].size.constant
|
||||||
* BITS_PER_UNIT,
|
* BITS_PER_UNIT,
|
||||||
|
@ -3985,7 +3987,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||||
force_operand (XEXP (mem_value, 0),
|
force_operand (XEXP (mem_value, 0),
|
||||||
NULL_RTX)));
|
NULL_RTX)));
|
||||||
if (GET_CODE (struct_value_rtx) == REG)
|
if (GET_CODE (struct_value_rtx) == REG)
|
||||||
use_reg (&call_fusage, struct_value_rtx);
|
use_reg (&call_fusage, struct_value_rtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't allow popping to be deferred, since then
|
/* Don't allow popping to be deferred, since then
|
||||||
|
@ -3997,7 +3999,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||||
#ifdef PREFERRED_STACK_BOUNDARY
|
#ifdef PREFERRED_STACK_BOUNDARY
|
||||||
/* Stack must be properly aligned now. */
|
/* Stack must be properly aligned now. */
|
||||||
if (stack_pointer_delta & (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT - 1))
|
if (stack_pointer_delta & (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT - 1))
|
||||||
abort();
|
abort ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* We pass the old value of inhibit_defer_pop + 1 to emit_call_1, which
|
/* We pass the old value of inhibit_defer_pop + 1 to emit_call_1, which
|
||||||
|
@ -4007,11 +4009,11 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||||
always signed. We also assume that the list of arguments passed has
|
always signed. We also assume that the list of arguments passed has
|
||||||
no impact, so we pretend it is unknown. */
|
no impact, so we pretend it is unknown. */
|
||||||
|
|
||||||
emit_call_1 (fun,
|
emit_call_1 (fun,
|
||||||
get_identifier (XSTR (orgfun, 0)),
|
get_identifier (XSTR (orgfun, 0)),
|
||||||
build_function_type (outmode == VOIDmode ? void_type_node
|
build_function_type (outmode == VOIDmode ? void_type_node
|
||||||
: type_for_mode (outmode, 0), NULL_TREE),
|
: type_for_mode (outmode, 0), NULL_TREE),
|
||||||
original_args_size.constant, args_size.constant,
|
original_args_size.constant, args_size.constant,
|
||||||
struct_value_size,
|
struct_value_size,
|
||||||
FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
|
FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
|
||||||
valreg,
|
valreg,
|
||||||
|
@ -4103,7 +4105,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||||
PARM_BOUNDARY);
|
PARM_BOUNDARY);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If we saved any argument areas, restore them. */
|
/* If we saved any argument areas, restore them. */
|
||||||
for (count = 0; count < nargs; count++)
|
for (count = 0; count < nargs; count++)
|
||||||
if (argvec[count].save_area)
|
if (argvec[count].save_area)
|
||||||
|
@ -4249,20 +4251,19 @@ target_for_arg (type, size, args_addr, offset)
|
||||||
or 0 on a machine where arguments are pushed individually.
|
or 0 on a machine where arguments are pushed individually.
|
||||||
|
|
||||||
MAY_BE_ALLOCA nonzero says this could be a call to `alloca'
|
MAY_BE_ALLOCA nonzero says this could be a call to `alloca'
|
||||||
so must be careful about how the stack is used.
|
so must be careful about how the stack is used.
|
||||||
|
|
||||||
VARIABLE_SIZE nonzero says that this was a variable-sized outgoing
|
VARIABLE_SIZE nonzero says that this was a variable-sized outgoing
|
||||||
argument stack. This is used if ACCUMULATE_OUTGOING_ARGS to indicate
|
argument stack. This is used if ACCUMULATE_OUTGOING_ARGS to indicate
|
||||||
that we need not worry about saving and restoring the stack.
|
that we need not worry about saving and restoring the stack.
|
||||||
|
|
||||||
FNDECL is the declaration of the function we are calling.
|
FNDECL is the declaration of the function we are calling.
|
||||||
|
|
||||||
Return non-zero if this arg should cause sibcall failure,
|
Return non-zero if this arg should cause sibcall failure,
|
||||||
zero otherwise. */
|
zero otherwise. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
store_one_arg (arg, argblock, flags, variable_size,
|
store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
|
||||||
reg_parm_stack_space)
|
|
||||||
struct arg_data *arg;
|
struct arg_data *arg;
|
||||||
rtx argblock;
|
rtx argblock;
|
||||||
int flags;
|
int flags;
|
||||||
|
@ -4330,7 +4331,7 @@ store_one_arg (arg, argblock, flags, variable_size,
|
||||||
arg->size.constant, 0);
|
arg->size.constant, 0);
|
||||||
MEM_SET_IN_STRUCT_P (arg->save_area,
|
MEM_SET_IN_STRUCT_P (arg->save_area,
|
||||||
AGGREGATE_TYPE_P (TREE_TYPE
|
AGGREGATE_TYPE_P (TREE_TYPE
|
||||||
(arg->tree_value)));
|
(arg->tree_value)));
|
||||||
preserve_temp_slots (arg->save_area);
|
preserve_temp_slots (arg->save_area);
|
||||||
emit_block_move (validize_mem (arg->save_area), stack_area,
|
emit_block_move (validize_mem (arg->save_area), stack_area,
|
||||||
GEN_INT (arg->size.constant),
|
GEN_INT (arg->size.constant),
|
||||||
|
@ -4366,7 +4367,7 @@ store_one_arg (arg, argblock, flags, variable_size,
|
||||||
here. */
|
here. */
|
||||||
if (arg->n_aligned_regs != 0)
|
if (arg->n_aligned_regs != 0)
|
||||||
reg = 0;
|
reg = 0;
|
||||||
|
|
||||||
/* If this is being passed partially in a register, we can't evaluate
|
/* If this is being passed partially in a register, we can't evaluate
|
||||||
it directly into its stack slot. Otherwise, we can. */
|
it directly into its stack slot. Otherwise, we can. */
|
||||||
if (arg->value == 0)
|
if (arg->value == 0)
|
||||||
|
@ -4420,7 +4421,7 @@ store_one_arg (arg, argblock, flags, variable_size,
|
||||||
if (current_function_check_memory_usage && GET_CODE (arg->stack) == MEM)
|
if (current_function_check_memory_usage && GET_CODE (arg->stack) == MEM)
|
||||||
{
|
{
|
||||||
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
|
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
|
||||||
XEXP (arg->stack, 0), Pmode,
|
XEXP (arg->stack, 0), Pmode,
|
||||||
ARGS_SIZE_RTX (arg->size),
|
ARGS_SIZE_RTX (arg->size),
|
||||||
TYPE_MODE (sizetype),
|
TYPE_MODE (sizetype),
|
||||||
GEN_INT (MEMORY_USE_RW),
|
GEN_INT (MEMORY_USE_RW),
|
||||||
|
@ -4434,7 +4435,7 @@ store_one_arg (arg, argblock, flags, variable_size,
|
||||||
/* Argument is a scalar, not entirely passed in registers.
|
/* Argument is a scalar, not entirely passed in registers.
|
||||||
(If part is passed in registers, arg->partial says how much
|
(If part is passed in registers, arg->partial says how much
|
||||||
and emit_push_insn will take care of putting it there.)
|
and emit_push_insn will take care of putting it there.)
|
||||||
|
|
||||||
Push it, and if its size is less than the
|
Push it, and if its size is less than the
|
||||||
amount of space allocated to it,
|
amount of space allocated to it,
|
||||||
also bump stack pointer by the additional space.
|
also bump stack pointer by the additional space.
|
||||||
|
@ -4532,9 +4533,8 @@ store_one_arg (arg, argblock, flags, variable_size,
|
||||||
ARGS_SIZE_RTX (arg->alignment_pad));
|
ARGS_SIZE_RTX (arg->alignment_pad));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Unless this is a partially-in-register argument, the argument is now
|
/* Unless this is a partially-in-register argument, the argument is now
|
||||||
in the stack.
|
in the stack.
|
||||||
|
|
||||||
??? Note that this can change arg->value from arg->stack to
|
??? Note that this can change arg->value from arg->stack to
|
||||||
arg->stack_slot and it matters when they are not the same.
|
arg->stack_slot and it matters when they are not the same.
|
||||||
|
|
Loading…
Reference in New Issue