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 Darwin 1/2] fix PPC64 ABI


Hi,

Part 1, a long-overdue merge from the apple-local 4.2 branch.
It doesn't touch anything outside darwin-specific code, other than adding a darwin-specific field to the CUMULATIVE_ARGS structure.


OK for trunk (and 4.5 when it re-opens) ?

Iain

gcc/

	PR target/35491
	PR target/29090

	Merge from Apple local 4.2.1.
	2005-05-11  Stan Shebs  <shebs@apple.com>
	Fix 64-bit varargs for Darwin (Radar 4028089).
	* config/rs6000/rs6000.h (rs6000_args): New field floats_in_gpr.
	* config/rs6000/rs6000.c (rs6000_darwin64_record_arg_advance_flush):
	Add argument, add case for 8-byte register half-filled with a float.
	(rs6000_darwin64_record_arg_advance_recurse): Detect and handle
	single-precision floats specially.


Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 162457) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -1673,6 +1673,8 @@ typedef struct rs6000_args int sysv_gregno; /* next available GP register */ int intoffset; /* running offset in struct (darwin64) */ int use_stack; /* any part of struct on stack (darwin64) */ + int floats_in_gpr; /* count of SFmode floats taking up + GPR space (darwin64) */ int named; /* false for varargs params */ } CUMULATIVE_ARGS;

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c (revision 162457)
+++ gcc/config/rs6000/rs6000.c (working copy)
@@ -1154,7 +1154,7 @@ static rtx rs6000_complex_function_value (enum mac
static rtx rs6000_spe_function_arg (CUMULATIVE_ARGS *,
enum machine_mode, tree);
static void rs6000_darwin64_record_arg_advance_flush (CUMULATIVE_ARGS *,
- HOST_WIDE_INT);
+ HOST_WIDE_INT, int);
static void rs6000_darwin64_record_arg_advance_recurse (CUMULATIVE_ARGS *,
tree, HOST_WIDE_INT);
static void rs6000_darwin64_record_arg_flush (CUMULATIVE_ARGS *,
@@ -7542,17 +7542,31 @@ rs6000_arg_size (enum machine_mode mode, tree type


 static void
 rs6000_darwin64_record_arg_advance_flush (CUMULATIVE_ARGS *cum,
-					  HOST_WIDE_INT bitpos)
+					  HOST_WIDE_INT bitpos, int final)
 {
   unsigned int startbit, endbit;
   int intregs, intoffset;
   enum machine_mode mode;

+  /* Handle the situations where a float is taking up the first half
+     of the GPR, and the other half is empty (typically due to
+     alignment restrictions). We can detect this by a 8-byte-aligned
+     int field, or by seeing that this is the final flush for this
+     argument. Count the word and continue on.  */
+  if (cum->floats_in_gpr == 1
+      && (cum->intoffset % 64 == 0
+	  || (cum->intoffset == -1 && final)))
+    {
+      cum->words++;
+      cum->floats_in_gpr = 0;
+    }
+
   if (cum->intoffset == -1)
     return;

   intoffset = cum->intoffset;
   cum->intoffset = -1;
+  cum->floats_in_gpr = 0;

if (intoffset % BITS_PER_WORD != 0)
{
@@ -7572,6 +7586,12 @@ rs6000_darwin64_record_arg_advance_flush (CUMULATI
endbit = (bitpos + BITS_PER_WORD - 1) & -BITS_PER_WORD;
intregs = (endbit - startbit) / BITS_PER_WORD;
cum->words += intregs;
+ /* words should be unsigned. */
+ if ((unsigned)cum->words < (endbit/BITS_PER_WORD))
+ {
+ int pad = (endbit/BITS_PER_WORD) - cum->words;
+ cum->words += pad;
+ }
}


/* The darwin64 ABI calls for us to recurse down through structs,
@@ -7606,13 +7626,47 @@ rs6000_darwin64_record_arg_advance_recurse (CUMULA
rs6000_darwin64_record_arg_advance_recurse (cum, ftype, bitpos);
else if (USE_FP_FOR_ARG_P (cum, mode, ftype))
{
- rs6000_darwin64_record_arg_advance_flush (cum, bitpos);
+ rs6000_darwin64_record_arg_advance_flush (cum, bitpos, 0);
cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3;
- cum->words += (GET_MODE_SIZE (mode) + 7) >> 3;
+ /* Single-precision floats present a special problem for
+ us, because they are smaller than an 8-byte GPR, and so
+ the structure-packing rules combined with the standard
+ varargs behavior mean that we want to pack float/float
+ and float/int combinations into a single register's
+ space. This is complicated by the arg advance flushing,
+ which works on arbitrarily large groups of int-type
+ fields. */
+ if (mode == SFmode)
+ {
+ if (cum->floats_in_gpr == 1)
+ {
+ /* Two floats in a word; count the word and reset
+ the float count. */
+ cum->words++;
+ cum->floats_in_gpr = 0;
+ }
+ else if (bitpos % 64 == 0)
+ {
+ /* A float at the beginning of an 8-byte word;
+ count it and put off adjusting cum->words until
+ we see if a arg advance flush is going to do it
+ for us. */
+ cum->floats_in_gpr++;
+ }
+ else
+ {
+ /* The float is at the end of a word, preceded
+ by integer fields, so the arg advance flush
+ just above has already set cum->words and
+ everything is taken care of. */
+ }
+ }
+ else
+ cum->words += (GET_MODE_SIZE (mode) + 7) >> 3;
}
else if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, 1))
{
- rs6000_darwin64_record_arg_advance_flush (cum, bitpos);
+ rs6000_darwin64_record_arg_advance_flush (cum, bitpos, 0);
cum->vregno++;
cum->words += 2;
}
@@ -7718,10 +7772,20 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum m
{ int; double; int; } [powerpc alignment]. We have to
grovel through the fields for these too. */
cum->intoffset = 0;
+ cum->floats_in_gpr = 0;
rs6000_darwin64_record_arg_advance_recurse (cum, type, 0);
rs6000_darwin64_record_arg_advance_flush (cum,
- size * BITS_PER_UNIT);
+ size * BITS_PER_UNIT, 1);
}
+ if (TARGET_DEBUG_ARG)
+ {
+ fprintf (stderr, "function_adv: words = %2d, align=%d, size=%d",
+ cum->words, TYPE_ALIGN (type), size);
+ fprintf (stderr,
+ "nargs = %4d, proto = %d, mode = %4s (darwin64 abi BLK)\n",
+ cum->nargs_prototype, cum->prototype,
+ GET_MODE_NAME (mode));
+ }
}
else if (DEFAULT_ABI == ABI_V4)
{
@@ -8920,8 +8984,8 @@ rs6000_gimplify_va_arg (tree valist, tree type, gi
tree gpr, fpr, ovf, sav, reg, t, u;
int size, rsize, n_reg, sav_ofs, sav_scale;
tree lab_false, lab_over, addr;
+ tree ptrtype = build_pointer_type_for_mode (type, ptr_mode, true);
int align;
- tree ptrtype = build_pointer_type_for_mode (type, ptr_mode, true);
int regalign = 0;
gimple stmt;




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