This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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)
   ])
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]