PATCH: Fix 2 PPC/SYSV varargs problems
Franz Sirl
Franz.Sirl-kernel at lauterbach.com
Fri Apr 30 10:09:09 EST 1999
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.
-------------- next part --------------
#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);
}
-------------- next part --------------
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);
}
/* 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);
More information about the Linuxppc-dev
mailing list