diff options
Diffstat (limited to 'gcc/calls.c')
-rw-r--r-- | gcc/calls.c | 113 |
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); } |