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]

PPC SVR4 ABI fix - take two


This is a revised version of the patch to correct GCC's implementation
of structure return under the PPC SVR4 ABI.  I moved two entries out
of target_flags, leaving room for the bit I need, and one more for
future expansion (which I have plans for, take note).

Tested by i386-linux -> powerpc-eabisim cross compiler and simulated
testsuite run, C only.  The tree had my patch to fold
(build,cross)-make into configure.in applied to it.  A list of
testsuite failures is appended to this message.

There's also a warning fix - the init_builtins backend hook no longer
takes any arguments.  Finally, I took '$' and '*' out of
PRINT_OPERAND_PUNCT_VALID_P, they are no longer used.

zw

	* config/rs6000/rs6000.h (MASK_ALTIVEC_ABI,
	MASK_LONG_DOUBLE_128): Delete.
	(MASK_AIX_STRUCT_RET, MASK_AIX_STRUCT_RET_SET,
	TARGET_AIX_STRUCT_RET): New flags.
	(TARGET_SWITCHES): Remove entries for -mlong-double-128 and
	-mlong-double-64.  Add entries for -m(no-)aix-struct-return
	and -m(no-)svr4-struct-return.
	(TARGET_OPTIONS): Add entry for -mlong-double-.
	(rs6000_long_double_size_string, rs6000_long_double_type_size,
	rs6000_altivec_abi): Declare.
	(TARGET_LONG_DOUBLE_128, TARGET_ALTIVEC_ABI,
	LONG_DOUBLE_TYPE_SIZE): Change definitions to match.
	(RETURN_IN_MEMORY): If !TARGET_AIX_STRUCT_RET, return
	structures of size <= 8 bytes in registers.
	(PRINT_OPERAND_PUNCT_VALID_P): Take out '$' and '*'.

	* config/rs6000/rs6000.c (rs6000_long_double_size_string,
	rs6000_long_double_type_size, rs6000_altivec_abi): New
	globals.
	(rs6000_override_options): Set rs6000_long_double_type_size
	from rs6000_long_double_size_string, if nonzero.  Set the
	MASK_AIX_STRUCT_RET bit in target_flags from DEFAULT_ABI, if
	not already set.
	(rs6000_parse_abi_options): Set rs6000_altivec_abi, not a
	target_flags bit.
	(rs6000_init_builtins): This hook now takes no arguments.

	* config/rs6000/netbsd.h, config/rs6000/linux.h: Define
	DRAFT_V4_STRUCT_RET to 1.

===================================================================
Index: config/rs6000/linux.h
--- config/rs6000/linux.h	2001/11/15 05:21:06	1.30
+++ config/rs6000/linux.h	2001/12/03 00:00:17
@@ -69,6 +69,11 @@ Boston, MA 02111-1307, USA.  */
 #undef ASM_APP_OFF
 #define ASM_APP_OFF "#NO_APP\n"
 
+/* For backward compatibility, we must continue to use the AIX
+   structure return convention.  */
+#undef DRAFT_V4_STRUCT_RET
+#define DRAFT_V4_STRUCT_RET 1
+
 /* Do code reading to identify a signal frame, and set the frame
    state data appropriately.  See unwind-dw2.c for the structs.  */
 
===================================================================
Index: config/rs6000/netbsd.h
--- config/rs6000/netbsd.h	2001/11/15 05:21:06	1.2
+++ config/rs6000/netbsd.h	2001/12/03 00:00:17
@@ -59,3 +59,8 @@ Boston, MA 02111-1307, USA.  */
 
 #undef TARGET_VERSION
 #define TARGET_VERSION fprintf (stderr, " (PowerPC NetBSD/ELF)");
+
+/* For backward compatibility, we must continue to use the AIX
+   structure return convention.  */
+#undef DRAFT_V4_STRUCT_RET
+#define DRAFT_V4_STRUCT_RET 1
===================================================================
Index: config/rs6000/rs6000.c
--- config/rs6000/rs6000.c	2001/12/02 08:29:22	1.248
+++ config/rs6000/rs6000.c	2001/12/03 00:00:18
@@ -68,6 +68,13 @@ struct rs6000_cpu_select rs6000_select[3
   { (const char *)0,	"-mtune=",		1,	0 },
 };
 
+/* Size of long double */
+const char *rs6000_long_double_size_string;
+int rs6000_long_double_type_size;
+
+/* Whether -mabi=altivec has appeared */
+int rs6000_altivec_abi;
+
 /* Set to non-zero once AIX common-mode calls have been defined.  */
 static int common_mode_defined;
 
@@ -150,7 +157,7 @@ static int rs6000_adjust_cost PARAMS ((r
 static int rs6000_adjust_priority PARAMS ((rtx, int));
 static int rs6000_issue_rate PARAMS ((void));
 
-static void rs6000_init_builtins PARAMS ((tree));
+static void rs6000_init_builtins PARAMS ((void));
 static void altivec_init_builtins PARAMS ((void));
 static rtx rs6000_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
 static rtx altivec_expand_builtin PARAMS ((tree, rtx));
@@ -475,6 +482,19 @@ rs6000_override_options (default_cpu)
 	error ("Unknown -mdebug-%s switch", rs6000_debug_name);
     }
 
+  /* Set size of long double */
+  rs6000_long_double_type_size = 64;
+  if (rs6000_long_double_size_string)
+    {
+      char *tail;
+      int size = strtol (rs6000_long_double_size_string, &tail, 10);
+      if (*tail != '\0' || (size != 64 && size != 128))
+	error ("Unknown switch -mlong-double-%s",
+	       rs6000_long_double_size_string);
+      else
+	rs6000_long_double_type_size = size;
+    }
+
   /* Handle -mabi= options.  */
   rs6000_parse_abi_options ();
 
@@ -489,6 +509,17 @@ rs6000_override_options (default_cpu)
   SUBTARGET_OVERRIDE_OPTIONS;
 #endif
 
+  /* Set TARGET_AIX_STRUCT_RET last, after the ABI is determined.
+     If -maix-struct-return or -msvr4-struct-return was explicitly
+     used, don't override with the ABI default.  */
+  if (!(target_flags & MASK_AIX_STRUCT_RET_SET))
+    {
+      if (DEFAULT_ABI == ABI_V4 && !DRAFT_V4_STRUCT_RET)
+	target_flags = (target_flags & ~MASK_AIX_STRUCT_RET);
+      else
+	target_flags |= MASK_AIX_STRUCT_RET;
+    }
+
   /* Register global variables with the garbage collector.  */
   rs6000_add_gc_roots ();
 
@@ -510,7 +541,7 @@ rs6000_parse_abi_options ()
   if (rs6000_abi_string == 0)
     return;
   else if (! strcmp (rs6000_abi_string, "altivec"))
-    target_flags |= MASK_ALTIVEC_ABI;
+    rs6000_altivec_abi = 1;
   else
     error ("Unknown ABI specified: '%s'", rs6000_abi_string);
 }
@@ -3322,8 +3353,7 @@ rs6000_expand_builtin (exp, target, subt
 }
 
 static void
-rs6000_init_builtins (list_node)
-     tree list_node ATTRIBUTE_UNUSED;
+rs6000_init_builtins ()
 {
   if (TARGET_ALTIVEC)
     altivec_init_builtins ();
===================================================================
Index: config/rs6000/rs6000.h
--- config/rs6000/rs6000.h	2001/12/02 08:29:22	1.148
+++ config/rs6000/rs6000.h	2001/12/03 00:00:19
@@ -213,12 +213,14 @@ extern int target_flags;
 /* Use AltiVec instructions.  */
 #define MASK_ALTIVEC		0x00080000
 
-/* Enhance the current ABI with AltiVec extensions.  */
-#define MASK_ALTIVEC_ABI	0x00100000
+/* Return small structures in memory (as the AIX ABI requires).  */
+#define MASK_AIX_STRUCT_RET	0x00100000
+#define MASK_AIX_STRUCT_RET_SET	0x00200000
+
+/* The only remaining free bit is 0x00400000. sysv4.h uses
+   0x00800000 -> 0x40000000, and 0x80000000 is not available
+   because target_flags is signed.  */
 
-/* Use 128-bit long double.  */
-#define MASK_LONG_DOUBLE_128	0x00200000
-
 #define TARGET_POWER		(target_flags & MASK_POWER)
 #define TARGET_POWER2		(target_flags & MASK_POWER2)
 #define TARGET_POWERPC		(target_flags & MASK_POWERPC)
@@ -238,8 +240,7 @@ extern int target_flags;
 #define TARGET_NO_FUSED_MADD	(target_flags & MASK_NO_FUSED_MADD)
 #define TARGET_SCHED_PROLOG	(target_flags & MASK_SCHED_PROLOG)
 #define TARGET_ALTIVEC		(target_flags & MASK_ALTIVEC)
-#define TARGET_ALTIVEC_ABI	(target_flags & MASK_ALTIVEC_ABI)
-#define TARGET_LONG_DOUBLE_128	(target_flags & MASK_LONG_DOUBLE_128)
+#define TARGET_AIX_STRUCT_RET	(target_flags & MASK_AIX_STRUCT_RET)
 
 #define TARGET_32BIT		(! TARGET_64BIT)
 #define TARGET_HARD_FLOAT	(! TARGET_SOFT_FLOAT)
@@ -344,10 +345,6 @@ extern int target_flags;
 			N_("Generate fused multiply/add instructions")},\
   {"no-fused-madd",	MASK_NO_FUSED_MADD,				\
 			N_("Don't generate fused multiply/add instructions")},\
-  {"long-double-64",	-MASK_LONG_DOUBLE_128,				\
-			N_("Use 64 bit long doubles") },		\
-  {"long-double-128",	 MASK_LONG_DOUBLE_128, 				\
-			N_("Use 128 bit long doubles") },		\
   {"sched-prolog",      MASK_SCHED_PROLOG,                              \
 			""},						\
   {"no-sched-prolog",   -MASK_SCHED_PROLOG,                             \
@@ -356,6 +353,18 @@ extern int target_flags;
 			""},						\
   {"no-sched-epilog",   -MASK_SCHED_PROLOG,                             \
 			""},						\
+  {"aix-struct-return",	MASK_AIX_STRUCT_RET | MASK_AIX_STRUCT_RET_SET,	\
+			N_("Return all structures in memory (AIX default)")},\
+  {"svr4-struct-return", - MASK_AIX_STRUCT_RET,\
+			N_("Return small structures in registers (SVR4 default)")},\
+  {"svr4-struct-return",MASK_AIX_STRUCT_RET_SET,\
+			""},\
+  {"no-aix-struct-return", - MASK_AIX_STRUCT_RET,\
+			""},\
+  {"no-aix-struct-return", MASK_AIX_STRUCT_RET_SET,\
+			""},\
+  {"no-svr4-struct-return", MASK_AIX_STRUCT_RET | MASK_AIX_STRUCT_RET_SET,\
+			""},\
   SUBTARGET_SWITCHES							\
   {"",			TARGET_DEFAULT | MASK_SCHED_PROLOG,		\
 			""}}
@@ -431,6 +440,8 @@ extern enum processor_type rs6000_cpu;
     N_("Schedule code for given CPU") },				\
    {"debug=", &rs6000_debug_name, N_("Enable debug output") },		\
    {"abi=", &rs6000_abi_string, N_("Specify ABI to use") },		\
+   {"long-double-", &rs6000_long_double_size_string,			\
+    N_("Specify size of long double (64 or 128 bits)") },		\
    SUBTARGET_OPTIONS							\
 }
 
@@ -454,6 +465,15 @@ extern int rs6000_debug_arg;		/* debug a
 #define	TARGET_DEBUG_STACK	rs6000_debug_stack
 #define	TARGET_DEBUG_ARG	rs6000_debug_arg
 
+/* These are separate from target_flags because we've run out of bits
+   there.  */
+extern const char *rs6000_long_double_size_string;
+extern int rs6000_long_double_type_size;
+extern int rs6000_altivec_abi;
+
+#define TARGET_LONG_DOUBLE_128 (rs6000_long_double_type_size == 128)
+#define TARGET_ALTIVEC_ABI rs6000_altivec_abi
+
 /* Sometimes certain combinations of command options do not make sense
    on a particular target machine.  You can define a macro
    `OVERRIDE_OPTIONS' to take account of this.  This macro, if
@@ -583,7 +603,7 @@ extern int rs6000_debug_arg;		/* debug a
 /* A C expression for the size in bits of the type `long double' on
    the target machine.  If you don't define this, the default is two
    words.  */
-#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
+#define LONG_DOUBLE_TYPE_SIZE rs6000_long_double_type_size
 
 /* Constant which presents upper bound of the above value.  */
 #define MAX_LONG_DOUBLE_TYPE_SIZE 128
@@ -1458,14 +1478,22 @@ typedef struct rs6000_stack {
 		     && TARGET_HARD_FLOAT				\
 		     ? FP_ARG_RETURN : GP_ARG_RETURN)
 
-/* The definition of this macro implies that there are cases where
-   a scalar value cannot be returned in registers.
-
-   For the RS/6000, any structure or union type is returned in memory.
-   (FIXME: Except for V.4, where those <= 8 bytes are returned in
-   registers.  Can't change this without breaking compatibility.)  */
+/* The AIX ABI for the RS/6000 specifies that all structures are
+   returned in memory.  The Darwin ABI does the same.  The SVR4 ABI
+   specifies that structures <= 8 bytes are returned in r3/r4, but a
+   draft put them in memory, and GCC used to implement the draft
+   instead of the final standard.  Therefore, TARGET_AIX_STRUCT_RET
+   controls this instead of DEFAULT_ABI; V.4 targets needing backward
+   compatibility can change DRAFT_V4_STRUCT_RET to override the
+   default, and -m switches get the final word.  See
+   rs6000_override_options for more details.  */
+   
+#define RETURN_IN_MEMORY(TYPE) \
+  (AGGREGATE_TYPE_P (TYPE) && \
+   (TARGET_AIX_STRUCT_RET || int_size_in_bytes (TYPE) > 8))
 
-#define RETURN_IN_MEMORY(TYPE) AGGREGATE_TYPE_P (TYPE)
+/* DRAFT_V4_STRUCT_RET defaults off.  */
+#define DRAFT_V4_STRUCT_RET 0
 
 /* Let RETURN_IN_MEMORY control what happens.  */
 #define DEFAULT_PCC_STRUCT_RETURN 0
@@ -2773,7 +2801,7 @@ do {									\
 /* Define which CODE values are valid.  */
 
 #define PRINT_OPERAND_PUNCT_VALID_P(CODE)  \
-  ((CODE) == '.' || (CODE) == '*' || (CODE) == '$')
+  ((CODE) == '.')
 
 /* Print a memory address as an operand to reference that memory location.  */
 


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