aboutsummaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/calls.c')
-rw-r--r--gcc/calls.c113
1 files changed, 65 insertions, 48 deletions
diff --git a/gcc/calls.c b/gcc/calls.c
index 9c77b879701..3c20fa3d6d8 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -27,26 +27,12 @@ Boston, MA 02111-1307, USA. */
#include "expr.h"
#include "function.h"
#include "regs.h"
-#include "insn-flags.h"
#include "toplev.h"
#include "output.h"
#include "tm_p.h"
#include "timevar.h"
#include "sbitmap.h"
-#ifndef ACCUMULATE_OUTGOING_ARGS
-#define ACCUMULATE_OUTGOING_ARGS 0
-#endif
-
-/* Supply a default definition for PUSH_ARGS. */
-#ifndef PUSH_ARGS
-#ifdef PUSH_ROUNDING
-#define PUSH_ARGS !ACCUMULATE_OUTGOING_ARGS
-#else
-#define PUSH_ARGS 0
-#endif
-#endif
-
#if !defined FUNCTION_OK_FOR_SIBCALL
#define FUNCTION_OK_FOR_SIBCALL(DECL) 1
#endif
@@ -218,7 +204,6 @@ static void compute_argument_addresses PARAMS ((struct arg_data *,
static rtx rtx_for_function_call PARAMS ((tree, tree));
static void load_register_parameters PARAMS ((struct arg_data *,
int, rtx *, int));
-static int libfunc_nothrow PARAMS ((rtx));
static rtx emit_library_call_value_1 PARAMS ((int, rtx, rtx,
enum libcall_type,
enum machine_mode,
@@ -2384,8 +2369,8 @@ expand_call (exp, target, ignore)
args = (struct arg_data *) alloca (num_actuals * sizeof (struct arg_data));
memset ((char *) args, 0, num_actuals * sizeof (struct arg_data));
- /* Build up entries inthe ARGS array, compute the size of the arguments
- into ARGS_SIZE, etc. */
+ /* Build up entries in the ARGS array, compute the size of the
+ arguments into ARGS_SIZE, etc. */
initialize_argument_information (num_actuals, args, &args_size,
n_named_args, actparms, fndecl,
&args_so_far, reg_parm_stack_space,
@@ -2526,8 +2511,9 @@ expand_call (exp, target, ignore)
{
tree var = build_decl (VAR_DECL, NULL_TREE,
TREE_TYPE (args[i].tree_value));
- DECL_RTL (var) = expand_expr (args[i].tree_value, NULL_RTX,
- VOIDmode, EXPAND_NORMAL);
+ SET_DECL_RTL (var,
+ expand_expr (args[i].tree_value, NULL_RTX,
+ VOIDmode, EXPAND_NORMAL));
args[i].tree_value = var;
}
break;
@@ -3457,25 +3443,9 @@ expand_call (exp, target, ignore)
return target;
}
-/* Returns nonzero if FUN is the symbol for a library function which can
- not throw. */
-
-static int
-libfunc_nothrow (fun)
- rtx fun;
-{
- if (fun == throw_libfunc
- || fun == rethrow_libfunc
- || fun == sjthrow_libfunc
- || fun == sjpopnthrow_libfunc)
- return 0;
-
- return 1;
-}
-
/* Output a library call to function FUN (a SYMBOL_REF rtx).
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 below. */
static rtx
emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
int retval;
@@ -3514,9 +3484,10 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
rtx valreg;
int pcc_struct_value = 0;
int struct_value_size = 0;
- int flags = 0;
+ int flags;
int reg_parm_stack_space = 0;
int needed;
+ rtx before_call;
#ifdef REG_PARM_STACK_SPACE
/* Define the boundary of the register parm stack space that needs to be
@@ -3537,14 +3508,30 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
#endif
#endif
- if (fn_type == LCT_CONST_MAKE_BLOCK)
- flags |= ECF_CONST;
- else if (fn_type == LCT_PURE_MAKE_BLOCK)
- flags |= ECF_PURE;
- fun = orgfun;
+ /* By default, library functions can not throw. */
+ flags = ECF_NOTHROW;
- if (libfunc_nothrow (fun))
- flags |= ECF_NOTHROW;
+ switch (fn_type)
+ {
+ case LCT_NORMAL:
+ case LCT_CONST:
+ case LCT_PURE:
+ /* Nothing to do here. */
+ break;
+ case LCT_CONST_MAKE_BLOCK:
+ flags |= ECF_CONST;
+ break;
+ case LCT_PURE_MAKE_BLOCK:
+ flags |= ECF_PURE;
+ break;
+ case LCT_NORETURN:
+ flags |= ECF_NORETURN;
+ break;
+ case LCT_THROW:
+ flags = ECF_NORETURN;
+ break;
+ }
+ fun = orgfun;
#ifdef PREFERRED_STACK_BOUNDARY
/* Ensure current function's preferred stack boundary is at least
@@ -4054,6 +4041,8 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
abort ();
#endif
+ before_call = get_last_insn ();
+
/* We pass the old value of inhibit_defer_pop + 1 to emit_call_1, which
will set inhibit_defer_pop to that value. */
/* The return type is needed to decide how many bytes the function pops.
@@ -4071,6 +4060,34 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
valreg,
old_inhibit_defer_pop + 1, call_fusage, flags);
+ /* For calls to `setjmp', etc., inform flow.c it should complain
+ if nonvolatile values are live. For functions that cannot return,
+ inform flow that control does not fall through. */
+
+ if (flags & (ECF_RETURNS_TWICE | ECF_NORETURN | ECF_LONGJMP))
+ {
+ /* The barrier or NOTE_INSN_SETJMP note must be emitted
+ immediately after the CALL_INSN. Some ports emit more than
+ just a CALL_INSN above, so we must search for it here. */
+
+ rtx last = get_last_insn ();
+ while (GET_CODE (last) != CALL_INSN)
+ {
+ last = PREV_INSN (last);
+ /* There was no CALL_INSN? */
+ if (last == before_call)
+ abort ();
+ }
+
+ if (flags & ECF_RETURNS_TWICE)
+ {
+ emit_note_after (NOTE_INSN_SETJMP, last);
+ current_function_calls_setjmp = 1;
+ }
+ else
+ emit_barrier_after (last);
+ }
+
/* Now restore inhibit_defer_pop to its actual original value. */
OK_DEFER_POP;
@@ -4593,10 +4610,10 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
{
rtx size_rtx1 = GEN_INT (reg_parm_stack_space - arg->offset.constant);
emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx1,
- TYPE_ALIGN (TREE_TYPE (pval)) / BITS_PER_UNIT,
- partial, reg, excess, argblock,
- ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
- ARGS_SIZE_RTX (arg->alignment_pad));
+ TYPE_ALIGN (TREE_TYPE (pval)), partial, reg,
+ excess, argblock, ARGS_SIZE_RTX (arg->offset),
+ reg_parm_stack_space,
+ ARGS_SIZE_RTX (arg->alignment_pad));
size_rtx = GEN_INT (INTVAL(size_rtx) - reg_parm_stack_space);
}