This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
bugfix: incorrect va_arg() definition for 32bit MIPS
- To: gcc-bugs at gcc dot gnu dot org
- Subject: bugfix: incorrect va_arg() definition for 32bit MIPS
- From: Hiroyuki Machida <machida at sm dot sony dot co dot jp>
- Date: Wed, 26 Jan 2000 13:27:53 +0900
- Cc: linux at cthulhu dot engr dot sgi dot com, linux-gcc at vger dot rutgers dot edu
Hi.
I have been building gcc 2.95.2 on 32bit MIPS/Linux box.
During this work, I found a inverted 'ifdef' on defining
va_arg() macro in gcc/ginclude/va-mips.h.
That is, definition of va_arg for 32bit little endian and 32bit big
endian is inverted.
You can repeat this problem running a attached test program.
I guess gcc on IRIX 5.? or O32 ABI box has same problem.
Have you ever experienced same problem on 32bit MIPS box?
Sample fix is attached at the bottom.
VERSION:
gcc 2.95.2 on MIPS/Linux
gcc 2.7.2 on MIPS/Linux
egcs-1.0.2 on MIPS/Linux
REPEAT BY:
Compile and run this program.
The program will print "OK", if va_arg() accept args correclty.
/*
*
* stdarg.c -- Simple stdarg test.
* Pass #of pairs and (type, value) pairs using stdarg.h.
* And check if passed values are correctly accepted.
*
*/
#include<stdarg.h>
int foo(int nargs, ...)
{
va_list ap;
int i;
int ng = 0;
long long expected;
long long passed;
/* get # of args */
va_start(ap, nargs);
printf(" # of args:%d\n",nargs);
for (i=1; i<= nargs ; i++) {
char type;
int d; long long ll; char c; char *s;
/* calc. expceted value */
expected=i;
if ( expected & 1 ) expected = -expected;
/* get type of the arg */
type = (char ) va_arg(ap, char);
switch (type) {
case 'i': /* int */
d = va_arg(ap, int);
passed=d;
printf("%10s: expected:%3lld,\t passed:%3lld\n",
"int", expected, passed);
if ( passed != expected) ng ++;
break;
case 'L': /* long long */
ll = va_arg(ap, long long);
passed=ll;
printf("%10s: expected:%3lld,\t passed:%3lld\n",
"long long", expected, passed);
if ( passed != expected) ng ++;
break;
case 'c': /* char */
c = (char) va_arg(ap, char);
passed=(long long) (c - '0');
printf("%10s: expected:%3lld,\t passed:%3lld\n",
"char", expected, passed);
if ( passed != expected) ng ++;
break;
case 's': /* char * */
s = va_arg(ap, char *);
passed=(long long)atol(s);
printf("%10s: expected:%3lld,\t passed:%3lld\n",
"string", expected, passed);
if ( passed != expected) ng ++;
break;
default: /* Unknown */
printf(" unkown type:%4d: argptr:0x%8.8x\n",
type,(void *)ap);
ng ++;
break;
}
}
va_end(ap);
return ng;
}
int main()
{
int ng;
printf("*\n");
printf("* Simple stdarg test.\n");
printf("*\n");
/* Pass # of pairs and (type, order<*>) pairs */
/* order<*> number must be minus value if order is odd */
ng = foo(6,
'i', -1,
'c', '2',
'L', (long long)-3,
's', "4",
'i', -5 ,
'c', '6');
if (ng) {
printf("NG\n");
}
else {
printf("OK\n");
}
return ng;
}
SAMPLE FIX:
gcc/ginclude/va-mips.h
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -p -r1.1.1.1 -r1.2
--- va-mips.h 1999/05/19 13:14:31 1.1.1.1
+++ va-mips.h 1999/11/08 09:48:26 1.2
@@ -254,19 +254,19 @@ void va_end (__gnuc_va_list); /* Define
#ifdef __MIPSEB__
/* For big-endian machines. */
+#define va_arg(__AP, __type) \
+ ((__type *) (void *) (__AP = (char *) ((__alignof__(__type) > 4 \
+ ? ((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8 \
+ : ((__PTRDIFF_TYPE__)__AP + 4 - 1) & -4) \
+ + __va_rounded_size(__type))))[-1]
+#else
+/* For little-endian machines. */
#define va_arg(__AP, __type) \
((__AP = (char *) ((__alignof__ (__type) > 4 \
? ((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8 \
: ((__PTRDIFF_TYPE__)__AP + 4 - 1) & -4) \
+ __va_rounded_size (__type))), \
*(__type *) (void *) (__AP - __va_rounded_size (__type)))
-#else
-/* For little-endian machines. */
-#define va_arg(__AP, __type) \
- ((__type *) (void *) (__AP = (char *) ((__alignof__(__type) > 4 \
- ? ((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8 \
- : ((__PTRDIFF_TYPE__)__AP + 4 - 1) & -4) \
- + __va_rounded_size(__type))))[-1]
#endif
#endif
#endif /* ! defined (__mips_eabi) */
---
Hiroyuki Machida machida@sm.sony.co.jp
Creative Station SCEI / Sony Corp.