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]

[PATCH] Fix PR target/10142 (SPARC64)


Hi,

GCC currently (all 3.x releases I tested) doesn't correctly pass by value 
structures whose size is 8 < s <=16 on SPARC64. The 64-bit ABI requires such 
structures to be passed in registers if possible, (partially) on the stack 
otherwise. It turns out that, if a structure contains an "integer" field and 
the six integer slots have already been filled, the "integer" field is 
simply not passed at all.

Bootstrapped/regtested (c,c++,objc,f77 mainine) on sparc64-sun-solaris2.9.

No testcase because the patch fixes

FAIL: gcc.dg/compat/struct-by-value-2 c_compat_x_tst.o-c_compat_y_tst.o 
execute 
FAIL: gcc.dg/compat/struct-by-value-4 c_compat_x_tst.o-c_compat_y_tst.o 
execute 
FAIL: gcc.dg/compat/struct-by-value-8 c_compat_x_tst.o-c_compat_y_tst.o 
execute

against self as well as against the Sun Forte C compiler on mainline.

Ok for mainline? What about the 3.3 branch?

-- 
Eric Botcazou


2003-06-11  Eric Botcazou  <ebotcazou@libertysurf.fr>
               Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de>

	PR target/10142
	* config/sparc/sparc.c (function_arg_record_value_parms): Add
	new 'stack' field.
	(function_arg_record_value_1): Set 'stack' to 1 if we run out of
	integer slots for an integer field.
	(function_arg_record_value_3): Shift vector index.
	(function_arg_record_value_2): Likewise.
	(function_arg_record_value): Initialize 'stack' to 0.
	Set 'stack' to 1 if we run out of integer slots for an integer field.
	Generate (parallel [(expr_list (nil) ...) ...]) if 'stack' is set to 1.
Index: config/sparc/sparc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.c,v
retrieving revision 1.243
diff -u -p -r1.243 sparc.c
--- config/sparc/sparc.c	4 Jun 2003 07:13:01 -0000	1.243
+++ config/sparc/sparc.c	11 Jun 2003 12:38:32 -0000
@@ -4530,10 +4530,13 @@ function_arg_slotno (cum, mode, type, na
 
 struct function_arg_record_value_parms
 {
-  rtx ret;
-  int slotno, named, regbase;
-  unsigned int nregs;
-  int intoffset;
+  rtx ret;		/* return expression being built.  */
+  int slotno;		/* slot number of the argument.  */
+  int named;		/* whether the argument is named.  */
+  int regbase;		/* regno of the base register.  */
+  int stack;		/* 1 if part of the argument is on the stack.  */
+  int intoffset;	/* offset of the pending integer field.  */
+  unsigned int nregs;	/* number of words passed in registers.  */
 };
 
 static void function_arg_record_value_3
@@ -4608,8 +4611,13 @@ function_arg_record_value_1 (type, start
 		  this_slotno = parms->slotno + parms->intoffset
 		    / BITS_PER_WORD;
 
-		  intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno);
-		  intslots = MAX (intslots, 0);
+		  if (intslots > 0 && intslots > SPARC_INT_ARG_MAX - this_slotno)
+		    {
+		      intslots = MAX (0, SPARC_INT_ARG_MAX - this_slotno);
+		      /* We need to pass this field on the stack.  */
+		      parms->stack = 1;
+		    }
+
 		  parms->nregs += intslots;
 		  parms->intoffset = -1;
 		}
@@ -4674,7 +4682,7 @@ function_arg_record_value_3 (bitpos, par
     {
       regno = parms->regbase + this_slotno;
       reg = gen_rtx_REG (mode, regno);
-      XVECEXP (parms->ret, 0, parms->nregs)
+      XVECEXP (parms->ret, 0, parms->stack + parms->nregs)
 	= gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (intoffset));
 
       this_slotno += 1;
@@ -4747,7 +4755,7 @@ function_arg_record_value_2 (type, start
 		default: break;
 		}
 	      reg = gen_rtx_REG (mode, regno);
-	      XVECEXP (parms->ret, 0, parms->nregs)
+	      XVECEXP (parms->ret, 0, parms->stack + parms->nregs)
 		= gen_rtx_EXPR_LIST (VOIDmode, reg,
 			   GEN_INT (bitpos / BITS_PER_UNIT));
 	      parms->nregs += 1;
@@ -4755,7 +4763,7 @@ function_arg_record_value_2 (type, start
 		{
 		  regno += GET_MODE_SIZE (mode) / 4;
 	  	  reg = gen_rtx_REG (mode, regno);
-		  XVECEXP (parms->ret, 0, parms->nregs)
+		  XVECEXP (parms->ret, 0, parms->stack + parms->nregs)
 		    = gen_rtx_EXPR_LIST (VOIDmode, reg,
 			GEN_INT ((bitpos + GET_MODE_BITSIZE (mode))
 				 / BITS_PER_UNIT));
@@ -4772,8 +4780,19 @@ function_arg_record_value_2 (type, start
 }
 
 /* Used by function_arg and function_value to implement the complex
-   SPARC64 structure calling conventions.  */
-
+   conventions of the 64-bit ABI for passing and returning structures.
+   Return an expression valid as a return value for the two macros
+   FUNCTION_ARG and FUNCTION_VALUE.
+
+   TYPE is the data type of the argument (as a tree).
+    This is null for libcalls where that information may
+    not be available.
+   MODE is the argument's machine mode.
+   SLOTNO is the index number of the argument's slot in the parameter array.
+   NAMED is nonzero if this argument is a named parameter
+    (otherwise it is an extra parameter matching an ellipsis).
+   REGBASE is the regno of the base register for the parameter array.  */
+   
 static rtx
 function_arg_record_value (type, mode, slotno, named, regbase)
      tree type;
@@ -4788,6 +4807,7 @@ function_arg_record_value (type, mode, s
   parms.slotno = slotno;
   parms.named = named;
   parms.regbase = regbase;
+  parms.stack = 0;
 
   /* Compute how many registers we need.  */
   parms.nregs = 0;
@@ -4804,8 +4824,12 @@ function_arg_record_value (type, mode, s
       intslots = (endbit - startbit) / BITS_PER_WORD;
       this_slotno = slotno + parms.intoffset / BITS_PER_WORD;
 
-      intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno);
-      intslots = MAX (intslots, 0);
+      if (intslots > 0 && intslots > SPARC_INT_ARG_MAX - this_slotno)
+        {
+	  intslots = MAX (0, SPARC_INT_ARG_MAX - this_slotno);
+	  /* We need to pass this field on the stack.  */
+	  parms.stack = 1;
+        }
 
       parms.nregs += intslots;
     }
@@ -4835,7 +4859,17 @@ function_arg_record_value (type, mode, s
   if (nregs == 0)
     abort ();
 
-  parms.ret = gen_rtx_PARALLEL (mode, rtvec_alloc (nregs));
+  parms.ret = gen_rtx_PARALLEL (mode, rtvec_alloc (parms.stack + nregs));
+
+  /* If at least one field must be passed on the stack, generate
+     (parallel [(expr_list (nil) ...) ...]) so that all fields will
+     also be passed on the stack.  We can't do much better because the
+     semantics of FUNCTION_ARG_PARTIAL_NREGS doesn't handle the case
+     of structures for which the fields passed exclusively in registers
+     are not at the beginning of the structure.  */
+  if (parms.stack)
+    XVECEXP (parms.ret, 0, 0)
+      = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
 
   /* Fill in the entries.  */
   parms.nregs = 0;

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