/* The function exp may have the `pure' attribute. */
if (DECL_IS_PURE (exp))
- flags |= ECF_PURE | ECF_LIBCALL_BLOCK;
+ flags |= ECF_PURE;
if (DECL_IS_NOVOPS (exp))
flags |= ECF_NOVOPS;
flags |= ECF_NOTHROW;
if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
- flags |= ECF_LIBCALL_BLOCK | ECF_CONST;
+ flags |= ECF_CONST;
flags = special_function_p (exp, flags);
}
if (TREE_CODE (type) == FUNCTION_TYPE && TYPE_RETURNS_STACK_DEPRESSED (type))
{
flags |= ECF_SP_DEPRESSED;
- flags &= ~(ECF_PURE | ECF_CONST | ECF_LIBCALL_BLOCK);
+ flags &= ~(ECF_PURE | ECF_CONST);
}
return flags;
return funexp;
}
+/* Return true if and only if SIZE storage units (usually bytes)
+ starting from address ADDR overlap with already clobbered argument
+ area. This function is used to determine if we should give up a
+ sibcall. */
+
+static bool
+mem_overlaps_already_clobbered_arg_p (rtx addr, unsigned HOST_WIDE_INT size)
+{
+ HOST_WIDE_INT i;
+
+ if (addr == current_function_internal_arg_pointer)
+ i = 0;
+ else if (GET_CODE (addr) == PLUS
+ && (XEXP (addr, 0)
+ == current_function_internal_arg_pointer)
+ && GET_CODE (XEXP (addr, 1)) == CONST_INT)
+ i = INTVAL (XEXP (addr, 1));
+ else
+ return false;
+
+#ifdef ARGS_GROW_DOWNWARD
+ i = -i - size;
+#endif
+ if (size > 0)
+ {
+ unsigned HOST_WIDE_INT k;
+
+ for (k = 0; k < size; k++)
+ if (i + k < stored_args_map->n_bits
+ && TEST_BIT (stored_args_map, i + k))
+ return true;
+ }
+
+ return false;
+}
+
/* 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
expressions were already evaluated.
Mark all register-parms as living through the call, putting these USE
insns in the CALL_INSN_FUNCTION_USAGE field.
- When IS_SIBCALL, perform the check_sibcall_overlap_argument_overlap
+ When IS_SIBCALL, perform the check_sibcall_argument_overlap
checking, setting *SIBCALL_FAILURE if appropriate. */
static void
{
rtx mem = validize_mem (args[i].value);
+ /* Check for overlap with already clobbered argument area. */
+ if (is_sibcall
+ && mem_overlaps_already_clobbered_arg_p (XEXP (args[i].value, 0),
+ size))
+ *sibcall_failure = 1;
+
/* Handle a BLKmode that needs shifting. */
if (nregs == 1 && size < UNITS_PER_WORD
#ifdef BLOCK_REG_PADDING
{
RTX_CODE code;
int i, j;
- unsigned int k;
const char *fmt;
if (x == NULL_RTX)
code = GET_CODE (x);
if (code == MEM)
- {
- if (XEXP (x, 0) == current_function_internal_arg_pointer)
- i = 0;
- else if (GET_CODE (XEXP (x, 0)) == PLUS
- && XEXP (XEXP (x, 0), 0) ==
- current_function_internal_arg_pointer
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
- i = INTVAL (XEXP (XEXP (x, 0), 1));
- else
- return 0;
-
-#ifdef ARGS_GROW_DOWNWARD
- i = -i - GET_MODE_SIZE (GET_MODE (x));
-#endif
-
- for (k = 0; k < GET_MODE_SIZE (GET_MODE (x)); k++)
- if (i + k < stored_args_map->n_bits
- && TEST_BIT (stored_args_map, i + k))
- return 1;
-
- return 0;
- }
+ return mem_overlaps_already_clobbered_arg_p (XEXP (x, 0),
+ GET_MODE_SIZE (GET_MODE (x)));
/* Scan all subexpressions. */
fmt = GET_RTX_FORMAT (code);
if (pass && (flags & (ECF_LIBCALL_BLOCK | ECF_MALLOC)))
start_sequence ();
+ if (pass == 0 && cfun->stack_protect_guard)
+ stack_protect_epilogue ();
+
adjusted_args_size = args_size;
/* Compute the actual size of the argument block required. The variable
and constant sizes must be combined, the size may have to be rounded,
use = plus_constant (argblock,
argvec[argnum].locate.offset.constant);
else
- /* When arguemnts are pushed, trying to tell alias.c where
+ /* When arguments are pushed, trying to tell alias.c where
exactly this argument is won't work, because the
auto-increment causes confusion. So we merely indicate
that we access something with a known mode somewhere on
}
/* Check for overlap with already clobbered argument area. */
- if ((flags & ECF_SIBCALL) && MEM_P (arg->value))
- {
- int i = -1;
- unsigned int k;
- rtx x = arg->value;
-
- if (XEXP (x, 0) == current_function_internal_arg_pointer)
- i = 0;
- else if (GET_CODE (XEXP (x, 0)) == PLUS
- && XEXP (XEXP (x, 0), 0) ==
- current_function_internal_arg_pointer
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
- i = INTVAL (XEXP (XEXP (x, 0), 1));
- else
- i = -1;
-
- if (i >= 0)
- {
-#ifdef ARGS_GROW_DOWNWARD
- i = -i - arg->locate.size.constant;
-#endif
- for (k = 0; k < arg->locate.size.constant; k++)
- if (i + k < stored_args_map->n_bits
- && TEST_BIT (stored_args_map, i + k))
- {
- sibcall_failure = 1;
- break;
- }
- }
- }
+ if ((flags & ECF_SIBCALL)
+ && MEM_P (arg->value)
+ && mem_overlaps_already_clobbered_arg_p (XEXP (arg->value, 0),
+ arg->locate.size.constant))
+ sibcall_failure = 1;
/* Don't allow anything left on stack from computation
of argument to alloca. */