/* If REG was promoted from the actual mode of the argument expression,
indicates whether the promotion is sign- or zero-extended. */
int unsignedp;
- /* Number of registers to use. 0 means put the whole arg in registers.
- Also 0 if not passed in registers. */
+ /* Number of bytes to put in registers. 0 means put the whole arg
+ in registers. Also 0 if not passed in registers. */
int partial;
/* Nonzero if argument must be passed on stack.
Note that some arguments may be passed on the stack
returns a BLKmode struct) and expand_call must take special action
to make sure the object being constructed does not overlap the
argument list for the constructor call. */
-int stack_arg_under_construction;
+static int stack_arg_under_construction;
static void emit_call_1 (rtx, tree, tree, tree, HOST_WIDE_INT, HOST_WIDE_INT,
HOST_WIDE_INT, rtx, rtx, int, rtx, int,
if (ecf_flags & ECF_NORETURN)
REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_NORETURN, const0_rtx,
REG_NOTES (call_insn));
- if (ecf_flags & ECF_ALWAYS_RETURN)
- REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_ALWAYS_RETURN, const0_rtx,
- REG_NOTES (call_insn));
if (ecf_flags & ECF_RETURNS_TWICE)
{
For example, if the function might return more than one time (setjmp), then
set RETURNS_TWICE to a nonzero value.
- Similarly set LONGJMP for if the function is in the longjmp family.
+ Similarly set NORETURN if the function is in the longjmp family.
Set MAY_BE_ALLOCA for any memory allocation function that might allocate
space from the stack such as alloca. */
return flags;
}
-/* Return nonzero when tree represent call to longjmp. */
+/* Return nonzero when FNDECL represents a call to setjmp. */
int
setjmp_call_p (tree fndecl)
if (DECL_IS_MALLOC (exp))
flags |= ECF_MALLOC;
+ /* The function exp may have the `returns_twice' attribute. */
+ if (DECL_IS_RETURNS_TWICE (exp))
+ flags |= ECF_RETURNS_TWICE;
+
/* The function exp may have the `pure' attribute. */
if (DECL_IS_PURE (exp))
flags |= ECF_PURE | ECF_LIBCALL_BLOCK;
+ if (DECL_IS_NOVOPS (exp))
+ flags |= ECF_NOVOPS;
+
if (TREE_NOTHROW (exp))
flags |= ECF_NOTHROW;
int nregs;
int size = 0;
rtx before_arg = get_last_insn ();
- /* Set to non-negative if must move a word at a time, even if just
- one word (e.g, partial == 1 && mode == DFmode). Set to -1 if
- we just use a normal move insn. This value can be zero if the
- argument is a zero size structure with no fields. */
+ /* Set non-negative if we must move a word at a time, even if
+ just one word (e.g, partial == 4 && mode == DFmode). Set
+ to -1 if we just use a normal move insn. This value can be
+ zero if the argument is a zero size structure. */
nregs = -1;
if (GET_CODE (reg) == PARALLEL)
;
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
i = INTVAL (XEXP (XEXP (x, 0), 1));
else
- return 1;
+ return 0;
#ifdef ARGS_GROW_DOWNWARD
i = -i - GET_MODE_SIZE (GET_MODE (x));
return true;
}
-/* Remove all REG_EQUIV notes found in the insn chain. */
-
-static void
-purge_reg_equiv_notes (void)
-{
- rtx insn;
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- while (1)
- {
- rtx note = find_reg_note (insn, REG_EQUIV, 0);
- if (note)
- {
- /* Remove the note and keep looking at the notes for
- this insn. */
- remove_note (insn, note);
- continue;
- }
- break;
- }
- }
-}
-
/* Generate all the code for a function call
and return an rtx for its value.
Store the value in TARGET (specified as an rtx) if convenient.
/* Warn if this value is an aggregate type,
regardless of which calling convention we are using for it. */
- if (warn_aggregate_return && AGGREGATE_TYPE_P (TREE_TYPE (exp)))
- warning ("function call has aggregate value");
+ if (AGGREGATE_TYPE_P (TREE_TYPE (exp)))
+ warning (OPT_Waggregate_return, "function call has aggregate value");
/* If the result of a pure or const function call is ignored (or void),
and none of its arguments are volatile, we can avoid expanding the
the argument areas are shared. */
|| (fndecl && decl_function_context (fndecl) == current_function_decl)
/* If this function requires more stack slots than the current
- function, we cannot change it into a sibling call. */
- || args_size.constant > current_function_args_size
+ function, we cannot change it into a sibling call.
+ current_function_pretend_args_size is not part of the
+ stack allocated by our caller. */
+ || args_size.constant > (current_function_args_size
+ - current_function_pretend_args_size)
/* If the callee pops its own arguments, then it must pop exactly
the same number of arguments as the current function. */
|| (RETURN_POPS_ARGS (fndecl, funtype, args_size.constant)
Also, do all pending adjustments now if there is any chance
this might be a call to alloca or if we are expanding a sibling
call sequence or if we are calling a function that is to return
- with stack pointer depressed. */
+ with stack pointer depressed.
+ Also do the adjustments before a throwing call, otherwise
+ exception handling can fail; PR 19225. */
if (pending_stack_adjust >= 32
|| (pending_stack_adjust > 0
&& (flags & (ECF_MAY_BE_ALLOCA | ECF_SP_DEPRESSED)))
+ || (pending_stack_adjust > 0
+ && flag_exceptions && !(flags & ECF_NOTHROW))
|| pass == 0)
do_pending_stack_adjust ();
end_sequence ();
if (flag_unsafe_math_optimizations
&& fndecl
- && DECL_BUILT_IN (fndecl)
+ && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
&& (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SQRT
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SQRTF
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SQRTL))
this function's incoming arguments.
At the start of RTL generation we know the only REG_EQUIV notes
- in the rtl chain are those for incoming arguments, so we can safely
- flush any REG_EQUIV note.
+ in the rtl chain are those for incoming arguments, so we can look
+ for REG_EQUIV notes between the start of the function and the
+ NOTE_INSN_FUNCTION_BEG.
This is (slight) overkill. We could keep track of the highest
argument we clobber and be more selective in removing notes, but it
does not seem to be worth the effort. */
+
void
fixup_tail_calls (void)
{
- purge_reg_equiv_notes ();
+ rtx insn;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ /* There are never REG_EQUIV notes for the incoming arguments
+ after the NOTE_INSN_FUNCTION_BEG note, so stop if we see it. */
+ if (NOTE_P (insn)
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
+ break;
+
+ while (1)
+ {
+ rtx note = find_reg_note (insn, REG_EQUIV, 0);
+ if (note)
+ {
+ /* Remove the note and keep looking at the notes for
+ this insn. */
+ remove_note (insn, note);
+ continue;
+ }
+ break;
+ }
+ }
}
/* Traverse an argument list in VALUES and expand all complex
case LCT_THROW:
flags = ECF_NORETURN;
break;
- case LCT_ALWAYS_RETURN:
- flags = ECF_ALWAYS_RETURN;
- break;
case LCT_RETURNS_TWICE:
flags = ECF_RETURNS_TWICE;
break;