#define PUSH_ARGS_REVERSED 0
#endif
+#ifndef STACK_POINTER_OFFSET
+#define STACK_POINTER_OFFSET 0
+#endif
+
/* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits. */
#define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
if ((flags & (ECF_CONST | ECF_PURE))
|| calls_function (args[i].tree_value, !ACCUMULATE_OUTGOING_ARGS))
{
+ enum machine_mode mode;
+
/* If this is an addressable type, we cannot pre-evaluate it. */
if (TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)))
abort ();
args[i].initial_value = args[i].value
= protect_from_queue (args[i].value, 0);
- if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) != args[i].mode)
+ mode = TYPE_MODE (TREE_TYPE (args[i].tree_value));
+ if (mode != args[i].mode)
{
args[i].value
- = convert_modes (args[i].mode,
- TYPE_MODE (TREE_TYPE (args[i].tree_value)),
+ = convert_modes (args[i].mode, mode,
args[i].value, args[i].unsignedp);
#ifdef PROMOTE_FOR_CALL_ONLY
/* CSE will replace this only if it contains args[i].value
&& GET_MODE_CLASS (args[i].mode) == MODE_INT)
{
args[i].initial_value
- = gen_rtx_SUBREG (TYPE_MODE (TREE_TYPE (args[i].tree_value)),
- args[i].value, 0);
+ = gen_lowpart_SUBREG (mode, args[i].value);
SUBREG_PROMOTED_VAR_P (args[i].initial_value) = 1;
SUBREG_PROMOTED_UNSIGNED_P (args[i].initial_value)
= args[i].unsignedp;
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,
{
tree type = TREE_TYPE (exp);
int unsignedp = TREE_UNSIGNED (type);
+ int offset = 0;
/* If we don't promote as expected, something is wrong. */
if (GET_MODE (target)
!= promote_mode (type, TYPE_MODE (type), &unsignedp, 1))
abort ();
- target = gen_rtx_SUBREG (TYPE_MODE (type), target, 0);
+ if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
+ && GET_MODE_SIZE (GET_MODE (target))
+ > GET_MODE_SIZE (TYPE_MODE (type)))
+ {
+ offset = GET_MODE_SIZE (GET_MODE (target))
+ - GET_MODE_SIZE (TYPE_MODE (type));
+ if (! BYTES_BIG_ENDIAN)
+ offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
+ else if (! WORDS_BIG_ENDIAN)
+ offset %= UNITS_PER_WORD;
+ }
+ target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
SUBREG_PROMOTED_VAR_P (target) = 1;
SUBREG_PROMOTED_UNSIGNED_P (target) = unsignedp;
}
#endif
#endif
- /* No library functions can throw. */
+ /* By default, library functions can not throw. */
flags = ECF_NOTHROW;
- if (fn_type == LCT_CONST_MAKE_BLOCK)
- flags |= ECF_CONST;
- else if (fn_type == LCT_PURE_MAKE_BLOCK)
- flags |= ECF_PURE;
- else if (fn_type == LCT_NORETURN)
- flags |= ECF_NORETURN;
+ 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
highest_outgoing_arg_in_use - initial_highest_arg_in_use);
needed = 0;
- /* The address of the outgoing argument list must not be copied to a
- register here, because argblock would be left pointing to the
- wrong place after the call to allocate_dynamic_stack_space below. */
+ /* We must be careful to use virtual regs before they're instantiated,
+ and real regs afterwards. Loop optimization, for example, can create
+ new libcalls after we've instantiated the virtual regs, and if we
+ use virtuals anyway, they won't match the rtl patterns. */
- argblock = virtual_outgoing_args_rtx;
+ if (virtuals_instantiated)
+ argblock = plus_constant (stack_pointer_rtx, STACK_POINTER_OFFSET);
+ else
+ argblock = virtual_outgoing_args_rtx;
}
else
{
{
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,
+ 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);