(struct arg_data): New field MODE.

(expand_call, store_one_arg): Use it to ensure that all args get
promoted if requested, not just those passed in registers.

From-SVN: r3436
This commit is contained in:
Richard Kenner 1993-02-07 16:12:57 -05:00
parent 2e90c25ade
commit 1efe644834
1 changed files with 30 additions and 21 deletions

View File

@ -42,6 +42,8 @@ struct arg_data
{
/* 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. */
@ -947,6 +949,7 @@ expand_call (exp, target, ignore)
}
#endif
args[i].mode = mode;
args[i].reg = FUNCTION_ARG (args_so_far, mode, type,
argpos < n_named_args);
#ifdef FUNCTION_ARG_PARTIAL_NREGS
@ -985,7 +988,7 @@ expand_call (exp, target, ignore)
|| 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
@ -1176,7 +1179,13 @@ expand_call (exp, target, ignore)
{
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,
@ -1367,8 +1376,7 @@ expand_call (exp, target, ignore)
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));
@ -1376,8 +1384,7 @@ expand_call (exp, target, ignore)
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);
}
}
@ -1426,8 +1433,6 @@ expand_call (exp, target, ignore)
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)
@ -1444,11 +1449,10 @@ expand_call (exp, target, ignore)
/* 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);
}
@ -1608,7 +1612,7 @@ expand_call (exp, target, ignore)
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)
@ -2019,6 +2023,14 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl,
#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--;
@ -2033,7 +2045,7 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl,
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;
@ -2047,7 +2059,7 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl,
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. */
@ -2058,17 +2070,15 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl,
/* 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
{
@ -2099,8 +2109,7 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl,
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));
}