This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix complex packed structures handling (SPARC64)
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 18 Oct 2003 00:20:50 +0200
- Subject: [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)