aboutsummaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>2000-10-06 18:45:21 -0700
committerRichard Henderson <rth@gcc.gnu.org>2000-10-06 18:45:21 -0700
commit3e4eac3fe9f4b590e6c95356c3fcb7b08630acf2 (patch)
tree9d13e5f3092be6335d2cfa6ba7da64b6af514668 /gcc/function.c
parent15f18aaca64d6d5b27f29cc0072f46b5f04dbbe2 (diff)
downloadgcc-3e4eac3fe9f4b590e6c95356c3fcb7b08630acf2.zip
gcc-3e4eac3fe9f4b590e6c95356c3fcb7b08630acf2.tar.gz
gcc-3e4eac3fe9f4b590e6c95356c3fcb7b08630acf2.tar.bz2
function.c (diddle_return_value): Examine current_function_return_rtx instead of the DECL_RESULT.
* function.c (diddle_return_value): Examine current_function_return_rtx instead of the DECL_RESULT. (expand_function_end): Handle reloading DECL_RESULT from memory into a hard register. Query promote_mode for sign of mismatched modes. From-SVN: r36769
Diffstat (limited to 'gcc/function.c')
-rw-r--r--gcc/function.c76
1 files changed, 48 insertions, 28 deletions
diff --git a/gcc/function.c b/gcc/function.c
index 85a18bf..11ceea7 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -6444,8 +6444,7 @@ diddle_return_value (doit, arg)
/* If this is a BLKmode structure being returned in registers, then use
the mode computed in expand_return. */
if (GET_MODE (outgoing) == BLKmode)
- PUT_MODE (outgoing,
- GET_MODE (DECL_RTL (DECL_RESULT (current_function_decl))));
+ PUT_MODE (outgoing, GET_MODE (current_function_return_rtx));
REG_FUNCTION_VALUE_P (outgoing) = 1;
}
@@ -6730,37 +6729,58 @@ expand_function_end (filename, line, end_bindings)
emit_stack_restore (SAVE_FUNCTION, tem, NULL_RTX);
}
- /* If scalar return value was computed in a pseudo-reg,
- copy that to the hard return register. */
- if (DECL_RTL (DECL_RESULT (current_function_decl)) != 0
- && GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) == REG
- && (REGNO (DECL_RTL (DECL_RESULT (current_function_decl)))
- >= FIRST_PSEUDO_REGISTER))
+ /* If scalar return value was computed in a pseudo-reg, or was a named
+ return value that got dumped to the stack, copy that to the hard
+ return register. */
+ if (DECL_RTL (DECL_RESULT (current_function_decl)) != 0)
{
- rtx real_decl_result;
+ tree decl_result = DECL_RESULT (current_function_decl);
+ rtx decl_rtl = DECL_RTL (decl_result);
+
+ if (REG_P (decl_rtl)
+ ? REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER
+ : DECL_REGISTER (decl_result))
+ {
+ rtx real_decl_rtl;
#ifdef FUNCTION_OUTGOING_VALUE
- real_decl_result
- = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (current_function_decl)),
- current_function_decl);
+ real_decl_rtl = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl_result),
+ current_function_decl);
#else
- real_decl_result
- = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (current_function_decl)),
- current_function_decl);
+ real_decl_rtl = FUNCTION_VALUE (TREE_TYPE (decl_result),
+ current_function_decl);
#endif
- REG_FUNCTION_VALUE_P (real_decl_result) = 1;
- /* If this is a BLKmode structure being returned in registers, then use
- the mode computed in expand_return. */
- if (GET_MODE (real_decl_result) == BLKmode)
- PUT_MODE (real_decl_result,
- GET_MODE (DECL_RTL (DECL_RESULT (current_function_decl))));
- emit_move_insn (real_decl_result,
- DECL_RTL (DECL_RESULT (current_function_decl)));
-
- /* The delay slot scheduler assumes that current_function_return_rtx
- holds the hard register containing the return value, not a temporary
- pseudo. */
- current_function_return_rtx = real_decl_result;
+ REG_FUNCTION_VALUE_P (real_decl_rtl) = 1;
+
+ /* If this is a BLKmode structure being returned in registers,
+ then use the mode computed in expand_return. Note that if
+ decl_rtl is memory, then its mode may have been changed,
+ but that current_function_return_rtx has not. */
+ if (GET_MODE (real_decl_rtl) == BLKmode)
+ PUT_MODE (real_decl_rtl, GET_MODE (current_function_return_rtx));
+
+ /* 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))
+ {
+ int unsignedp = TREE_UNSIGNED (TREE_TYPE (decl_result));
+
+#ifdef PROMOTE_FUNCTION_RETURN
+ promote_mode (TREE_TYPE (decl_result), GET_MODE (decl_rtl),
+ &unsignedp, 1);
+#endif
+
+ convert_move (real_decl_rtl, decl_rtl, unsignedp);
+ }
+ else
+ emit_move_insn (real_decl_rtl, decl_rtl);
+
+ /* The delay slot scheduler assumes that current_function_return_rtx
+ holds the hard register containing the return value, not a
+ temporary pseudo. */
+ current_function_return_rtx = real_decl_rtl;
+ }
}
/* If returning a structure, arrange to return the address of the value