PATCH: Fix 2 PPC/SYSV varargs problems

Franz Sirl Franz.Sirl-kernel@lauterbach.com
Mon May 31 20:56:00 GMT 1999


Am Sat, 08 May 1999 schrieb Richard Henderson:
>> 	* rs6000.h: remove all traces of now superflous RS6000_VARARGS_OFFSET
>> 	(CUMULATIVE_ARGS): remove now superflous varargs_offset member, update
>> 	comment
>>  	* rs6000.c: Fix Typo in last patch.
>> 	Remove all uses of RS6000_VARARGS_OFFSET and varargs_offset
>> 	* linux.h (NO_IMPLICIT_EXTERN_C): define to synchronize with other
>> 	linux ports
>> 	(MD_EXEC_PREFIX): undefine for the same reason
>> 	(MD_STARTFILE_PREFIX): Ditto.
>
>Applied, thanks.

Fine. These leaves the problems with more than 8 float args, for which I already
sent a patch earlier. I've looked over the code again and came up with the new
and much simpler appended patch. It turned out that the sum
cum->words+cum->sysv_ovf_fwords is actually never needed (or even worse,
produces incorrect code), which makes it possible to drop all the
cum->words-cum->sysv_ovf_fwords calculations in my first patch. The only place
where cum->sysv_ovf_fwords is used now is in expand_builtin_saveregs() to
calculate the correct value for the overflow_area pointer. The compiler still
bootstraps with the patch applied, passes the testsuite and all the varargs
testcases I constructed (and triggered bugs before).

I'm still unsure about the following items I noticed during debugging:
- why is *pretend_size only incremented for GP reg args and not FP args in
setup_incoming_varargs()?
- why does the code in setup_incoming_varargs() push one more FP reg than
needed (it checks >= instead of >), bug or feature? And related to that, what is
the addition of 8 in RS6000_ARGS_SIZE good for then? ABI issue?
- current cvs-egcs calculates the vars_size on the stack 4 times as big as
egcs-1.1.2 did, but I can see no apparent reason for that. get_frame_size() has
changed a lot since 1.1.2, but the controlling macros in rs6000.h/sysv4.h are
unchanged as far I can see.

Franz.

	* rs6000.c (init_cumulative_args): initiatlize cum->sysv_ovf_fwords to 0
	(function_arg_advance): increment it for MODE_FLOAT
	(expand_builtin_saveregs): use it to calculate overflow_area position
	* rs6000.h (CUMULATIVE_ARGS): introduce new member sysv_ovf_fwords,
	update commentary

Index: rs6000.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.68
diff -u -p -r1.68 rs6000.c
--- rs6000.c	1999/05/08 01:46:12	1.68
+++ rs6000.c	1999/05/10 21:43:24
@@ -1256,6 +1261,7 @@ init_cumulative_args (cum, fntype, libna
   cum->fregno = FP_ARG_MIN_REG;
   cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
   cum->call_cookie = CALL_NORMAL;
+  cum->sysv_ovf_fwords = 0;
 
   if (incoming)
     cum->nargs_prototype = 1000;		/* don't return a PARALLEL */
@@ -1391,6 +1397,9 @@ function_arg_advance (cum, mode, type, n
 	       && cum->fregno <= FP_ARG_V4_MAX_REG)
 	cum->fregno++;
 
+      else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+	cum->sysv_ovf_fwords += RS6000_ARG_SIZE (mode, type, 1);
+
       else
 	cum->words += RS6000_ARG_SIZE (mode, type, 1);
     }
@@ -1404,8 +1413,8 @@ function_arg_advance (cum, mode, type, n
 
   if (TARGET_DEBUG_ARG)
     fprintf (stderr,
-	     "function_adv: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d, align = %d\n",
-	     cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named, align);
+	     "function_adv: words = %2d, sysv_ovf_fwords = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d, align = %d\n",
+	     cum->words, cum->sysv_ovf_fwords, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named, align);
 }
 
 /* Determine where to put an argument to a function.
@@ -1444,8 +1453,8 @@ function_arg (cum, mode, type, named)
 
   if (TARGET_DEBUG_ARG)
     fprintf (stderr,
-	     "function_arg: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d, align = %d\n",
-	     cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named, align);
+	     "function_arg: words = %2d, sysv_ovf_fwords = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d, align = %d\n",
+	     cum->words, cum->sysv_ovf_fwords, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named, align);
 
   /* Return a marker to indicate whether CR1 needs to set or clear the bit that V.4
      uses to say fp args were passed in registers.  Assume that we don't need the
@@ -1619,8 +1628,8 @@ setup_incoming_varargs (cum, mode, type,
 
   if (TARGET_DEBUG_ARG)
     fprintf (stderr,
-	     "setup_vararg: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, no_rtl= %d\n",
-	     cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), no_rtl);
+	     "setup_vararg: words = %2d, sysv_ovf_fwords = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, no_rtl= %d\n",
+	     cum->words, cum->sysv_ovf_fwords, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), no_rtl);
 
   if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
     {
@@ -1712,7 +1721,7 @@ expand_builtin_saveregs (args)
   rtx block, mem_gpr_fpr, mem_reg_save_area, mem_overflow, tmp;
   tree fntype;
   int stdarg_p;
-  HOST_WIDE_INT words, gpr, fpr;
+  HOST_WIDE_INT overflow_fwords, words, gpr, fpr;
 
   if (DEFAULT_ABI != ABI_V4 && DEFAULT_ABI != ABI_SOLARIS)
     return virtual_incoming_args_rtx;
@@ -1737,6 +1746,7 @@ expand_builtin_saveregs (args)
 
   /* Construct the two characters of `gpr' and `fpr' as a unit.  */
   words = current_function_args_info.words - !stdarg_p;
+  overflow_fwords = current_function_args_info.sysv_ovf_fwords;
   gpr = (words > 8 ? 8 : words);
   fpr = current_function_args_info.fregno - 33;
 
@@ -1757,11 +1767,15 @@ expand_builtin_saveregs (args)
   emit_move_insn (mem_gpr_fpr, tmp);
 
   /* Find the overflow area.  */
-  if (words <= 8)
+  if (words <= 8 && overflow_fwords == 0)
     tmp = virtual_incoming_args_rtx;
+  else if (words <= 8 && overflow_fwords > 0 )
+    tmp = expand_binop (Pmode, add_optab, virtual_incoming_args_rtx,
+		        GEN_INT (overflow_fwords * UNITS_PER_WORD),
+		        mem_overflow, 0, OPTAB_WIDEN);
   else
     tmp = expand_binop (Pmode, add_optab, virtual_incoming_args_rtx,
-		        GEN_INT ((words - 8) * UNITS_PER_WORD),
+		        GEN_INT ((words - 8 + overflow_fwords) * UNITS_PER_WORD),
 		        mem_overflow, 0, OPTAB_WIDEN);
   if (tmp != mem_overflow)
     emit_move_insn (mem_overflow, tmp);
Index: rs6000.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.47
diff -u -p -r1.47 rs6000.h
--- rs6000.h	1999/05/08 01:46:13	1.47
+++ rs6000.h	1999/05/10 21:44:17
@@ -1439,12 +1474,13 @@ extern int rs6000_sysv_varargs_p;
 
 typedef struct rs6000_args
 {
-  int words;			/* # words uses for passing GP registers */
+  int words;			/* # words used for passing GP values */
   int fregno;			/* next available FP register */
   int nargs_prototype;		/* # args left in the current prototype */
   int orig_nargs;		/* Original value of nargs_prototype */
   int prototype;		/* Whether a prototype was defined */
   int call_cookie;		/* Do special things for this call */
+  int sysv_ovf_fwords;		/* # words used for passing overflowed (non-register) FP values */
 } CUMULATIVE_ARGS;
 
 /* Define intermediate macro to compute the size (in registers) of an argument


More information about the Gcc-patches mailing list