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 complex packed structures handling (SPARC64)


Hi,

The SPARC64 port doesn't properly (pass and) return packed structures that 
contain non-packed structures that contain floating-point members(!). For 
example, in order to return 'struct B3_p_outer' as defined by

struct A3_p_outer {
  double d;
  int i;
};

struct B3_p_outer {
  char c;
  struct A3_p_outer a3;
} __attribute__ ((packed));

the compiler generates two (reg:BLK) patterns among other things.


I think the problem is that we don't apply recursively what is described in 
function_arg_record_value_1:

  /* The ABI obviously doesn't specify how packed structures are
     passed.  These are defined to be passed in int regs if possible,
     otherwise memory.  */

that is, we apply it only to 'c' and 'a3' as members of struct B3_p_outer and 
not to 'a3' as a structure itself (i.e to 'd' and 'i').

The proposed fix is to implement this recursion. This will change the ABI for 
such complex packed structures that happen to be correctly passed.

Bootstrapped/regtested sparc64-sun-solaris2.9 (mainline, except Ada).

It fixes

FAIL: gcc.dg/compat/struct-align-1 c_compat_x_tst.o compile
FAIL: gcc.dg/compat/struct-align-1 c_compat_y_tst.o compile


2003-10-17  Eric Botcazou  <ebotcazou@libertysurf.fr>

	* config/sparc/sparc.c (function_arg_record_value_1): New fourth
	parameter packed_p.  Search for a DECL_PACKED field only if
	packed_p is false.  Pass packed_p recursively.
	(function_arg_record_value_2): Likewise.
	(function_arg_record_value): Update calls to function_arg_record_value_1
	and function_arg_record_value_2.


-- 
Eric Botcazou
Index: config/sparc/sparc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.c,v
retrieving revision 1.264
diff -u -p -r1.264 sparc.c
--- config/sparc/sparc.c	13 Oct 2003 09:57:48 -0000	1.264
+++ config/sparc/sparc.c	16 Oct 2003 12:11:04 -0000
@@ -4913,9 +4913,9 @@ struct function_arg_record_value_parms
 static void function_arg_record_value_3
  (HOST_WIDE_INT, struct function_arg_record_value_parms *);
 static void function_arg_record_value_2
- (tree, HOST_WIDE_INT, struct function_arg_record_value_parms *);
+ (tree, HOST_WIDE_INT, struct function_arg_record_value_parms *, bool);
 static void function_arg_record_value_1
- (tree, HOST_WIDE_INT, struct function_arg_record_value_parms *);
+ (tree, HOST_WIDE_INT, struct function_arg_record_value_parms *, bool);
 static rtx function_arg_record_value (tree, enum machine_mode, int, int, int);
 
 /* A subroutine of function_arg_record_value.  Traverse the structure
@@ -4923,27 +4923,27 @@ static rtx function_arg_record_value (tr
 
 static void
 function_arg_record_value_1 (tree type, HOST_WIDE_INT startbitpos,
-			     struct function_arg_record_value_parms *parms)
+			     struct function_arg_record_value_parms *parms,
+			     bool packed_p)
 {
   tree field;
 
-  /* The ABI obviously doesn't specify how packed structures are
-     passed.  These are defined to be passed in int regs if possible,
-     otherwise memory.  */
-  int packed_p = 0;
-
   /* We need to compute how many registers are needed so we can
      allocate the PARALLEL but before we can do that we need to know
-     whether there are any packed fields.  If there are, int regs are
-     used regardless of whether there are fp values present.  */
-  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
-    {
-      if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
-	{
-	  packed_p = 1;
-	  break;
-	}
-    }
+     whether there are any packed fields.  The ABI obviously doesn't
+     specify how structures are passed in this case, so they are
+     defined to be passed in int regs if possible, otherwise memory,
+     regardless of whether there are fp values present.  */
+
+  if (! packed_p)
+    for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+      {
+	if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
+	  {
+	    packed_p = true;
+	    break;
+	  }
+      }
 
   /* Compute how many registers we need.  */
   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
@@ -4959,7 +4959,10 @@ function_arg_record_value_1 (tree type, 
 	  /* ??? FIXME: else assume zero offset.  */
 
 	  if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
-	    function_arg_record_value_1 (TREE_TYPE (field), bitpos, parms);
+	    function_arg_record_value_1 (TREE_TYPE (field),
+	    				 bitpos,
+					 parms,
+					 packed_p);
 	  else if ((TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
 		    || (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE
 			&& (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
@@ -5065,19 +5068,20 @@ function_arg_record_value_3 (HOST_WIDE_I
 
 static void
 function_arg_record_value_2 (tree type, HOST_WIDE_INT startbitpos,
-			     struct function_arg_record_value_parms *parms)
+			     struct function_arg_record_value_parms *parms,
+			     bool packed_p)
 {
   tree field;
-  int packed_p = 0;
 
-  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
-    {
-      if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
-	{
-	  packed_p = 1;
-	  break;
-	}
-    }
+  if (! packed_p)
+    for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+      {
+	if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
+	  {
+	    packed_p = true;
+	    break;
+	  }
+      }
 
   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
     {
@@ -5092,7 +5096,10 @@ function_arg_record_value_2 (tree type, 
 	  /* ??? FIXME: else assume zero offset.  */
 
 	  if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
-	    function_arg_record_value_2 (TREE_TYPE (field), bitpos, parms);
+	    function_arg_record_value_2 (TREE_TYPE (field),
+	    				 bitpos,
+					 parms,
+					 packed_p);
 	  else if ((TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
 		    || (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE
 			&& (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
@@ -5173,7 +5180,7 @@ function_arg_record_value (tree type, en
   /* Compute how many registers we need.  */
   parms.nregs = 0;
   parms.intoffset = 0;
-  function_arg_record_value_1 (type, 0, &parms);
+  function_arg_record_value_1 (type, 0, &parms, false);
 
   if (parms.intoffset != -1)
     {
@@ -5235,7 +5242,7 @@ function_arg_record_value (tree type, en
   /* Fill in the entries.  */
   parms.nregs = 0;
   parms.intoffset = 0;
-  function_arg_record_value_2 (type, 0, &parms);
+  function_arg_record_value_2 (type, 0, &parms, false);
   function_arg_record_value_3 (typesize * BITS_PER_UNIT, &parms);
 
   if (parms.nregs != nregs)

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