(struct arg_data): New field unsignedp.

(expand_call): Handle PROMOTE_FUNCTION_ARGS and PROMOTE_FUNCTION_RETURN.

From-SVN: r2264
This commit is contained in:
Richard Kenner 1992-09-27 18:19:16 -04:00
parent a53e14c093
commit 84b55618e8
1 changed files with 59 additions and 4 deletions

View File

@ -50,6 +50,9 @@ struct arg_data
EXPR_LIST if the arg is to be copied into multiple different
registers. */
rtx reg;
/* 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. */
int partial;
@ -854,6 +857,7 @@ expand_call (exp, target, ignore)
for (p = actparms, argpos = 0; p; p = TREE_CHAIN (p), i += inc, argpos++)
{
tree type = TREE_TYPE (TREE_VALUE (p));
enum machine_mode mode;
args[i].tree_value = TREE_VALUE (p);
@ -914,16 +918,31 @@ expand_call (exp, target, ignore)
}
#endif
args[i].reg = FUNCTION_ARG (args_so_far, TYPE_MODE (type), type,
mode = TYPE_MODE (type);
#ifdef PROMOTE_FUNCTION_ARGS
/* Compute the mode in which the arg is actually to be extended to. */
if (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == ENUMERAL_TYPE
|| TREE_CODE (type) == BOOLEAN_TYPE || TREE_CODE (type) == CHAR_TYPE
|| TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == POINTER_TYPE
|| TREE_CODE (type) == OFFSET_TYPE)
{
int unsignedp = TREE_UNSIGNED (type);
PROMOTE_MODE (mode, unsignedp, type);
args[i].unsignedp = unsignedp;
}
#endif
args[i].reg = FUNCTION_ARG (args_so_far, mode, type,
argpos < n_named_args);
#ifdef FUNCTION_ARG_PARTIAL_NREGS
if (args[i].reg)
args[i].partial
= FUNCTION_ARG_PARTIAL_NREGS (args_so_far, TYPE_MODE (type), type,
= FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, type,
argpos < n_named_args);
#endif
args[i].pass_on_stack = MUST_PASS_IN_STACK (TYPE_MODE (type), type);
args[i].pass_on_stack = MUST_PASS_IN_STACK (mode, type);
/* If FUNCTION_ARG returned an (expr_list (nil) FOO), it means that
we are to pass this arg in the register(s) designated by FOO, but
@ -1385,6 +1404,8 @@ 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)
@ -1398,6 +1419,15 @@ expand_call (exp, target, ignore)
but PCC has one, so this will avoid some problems. */
emit_queue ();
}
/* 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 (GET_MODE (args[i].value) != mode)
args[i].value = convert_to_mode (mode, args[i].value,
args[i].unsignedp);
}
#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
@ -1666,7 +1696,8 @@ expand_call (exp, target, ignore)
expr_size (exp),
TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
}
else if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp)))
else if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp))
&& GET_MODE (target) == GET_MODE (valreg))
/* TARGET and VALREG cannot be equal at this point because the latter
would not have REG_FUNCTION_VALUE_P true, while the former would if
it were referring to the same register.
@ -1677,6 +1708,30 @@ expand_call (exp, target, ignore)
else
target = copy_to_reg (valreg);
#ifdef PROMOTE_FUNCTION_RETURN
/* If we promoted this return value, make the proper SUBREG. */
if (GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
{
enum machine_mode mode = GET_MODE (target);
int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
if (TREE_CODE (TREE_TYPE (exp)) == INTEGER_TYPE
|| TREE_CODE (TREE_TYPE (exp)) == ENUMERAL_TYPE
|| TREE_CODE (TREE_TYPE (exp)) == BOOLEAN_TYPE
|| TREE_CODE (TREE_TYPE (exp)) == CHAR_TYPE
|| TREE_CODE (TREE_TYPE (exp)) == REAL_TYPE
|| TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE
|| TREE_CODE (TREE_TYPE (exp)) == OFFSET_TYPE)
{
PROMOTE_MODE (mode, unsignedp, TREE_TYPE (exp));
}
target = gen_rtx (SUBREG, TYPE_MODE (TREE_TYPE (exp)), target, 0);
SUBREG_PROMOTED_VAR_P (target) = 1;
SUBREG_PROMOTED_UNSIGNED_P (target) = unsignedp;
}
#endif
/* Perform all cleanups needed for the arguments of this call
(i.e. destructors in C++). */
expand_cleanups_to (old_cleanups);