diff options
author | Richard Sandiford <rsandifo@redhat.com> | 2004-11-24 18:50:26 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2004-11-24 18:50:26 +0000 |
commit | bef5d8b61f6732bec53128324913bfa8a5093a07 (patch) | |
tree | b60ced5605459fa37b62bcb5a6c1cced24e7b3fd /gcc/function.c | |
parent | 6e2993bf5b71c17c2b60e0dec787750f44925e66 (diff) | |
download | gcc-bef5d8b61f6732bec53128324913bfa8a5093a07.zip gcc-bef5d8b61f6732bec53128324913bfa8a5093a07.tar.gz gcc-bef5d8b61f6732bec53128324913bfa8a5093a07.tar.bz2 |
optabs.h (force_expand_binop): Declare.
* optabs.h (force_expand_binop): Declare.
* optabs.c (force_expand_binop): Export.
* stmt.c (shift_return_value): Delete.
(expand_return): Don't call it.
* expr.h (shift_return_value): Declare.
* calls.c (shift_returned_value): Delete in favor of...
(shift_return_value): ...this new function. Leave the caller to check
for non-BLKmode values passed in the msb of a register. Take said mode
and a shift direction as argument. Operate on the hard function value,
not a pseudo.
(expand_call): Adjust accordingly.
* function.c (expand_function_start): If a non-BLKmode return value
is padded at the last significant end of the return register, use the
return value's natural mode for the DECL_RESULT, not the mode of the
padded register.
(expand_function_end): Shift the same sort of return values left by
the appropriate amount.
From-SVN: r91187
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 51 |
1 files changed, 36 insertions, 15 deletions
diff --git a/gcc/function.c b/gcc/function.c index da78d3f..1021fc2 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -4059,22 +4059,31 @@ expand_function_start (tree subr) { /* Compute the return values into a pseudo reg, which we will copy into the true return register after the cleanups are done. */ - - /* In order to figure out what mode to use for the pseudo, we - figure out what the mode of the eventual return register will - actually be, and use that. */ - rtx hard_reg - = hard_function_value (TREE_TYPE (DECL_RESULT (subr)), - subr, 1); - - /* Structures that are returned in registers are not aggregate_value_p, - so we may see a PARALLEL or a REG. */ - if (REG_P (hard_reg)) - SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg))); + tree return_type = TREE_TYPE (DECL_RESULT (subr)); + if (TYPE_MODE (return_type) != BLKmode + && targetm.calls.return_in_msb (return_type)) + /* expand_function_end will insert the appropriate padding in + this case. Use the return value's natural (unpadded) mode + within the function proper. */ + SET_DECL_RTL (DECL_RESULT (subr), + gen_reg_rtx (TYPE_MODE (return_type))); else { - gcc_assert (GET_CODE (hard_reg) == PARALLEL); - SET_DECL_RTL (DECL_RESULT (subr), gen_group_rtx (hard_reg)); + /* In order to figure out what mode to use for the pseudo, we + figure out what the mode of the eventual return register will + actually be, and use that. */ + rtx hard_reg = hard_function_value (return_type, subr, 1); + + /* Structures that are returned in registers are not + aggregate_value_p, so we may see a PARALLEL or a REG. */ + if (REG_P (hard_reg)) + SET_DECL_RTL (DECL_RESULT (subr), + gen_reg_rtx (GET_MODE (hard_reg))); + else + { + gcc_assert (GET_CODE (hard_reg) == PARALLEL); + SET_DECL_RTL (DECL_RESULT (subr), gen_group_rtx (hard_reg)); + } } /* Set DECL_REGISTER flag so that expand_function_end will copy the @@ -4368,10 +4377,22 @@ expand_function_end (void) if (GET_MODE (real_decl_rtl) == BLKmode) PUT_MODE (real_decl_rtl, GET_MODE (decl_rtl)); + /* If a non-BLKmode return value should be padded at the least + significant end of the register, shift it left by the appropriate + amount. BLKmode results are handled using the group load/store + machinery. */ + if (TYPE_MODE (TREE_TYPE (decl_result)) != BLKmode + && targetm.calls.return_in_msb (TREE_TYPE (decl_result))) + { + emit_move_insn (gen_rtx_REG (GET_MODE (decl_rtl), + REGNO (real_decl_rtl)), + decl_rtl); + shift_return_value (GET_MODE (decl_rtl), true, real_decl_rtl); + } /* If a named return value dumped decl_return to memory, then we may need to re-do the PROMOTE_MODE signed/unsigned extension. */ - if (GET_MODE (real_decl_rtl) != GET_MODE (decl_rtl)) + else if (GET_MODE (real_decl_rtl) != GET_MODE (decl_rtl)) { int unsignedp = TYPE_UNSIGNED (TREE_TYPE (decl_result)); |