#include "tree.h"
#include "flags.h"
#include "expr.h"
+#include "function.h"
#include "regs.h"
#include "insn-flags.h"
#include "toplev.h"
static int calls_function PROTO ((tree, int));
static int calls_function_1 PROTO ((tree, int));
static void emit_call_1 PROTO ((rtx, tree, tree, HOST_WIDE_INT,
- HOST_WIDE_INT, rtx, rtx,
- int, rtx, int));
+ HOST_WIDE_INT, HOST_WIDE_INT, rtx,
+ rtx, int, rtx, int));
static void special_function_p PROTO ((char *, tree, int *, int *,
int *, int *));
static void precompute_register_parameters PROTO ((int, struct arg_data *,
if ((DECL_BUILT_IN (fndecl)
&& DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA)
|| (DECL_SAVED_INSNS (fndecl)
- && (FUNCTION_FLAGS (DECL_SAVED_INSNS (fndecl))
- & FUNCTION_FLAGS_CALLS_ALLOCA)))
+ && DECL_SAVED_INSNS (fndecl)->calls_alloca))
return 1;
}
IS_CONST is true if this is a `const' call. */
static void
-emit_call_1 (funexp, fndecl, funtype, stack_size, struct_value_size,
- next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
- is_const)
+emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
+ struct_value_size, next_arg_reg, valreg, old_inhibit_defer_pop,
+ call_fusage, is_const)
rtx funexp;
tree fndecl ATTRIBUTE_UNUSED;
tree funtype ATTRIBUTE_UNUSED;
HOST_WIDE_INT stack_size;
+ HOST_WIDE_INT rounded_stack_size;
HOST_WIDE_INT struct_value_size;
rtx next_arg_reg;
rtx valreg;
rtx call_fusage;
int is_const;
{
- rtx stack_size_rtx = GEN_INT (stack_size);
+ rtx rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
rtx struct_value_size_rtx = GEN_INT (struct_value_size);
rtx call_insn;
#ifndef ACCUMULATE_OUTGOING_ARGS
int already_popped = 0;
+ HOST_WIDE_INT n_popped = RETURN_POPS_ARGS (fndecl, funtype, stack_size);
#endif
/* Ensure address is valid. SYMBOL_REF is already valid, so no need,
#ifndef ACCUMULATE_OUTGOING_ARGS
#if defined (HAVE_call_pop) && defined (HAVE_call_value_pop)
- if (HAVE_call_pop && HAVE_call_value_pop
- && (RETURN_POPS_ARGS (fndecl, funtype, stack_size) > 0
- || stack_size == 0))
+ if (HAVE_call_pop && HAVE_call_value_pop && n_popped > 0)
{
- rtx n_pop = GEN_INT (RETURN_POPS_ARGS (fndecl, funtype, stack_size));
+ rtx n_pop = GEN_INT (n_popped);
rtx pat;
/* If this subroutine pops its own args, record that in the call insn
if (valreg)
pat = gen_call_value_pop (valreg,
gen_rtx_MEM (FUNCTION_MODE, funexp),
- stack_size_rtx, next_arg_reg, n_pop);
+ rounded_stack_size_rtx, next_arg_reg, n_pop);
else
pat = gen_call_pop (gen_rtx_MEM (FUNCTION_MODE, funexp),
- stack_size_rtx, next_arg_reg, n_pop);
+ rounded_stack_size_rtx, next_arg_reg, n_pop);
emit_call_insn (pat);
already_popped = 1;
if (valreg)
emit_call_insn (gen_call_value (valreg,
gen_rtx_MEM (FUNCTION_MODE, funexp),
- stack_size_rtx, next_arg_reg,
+ rounded_stack_size_rtx, next_arg_reg,
NULL_RTX));
else
emit_call_insn (gen_call (gen_rtx_MEM (FUNCTION_MODE, funexp),
- stack_size_rtx, next_arg_reg,
+ rounded_stack_size_rtx, next_arg_reg,
struct_value_size_rtx));
}
else
If returning from the subroutine does pop the args, indicate that the
stack pointer will be changed. */
- if (stack_size != 0 && RETURN_POPS_ARGS (fndecl, funtype, stack_size) > 0)
+ if (n_popped > 0)
{
if (!already_popped)
CALL_INSN_FUNCTION_USAGE (call_insn)
= gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_CLOBBER (VOIDmode, stack_pointer_rtx),
CALL_INSN_FUNCTION_USAGE (call_insn));
- stack_size -= RETURN_POPS_ARGS (fndecl, funtype, stack_size);
- stack_size_rtx = GEN_INT (stack_size);
+ rounded_stack_size -= n_popped;
+ rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
}
- if (stack_size != 0)
+ if (rounded_stack_size != 0)
{
if (flag_defer_pop && inhibit_defer_pop == 0 && !is_const)
- pending_stack_adjust += stack_size;
+ pending_stack_adjust += rounded_stack_size;
else
- adjust_stack (stack_size_rtx);
+ adjust_stack (rounded_stack_size_rtx);
}
#endif
}
actparms, fndecl, args_so_far,
reg_parm_stack_space, old_stack_level,
old_pending_adj, must_preallocate, is_const)
- int num_actuals;
+ int num_actuals ATTRIBUTE_UNUSED;
struct arg_data *args;
struct args_size *args_size;
- int n_named_args;
+ int n_named_args ATTRIBUTE_UNUSED;
tree actparms;
tree fndecl;
CUMULATIVE_ARGS *args_so_far;
else
{
#ifdef PREFERRED_STACK_BOUNDARY
- args_size->constant = (((args_size->constant + (STACK_BYTES - 1))
- / STACK_BYTES) * STACK_BYTES);
+ args_size->constant = (((args_size->constant
+ + pending_stack_adjust
+ + STACK_BYTES - 1)
+ / STACK_BYTES * STACK_BYTES)
+ - pending_stack_adjust);
#endif
args_size->constant = MAX (args_size->constant,
else
/* Generate an rtx (probably a pseudo-register) for the address. */
{
+ rtx funaddr;
push_temp_slots ();
- funexp = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
+ funaddr = 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);
+ {
+#ifdef POINTERS_EXTEND_UNSIGNED
+ /* It might be OK to convert funexp in place, but there's
+ a lot going on between here and when it happens naturally
+ that this seems safer. */
+ funaddr = convert_memory_address (Pmode, funexp);
+#endif
+ emit_library_call (chkr_check_exec_libfunc, 1,
+ VOIDmode, 1,
+ funaddr, Pmode);
+ }
emit_queue ();
}
return funexp;
&& fndecl != current_function_decl
&& DECL_INLINE (fndecl)
&& DECL_SAVED_INSNS (fndecl)
- && RTX_INTEGRATED_P (DECL_SAVED_INSNS (fndecl)))
+ && DECL_SAVED_INSNS (fndecl)->inlinable)
is_integrable = 1;
else if (! TREE_ADDRESSABLE (fndecl))
{
rtx insn, seq;
/* Look for a call in the inline function code.
- If OUTGOING_ARGS_SIZE (DECL_SAVED_INSNS (fndecl)) is
+ If DECL_SAVED_INSNS (fndecl)->outgoing_args_size is
nonzero then there is a call and it is not necessary
to scan the insns. */
- if (OUTGOING_ARGS_SIZE (DECL_SAVED_INSNS (fndecl)) == 0)
+ if (DECL_SAVED_INSNS (fndecl)->outgoing_args_size == 0)
for (insn = first_insn; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == CALL_INSN)
break;
value of reg_parm_stack_space is wrong, but gives
correct results on all supported machines. */
- int adjust = (OUTGOING_ARGS_SIZE (DECL_SAVED_INSNS (fndecl))
+ int adjust = (DECL_SAVED_INSNS (fndecl)->outgoing_args_size
+ reg_parm_stack_space);
start_sequence ();
if (current_function_check_memory_usage)
emit_library_call (chkr_set_right_libfunc, 1,
VOIDmode, 3,
- structure_value_addr, ptr_mode,
+ structure_value_addr, Pmode,
GEN_INT (struct_value_size), TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_WO),
TYPE_MODE (integer_type_node));
/* All arguments and registers used for the call must be set up by now! */
/* Generate the actual call instruction. */
- emit_call_1 (funexp, fndecl, funtype, args_size.constant, struct_value_size,
+ emit_call_1 (funexp, fndecl, funtype, unadjusted_args_size,
+ args_size.constant, struct_value_size,
FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
valreg, old_inhibit_defer_pop, call_fusage, is_const);
get_identifier (XSTR (orgfun, 0)),
build_function_type (outmode == VOIDmode ? void_type_node
: type_for_mode (outmode, 0), NULL_TREE),
- args_size.constant, 0,
+ original_args_size.constant, args_size.constant, 0,
FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
outmode != VOIDmode ? hard_libcall_value (outmode) : NULL_RTX,
old_inhibit_defer_pop + 1, call_fusage, no_queue);
emit_call_1 (fun,
get_identifier (XSTR (orgfun, 0)),
build_function_type (type_for_mode (outmode, 0), NULL_TREE),
- args_size.constant, struct_value_size,
+ original_args_size.constant, args_size.constant,
+ struct_value_size,
FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
mem_value == 0 ? hard_libcall_value (outmode) : NULL_RTX,
old_inhibit_defer_pop + 1, call_fusage, is_const);
if (current_function_check_memory_usage && GET_CODE (arg->stack) == MEM)
{
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
- XEXP (arg->stack, 0), ptr_mode,
+ XEXP (arg->stack, 0), Pmode,
ARGS_SIZE_RTX (arg->size),
TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW),