[IRIX 6/Ultrix V4] Non-MIPS-ABI conformant passing of small structures

Rainer Orth ro@TechFak.Uni-Bielefeld.DE
Wed Jun 23 11:50:00 GMT 1999


I've finally been able to fully track down and fix the wrong passing of
small structure arguments on IRIX 6.2 mentioned in

	http://egcs.cygnus.com/ml/egcs-bugs/1999-05/msg00402.html

The problem was two-fold:

* Because someone thought it's inefficient, mips.c (function_arg) decided
  not to follow the MIPS ABI in left-aligning small structures.  This
  broke e.g. inet_ntoa() on IRIX 6.2 as described in the FAQ.  I simply
  removed the test for !TARGET_64BIT since this convention is valid both
  for the o32 and n32/n64 ABIs, as described in 

	http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650 &db=bks&srch=&fname=/SGI_Developer/Mpro_n32_ABI/345

  and the Proposed 64-bit Extensions to the psMIPS ABI (section 3.2.2.5):

	http://www.mipsabi.org/Tech/Standards/psCh3.htm

  With this change, I successfully bootstrapped gcc on IRIX 6.2.  Running
  the testsuite revealed another problem: several tests passing small
  structures to variadic functions now failed.

* Small structure arguments to variadic functions follow the same alignment
  rules as `regular' structure arguments.  So va-mips.h (va_arg) had to be
  adapted too: there's no difference in the alignment requirements between
  the 32-bit (o32) and 64-bit (n32/n64) ABIs on big-endian targets: scalar
  arguments are right-aligned, structures are left-aligned.  So I removed
  the wrong special treatment of __mips64 and fixed va_arg for the
  big-endian case to match this.  With this fixed va-mips.h, I reran the
  testsuite, and all the regressions vanished.  Even one previously failing
  test case works now:

-FAIL: g++.other/new3.C  Execution test
  
* To check that my changes hadn't broken anything for little-endian MIPS
  targets, I checked if Ultrix V4.3 MIPS 2.1 cc and gcc calling conventions
  matched, and found that gcc is broken here, too: the left-alignment of
  small structures happens only on big-endian targets, as seen in the MIPS
  ABI above and Ultrix V4.3 and IRIX 6.2 native <stdarg.h>.  So I fixed
  this and the little-endian va_arg as well, and now cc and gcc agree about
  passing structures.  With this change, the testsuite showed no
  regressions: in fact, even two testsuite failures vanished with this
  change:

 Running target unix
-FAIL: gcc.c-torture/compile/zero-strct-1.c,  -O1  
-FAIL: gcc.c-torture/compile/zero-strct-1.c,  -O2  
-FAIL: gcc.c-torture/compile/zero-strct-1.c,  -O3 -fomit-frame-pointer  
-FAIL: gcc.c-torture/compile/zero-strct-1.c,  -O3 -g  
-FAIL: gcc.c-torture/compile/zero-strct-1.c,  -Os  
-FAIL: gcc.c-torture/execute/strct-stdarg-1.c execution,  -O0 
-FAIL: gcc.c-torture/execute/strct-stdarg-1.c execution,  -O1 
-FAIL: gcc.c-torture/execute/strct-stdarg-1.c execution,  -O2 
-FAIL: gcc.c-torture/execute/strct-stdarg-1.c execution,  -O3 -fomit-frame-pointer 
-FAIL: gcc.c-torture/execute/strct-stdarg-1.c execution,  -O3 -fomit-frame-pointer -funroll-loops 
-FAIL: gcc.c-torture/execute/strct-stdarg-1.c execution,  -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions 
-FAIL: gcc.c-torture/execute/strct-stdarg-1.c execution,  -O3 -g 
-FAIL: gcc.c-torture/execute/strct-stdarg-1.c execution,  -Os 
 XPASS: gcc.c-torture/execute/memcheck/blkarg.c execution,  -O0 
 XPASS: gcc.c-torture/execute/memcheck/blkarg.c execution,  -O1 
 XPASS: gcc.c-torture/execute/memcheck/blkarg.c execution,  -O2 

The test programs I used to verify IRIX and Ultrix cc and gcc agree in
their calling conventions are included below.  They are probably not
appropriate for the testsuite because they require the use of the native
cc.

Of course these changes break binary compatibility with previous versions
of gcc, but they are critical for gcc 2.95 to finally make gcc's structure
passing conventions conform to the MIPS ABI and so match the system
libraries and native compilers.

If this change is integrated into the release branch, the FAQ should be
updated to mention this.  I can provide a patch if required.

	Rainer


Tue Jun 22 19:42:10 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>

	* ginclude/va-mips.h (va-arg): Removed wrong special treatment of
	__mips64.  Left-align structures on big-endian targets only.

Mon Jun 14 22:52:14 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>

	* mips/mips.c (function_arg): Pass small structures per MIPS ABI
	conventions, i.e. left-align on big-endian targets only.

Index: config/mips/mips.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/mips/mips.c,v
retrieving revision 1.56
diff -u -p -r1.56 mips.c
--- mips.c	1999/05/07 12:42:03	1.56
+++ mips.c	1999/06/23 17:13:18
@@ -3907,14 +3907,8 @@ function_arg (cum, mode, type, named)
 	 As a result, we compute more adjustments than we need here.
 	 See the CUMULATIVE_ARGS definition in mips.h.  */
 
-      /* ??? This scheme requires everything smaller than the word size to
-	 shifted to the left, but when TARGET_64BIT and ! TARGET_INT64,
-	 that would mean every int needs to be shifted left, which is very
-	 inefficient.  Let's not carry this compatibility to the 64 bit
-	 calling convention for now.  */
-
       if (struct_p && int_size_in_bytes (type) < UNITS_PER_WORD
-	  && ! TARGET_64BIT && mips_abi != ABI_EABI)
+	  && BYTES_BIG_ENDIAN && mips_abi != ABI_EABI)
 	{
 	  rtx amount = GEN_INT (BITS_PER_WORD
 				- int_size_in_bytes (type) * BITS_PER_UNIT);
Index: ginclude/va-mips.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/ginclude/va-mips.h,v
retrieving revision 1.5
diff -u -p -r1.5 va-mips.h
--- va-mips.h	1998/12/16 21:19:36	1.5
+++ va-mips.h	1999/06/23 17:13:18
@@ -233,41 +233,23 @@ void va_end (__gnuc_va_list);		/* Define
 
 /* We cast to void * and then to TYPE * because this avoids
    a warning about increasing the alignment requirement.  */
-/* The __mips64 cases are reversed from the 32 bit cases, because the standard
-   32 bit calling convention left-aligns all parameters smaller than a word,
-   whereas the __mips64 calling convention does not (and hence they are
-   right aligned).  */
-#ifdef __mips64
 #ifdef __MIPSEB__
-#define va_arg(__AP, __type)                                    \
-  ((__type *) (void *) (__AP = (char *)                         \
-                       ((((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8) \
-			   + __va_rounded_size (__type))))[-1]
-#else
-#define va_arg(__AP, __type)                                    \
-  ((__AP = (char *) ((((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8)	\
-		     + __va_rounded_size (__type))),		\
-   *(__type *) (void *) (__AP - __va_rounded_size (__type)))
-#endif
-
-#else /* not __mips64 */
-
-#ifdef __MIPSEB__
 /* For big-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)))
+   (__builtin_classify_type (*(__type *) 0) < __record_type_class	\
+   ? ((__type *) (void *) __AP)[-1]					\
+   : *(__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
+					 + sizeof(__type))))[-1]
 #endif
 #endif /* ! defined (__mips_eabi)  */
 


More information about the Gcc-patches mailing list