From: Richard Kenner Date: Sun, 27 Sep 1992 22:19:16 +0000 (-0400) Subject: (struct arg_data): New field unsignedp. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=84b55618e8191479ebc1935149354793faa27020;p=gcc.git (struct arg_data): New field unsignedp. (expand_call): Handle PROMOTE_FUNCTION_ARGS and PROMOTE_FUNCTION_RETURN. From-SVN: r2264 --- diff --git a/gcc/calls.c b/gcc/calls.c index 6c18536ef7a..5e4d7462e33 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -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);