This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR target/13666


Hi,

This is another deviation from the psABI on SPARC64.  The compiler passes the 
small unions right-justified, while the 64-bit ABI wants them to be passed 
left-justified, like structures.

Fixed by adding function_arg_union_value modeled on function_arg_record_value
to deal with union passing.  The patch was bootstrapped/regtested on 
sparc64-sun-solaris2.9 (except Ada and libgcj) and compat-regtested against 
the Sun ONE Studio 8 compiler.  It fixes the 2 attached compat testcases.

OK for the compat testcases?


2004-01-26  Eric Botcazou  <ebotcazou@libertysurf.fr>

        PR target/13666
        * config/sparc/sparc.c (function_arg_union_value): New function.
	(function_arg): Use it to deal with unions.
	(function_value): Likewise.  Define 'regbase' only for ARCH64.
	Replace a conditional statement by a simpler one.


2004-01-26  Eric Botcazou  <ebotcazou@libertysurf.fr>

        * gcc.dg/compat/union-by-value-1_main.c,
	union-by-value-1_x.c, union-by-value-1_y.c,
	union-check.h, union-defs.h,
	union-init.h, union-return-1_main.c,
	union-return-1_x.c, union-return-1_y.c: New files.


-- 
Eric Botcazou
Index: config/sparc/sparc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.c,v
retrieving revision 1.278
diff -u -p -r1.278 sparc.c
--- config/sparc/sparc.c	23 Jan 2004 09:16:56 -0000	1.278
+++ config/sparc/sparc.c	26 Jan 2004 10:17:44 -0000
@@ -4827,7 +4827,7 @@ init_cumulative_args (struct sparc_args 
    Sub-fields are not taken into account for the PACKED_P predicate.  */
 
 static void
-scan_record_type(tree type, int *intregs_p, int *fpregs_p, int *packed_p)
+scan_record_type (tree type, int *intregs_p, int *fpregs_p, int *packed_p)
 {
   tree field;
 
@@ -5002,6 +5002,7 @@ static void function_arg_record_value_2
 static void function_arg_record_value_1
  (tree, HOST_WIDE_INT, struct function_arg_record_value_parms *, bool);
 static rtx function_arg_record_value (tree, enum machine_mode, int, int, int);
+static rtx function_arg_union_value (int, int);
 
 /* A subroutine of function_arg_record_value.  Traverse the structure
    recursively and determine how many registers will be required.  */
@@ -5335,6 +5336,34 @@ function_arg_record_value (tree type, en
   return parms.ret;
 }
 
+/* Used by function_arg and function_value to implement the conventions
+   of the 64-bit ABI for passing and returning unions.
+   Return an expression valid as a return value for the two macros
+   FUNCTION_ARG and FUNCTION_VALUE.
+
+   SIZE is the size in bytes of the union.
+   REGNO is the hard register the union will be passed in.  */
+
+static rtx
+function_arg_union_value (int size, int regno)
+{
+  enum machine_mode mode;
+  rtx reg;
+
+  if (size <= UNITS_PER_WORD)
+    mode = word_mode;
+  else
+    mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+
+  reg = gen_rtx_REG (mode, regno);
+
+  /* Unions are passed left-justified.  */
+  return gen_rtx_PARALLEL (mode,
+			   gen_rtvec (1, gen_rtx_EXPR_LIST (VOIDmode,
+							    reg,
+							    const0_rtx)));
+}
+
 /* Handle the FUNCTION_ARG macro.
    Determine where to put an argument to a function.
    Value is zero to push the argument on the stack,
@@ -5384,14 +5413,12 @@ function_arg (const struct sparc_args *c
     }
   else if (type && TREE_CODE (type) == UNION_TYPE)
     {
-      enum machine_mode mode;
-      int bytes = int_size_in_bytes (type);
+      HOST_WIDE_INT size = int_size_in_bytes (type);
 
-      if (bytes > 16)
-	abort ();
+      if (size > 16)
+	abort (); /* shouldn't get here */
 
-      mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 0);
-      reg = gen_rtx_REG (mode, regno);
+      return function_arg_union_value (size, regno);
     }
   /* v9 fp args in reg slots beyond the int reg slots get passed in regs
      but also have the slot allocated for them.
@@ -5646,12 +5673,13 @@ rtx
 function_value (tree type, enum machine_mode mode, int incoming_p)
 {
   int regno;
-  int regbase = (incoming_p
-		 ? SPARC_OUTGOING_INT_ARG_FIRST
-		 : SPARC_INCOMING_INT_ARG_FIRST);
 
   if (TARGET_ARCH64 && type)
     {
+      int regbase = (incoming_p
+		     ? SPARC_OUTGOING_INT_ARG_FIRST
+		     : SPARC_INCOMING_INT_ARG_FIRST);
+
       if (TREE_CODE (type) == RECORD_TYPE)
 	{
 	  /* Structures up to 32 bytes in size are passed in registers,
@@ -5662,6 +5690,15 @@ function_value (tree type, enum machine_
 
 	  return function_arg_record_value (type, mode, 0, 1, regbase);
 	}
+      else if (TREE_CODE (type) == UNION_TYPE)
+	{
+	  HOST_WIDE_INT size = int_size_in_bytes (type);
+
+	  if (size > 32)
+	    abort (); /* shouldn't get here */
+
+	  return function_arg_union_value (size, regbase);
+	}
       else if (AGGREGATE_TYPE_P (type))
 	{
 	  /* All other aggregate types are passed in an integer register
@@ -5673,13 +5710,10 @@ function_value (tree type, enum machine_
 
 	  mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 0);
 	}
+      else if (GET_MODE_CLASS (mode) == MODE_INT
+	       && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+	mode = word_mode;
     }
-    
-  if (TARGET_ARCH64
-      && GET_MODE_CLASS (mode) == MODE_INT 
-      && GET_MODE_SIZE (mode) < UNITS_PER_WORD
-      && type && ! AGGREGATE_TYPE_P (type))
-    mode = DImode;
 
   if (incoming_p)
     regno = BASE_RETURN_VALUE_REG (mode);
--- /dev/null	Thu Apr 11 16:25:15 2002
+++ gcc.dg/compat/union-by-value-1_main.c	Sun Jan 25 11:26:44 2004
@@ -0,0 +1,13 @@
+/* Test function argument passing.  This was written when correcting
+   a deviation from the ABI on SPARC64 between 3.3 and 3.4.  */
+
+extern void union_by_value_1_x (void);
+extern void exit (int);
+int fails;
+
+int
+main ()
+{
+  union_by_value_1_x ();
+  exit (0);
+}
--- /dev/null	Thu Apr 11 16:25:15 2002
+++ gcc.dg/compat/union-by-value-1_x.c	Sun Jan 25 11:24:53 2004
@@ -0,0 +1,180 @@
+#include "compat-common.h"
+
+#define T(TYPE)							\
+TYPE g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE;		\
+TYPE g5s##TYPE, g6s##TYPE, g7s##TYPE, g8s##TYPE;		\
+TYPE g9s##TYPE, g10s##TYPE, g11s##TYPE, g12s##TYPE;		\
+TYPE g13s##TYPE, g14s##TYPE, g15s##TYPE, g16s##TYPE;		\
+								\
+extern void init##TYPE (TYPE *p, int i);			\
+extern void checkg##TYPE (void);				\
+extern void							\
+test##TYPE (TYPE s1, TYPE s2, TYPE s3, TYPE s4,			\
+	    TYPE s5, TYPE s6, TYPE s7, TYPE s8,			\
+	    TYPE s9, TYPE s10, TYPE s11, TYPE s12,		\
+	    TYPE s13, TYPE s14, TYPE s15, TYPE s16);		\
+extern void testva##TYPE (int n, ...);				\
+								\
+void								\
+test2_##TYPE (TYPE s1, TYPE s2, TYPE s3, TYPE s4,		\
+	      TYPE s5, TYPE s6, TYPE s7, TYPE s8)		\
+{								\
+  test##TYPE (s1, g2s##TYPE, s2, g4s##TYPE,			\
+	      s3, g6s##TYPE, s4, g8s##TYPE,			\
+	      s5, g10s##TYPE, s6, g12s##TYPE,			\
+	      s7, g14s##TYPE, s8, g16s##TYPE);			\
+}								\
+								\
+void								\
+testit##TYPE (void)						\
+{								\
+  DEBUG_FPUTS (#TYPE);						\
+  DEBUG_FPUTS (" init: ");					\
+  init##TYPE  ( &g1s##TYPE,  1);				\
+  init##TYPE  ( &g2s##TYPE,  2);				\
+  init##TYPE  ( &g3s##TYPE,  3);				\
+  init##TYPE  ( &g4s##TYPE,  4);				\
+  init##TYPE  ( &g5s##TYPE,  5);				\
+  init##TYPE  ( &g6s##TYPE,  6);				\
+  init##TYPE  ( &g7s##TYPE,  7);				\
+  init##TYPE  ( &g8s##TYPE,  8);				\
+  init##TYPE  ( &g9s##TYPE,  9);				\
+  init##TYPE  (&g10s##TYPE, 10);				\
+  init##TYPE  (&g11s##TYPE, 11);				\
+  init##TYPE  (&g12s##TYPE, 12);				\
+  init##TYPE  (&g13s##TYPE, 13);				\
+  init##TYPE  (&g14s##TYPE, 14);				\
+  init##TYPE  (&g15s##TYPE, 15);				\
+  init##TYPE  (&g16s##TYPE, 16);				\
+  checkg##TYPE ();						\
+  DEBUG_NL;							\
+  DEBUG_FPUTS (#TYPE);						\
+  DEBUG_FPUTS (" test: ");					\
+  test##TYPE (g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE,	\
+	      g5s##TYPE, g6s##TYPE, g7s##TYPE, g8s##TYPE,	\
+	      g9s##TYPE, g10s##TYPE, g11s##TYPE, g12s##TYPE,	\
+	      g13s##TYPE, g14s##TYPE, g15s##TYPE, g16s##TYPE);	\
+  DEBUG_NL;							\
+  DEBUG_FPUTS (#TYPE);						\
+  DEBUG_FPUTS (" testva:");					\
+  DEBUG_NL;							\
+  testva##TYPE (1,						\
+		g1s##TYPE);					\
+  DEBUG_NL;							\
+  testva##TYPE (2,						\
+		g1s##TYPE, g2s##TYPE);				\
+  DEBUG_NL;							\
+  testva##TYPE (3,						\
+		g1s##TYPE, g2s##TYPE, g3s##TYPE);		\
+  DEBUG_NL;							\
+  testva##TYPE (4,						\
+		g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE);	\
+  DEBUG_NL;							\
+  testva##TYPE (5,						\
+		g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE,	\
+		g5s##TYPE);					\
+  DEBUG_NL;							\
+  testva##TYPE (6,						\
+		g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE,	\
+		g5s##TYPE, g6s##TYPE);				\
+  DEBUG_NL;							\
+  testva##TYPE (7,						\
+		g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE,	\
+		g5s##TYPE, g6s##TYPE, g7s##TYPE);		\
+  DEBUG_NL;							\
+  testva##TYPE (8,						\
+		g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE,	\
+		g5s##TYPE, g6s##TYPE, g7s##TYPE, g8s##TYPE);	\
+  DEBUG_NL;							\
+  testva##TYPE (9,						\
+		g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE,	\
+		g5s##TYPE, g6s##TYPE, g7s##TYPE, g8s##TYPE,	\
+		g9s##TYPE);					\
+  DEBUG_NL;							\
+  testva##TYPE (10,						\
+		g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE,	\
+		g5s##TYPE, g6s##TYPE, g7s##TYPE, g8s##TYPE,	\
+		g9s##TYPE, g10s##TYPE);				\
+  DEBUG_NL;							\
+  testva##TYPE (11,						\
+		g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE,	\
+		g5s##TYPE, g6s##TYPE, g7s##TYPE, g8s##TYPE,	\
+		g9s##TYPE, g10s##TYPE, g11s##TYPE);		\
+  DEBUG_NL;							\
+  testva##TYPE (12,						\
+		g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE,	\
+		g5s##TYPE, g6s##TYPE, g7s##TYPE, g8s##TYPE,	\
+		g9s##TYPE, g10s##TYPE, g11s##TYPE, g12s##TYPE);	\
+  DEBUG_NL;							\
+  testva##TYPE (13,						\
+		g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE,	\
+		g5s##TYPE, g6s##TYPE, g7s##TYPE, g8s##TYPE,	\
+		g9s##TYPE, g10s##TYPE, g11s##TYPE, g12s##TYPE,	\
+		g13s##TYPE);					\
+  DEBUG_NL;							\
+  testva##TYPE (14,						\
+		g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE,	\
+		g5s##TYPE, g6s##TYPE, g7s##TYPE, g8s##TYPE,	\
+		g9s##TYPE, g10s##TYPE, g11s##TYPE, g12s##TYPE,	\
+		g13s##TYPE, g14s##TYPE);			\
+  DEBUG_NL;							\
+  testva##TYPE (15,						\
+		g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE,	\
+		g5s##TYPE, g6s##TYPE, g7s##TYPE, g8s##TYPE,	\
+		g9s##TYPE, g10s##TYPE, g11s##TYPE, g12s##TYPE,	\
+		g13s##TYPE, g14s##TYPE, g15s##TYPE);		\
+  DEBUG_NL;							\
+  testva##TYPE (16,						\
+		g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE,	\
+		g5s##TYPE, g6s##TYPE, g7s##TYPE, g8s##TYPE,	\
+		g9s##TYPE, g10s##TYPE, g11s##TYPE, g12s##TYPE,	\
+		g13s##TYPE, g14s##TYPE, g15s##TYPE, g16s##TYPE); \
+  DEBUG_NL;							\
+  DEBUG_FPUTS (#TYPE);						\
+  DEBUG_FPUTS (" test2:");					\
+  test2_##TYPE (g1s##TYPE, g3s##TYPE, g5s##TYPE, g7s##TYPE,	\
+		g9s##TYPE, g11s##TYPE, g13s##TYPE, g15s##TYPE);	\
+  DEBUG_NL;							\
+}
+
+#include "union-defs.h"
+#include "union-check.h"
+
+T(Ucs)
+T(Uci)
+T(Ucl)
+T(Ucll)
+T(Usi)
+T(Usl)
+T(Usll)
+T(Uil)
+T(Uill)
+T(Ulll)
+
+#undef T
+
+void
+union_by_value_1_x ()
+{
+DEBUG_INIT
+
+#define T(TYPE) testit##TYPE ();
+
+T(Ucs)
+T(Uci)
+T(Ucl)
+T(Ucll)
+T(Usi)
+T(Usl)
+T(Usll)
+T(Uil)
+T(Uill)
+T(Ulll)
+
+DEBUG_FINI
+
+if (fails != 0)
+  abort ();
+
+#undef T
+}
--- /dev/null	Thu Apr 11 16:25:15 2002
+++ gcc.dg/compat/union-by-value-1_y.c	Sun Jan 25 11:24:29 2004
@@ -0,0 +1,92 @@
+#include <stdarg.h>
+
+#include "compat-common.h"
+
+#ifdef SKIP_VA
+const int test_va = 0;
+#else
+const int test_va = 1;
+#endif
+
+#include "union-defs.h"
+#include "union-init.h"
+
+#define T(TYPE)							\
+extern void check##TYPE (TYPE x, int i);			\
+extern TYPE g1s##TYPE, g2s##TYPE, g3s##TYPE, g4s##TYPE;		\
+extern TYPE g5s##TYPE, g6s##TYPE, g7s##TYPE, g8s##TYPE;		\
+extern TYPE g9s##TYPE, g10s##TYPE, g11s##TYPE, g12s##TYPE;	\
+extern TYPE g13s##TYPE, g14s##TYPE, g15s##TYPE, g16s##TYPE;	\
+								\
+void								\
+checkg##TYPE (void)						\
+{								\
+  check##TYPE (  g1s##TYPE,  1);				\
+  check##TYPE (  g2s##TYPE,  2);				\
+  check##TYPE (  g3s##TYPE,  3);				\
+  check##TYPE (  g4s##TYPE,  4);				\
+  check##TYPE (  g5s##TYPE,  5);				\
+  check##TYPE (  g6s##TYPE,  6);				\
+  check##TYPE (  g7s##TYPE,  7);				\
+  check##TYPE (  g8s##TYPE,  8);				\
+  check##TYPE (  g9s##TYPE,  9);				\
+  check##TYPE ( g10s##TYPE, 10);				\
+  check##TYPE ( g11s##TYPE, 11);				\
+  check##TYPE ( g12s##TYPE, 12);				\
+  check##TYPE ( g13s##TYPE, 13);				\
+  check##TYPE ( g14s##TYPE, 14);				\
+  check##TYPE ( g15s##TYPE, 15);				\
+  check##TYPE ( g16s##TYPE, 16);				\
+}								\
+								\
+void								\
+test##TYPE (TYPE s1, TYPE s2, TYPE s3, TYPE s4,			\
+	    TYPE s5, TYPE s6, TYPE s7, TYPE s8,			\
+	    TYPE s9, TYPE s10, TYPE s11, TYPE s12,		\
+	    TYPE s13, TYPE s14, TYPE s15, TYPE s16)		\
+{								\
+  check##TYPE (s1, 1);						\
+  check##TYPE (s2, 2);						\
+  check##TYPE (s3, 3);						\
+  check##TYPE (s4, 4);						\
+  check##TYPE (s5, 5);						\
+  check##TYPE (s6, 6);						\
+  check##TYPE (s7, 7);						\
+  check##TYPE (s8, 8);						\
+  check##TYPE (s9, 9);						\
+  check##TYPE (s10, 10);					\
+  check##TYPE (s11, 11);					\
+  check##TYPE (s12, 12);					\
+  check##TYPE (s13, 13);					\
+  check##TYPE (s14, 14);					\
+  check##TYPE (s15, 15);					\
+  check##TYPE (s16, 16);					\
+}								\
+								\
+void								\
+testva##TYPE (int n, ...)					\
+{								\
+  int i;							\
+  va_list ap;							\
+  if (test_va)							\
+    {								\
+      va_start (ap, n);						\
+      for (i = 0; i < n; i++)					\
+	{							\
+	  TYPE t = va_arg (ap, TYPE);				\
+	  check##TYPE (t, i+1);					\
+	}							\
+      va_end (ap);						\
+    }								\
+}
+
+T(Ucs)
+T(Uci)
+T(Ucl)
+T(Ucll)
+T(Usi)
+T(Usl)
+T(Usll)
+T(Uil)
+T(Uill)
+T(Ulll)
--- /dev/null	Thu Apr 11 16:25:15 2002
+++ gcc.dg/compat/union-check.h	Sun Jan 25 11:31:09 2004
@@ -0,0 +1,34 @@
+/* Function definitions that are used by multiple tests.  */
+
+#define CHECK_CHAR(TYPE)		\
+  void check##TYPE (TYPE p, int i)	\
+   { if (p.c != (char)i) DEBUG_CHECK }
+
+CHECK_CHAR(Ucs)
+CHECK_CHAR(Uci)
+CHECK_CHAR(Ucl)
+CHECK_CHAR(Ucll)
+
+
+#define CHECK_SHORT(TYPE)		\
+  void check##TYPE (TYPE p, int i)	\
+   { if (p.s != (short)i) DEBUG_CHECK }
+
+CHECK_SHORT(Usi)
+CHECK_SHORT(Usl)
+CHECK_SHORT(Usll)
+
+
+#define CHECK_INT(TYPE)			\
+  void check##TYPE (TYPE p, int i)	\
+   { if (p.i != i) DEBUG_CHECK }
+
+CHECK_INT(Uil)
+CHECK_INT(Uill)
+
+
+#define CHECK_LONG(TYPE)		\
+  void check##TYPE (TYPE p, int i)	\
+   { if (p.l != (long)i) DEBUG_CHECK }
+
+CHECK_LONG(Ulll)
--- /dev/null	Thu Apr 11 16:25:15 2002
+++ gcc.dg/compat/union-defs.h	Sun Jan 25 11:01:40 2004
@@ -0,0 +1,15 @@
+/* Type definitions that are used by multiple tests.  */
+
+typedef union { char c; short s; } Ucs;
+typedef union { char c; int i; } Uci;
+typedef union { char c; long l; } Ucl;
+typedef union { char c; long long ll; } Ucll;
+
+typedef union { short s; int i; } Usi;
+typedef union { short s; long l; } Usl;
+typedef union { short s; long long ll; } Usll;
+
+typedef union { int i; long l; } Uil;
+typedef union { int i; long long ll; } Uill;
+
+typedef union { long l; long long ll; } Ulll;
--- /dev/null	Thu Apr 11 16:25:15 2002
+++ gcc.dg/compat/union-init.h	Sun Jan 25 11:09:09 2004
@@ -0,0 +1,34 @@
+/* Function definitions that are used by multiple tests.  */
+
+#define INIT_CHAR(TYPE)			\
+  void init##TYPE (TYPE *p, int i)	\
+   { p->c = (char)i; }
+
+INIT_CHAR(Ucs)
+INIT_CHAR(Uci)
+INIT_CHAR(Ucl)
+INIT_CHAR(Ucll)
+
+
+#define INIT_SHORT(TYPE)		\
+  void init##TYPE (TYPE *p, int i)	\
+   { p->s = (short)i; }
+
+INIT_SHORT(Usi)
+INIT_SHORT(Usl)
+INIT_SHORT(Usll)
+
+
+#define INIT_INT(TYPE)			\
+  void init##TYPE (TYPE *p, int i)	\
+   { p->i = i; }
+
+INIT_INT(Uil)
+INIT_INT(Uill)
+
+
+#define INIT_LONG(TYPE)			\
+  void init##TYPE (TYPE *p, int i)	\
+   { p->l = (long)i; }
+
+INIT_LONG(Ulll)
--- /dev/null	Thu Apr 11 16:25:15 2002
+++ gcc.dg/compat/union-return-1_main.c	Sun Jan 25 11:27:01 2004
@@ -0,0 +1,13 @@
+/* Test function return values.  This was written when correcting
+   a deviation from the ABI on SPARC64 between 3.3 and 3.4.  */
+
+extern void union_return_1_x (void);
+extern void exit (int);
+int fails;
+
+int
+main ()
+{
+  union_return_1_x ();
+  exit (0);
+}
--- /dev/null	Thu Apr 11 16:25:15 2002
+++ gcc.dg/compat/union-return-1_x.c	Sun Jan 25 11:28:09 2004
@@ -0,0 +1,124 @@
+#include "compat-common.h"
+
+#ifdef SKIP_VA
+const int test_va = 0;
+#else
+const int test_va = 1;
+#endif
+
+#define T(TYPE)							\
+TYPE g01##TYPE, g02##TYPE, g03##TYPE, g04##TYPE;		\
+TYPE g05##TYPE, g06##TYPE, g07##TYPE, g08##TYPE;		\
+TYPE g09##TYPE, g10##TYPE, g11##TYPE, g12##TYPE;		\
+TYPE g13##TYPE, g14##TYPE, g15##TYPE, g16##TYPE;		\
+								\
+extern void init##TYPE (TYPE *p, int i);			\
+extern void checkg##TYPE (void);				\
+extern TYPE test0##TYPE (void);					\
+extern TYPE test1##TYPE (TYPE);					\
+extern TYPE testva##TYPE (int n, ...);				\
+								\
+void								\
+testit##TYPE (void)						\
+{								\
+  TYPE rslt;							\
+  DEBUG_FPUTS (#TYPE);						\
+  DEBUG_FPUTS (" init: ");					\
+  init##TYPE  (&g01##TYPE,  1);					\
+  init##TYPE  (&g02##TYPE,  2);					\
+  init##TYPE  (&g03##TYPE,  3);					\
+  init##TYPE  (&g04##TYPE,  4);					\
+  init##TYPE  (&g05##TYPE,  5);					\
+  init##TYPE  (&g06##TYPE,  6);					\
+  init##TYPE  (&g07##TYPE,  7);					\
+  init##TYPE  (&g08##TYPE,  8);					\
+  init##TYPE  (&g09##TYPE,  9);					\
+  init##TYPE  (&g10##TYPE, 10);					\
+  init##TYPE  (&g11##TYPE, 11);					\
+  init##TYPE  (&g12##TYPE, 12);					\
+  init##TYPE  (&g13##TYPE, 13);					\
+  init##TYPE  (&g14##TYPE, 14);					\
+  init##TYPE  (&g15##TYPE, 15);					\
+  init##TYPE  (&g16##TYPE, 16);					\
+  checkg##TYPE ();						\
+  DEBUG_NL;							\
+  DEBUG_FPUTS (#TYPE);						\
+  DEBUG_FPUTS (" test0: ");					\
+  rslt = test0##TYPE ();					\
+  check##TYPE (rslt, 1);					\
+  DEBUG_NL;							\
+  DEBUG_FPUTS (#TYPE);						\
+  DEBUG_FPUTS (" test1: ");					\
+  rslt = test1##TYPE (g01##TYPE);				\
+  check##TYPE (rslt, 1);					\
+  if (test_va)							\
+    {								\
+      DEBUG_NL;							\
+      DEBUG_FPUTS (#TYPE);					\
+      DEBUG_FPUTS (" testva: ");				\
+      rslt = testva##TYPE (1, g01##TYPE);			\
+      check##TYPE (rslt, 1);					\
+      rslt = testva##TYPE (5, g01##TYPE, g02##TYPE,		\
+			   g03##TYPE, g04##TYPE,		\
+			   g05##TYPE);				\
+      check##TYPE (rslt, 5);					\
+      rslt = testva##TYPE (9, g01##TYPE, g02##TYPE,		\
+			   g03##TYPE, g04##TYPE,		\
+			   g05##TYPE, g06##TYPE,		\
+			   g07##TYPE, g08##TYPE,		\
+			   g09##TYPE);				\
+      check##TYPE (rslt, 9);					\
+      rslt = testva##TYPE (16, g01##TYPE, g02##TYPE,		\
+			   g03##TYPE, g04##TYPE,		\
+			   g05##TYPE, g06##TYPE,		\
+			   g07##TYPE, g08##TYPE,		\
+			   g09##TYPE, g10##TYPE,		\
+			   g11##TYPE, g12##TYPE,		\
+			   g13##TYPE, g14##TYPE,		\
+			   g15##TYPE, g16##TYPE);		\
+      check##TYPE (rslt, 16);					\
+    }								\
+  DEBUG_NL;							\
+}
+
+#include "union-defs.h"
+#include "union-check.h"
+
+T(Ucs)
+T(Uci)
+T(Ucl)
+T(Ucll)
+T(Usi)
+T(Usl)
+T(Usll)
+T(Uil)
+T(Uill)
+T(Ulll)
+
+#undef T
+
+void
+union_return_1_x ()
+{
+DEBUG_INIT
+
+#define T(TYPE) testit##TYPE ();
+
+T(Ucs)
+T(Uci)
+T(Ucl)
+T(Ucll)
+T(Usi)
+T(Usl)
+T(Usll)
+T(Uil)
+T(Uill)
+T(Ulll)
+
+DEBUG_FINI
+
+if (fails != 0)
+  abort ();
+
+#undef T
+}
--- /dev/null	Thu Apr 11 16:25:15 2002
+++ gcc.dg/compat/union-return-1_y.c	Sun Jan 25 11:29:04 2004
@@ -0,0 +1,71 @@
+#include <stdarg.h>
+
+#include "compat-common.h"
+
+#include "union-defs.h"
+#include "union-init.h"
+
+#define T(TYPE)							\
+extern TYPE g01##TYPE, g02##TYPE, g03##TYPE, g04##TYPE;		\
+extern TYPE g05##TYPE, g06##TYPE, g07##TYPE, g08##TYPE;		\
+extern TYPE g09##TYPE, g10##TYPE, g11##TYPE, g12##TYPE;		\
+extern TYPE g13##TYPE, g14##TYPE, g15##TYPE, g16##TYPE;		\
+								\
+extern void check##TYPE (TYPE x, int i);			\
+								\
+void								\
+checkg##TYPE (void)						\
+{								\
+  check##TYPE (g01##TYPE,  1);					\
+  check##TYPE (g02##TYPE,  2);					\
+  check##TYPE (g03##TYPE,  3);					\
+  check##TYPE (g04##TYPE,  4);					\
+  check##TYPE (g05##TYPE,  5);					\
+  check##TYPE (g06##TYPE,  6);					\
+  check##TYPE (g07##TYPE,  7);					\
+  check##TYPE (g08##TYPE,  8);					\
+  check##TYPE (g09##TYPE,  9);					\
+  check##TYPE (g10##TYPE, 10);					\
+  check##TYPE (g11##TYPE, 11);					\
+  check##TYPE (g12##TYPE, 12);					\
+  check##TYPE (g13##TYPE, 13);					\
+  check##TYPE (g14##TYPE, 14);					\
+  check##TYPE (g15##TYPE, 15);					\
+  check##TYPE (g16##TYPE, 16);					\
+}								\
+								\
+TYPE								\
+test0##TYPE (void)						\
+{								\
+  return g01##TYPE;						\
+}								\
+								\
+TYPE								\
+test1##TYPE (TYPE x01)						\
+{								\
+  return x01;							\
+}								\
+								\
+TYPE								\
+testva##TYPE (int n, ...)					\
+{								\
+  int i;							\
+  TYPE rslt;							\
+  va_list ap;							\
+  va_start (ap, n);						\
+  for (i = 0; i < n; i++)					\
+      rslt = va_arg (ap, TYPE);					\
+  va_end (ap);							\
+  return rslt;							\
+}
+
+T(Ucs)
+T(Uci)
+T(Ucl)
+T(Ucll)
+T(Usi)
+T(Usl)
+T(Usll)
+T(Uil)
+T(Uill)
+T(Ulll)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]