linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* PATCH: Fix 2 PPC/SYSV varargs problems
@ 1999-04-30  0:09 Franz Sirl
  1999-04-30  2:48 ` Richard Henderson
  1999-05-12  6:19 ` Jeffrey A Law
  0 siblings, 2 replies; 13+ messages in thread
From: Franz Sirl @ 1999-04-30  0:09 UTC (permalink / raw)
  To: egcs-patches; +Cc: rth, meissner, David Edelsohn, linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 706 bytes --]

Hi,

this patch is supposed to fix the following problems on PPC/SYSV:

1. the varargs save area calculation bug, this is a hack and Richard ;-) 
probably won't like it, but maybe it's good enough for egcs-1.2

2. if you call a function that uses more then 8 float args before all 
integer argument passing registers are consumed, egcs will missetup the 
calling sequence. I introduced a new variable cum->sysv_fwords in the 
CUMULATIVE_ARGS struct, which counts the saved float words and adjusted 
cum->words where needed (I hope). There maybe better/nicer ways to 
implement that, so tell me if you want a different solution. A testcase is 
attached, the original problem happens with gnuplot.

Franz.



[-- Attachment #2: varargs.testcase.c --]
[-- Type: text/plain, Size: 2115 bytes --]

#include <stdarg.h>

inline void debug(const char *fp,const char *msg,...)
{
       va_list ap;
       double df;
   

       if (*fp != '1')
             abort();
       if (*msg != '2')
             abort();
   
       va_start( ap, msg );
   
       df = va_arg(ap,double);
       if (df <1.09 || df >1.11)
             abort();
       df = va_arg(ap,double);
       if (df <1.19 || df >1.21)
             abort();
       df = va_arg(ap,double);
       if (df <1.29 || df >1.31)
             abort();
       df = va_arg(ap,double);
       if (df <1.39 || df >1.41)
             abort();
       df = va_arg(ap,double);
       if (df <1.49 || df >1.51)
             abort();
       if ( *va_arg(ap,char*) != '3')
             abort();
       if ( *va_arg(ap,char*) != '4')
             abort();
       if ( *va_arg(ap,char*) != '5')
             abort();
       df = va_arg(ap,double);
       if (df <1.59 || df >1.61)
             abort();
       df = va_arg(ap,double);
       if (df <1.69 || df >1.71)
             abort();
       df = va_arg(ap,double);
       if (df <1.79 || df >1.81)
             abort();
       df = va_arg(ap,double);
       if (df <1.89 || df >1.91)
             abort();
       if ( va_arg(ap,int) != 101)
             abort();
       if ( va_arg(ap,int) != 102)
             abort();
       if ( va_arg(ap,int) != 103)
             abort();
       if ( va_arg(ap,int) != 104)
             abort();
       if ( *va_arg(ap,char*) != '6')
             abort();
       if ( va_arg(ap,int) != 105)
             abort();
       if ( va_arg(ap,int) != 106)
             abort();
       if ( va_arg(ap,int) != 107)
             abort();
       if ( va_arg(ap,int) != 108)
             abort();
       if ( va_arg(ap,int) != 109)
             abort();

   
       if ( va_arg(ap,int) != 110)
             abort();

       va_end( ap );
}

int main(void)
{
     debug("1 filepointer", "2 format", 1.1,1.2,1.3,1.4,1.5, "3","4","5", 1.6,1.7,1.8,1.9, 101,102,103,104, "6", 105,106,107,108,109,110);
     exit(0);
}


[-- Attachment #3: varargsfix2.patch --]
[-- Type: text/plain, Size: 7744 bytes --]

Index: expr.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/expr.c,v
retrieving revision 1.141
diff -u -p -r1.141 expr.c
--- expr.c	1999/04/27 05:34:43	1.141
+++ gcc/expr.c	1999/04/28 22:23:47
@@ -8951,7 +8951,13 @@ expand_builtin (exp, target, subtarget, 
 		if (wordnum < 0 || wordnum >= nwords || TREE_INT_CST_HIGH (arg))
 		  error ("argument of `__builtin_args_info' out of range");
 		else
-		  return GEN_INT (word_ptr[wordnum]);
+		  {
+#ifdef CUMULATIVE_ARG_INFO_IS_RTX
+		    if (CUMULATIVE_ARG_INFO_IS_RTX(wordnum))
+		      return word_ptr[wordnum];
+#endif
+		    return GEN_INT (word_ptr[wordnum]);
+	          }
 	      }
 	  }
 	else
Index: va-ppc.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/ginclude/va-ppc.h,v
retrieving revision 1.4
diff -u -p -r1.4 va-ppc.h
--- va-ppc.h	1998/12/16 21:19:40	1.4
+++ gcc/ginclude/va-ppc.h	1999/04/28 23:23:10
@@ -80,8 +80,7 @@ __extension__ ({							\
 									\
    (AP)->gpr = (__words < 8) ? __words : 8;				\
    (AP)->fpr = __va_fregno - 33;					\
-   (AP)->reg_save_area = (((char *) __builtin_frame_address (0))	\
-			  + __va_varargs_offset);			\
+   (AP)->reg_save_area = ((char *) __builtin_args_info (8));		\
    __va_overflow(AP) = ((char *)__builtin_saveregs ()			\
 			+ (((__words >= 8) ? __words - 8 : 0)		\
 			   * sizeof (long)));				\
Index: rs6000.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.45
diff -u -p -r1.45 rs6000.h
--- rs6000.h	1999/04/27 12:39:56	1.45
+++ gcc/config/rs6000/rs6000.h	1999/04/29 23:16:17
@@ -1445,15 +1445,19 @@ extern int rs6000_sysv_varargs_p;
 
 typedef struct rs6000_args
 {
-  int words;			/* # words uses for passing GP registers */
+  int words;			/* # words uses for passing GP+FP registers */
   int fregno;			/* next available FP register */
   int nargs_prototype;		/* # args left in the current prototype */
   int orig_nargs;		/* Original value of nargs_prototype */
   int varargs_offset;		/* offset of the varargs save area */
   int prototype;		/* Whether a prototype was defined */
   int call_cookie;		/* Do special things for this call */
+  int sysv_fwords;		/* # words uses for passing FP registers */
+  void *save_area;		/* setup with rtx pointing to varargs_save_area */
 } CUMULATIVE_ARGS;
 
+#define CUMULATIVE_ARG_INFO_IS_RTX(idx) ((idx) == 8)
+
 /* Define intermediate macro to compute the size (in registers) of an argument
    for the RS/6000.  */
 
Index: rs6000.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.66
diff -u -p -r1.66 rs6000.c
--- rs6000.c	1999/04/27 12:39:58	1.66
+++ gcc/config/rs6000/rs6000.c	1999/04/29 23:16:29
@@ -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_fwords = 0;
 
   if (incoming)
     {
@@ -1381,10 +1387,10 @@ function_arg_advance (cum, mode, type, n
       /* Long longs must not be split between registers and stack */
       if ((GET_MODE_CLASS (mode) != MODE_FLOAT || TARGET_SOFT_FLOAT)
 	  && type && !AGGREGATE_TYPE_P (type)
-	  && cum->words < GP_ARG_NUM_REG
-	  && cum->words + RS6000_ARG_SIZE (mode, type, named) > GP_ARG_NUM_REG)
+	  && cum->words - cum->sysv_fwords < GP_ARG_NUM_REG
+	  && cum->words - cum->sysv_fwords + RS6000_ARG_SIZE (mode, type, named) > GP_ARG_NUM_REG)
 	{
-	  cum->words = GP_ARG_NUM_REG;
+	  cum->words = GP_ARG_NUM_REG + cum->sysv_fwords;
 	}
 
       /* Aggregates get passed as pointers */
@@ -1399,7 +1405,11 @@ function_arg_advance (cum, mode, type, n
 	cum->fregno++;
 
       else
-	cum->words += RS6000_ARG_SIZE (mode, type, 1);
+	{ 
+	  cum->words += RS6000_ARG_SIZE (mode, type, 1);
+	  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+	    cum->sysv_fwords += RS6000_ARG_SIZE (mode, type, 1);
+	}
     }
   else
     if (named)
@@ -1411,8 +1421,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_fwords = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d, align = %d\n",
+	     cum->words, cum->sysv_fwords, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named, align);
 }
 \f
 /* Determine where to put an argument to a function.
@@ -1451,8 +1461,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_fwords = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d, align = %d\n",
+	     cum->words, cum->sysv_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
@@ -1522,14 +1532,14 @@ function_arg (cum, mode, type, named)
   /* Long longs won't be split between register and stack;
      FP arguments get passed on the stack if they didn't get a register.  */
   else if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) &&
-	   (align_words + RS6000_ARG_SIZE (mode, type, named) > GP_ARG_NUM_REG
+	   (align_words - cum->sysv_fwords + RS6000_ARG_SIZE (mode, type, named) > GP_ARG_NUM_REG
 	    || (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_HARD_FLOAT)))
     {
       return NULL_RTX;
     }
 
-  else if (align_words < GP_ARG_NUM_REG)
-    return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
+  else if (align_words - cum->sysv_fwords < GP_ARG_NUM_REG)
+    return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words - cum->sysv_fwords);
 
   return NULL_RTX;
 }
@@ -1626,21 +1636,24 @@ 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_fwords = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, no_rtl= %d\n",
+	     cum->words, cum->sysv_fwords, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), no_rtl);
 
   if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
     {
       rs6000_sysv_varargs_p = 1;
       if (! no_rtl)
-	save_area = plus_constant (frame_pointer_rtx, RS6000_VARARGS_OFFSET);
+	{
+	  save_area = plus_constant (virtual_stack_vars_rtx, -RS6000_VARARGS_SIZE);
+	  (rtx) cum->save_area = save_area;
+	}
     }
   else
     rs6000_sysv_varargs_p = 0;
 
-  if (cum->words < 8)
+  if (cum->words - cum->sysv_fwords < 8)
     {
-      int first_reg_offset = cum->words;
+      int first_reg_offset = cum->words - cum->sysv_fwords;
 
       if (MUST_PASS_IN_STACK (mode, type))
 	first_reg_offset += RS6000_ARG_SIZE (TYPE_MODE (type), type, 1);

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Fix 2 PPC/SYSV varargs problems
  1999-04-30  0:09 PATCH: Fix 2 PPC/SYSV varargs problems Franz Sirl
@ 1999-04-30  2:48 ` Richard Henderson
  1999-04-30  2:55   ` Zack Weinberg
  1999-04-30 13:42   ` Franz Sirl
  1999-05-12  6:19 ` Jeffrey A Law
  1 sibling, 2 replies; 13+ messages in thread
From: Richard Henderson @ 1999-04-30  2:48 UTC (permalink / raw)
  To: Franz Sirl, egcs-patches; +Cc: meissner, David Edelsohn, linuxppc-dev


On Fri, Apr 30, 1999 at 02:09:09AM +0200, Franz Sirl wrote:
> 1. the varargs save area calculation bug, this is a hack and Richard ;-) 
> probably won't like it, but maybe it's good enough for egcs-1.2

You're right -- I hate it.  You'll have made it so I can't build a
ppc cross compiler on my Alphas, and you'll have killed the compiler
for a ppc64-linux.

Here's an implementation of what I'd suggested before.  It looks ok
to the eye, but I don't have a ppc-linux box handy to try it out on.


r~


	* va-ppc.h (__va_start_common): Let __builtin_saveregs do the work.
	* rs6000.c (expand_builtin_saveregs): For SYSV, initialize a private
	va_list struct, and return a pointer to it.

Index: ginclude/va-ppc.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/ginclude/va-ppc.h,v
retrieving revision 1.4
diff -c -p -d -r1.4 va-ppc.h
*** va-ppc.h	1998/12/16 21:19:40	1.4
--- va-ppc.h	1999/04/30 02:45:30
*************** typedef struct {
*** 59,92 ****
    ((TYPE *) (void *) (&(((__va_regsave_t *)				\
  			 (AP)->reg_save_area)->__gp_save[(int)(AP)->gpr])))
  
! /* Common code for va_start for both varargs and stdarg.  This depends
!    on the format of rs6000_args in rs6000.h.  The fields used are:
! 
!    #0	WORDS			# words used for GP regs/stack values
!    #1	FREGNO			next available FP register
!    #2	NARGS_PROTOTYPE		# args left in the current prototype
!    #3	ORIG_NARGS		original value of NARGS_PROTOTYPE
!    #4	VARARGS_OFFSET		offset from frame pointer of varargs area */
! 
! #define __va_words		__builtin_args_info (0)
! #define __va_fregno		__builtin_args_info (1)
! #define	__va_nargs		__builtin_args_info (2)
! #define __va_orig_nargs		__builtin_args_info (3)
! #define __va_varargs_offset	__builtin_args_info (4)
  
! #define __va_start_common(AP, FAKE)					\
! __extension__ ({							\
!    register int __words = __va_words - FAKE;				\
! 									\
!    (AP)->gpr = (__words < 8) ? __words : 8;				\
!    (AP)->fpr = __va_fregno - 33;					\
!    (AP)->reg_save_area = (((char *) __builtin_frame_address (0))	\
! 			  + __va_varargs_offset);			\
!    __va_overflow(AP) = ((char *)__builtin_saveregs ()			\
! 			+ (((__words >= 8) ? __words - 8 : 0)		\
! 			   * sizeof (long)));				\
!    (void)0;								\
! })
  
  #ifdef _STDARG_H /* stdarg.h support */
  
--- 59,71 ----
    ((TYPE *) (void *) (&(((__va_regsave_t *)				\
  			 (AP)->reg_save_area)->__gp_save[(int)(AP)->gpr])))
  
! /* Common code for va_start for both varargs and stdarg.  We allow all
!    the work to be done by __builtin_saveregs.  It returns a pointer to
!    a va_list that was constructed on the stack; we must simply copy it
!    to the user's variable.  */
  
! #define __va_start_common(AP, FAKE) \
!   __builtin_memcpy ((AP), __builtin_saveregs (), sizeof(__gnuc_va_list))
  
  #ifdef _STDARG_H /* stdarg.h support */
  
Index: config/rs6000/rs6000.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.66
diff -c -p -d -r1.66 rs6000.c
*** rs6000.c	1999/04/27 12:39:58	1.66
--- rs6000.c	1999/04/30 02:45:30
*************** setup_incoming_varargs (cum, mode, type,
*** 1704,1716 ****
     
     On the Power/PowerPC return the address of the area on the stack
     used to hold arguments.  Under AIX, this includes the 8 word register
!    save area.  Under V.4 this does not.  */
  
  struct rtx_def *
  expand_builtin_saveregs (args)
       tree args ATTRIBUTE_UNUSED;
  {
!   return virtual_incoming_args_rtx;
  }
  
  \f
--- 1704,1786 ----
     
     On the Power/PowerPC return the address of the area on the stack
     used to hold arguments.  Under AIX, this includes the 8 word register
!    save area. 
! 
!    Under V.4, things are more complicated.  We do not have access to
!    all of the virtual registers required for va_start to do its job,
!    so we construct the va_list in its entirity here, and reduce va_start
!    to a block copy.  This is similar to the way we do things on Alpha.  */
  
  struct rtx_def *
  expand_builtin_saveregs (args)
       tree args ATTRIBUTE_UNUSED;
  {
!   rtx block, mem_gpr_fpr, mem_reg_save_area, mem_overflow, tmp;
!   tree fntype;
!   int stdarg_p;
!   HOST_WIDE_INT words, gpr, fpr;
! 
!   if (DEFAULT_ABI != ABI_V4 && DEFAULT_ABI != ABI_SOLARIS)
!     return virtual_incoming_args_rtx;
! 
!   fntype = TREE_TYPE (current_function_decl);
!   stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
! 	      && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
! 		  != void_type_node));
! 
!   /* Allocate the va_list constructor.  */
!   block = assign_stack_local (BLKmode, 3 * UNITS_PER_WORD, BITS_PER_WORD);
!   RTX_UNCHANGING_P (block) = 1;
!   RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
! 
!   mem_gpr_fpr = change_address (block, word_mode, XEXP (block, 0));
!   mem_overflow = change_address (block, ptr_mode, 
! 			         plus_constant (XEXP (block, 0),
! 						UNITS_PER_WORD));
!   mem_reg_save_area = change_address (block, ptr_mode, 
! 				      plus_constant (XEXP (block, 0),
! 						     2 * UNITS_PER_WORD));
! 
!   /* Construct the two characters of `gpr' and `fpr' as a unit.  */
!   words = current_function_args_info.words - !stdarg_p;
!   gpr = (words > 8 ? 8 : words);
!   fpr = current_function_args_info.fregno - 33;
! 
!   if (BYTES_BIG_ENDIAN)
!     {
!       HOST_WIDE_INT bits = gpr << 8 | fpr;
!       if (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD)
!         tmp = GEN_INT (bits << (BITS_PER_WORD - 16));
!       else
! 	{
! 	  bits <<= BITS_PER_WORD - HOST_BITS_PER_WIDE_INT - 16;
! 	  tmp = immed_double_const (0, bits, word_mode);
! 	}
!     }
!   else
!     tmp = GEN_INT (fpr << 8 | gpr);
! 
!   emit_move_insn (mem_gpr_fpr, tmp);
! 
!   /* Find the overflow area.  */
!   if (words <= 8)
!     tmp = virtual_incoming_args_rtx;
!   else
!     tmp = expand_binop (Pmode, add_optab, virtual_incoming_args_rtx,
! 		        GEN_INT ((words - 8) * UNITS_PER_WORD),
! 		        mem_overflow, 0, OPTAB_WIDEN);
!   if (tmp != mem_overflow)
!     emit_move_insn (mem_overflow, tmp);
! 
!   /* Find the register save area.  */
!   tmp = expand_binop (Pmode, add_optab, virtual_stack_vars_rtx,
! 		      GEN_INT (-RS6000_VARARGS_SIZE),
! 		      mem_reg_save_area, 0, OPTAB_WIDEN);
!   if (tmp != mem_reg_save_area)
!     emit_move_insn (mem_reg_save_area, tmp);
! 
!   /* Return the address of the va_list constructor.  */
!   return XEXP (block, 0);
  }
  
  \f

[[ This message was sent via the linuxppc-dev mailing list.  Replies are ]]
[[ not  forced  back  to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting.   ]]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Fix 2 PPC/SYSV varargs problems
  1999-04-30  2:48 ` Richard Henderson
@ 1999-04-30  2:55   ` Zack Weinberg
  1999-04-30  3:02     ` Richard Henderson
  1999-04-30  4:49     ` Gary Thomas
  1999-04-30 13:42   ` Franz Sirl
  1 sibling, 2 replies; 13+ messages in thread
From: Zack Weinberg @ 1999-04-30  2:55 UTC (permalink / raw)
  To: Richard Henderson; +Cc: meissner, David Edelsohn, linuxppc-dev


On Thu, 29 Apr 1999 19:48:17 -0700, Richard Henderson wrote:
>On Fri, Apr 30, 1999 at 02:09:09AM +0200, Franz Sirl wrote:
>> 1. the varargs save area calculation bug, this is a hack and Richard ;-) 
>> probably won't like it, but maybe it's good enough for egcs-1.2
>
>You're right -- I hate it.  You'll have made it so I can't build a
>ppc cross compiler on my Alphas, and you'll have killed the compiler
>for a ppc64-linux.

ObDumbQuestion: Is this a bug we really need to fix for 1.2?  It's
been around for awhile and all the proposed solutions are either dirty
kludges or too invasive.

zw

[[ This message was sent via the linuxppc-dev mailing list.  Replies are ]]
[[ not  forced  back  to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting.   ]]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Fix 2 PPC/SYSV varargs problems
  1999-04-30  2:55   ` Zack Weinberg
@ 1999-04-30  3:02     ` Richard Henderson
  1999-04-30  3:08       ` David Edelsohn
  1999-04-30  4:49     ` Gary Thomas
  1 sibling, 1 reply; 13+ messages in thread
From: Richard Henderson @ 1999-04-30  3:02 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: meissner, David Edelsohn, linuxppc-dev


On Thu, Apr 29, 1999 at 10:55:36PM -0400, Zack Weinberg wrote:
> ObDumbQuestion: Is this a bug we really need to fix for 1.2?  It's
> been around for awhile and all the proposed solutions are either dirty
> kludges or too invasive.

A reasonable question.  Though I don't think my last patch is either.

It certainly isn't invasive; as for kludginess, it's in good company
with the way the alpha port has done things for a long time.  Infer
what you will with that.  ;-)


r~

[[ This message was sent via the linuxppc-dev mailing list.  Replies are ]]
[[ not  forced  back  to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting.   ]]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Fix 2 PPC/SYSV varargs problems
  1999-04-30  3:02     ` Richard Henderson
@ 1999-04-30  3:08       ` David Edelsohn
  0 siblings, 0 replies; 13+ messages in thread
From: David Edelsohn @ 1999-04-30  3:08 UTC (permalink / raw)
  To: Richard Henderson, Franz Sirl
  Cc: Zack Weinberg, meissner, linuxppc-dev, egcs-patches


>>>>> Richard Henderson writes:

Richard> It certainly isn't invasive; as for kludginess, it's in good company
Richard> with the way the alpha port has done things for a long time.  Infer
Richard> what you will with that.  ;-)

	I am much more comfortable with a patch along the lines of
Richard's proposal -- both in the short term for egcs-1.2 release and as a
long-term solution.  I do not think that there is an elegant way to fix
this. 

David

[[ This message was sent via the linuxppc-dev mailing list.  Replies are ]]
[[ not  forced  back  to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting.   ]]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Fix 2 PPC/SYSV varargs problems
  1999-04-30  2:55   ` Zack Weinberg
  1999-04-30  3:02     ` Richard Henderson
@ 1999-04-30  4:49     ` Gary Thomas
  1 sibling, 0 replies; 13+ messages in thread
From: Gary Thomas @ 1999-04-30  4:49 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: linuxppc-dev, David Edelsohn, meissner, Richard Henderson



On 30-Apr-99 Zack Weinberg wrote:
> 
> On Thu, 29 Apr 1999 19:48:17 -0700, Richard Henderson wrote:
>>On Fri, Apr 30, 1999 at 02:09:09AM +0200, Franz Sirl wrote:
>>> 1. the varargs save area calculation bug, this is a hack and Richard ;-) 
>>> probably won't like it, but maybe it's good enough for egcs-1.2
>>
>>You're right -- I hate it.  You'll have made it so I can't build a
>>ppc cross compiler on my Alphas, and you'll have killed the compiler
>>for a ppc64-linux.
> 
> ObDumbQuestion: Is this a bug we really need to fix for 1.2?  It's
> been around for awhile and all the proposed solutions are either dirty
> kludges or too invasive.
> 

It's a serious problem that has caused trouble in the past.  Fixing it
would be very nice, indeed.

However, I provide a patch for the compiler that detects potential 
occurrances and print a warning.  At least it's not a slient killer.

------------------------------------------------------------------------
Gary Thomas                              |
email: gdt@linuxppc.org                  | "Fine wine is a necessity of
   ... opinions expressed here are mine  |        life for me"
       and no one else would claim them! |
                                         |      Thomas Jefferson
------------------------------------------------------------------------



[[ This message was sent via the linuxppc-dev mailing list.  Replies are ]]
[[ not  forced  back  to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting.   ]]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Fix 2 PPC/SYSV varargs problems
  1999-04-30  2:48 ` Richard Henderson
  1999-04-30  2:55   ` Zack Weinberg
@ 1999-04-30 13:42   ` Franz Sirl
  1999-04-30 22:08     ` Richard Henderson
  1 sibling, 1 reply; 13+ messages in thread
From: Franz Sirl @ 1999-04-30 13:42 UTC (permalink / raw)
  To: Richard Henderson; +Cc: egcs-patches, meissner, David Edelsohn, linuxppc-dev


At 04:48 30.04.99 , Richard Henderson wrote:
>On Fri, Apr 30, 1999 at 02:09:09AM +0200, Franz Sirl wrote:
> > 1. the varargs save area calculation bug, this is a hack and Richard ;-)
> > probably won't like it, but maybe it's good enough for egcs-1.2
>
>You're right -- I hate it.  You'll have made it so I can't build a
>ppc cross compiler on my Alphas, and you'll have killed the compiler
>for a ppc64-linux.

Yes, thought so ;-).

>Here's an implementation of what I'd suggested before.  It looks ok
>to the eye, but I don't have a ppc-linux box handy to try it out on.

Yes, this looks good (such a patch is certainly above my current knowledge 
of egcs :-) ) and works fine on powerpc-linux-gnu, I just bootstrapped and 
checked the mainline with it. You just missed a small bit in 
setup_incoming_varargs():

    if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
      {
        rs6000_sysv_varargs_p = 1;
        if (! no_rtl)
-       save_area = plus_constant (frame_pointer_rtx, RS6000_VARARGS_OFFSET);
+       save_area = plus_constant (virtual_stack_vars_rtx, 
-RS6000_VARARGS_SIZE);
      }

Can you check in this stuff in that shape? And maybe the second part (the 
gnuplot fix) of my patch if it is OK and the testcase?

Franz


[[ This message was sent via the linuxppc-dev mailing list.  Replies are ]]
[[ not  forced  back  to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting.   ]]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Fix 2 PPC/SYSV varargs problems
  1999-04-30 13:42   ` Franz Sirl
@ 1999-04-30 22:08     ` Richard Henderson
  1999-05-03 12:44       ` Franz Sirl
  0 siblings, 1 reply; 13+ messages in thread
From: Richard Henderson @ 1999-04-30 22:08 UTC (permalink / raw)
  To: Franz Sirl; +Cc: egcs-patches, meissner, David Edelsohn, linuxppc-dev


> Can you check in this stuff in that shape?

Done.

> And maybe the second part (the 
> gnuplot fix) of my patch if it is OK and the testcase?

I'll look at this again later tonight or tomorrow -- despite
the subject line, I'd missed the fact that you were trying to
fix two separate problems.


r~

[[ This message was sent via the linuxppc-dev mailing list.  Replies are ]]
[[ not  forced  back  to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting.   ]]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Fix 2 PPC/SYSV varargs problems
  1999-04-30 22:08     ` Richard Henderson
@ 1999-05-03 12:44       ` Franz Sirl
  0 siblings, 0 replies; 13+ messages in thread
From: Franz Sirl @ 1999-05-03 12:44 UTC (permalink / raw)
  To: Richard Henderson; +Cc: egcs-patches, meissner, David Edelsohn, linuxppc-dev


At 00:08 01.05.99 , Richard Henderson wrote:
> > Can you check in this stuff in that shape?
>
>Done.

Thanks.

> > And maybe the second part (the
> > gnuplot fix) of my patch if it is OK and the testcase?
>
>I'll look at this again later tonight or tomorrow -- despite
>the subject line, I'd missed the fact that you were trying to
>fix two separate problems.

I did look at the argument handling again yesterday, and I now think there 
might be additional bugs in the handling of CUMULATIVE_ARGS->words for the 
SYSV ABI case. I'll try to construct testcases for the suspect cases.

Franz.


[[ This message was sent via the linuxppc-dev mailing list.  Replies are ]]
[[ not  forced  back  to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting.   ]]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Fix 2 PPC/SYSV varargs problems
  1999-04-30  0:09 PATCH: Fix 2 PPC/SYSV varargs problems Franz Sirl
  1999-04-30  2:48 ` Richard Henderson
@ 1999-05-12  6:19 ` Jeffrey A Law
  1999-05-12  6:48   ` Richard Henderson
  1 sibling, 1 reply; 13+ messages in thread
From: Jeffrey A Law @ 1999-05-12  6:19 UTC (permalink / raw)
  To: Franz Sirl; +Cc: egcs-patches, rth, meissner, David Edelsohn, linuxppc-dev


  In message <4.2.0.37.19990430013458.0489a950@mail.lauterbach.com>you write:
  > --=====================_53744284==_
  > Content-Type: text/plain; charset="us-ascii"; format=flowed
  > 
  > Hi,
  > 
  > this patch is supposed to fix the following problems on PPC/SYSV:
  > 
  > 1. the varargs save area calculation bug, this is a hack and Richard ;-) 
  > probably won't like it, but maybe it's good enough for egcs-1.2
  > 
  > 2. if you call a function that uses more then 8 float args before all 
  > integer argument passing registers are consumed, egcs will missetup the 
  > calling sequence. I introduced a new variable cum->sysv_fwords in the 
  > CUMULATIVE_ARGS struct, which counts the saved float words and adjusted 
  > cum->words where needed (I hope). There maybe better/nicer ways to 
  > implement that, so tell me if you want a different solution. A testcase is 
  > attached, the original problem happens with gnuplot.
Has this problem been fixed?  I see patch from Richard which looks like it
is related:

       * va-ppc.h (__va_start_common): Let __builtin_saveregs do the work.
        * rs6000.c (expand_builtin_saveregs): For V4, initialize a private
        va_list struct, and return a pointer to it.
        (setup_incoming_varargs): V4 save area based off virtual_stack_vars
        instead of frame_pointer.

[ yes, I'm going through my backlog now trying to weed out issues that I
  don't need to deal with :-) ]

jeff

[[ This message was sent via the linuxppc-dev mailing list.  Replies are ]]
[[ not  forced  back  to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting.   ]]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Fix 2 PPC/SYSV varargs problems
  1999-05-12  6:19 ` Jeffrey A Law
@ 1999-05-12  6:48   ` Richard Henderson
  1999-05-12 10:21     ` Franz Sirl
  1999-05-12 15:24     ` David Edelsohn
  0 siblings, 2 replies; 13+ messages in thread
From: Richard Henderson @ 1999-05-12  6:48 UTC (permalink / raw)
  To: law, Franz Sirl; +Cc: egcs-patches, meissner, David Edelsohn, linuxppc-dev


On Wed, May 12, 1999 at 12:19:53AM -0600, Jeffrey A Law wrote:
> Has this problem been fixed?  I see patch from Richard which looks like it
> is related:

No, this is a different, though related, problem.  I need to sit
down with the ABI to properly evaluate the patch.  PPC SVR4 varargs
seems needlessly complex.

Franz, could you point me at the test cases for this?


r~

[[ This message was sent via the linuxppc-dev mailing list.  Replies are ]]
[[ not  forced  back  to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting.   ]]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Fix 2 PPC/SYSV varargs problems
  1999-05-12  6:48   ` Richard Henderson
@ 1999-05-12 10:21     ` Franz Sirl
  1999-05-12 15:24     ` David Edelsohn
  1 sibling, 0 replies; 13+ messages in thread
From: Franz Sirl @ 1999-05-12 10:21 UTC (permalink / raw)
  To: Richard Henderson
  Cc: law, egcs-patches, meissner, David Edelsohn, linuxppc-dev


At 08:48 12.05.99 , Richard Henderson wrote:
>On Wed, May 12, 1999 at 12:19:53AM -0600, Jeffrey A Law wrote:
> > Has this problem been fixed?  I see patch from Richard which looks like it
> > is related:
>
>No, this is a different, though related, problem.  I need to sit
>down with the ABI to properly evaluate the patch.  PPC SVR4 varargs
>seems needlessly complex.

To me it looked more like some 95%-finished stuff with untested corner cases.

>Franz, could you point me at the test cases for this?

Oops, sure. I meant them to attach to my last mail, which contained my new 
patch fixing both problems below.

Thanks again for your expand_builtin_saveregs() patch, it makes life a lot 
easier on PPC :-).

Franz.

-----< testcase1
/* this testcase is a modified testcase from execute/980608-1.c.
    It additionally tests the handling of float args. The varargs
    handling on SYSV ABI contained a bug where using more than 8 float
    args before all GP regs were consumed caused a wrong stack/register
    layout to be passed by the caller. The overflowed (not fitting in FP
    registers) float args virtually consumed args fitting in GP regs (counted
    by cum->words).
    This was uncovered in real world by gnuplot.
*/

#include <stdarg.h>

static int test=23;

void f1(int a1,int a2,int a3,int a4,int a5, int a6,int a7,int a8,int a9,
         int a10)
{
        test = a9;
        return;
}

inline void debug(const char *fp,const char *msg,...)
{
        int local_var[10] = {10,};
        va_list ap;
        double df;

        local_var[0] += test;

        if (*fp != '1')
              abort();
        if (*msg != '2')
              abort();
        f1(1,2,3,4,5,6,7,8,9,local_var[0]);

        va_start( ap, msg );

        df = va_arg(ap,double);
        if (df <1.09 || df >1.11)
              abort();
        df = va_arg(ap,double);
        if (df <1.19 || df >1.21)
              abort();
        df = va_arg(ap,double);
        if (df <1.29 || df >1.31)
              abort();
        df = va_arg(ap,double);
        if (df <1.39 || df >1.41)
              abort();
        df = va_arg(ap,double);
        if (df <1.49 || df >1.51)
              abort();
        if ( *va_arg(ap,char*) != '3')
              abort();
        if ( *va_arg(ap,char*) != '4')
              abort();
        if ( *va_arg(ap,char*) != '5')
              abort();
        df = va_arg(ap,double);
        if (df <1.59 || df >1.61)
              abort();
        df = va_arg(ap,double);
        if (df <1.69 || df >1.71)
              abort();
        df = va_arg(ap,double);
        if (df <1.79 || df >1.81)
              abort();
        df = va_arg(ap,double);
        if (df <1.89 || df >1.91)
              abort();
        if ( va_arg(ap,int) != 101)
              abort();
        if ( va_arg(ap,int) != 102)
              abort();
        if ( va_arg(ap,int) != 103)
              abort();
        if ( va_arg(ap,int) != 104)
              abort();
        if ( *va_arg(ap,char*) != '6')
              abort();
        if ( va_arg(ap,int) != 105)
              abort();
        if ( va_arg(ap,int) != 106)
              abort();
        if ( va_arg(ap,int) != 107)
              abort();
        if ( va_arg(ap,int) != 108)
              abort();
        if ( va_arg(ap,int) != 109)
              abort();


        if ( va_arg(ap,int) != 110)
              abort();

        va_end( ap );
}

int main(void)
{
      debug("1 filepointer", "2 format", 1.1,1.2,1.3,1.4,1.5, "3","4","5", 
1.6,1.7,1.8,1.9, 101,102,103,104, "6", 105,106,107,108,109,110);
      exit(0);
}
-----< testcase1


-----< testcase2
/* Yet another bug in PPC/SYSV ABI varargs handling.
    If the float args overflowed from FP regs into stack space before the
    varargs started, the calculation of the overflow_area pointer in va_list
    was buggy.
    Not uncovered in real world (yet?), constructed by staring at the varargs
    code.
*/

#include <stdarg.h>

inline void debug2(const char *fp,
                   double d1,double d2,double d3,double d4,
                   double d5,double d6,double d7,double d8,double d9,
                   const char *msg,...)
{
        va_list ap;
        double df;

        if (*fp != '1')
              abort();
        if (*msg != '2')
              abort();

        va_start( ap, msg );

        df = va_arg(ap,double);
        if (df <1.09 || df >1.11)
              abort();
        df = va_arg(ap,double);
        if (df <1.19 || df >1.21)
              abort();
        df = va_arg(ap,double);
        if (df <1.29 || df >1.31)
              abort();
        df = va_arg(ap,double);
        if (df <1.39 || df >1.41)
              abort();
        df = va_arg(ap,double);
        if (df <1.49 || df >1.51)
              abort();
        if ( *va_arg(ap,char*) != '3')
              abort();
        if ( *va_arg(ap,char*) != '4')
              abort();
        if ( *va_arg(ap,char*) != '5')
              abort();
        df = va_arg(ap,double);
        if (df <1.59 || df >1.61)
              abort();
        df = va_arg(ap,double);
        if (df <1.69 || df >1.71)
              abort();
        df = va_arg(ap,double);
        if (df <1.79 || df >1.81)
              abort();
        df = va_arg(ap,double);
        if (df <1.89 || df >1.91)
              abort();
        if ( va_arg(ap,int) != 101)
              abort();
        if ( va_arg(ap,int) != 102)
              abort();
        if ( va_arg(ap,int) != 103)
              abort();
        if ( va_arg(ap,int) != 104)
              abort();
        if ( *va_arg(ap,char*) != '6')
              abort();
        if ( va_arg(ap,int) != 105)
              abort();
        if ( va_arg(ap,int) != 106)
              abort();
        if ( va_arg(ap,int) != 107)
              abort();
        if ( va_arg(ap,int) != 108)
              abort();
        if ( va_arg(ap,int) != 109)
              abort();


        df = va_arg(ap,double);
        if (df <1.99 || df >2.01)
              abort();

        if ( va_arg(ap,int) != 110)
              abort();

        va_end( ap );
}

int main(void)
{
      debug2("1 filepointer", 20.1,20.2,20.3,20.4,20.5,20.6,20.7,20.8,20.9, 
"2 format", 1.1,1.2,1.3,1.4,1.5, "3","4","5", 1.6,1.7,1.8,1.9, 
101,102,103,104, "6", 105,106,107,108,109, 2.0, 110);
      exit(0);
}
-----< testcase2

[[ This message was sent via the linuxppc-dev mailing list.  Replies are ]]
[[ not  forced  back  to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting.   ]]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Fix 2 PPC/SYSV varargs problems
  1999-05-12  6:48   ` Richard Henderson
  1999-05-12 10:21     ` Franz Sirl
@ 1999-05-12 15:24     ` David Edelsohn
  1 sibling, 0 replies; 13+ messages in thread
From: David Edelsohn @ 1999-05-12 15:24 UTC (permalink / raw)
  To: Richard Henderson; +Cc: law, Franz Sirl, egcs-patches, meissner, linuxppc-dev


>>>>> Richard Henderson writes:


Richard> On Wed, May 12, 1999 at 12:19:53AM -0600, Jeffrey A Law wrote:
>> Has this problem been fixed?  I see patch from Richard which looks like it
>> is related:

Richard> No, this is a different, though related, problem.  I need to sit
Richard> down with the ABI to properly evaluate the patch.  PPC SVR4 varargs
Richard> seems needlessly complex.

	That is an understatement!  PPC SVR4 varargs is a monstrosity that
attempted to pack the registers as tightly as possible and created an
endless mess as a result.

David

[[ This message was sent via the linuxppc-dev mailing list.  Replies are ]]
[[ not  forced  back  to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting.   ]]

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~1999-05-12 15:24 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
1999-04-30  0:09 PATCH: Fix 2 PPC/SYSV varargs problems Franz Sirl
1999-04-30  2:48 ` Richard Henderson
1999-04-30  2:55   ` Zack Weinberg
1999-04-30  3:02     ` Richard Henderson
1999-04-30  3:08       ` David Edelsohn
1999-04-30  4:49     ` Gary Thomas
1999-04-30 13:42   ` Franz Sirl
1999-04-30 22:08     ` Richard Henderson
1999-05-03 12:44       ` Franz Sirl
1999-05-12  6:19 ` Jeffrey A Law
1999-05-12  6:48   ` Richard Henderson
1999-05-12 10:21     ` Franz Sirl
1999-05-12 15:24     ` David Edelsohn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).