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]

[3.3/mainline] Fix x86-64 returning of structures


Hi,
x86-64 ABI requires address of structure returned in memory to be returned in
RDI instead of RAX usual data are returned to save move instruction otherwise
necesary in each such function.  Apparently we don't have any target knob
to control this, so I had to add new one.
Regtested/bootstrapped i386, x86-64 testing in progress.
OK for 3.3 and mainline?

Honza

Thu Mar 13 18:23:44 CET 2003  Jan Hubicka  <jh at suse dot cz>
	* calls.c (expand_call): Update call of hard_function_value.
	* explow.c (hard_function_value): Use FUNCTION_STRUCT_RETURN_VALUE.
	* expr.h (hard_function_value): Update prototype.
	* function.c (aggregate_value_p, expand_function_start): Update
	call of hard_function_value.
	(expand_function_end): Use FUNCTION_STRUCT_RETURN_VALUE.
	* i386.h (FUNCTION_STRUCT_RETURN_VALUE): Declare.
	* i386.c (ix86_function_value_regno_p): Return true for rdi.
	* tm.texi (FUNCTION_STRUCT_RETURN_VALUE): Document.
Index: calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.262
diff -c -3 -p -r1.262 calls.c
*** calls.c	8 Mar 2003 01:38:24 -0000	1.262
--- calls.c	13 Mar 2003 17:21:47 -0000
*************** expand_call (exp, target, ignore)
*** 2227,2232 ****
--- 2227,2233 ----
    HOST_WIDE_INT preferred_stack_boundary;
    /* The alignment of the stack, in bytes.  */
    HOST_WIDE_INT preferred_unit_stack_boundary;
+   bool in_memory = false;
  
    /* See if this is "nothrow" function call.  */
    if (TREE_NOTHROW (exp))
*************** expand_call (exp, target, ignore)
*** 2976,2984 ****
  	{
  	  if (pcc_struct_value)
  	    valreg = hard_function_value (build_pointer_type (TREE_TYPE (exp)),
! 					  fndecl, (pass == 0));
  	  else
! 	    valreg = hard_function_value (TREE_TYPE (exp), fndecl, (pass == 0));
  	}
  
        /* Precompute all register parameters.  It isn't safe to compute anything
--- 2977,2986 ----
  	{
  	  if (pcc_struct_value)
  	    valreg = hard_function_value (build_pointer_type (TREE_TYPE (exp)),
! 					  fndecl, (pass == 0), 1);
  	  else
! 	    valreg = hard_function_value (TREE_TYPE (exp), fndecl, (pass == 0),
! 			    		  structure_value_addr != 0);
  	}
  
        /* Precompute all register parameters.  It isn't safe to compute anything
Index: explow.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/explow.c,v
retrieving revision 1.106
diff -c -3 -p -r1.106 explow.c
*** explow.c	20 Feb 2003 22:29:06 -0000	1.106
--- explow.c	13 Mar 2003 17:21:48 -0000
*************** probe_stack_range (first, size)
*** 1625,1637 ****
     and 0 otherwise.  */
  
  rtx
! hard_function_value (valtype, func, outgoing)
       tree valtype;
       tree func ATTRIBUTE_UNUSED;
       int outgoing ATTRIBUTE_UNUSED;
  {
    rtx val;
  
  #ifdef FUNCTION_OUTGOING_VALUE
    if (outgoing)
      val = FUNCTION_OUTGOING_VALUE (valtype, func);
--- 1625,1643 ----
     and 0 otherwise.  */
  
  rtx
! hard_function_value (valtype, func, outgoing, in_memory)
       tree valtype;
       tree func ATTRIBUTE_UNUSED;
       int outgoing ATTRIBUTE_UNUSED;
+      int in_memory ATTRIBUTE_UNUSED;
  {
    rtx val;
  
+ #ifdef FUNCTION_STRUCT_RETURN_VALUE
+   if (in_memory)
+     val = FUNCTION_STRUCT_RETURN_VALUE ();
+   else
+ #endif
  #ifdef FUNCTION_OUTGOING_VALUE
    if (outgoing)
      val = FUNCTION_OUTGOING_VALUE (valtype, func);
Index: expr.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.h,v
retrieving revision 1.130
diff -c -3 -p -r1.130 expr.h
*** expr.h	6 Mar 2003 04:04:17 -0000	1.130
--- expr.h	13 Mar 2003 17:21:48 -0000
*************** extern rtx trampoline_address PARAMS ((t
*** 557,563 ****
  
  /* Return an rtx that refers to the value returned by a function
     in its original home.  This becomes invalid if any more code is emitted.  */
! extern rtx hard_function_value PARAMS ((tree, tree, int));
  
  extern rtx prepare_call_address	PARAMS ((rtx, tree, rtx *, int, int));
  
--- 557,563 ----
  
  /* Return an rtx that refers to the value returned by a function
     in its original home.  This becomes invalid if any more code is emitted.  */
! extern rtx hard_function_value PARAMS ((tree, tree, int, int));
  
  extern rtx prepare_call_address	PARAMS ((rtx, tree, rtx *, int, int));
  
Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.405
diff -c -3 -p -r1.405 function.c
*** function.c	4 Mar 2003 06:20:12 -0000	1.405
--- function.c	13 Mar 2003 17:21:48 -0000
*************** aggregate_value_p (exp)
*** 4197,4203 ****
      return 1;
    /* Make sure we have suitable call-clobbered regs to return
       the value in; if not, we must return it in memory.  */
!   reg = hard_function_value (type, 0, 0);
  
    /* If we have something other than a REG (e.g. a PARALLEL), then assume
       it is OK.  */
--- 4197,4203 ----
      return 1;
    /* Make sure we have suitable call-clobbered regs to return
       the value in; if not, we must return it in memory.  */
!   reg = hard_function_value (type, 0, 0, 0);
  
    /* If we have something other than a REG (e.g. a PARALLEL), then assume
       it is OK.  */
*************** expand_function_start (subr, parms_have_
*** 6423,6428 ****
--- 6423,6429 ----
  {
    tree tem;
    rtx last_ptr = NULL_RTX;
+   bool in_memory = 0;
  
    /* Make sure volatile mem refs aren't considered
       valid operands of arithmetic insns.  */
*************** expand_function_start (subr, parms_have_
*** 6475,6480 ****
--- 6476,6482 ----
        /* Returning something that won't go in a register.  */
        rtx value_address = 0;
  
+       in_memory = true;
  #ifdef PCC_STATIC_STRUCT_RETURN
        if (current_function_returns_pcc_struct)
  	{
*************** expand_function_start (subr, parms_have_
*** 6513,6519 ****
  	 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.  */
--- 6515,6521 ----
  	 actually be, and use that.  */
        rtx hard_reg
  	= hard_function_value (TREE_TYPE (DECL_RESULT (subr)),
! 			       subr, 1, in_memory);
  
        /* Structures that are returned in registers are not aggregate_value_p,
  	 so we may see a PARALLEL or a REG.  */
*************** expand_function_end (filename, line, end
*** 6982,6987 ****
--- 6984,6992 ----
        rtx value_address
  	= XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
        tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
+ #ifdef FUNCTION_STRUCT_RETURN_VALUE
+       rtx outgoing = FUNCTION_STRUCT_RETURN_VALUE ();
+ #else
  #ifdef FUNCTION_OUTGOING_VALUE
        rtx outgoing
  	= FUNCTION_OUTGOING_VALUE (build_pointer_type (type),
*************** expand_function_end (filename, line, end
*** 6989,6994 ****
--- 6994,7000 ----
  #else
        rtx outgoing
  	= FUNCTION_VALUE (build_pointer_type (type), current_function_decl);
+ #endif
  #endif
  
        /* Mark this as a function return value so integrate will delete the
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.548
diff -c -3 -p -r1.548 i386.c
*** config/i386/i386.c	12 Mar 2003 18:06:29 -0000	1.548
--- config/i386/i386.c	13 Mar 2003 17:21:53 -0000
*************** ix86_function_value_regno_p (regno)
*** 2687,2692 ****
--- 2681,2687 ----
  	      || ((regno) == FIRST_SSE_REG && TARGET_SSE));
      }
    return ((regno) == 0 || (regno) == FIRST_FLOAT_REG
+ 	  || (regno) == 5
  	  || ((regno) == FIRST_SSE_REG && TARGET_SSE)
  	  || ((regno) == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387));
  }
Index: config/i386/i386.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.328
diff -c -3 -p -r1.328 i386.h
*** config/i386/i386.h	5 Mar 2003 01:33:26 -0000	1.328
--- config/i386/i386.h	13 Mar 2003 17:21:54 -0000
*************** enum reg_class
*** 1693,1698 ****
--- 1693,1703 ----
  #define FUNCTION_VALUE(VALTYPE, FUNC)  \
     ix86_function_value (VALTYPE)
  
+ /* Pointer to the structures returned in memory is returned in EAX for i386
+    and RDI for x86-64 ABI.  */
+ #define FUNCTION_STRUCT_RETURN_VALUE()  \
+    gen_rtx_REG (Pmode, TARGET_64BIT ? 5 : 0)
+ 
  #define FUNCTION_VALUE_REGNO_P(N) \
    ix86_function_value_regno_p (N)
  
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.208
diff -c -3 -p -r1.208 tm.texi
*** doc/tm.texi	11 Mar 2003 20:40:52 -0000	1.208
--- doc/tm.texi	13 Mar 2003 17:21:58 -0000
*************** If @code{FUNCTION_OUTGOING_VALUE} is not
*** 3841,3846 ****
--- 3841,3852 ----
  aggregate data types, because these are returned in another way.  See
  @code{STRUCT_VALUE_REGNUM} and related macros, below.
  
+ @findex FUNCTION_STRUCT_RETURN_VALUE
+ @item FUNCTION_STRUCT_RETURN_VALUE ()
+ A C expression to create an RTX representing the place where a
+ function returns a pointer to return value in the case value is
+ returned in memory.  Defaults to FUNCTION_VALUE when not defined.
+ 
  @findex LIBCALL_VALUE
  @item LIBCALL_VALUE (@var{mode})
  A C expression to create an RTX representing the place where a library


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