{
/* Tree node for this argument. */
tree tree_value;
+ /* Mode for value; TYPE_MODE unless promoted. */
+ enum machine_mode mode;
/* Current RTL value for argument, or 0 if it isn't precomputed. */
rtx value;
/* Initially-compute RTL value for argument; only for const functions. */
}
#endif
+ args[i].mode = mode;
args[i].reg = FUNCTION_ARG (args_so_far, mode, type,
argpos < n_named_args);
#ifdef FUNCTION_ARG_PARTIAL_NREGS
|| reg_parm_stack_space > 0
#endif
|| args[i].pass_on_stack)
- locate_and_pad_parm (TYPE_MODE (type), type,
+ locate_and_pad_parm (mode, type,
#ifdef STACK_PARMS_IN_REG_PARM_AREA
1,
#else
{
args[i].initial_value = args[i].value
= expand_expr (args[i].tree_value, NULL_RTX, VOIDmode, 0);
+
+ if (GET_MODE (args[i].value ) != VOIDmode
+ && GET_MODE (args[i].value) != args[i].mode)
+ args[i].value = convert_to_mode (args[i].mode, args[i].value,
+ args[i].unsignedp);
preserve_temp_slots (args[i].value);
+
free_temp_slots ();
/* ANSI doesn't require a sequence point here,
addr = gen_rtx (PLUS, Pmode, arg_reg, offset);
addr = plus_constant (addr, arg_offset);
- args[i].stack
- = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (args[i].tree_value)), addr);
+ args[i].stack = gen_rtx (MEM, args[i].mode, addr);
if (GET_CODE (slot_offset) == CONST_INT)
addr = plus_constant (arg_reg, INTVAL (slot_offset));
addr = gen_rtx (PLUS, Pmode, arg_reg, slot_offset);
addr = plus_constant (addr, arg_offset);
- args[i].stack_slot
- = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (args[i].tree_value)), addr);
+ args[i].stack_slot = gen_rtx (MEM, args[i].mode, addr);
}
}
for (i = 0; i < num_actuals; i++)
if (args[i].reg != 0 && ! args[i].pass_on_stack)
{
- enum machine_mode mode;
-
reg_parm_seen = 1;
if (args[i].value == 0)
/* If we are to promote the function arg to a wider mode,
do it now. */
- mode = (GET_CODE (args[i].reg) == EXPR_LIST
- ? GET_MODE (XEXP (args[i].reg, 0)) : GET_MODE (args[i].reg));
- if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) != mode)
- args[i].value = convert_to_mode (mode, args[i].value,
+ if (GET_MODE (args[i].value) != VOIDmode
+ && GET_MODE (args[i].value) != args[i].mode)
+ args[i].value = convert_to_mode (args[i].mode, args[i].value,
args[i].unsignedp);
}
else if (args[i].partial == 0 || args[i].pass_on_stack)
move_block_to_reg (REGNO (reg),
validize_mem (args[i].value), nregs,
- TYPE_MODE (TREE_TYPE (args[i].tree_value)));
+ args[i].mode);
push_to_sequence (use_insns);
if (nregs == 0)
#endif
arg->value = expand_expr (pval, partial ? NULL_RTX : arg->stack,
VOIDmode, 0);
+
+ /* If we are promoting object (or for any other reason) the mode
+ doesn't agree, convert the mode. */
+
+ if (GET_MODE (arg->value) != VOIDmode
+ && GET_MODE (arg->value) != arg->mode)
+ arg->value = convert_to_mode (arg->mode, arg->value, arg->unsignedp);
+
#ifdef ACCUMULATE_OUTGOING_ARGS
if (arg->pass_on_stack)
stack_arg_under_construction--;
if (arg->value == arg->stack)
/* If the value is already in the stack slot, we are done. */
;
- else if (TYPE_MODE (TREE_TYPE (pval)) != BLKmode)
+ else if (arg->mode != BLKmode)
{
register int size;
Note that in C the default argument promotions
will prevent such mismatches. */
- size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (pval)));
+ size = GET_MODE_SIZE (arg->mode);
/* Compute how much space the push instruction will push.
On many machines, pushing a byte will advance the stack
pointer by a halfword. */
/* Compute how much space the argument should get:
round up to a multiple of the alignment for arguments. */
- if (none != FUNCTION_ARG_PADDING (TYPE_MODE (TREE_TYPE (pval)),
- TREE_TYPE (pval)))
+ if (none != FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)))
used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
/ (PARM_BOUNDARY / BITS_PER_UNIT))
* (PARM_BOUNDARY / BITS_PER_UNIT));
/* This isn't already where we want it on the stack, so put it there.
This can either be done with push or copy insns. */
- emit_push_insn (arg->value, TYPE_MODE (TREE_TYPE (pval)),
- TREE_TYPE (pval), 0, 0, partial, reg,
- used - size, argblock, ARGS_SIZE_RTX (arg->offset));
+ emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), 0, 0, partial,
+ reg, used - size, argblock, ARGS_SIZE_RTX (arg->offset));
}
else
{
size_rtx = expand_expr (size, NULL_RTX, VOIDmode, 0);
}
- emit_push_insn (arg->value, TYPE_MODE (TREE_TYPE (pval)),
- TREE_TYPE (pval), size_rtx,
+ emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
TYPE_ALIGN (TREE_TYPE (pval)) / BITS_PER_UNIT, partial,
reg, excess, argblock, ARGS_SIZE_RTX (arg->offset));
}