This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RTL, ColdFire 35/63] Expose dual %d0/%a0 return value in RTL
GNU/Linux and NetBSD return pointers in %a0. However, to support
code that doesn't prototype functions properly, they also return
a copy in %d0.
The code that does this is a bit ad-hoc. During the epilogue, it scans
back to see if %d0 is already provably the same as %a0, and adds a move
if not. It seems better to expose the move at the rtl level instead.
This patch does that by extending the definition of TARGET_FUNCTION_VALUE
so that the first element of a PARALLEL can span the entire return
value and so that later elements contain complete or partial copies
of it. Callers should treat the first element as the canonical one.
The caller side already handles such PARALLELs correctly; it's just
like the normal PARALLEL case except that the parts happen to overlap.
Only the caller side needs adjusting.
Richard
gcc/
200x-xx-xx Kazu Hirata <kazu@codesourcery.com>
Richard Sandiford <richard@codesourcery.com>
* doc/tm.texi (TARGET_FUNCTION_VALUE): Expand documentation of
parallels.
* calls.c (expand_call): If the return value is a PARALLEL,
extract its first member.
* config/m68k/linux.h (FUNCTION_EXTRA_EPILOGUE): Remove.
* config/m68k/m68k.c (m68k_output_function_epilogue): Don't
use FUNCTION_EXTRA_EPILOGUE.
(m68k_function_value): Return a PARALLEL if the return value
is of a pointer type.
* config/m68k/netbsd-elf.h (current_function_returns_pointer)
(FUNCTION_EXTRA_EPILOGUE): Remove.
* config/m68k/m68k.md (D0_REG): New constant.
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi 2007-01-09 15:02:06.000000000 +0000
+++ gcc/doc/tm.texi 2007-01-09 15:02:13.000000000 +0000
@@ -4103,7 +4103,12 @@ place regardless of mode.) The value of
@code{reg} RTX for the hard register where the return value is stored.
The value can also be a @code{parallel} RTX, if the return value is in
multiple places. See @code{FUNCTION_ARG} for an explanation of the
-@code{parallel} form.
+@code{parallel} form. Note that the callee will populate every
+location specified in the @code{parallel}, but if the first element of
+the @code{parallel} contains the whole return value, callers will use
+that element as the canonical location and ignore the others. The m68k
+port uses this type of @code{parallel} to return pointers in both
+@samp{%a0} (the canonical location) and @samp{%d0}.
If @code{TARGET_PROMOTE_FUNCTION_RETURN} returns true, you must apply
the same promotion rules specified in @code{PROMOTE_MODE} if
Index: gcc/calls.c
===================================================================
--- gcc/calls.c 2007-01-09 13:18:12.000000000 +0000
+++ gcc/calls.c 2007-01-09 15:02:13.000000000 +0000
@@ -2536,6 +2536,19 @@ expand_call (tree exp, rtx target, int i
else
valreg = hard_function_value (TREE_TYPE (exp), fndecl, fntype,
(pass == 0));
+
+ /* If VALREG is a PARALLEL whose first member has a zero
+ offset, use that. This is for targets such as m68k that
+ return the same value in multiple places. */
+ if (GET_CODE (valreg) == PARALLEL)
+ {
+ rtx elem = XVECEXP (valreg, 0, 0);
+ rtx where = XEXP (elem, 0);
+ rtx offset = XEXP (elem, 1);
+ if (offset == const0_rtx
+ && GET_MODE (where) == GET_MODE (valreg))
+ valreg = where;
+ }
}
/* Precompute all register parameters. It isn't safe to compute anything
Index: gcc/config/m68k/linux.h
===================================================================
--- gcc/config/m68k/linux.h 2007-01-09 15:02:05.000000000 +0000
+++ gcc/config/m68k/linux.h 2007-01-09 15:02:13.000000000 +0000
@@ -179,20 +179,6 @@ #define NEEDS_UNTYPED_CALL 1
#define FUNCTION_VALUE(VALTYPE, FUNC) \
m68k_function_value (VALTYPE, FUNC)
-/* For compatibility with the large body of existing code which does
- not always properly declare external functions returning pointer
- types, the m68k/SVR4 convention is to copy the value returned for
- pointer functions from a0 to d0 in the function epilogue, so that
- callers that have neglected to properly declare the callee can
- still find the correct return value. */
-
-#define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) \
-do { \
- if (current_function_returns_pointer \
- && ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode)) \
- asm_fprintf (FILE, "\tmove.l %Ra0,%Rd0\n"); \
-} while (0);
-
/* Define how to find the value returned by a library function
assuming the value has mode MODE.
For m68k/SVR4 look for integer values in d0, pointer values in d0
Index: gcc/config/m68k/m68k.c
===================================================================
--- gcc/config/m68k/m68k.c 2007-01-09 15:02:13.000000000 +0000
+++ gcc/config/m68k/m68k.c 2007-01-09 15:02:13.000000000 +0000
@@ -1081,10 +1081,6 @@ m68k_output_function_epilogue (FILE *str
if (insn && GET_CODE (insn) == BARRIER)
return;
-#ifdef FUNCTION_EXTRA_EPILOGUE
- FUNCTION_EXTRA_EPILOGUE (stream, size);
-#endif
-
fsize = current_frame.size;
/* FIXME: leaf_function_p below is too strong.
@@ -4130,9 +4126,26 @@ m68k_function_value (tree valtype, tree
break;
}
- /* If the function returns a pointer, push that into %a0 */
- if (POINTER_TYPE_P (valtype))
- return gen_rtx_REG (mode, 8);
+ /* If the function returns a pointer, push that into %a0. */
+ if (func && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (func))))
+ /* For compatibility with the large body of existing code which
+ does not always properly declare external functions returning
+ pointer types, the m68k/SVR4 convention is to copy the value
+ returned for pointer functions from a0 to d0 in the function
+ epilogue, so that callers that have neglected to properly
+ declare the callee can still find the correct return value in
+ d0. */
+ return gen_rtx_PARALLEL
+ (mode,
+ gen_rtvec (2,
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (mode, A0_REG),
+ const0_rtx),
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (mode, D0_REG),
+ const0_rtx)));
+ else if (POINTER_TYPE_P (valtype))
+ return gen_rtx_REG (mode, A0_REG);
else
- return gen_rtx_REG (mode, 0);
+ return gen_rtx_REG (mode, D0_REG);
}
Index: gcc/config/m68k/netbsd-elf.h
===================================================================
--- gcc/config/m68k/netbsd-elf.h 2007-01-09 15:02:00.000000000 +0000
+++ gcc/config/m68k/netbsd-elf.h 2007-01-09 15:02:13.000000000 +0000
@@ -273,24 +273,6 @@ #define FUNCTION_VALUE(VALTYPE, FUNC)
m68k_function_value (VALTYPE, FUNC)
-/* For compatibility with the large body of existing code which does
- not always properly declare external functions returning pointer
- types, the m68k/SVR4 convention is to copy the value returned for
- pointer functions from a0 to d0 in the function epilogue, so that
- callers that have neglected to properly declare the callee can
- still find the correct return value. */
-
-extern int current_function_returns_pointer;
-#define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) \
-do \
- { \
- if (current_function_returns_pointer \
- && ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode)) \
- asm_fprintf (FILE, "\tmove.l %Ra0,%Rd0\n"); \
- } \
-while (0)
-
-
/* Define how to find the value returned by a library function
assuming the value has mode MODE.
For m68k/SVR4 look for integer values in d0, pointer values in d0
Index: gcc/config/m68k/m68k.md
===================================================================
--- gcc/config/m68k/m68k.md 2007-01-09 15:02:12.000000000 +0000
+++ gcc/config/m68k/m68k.md 2007-01-09 15:02:13.000000000 +0000
@@ -124,7 +124,8 @@ (define_constants
;; Registers by name.
(define_constants
- [(A0_REG 8)
+ [(D0_REG 0)
+ (A0_REG 8)
(SP_REG 15)
])