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]

fix alpha compat.exp failures


Most of the failures had to do with complex values.  And since
things were demonstrably broken anyway, I went ahead and changed
the port to use SPLIT_COMPLEX_ARGS as the ABI requires.

Janis, you should consider adding some tests for vector types as
well.  Not sure how, exactly, since not all vector types are legal
on all targets.


r~


        * config/alpha/alpha.c (function_arg): Don't pass small aggregates
        in floating point registers.  Validate that we don't receive complex
        values here.  Use #elif.
        (return_in_memory, function_value): New.
        (alpha_va_arg): Handle complex values as two arguments.
        * config/alpha/alpha.h (RETURN_IN_MEMORY): Use return_in_memory.
        (FUNCTION_VALUE, LIBCALL_VALUE): Use function_value.
        (SPLIT_COMPLEX_ARGS): New.
        * config/alpha/alpha-protos.h: Update.

Index: alpha-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha-protos.h,v
retrieving revision 1.48
diff -c -p -d -u -r1.48 alpha-protos.h
--- alpha-protos.h	19 Jun 2003 21:47:03 -0000	1.48
+++ alpha-protos.h	27 Jun 2003 17:47:09 -0000
@@ -135,6 +135,9 @@ extern void alpha_setup_incoming_varargs
 extern void alpha_va_start (tree, rtx);
 extern rtx alpha_va_arg (tree, tree);
 extern rtx function_arg (CUMULATIVE_ARGS, enum machine_mode, tree, int);
+extern rtx function_value (tree, tree, enum machine_mode);
+extern bool return_in_memory (tree, enum machine_mode);
+
 extern void alpha_start_function (FILE *, const char *, tree);
 extern void alpha_end_function (FILE *, const char *, tree);
 
Index: alpha.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.c,v
retrieving revision 1.319
diff -c -p -d -u -r1.319 alpha.c
--- alpha.c	27 Jun 2003 09:49:39 -0000	1.319
+++ alpha.c	27 Jun 2003 17:47:10 -0000
@@ -5864,14 +5864,25 @@ function_arg (CUMULATIVE_ARGS cum, enum 
   int basereg;
   int num_args;
 
-  /* Set up defaults for FP operands passed in FP registers, and
-     integral operands passed in integer registers.  */
-  if (TARGET_FPREGS
-      && (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
-	  || GET_MODE_CLASS (mode) == MODE_FLOAT))
-    basereg = 32 + 16;
-  else
+  /* Don't get confused and pass small structures in FP registers.  */
+  if (type && AGGREGATE_TYPE_P (type))
     basereg = 16;
+  else
+    {
+#ifdef ENABLE_CHECKING
+      /* With SPLIT_COMPLEX_ARGS, we shouldn't see any raw complex
+	 values here.  */
+      if (COMPLEX_MODE_P (mode))
+	abort ();
+#endif
+
+      /* Set up defaults for FP operands passed in FP registers, and
+	 integral operands passed in integer registers.  */
+      if (TARGET_FPREGS && GET_MODE_CLASS (mode) == MODE_FLOAT)
+	basereg = 32 + 16;
+      else
+	basereg = 16;
+    }
 
   /* ??? Irritatingly, the definition of CUMULATIVE_ARGS is different for
      the three platforms, so we can't avoid conditional compilation.  */
@@ -5884,8 +5895,7 @@ function_arg (CUMULATIVE_ARGS cum, enum 
       if (num_args >= 6 || MUST_PASS_IN_STACK (mode, type))
 	return NULL_RTX;
     }
-#else
-#if TARGET_ABI_UNICOSMK
+#elif TARGET_ABI_UNICOSMK
     {
       int size;
 
@@ -5949,7 +5959,7 @@ function_arg (CUMULATIVE_ARGS cum, enum 
 	    }
 	}
     }
-#else
+#elif TARGET_ABI_OSF
     {
       if (cum >= 6)
 	return NULL_RTX;
@@ -5963,12 +5973,119 @@ function_arg (CUMULATIVE_ARGS cum, enum 
       else if (FUNCTION_ARG_PASS_BY_REFERENCE (cum, mode, type, named))
 	basereg = 16;
     }
-#endif /* TARGET_ABI_UNICOSMK */
-#endif /* TARGET_ABI_OPEN_VMS */
+#else
+#error Unhandled ABI
+#endif
 
   return gen_rtx_REG (mode, num_args + basereg);
 }
 
+/* Return true if TYPE must be returned in memory, instead of in registers.  */
+
+bool
+return_in_memory (tree type, enum machine_mode mode)
+{
+  int size;
+
+  if (type)
+    {
+      mode = TYPE_MODE (type);
+
+      /* All aggregates are returned in memory.  */
+      if (AGGREGATE_TYPE_P (type))
+	return true;
+    }
+
+  size = GET_MODE_SIZE (mode);
+  switch (GET_MODE_CLASS (mode))
+    {
+    case MODE_VECTOR_FLOAT:
+      /* Pass all float vectors in memory, like an aggregate.  */
+      return true;
+
+    case MODE_COMPLEX_FLOAT:
+      /* We judge complex floats on the size of their element,
+	 not the size of the whole type.  */
+      size = GET_MODE_UNIT_SIZE (mode);
+      break;
+
+    case MODE_INT:
+    case MODE_FLOAT:
+    case MODE_COMPLEX_INT:
+    case MODE_VECTOR_INT:
+      break;
+
+    default:
+      /* ??? We get called on all sorts of random stuff from 
+	 aggregate_value_p.  We can't abort, but it's not clear
+	 what's safe to return.  Pretend it's a struct I guess.  */
+      return true;
+    }
+
+  /* Otherwise types must fit in one register.  */
+  return size > UNITS_PER_WORD;
+}
+
+/* Define how to find the value returned by a function.  VALTYPE is the
+   data type of the value (as a tree).  If the precise function being
+   called is known, FUNC is its FUNCTION_DECL; otherwise, FUNC is 0.
+   MODE is set instead of VALTYPE for libcalls.
+
+   On Alpha the value is found in $0 for integer functions and
+   $f0 for floating-point functions.  */
+
+rtx
+function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
+		enum machine_mode mode)
+{
+  unsigned int regnum;
+  enum mode_class class;
+
+#ifdef ENABLE_CHECKING
+  if (return_in_memory (valtype, mode))
+    abort ();
+#endif
+
+  if (valtype)
+    mode = TYPE_MODE (valtype);
+
+  class = GET_MODE_CLASS (mode);
+  switch (class)
+    {
+    case MODE_INT:
+      /* Do the same thing as PROMOTE_MODE.  */
+      mode = DImode;
+      /* FALLTHRU */
+
+    case MODE_COMPLEX_INT:
+    case MODE_VECTOR_INT:
+      regnum = 0;
+      break;
+
+    case MODE_FLOAT:
+      regnum = 32;
+      break;
+
+    case MODE_COMPLEX_FLOAT:
+      {
+	enum machine_mode cmode = GET_MODE_INNER (mode);
+
+	return gen_rtx_PARALLEL
+	  (VOIDmode,
+	   gen_rtvec (2,
+		      gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (cmode, 32),
+				         GEN_INT (0)),
+		      gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (cmode, 33),
+				         GEN_INT (GET_MODE_SIZE (cmode)))));
+      }
+
+    default:
+      abort ();
+    }
+
+  return gen_rtx_REG (mode, regnum);
+}
+
 tree
 alpha_build_va_list (void)
 {
@@ -6162,7 +6279,27 @@ alpha_va_arg (tree valist, tree type)
       indirect = 1;
       rounded_size = size_int (UNITS_PER_WORD);
     }
-  else if (FLOAT_TYPE_P (type))
+  else if (TREE_CODE (type) == COMPLEX_TYPE)
+    {
+      rtx real_part, imag_part, value, tmp;
+
+      real_part = alpha_va_arg (valist, TREE_TYPE (type));
+      imag_part = alpha_va_arg (valist, TREE_TYPE (type));
+
+      /* ??? Most irritatingly, we're not returning the value here,
+	 but the address.  Since real_part and imag_part are not
+	 necessarily contiguous, we must copy to local storage.  */
+
+      real_part = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (type)), real_part);
+      imag_part = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (type)), imag_part);
+      value = gen_rtx_CONCAT (TYPE_MODE (type), real_part, imag_part);
+
+      tmp = assign_temp (type, 0, 1, 0);
+      emit_move_insn (tmp, value);
+
+      return XEXP (tmp, 0);
+    }
+  else if (TREE_CODE (type) == REAL_TYPE)
     {
       tree fpaddend, cond;
 
Index: alpha.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.h,v
retrieving revision 1.201
diff -c -p -d -u -r1.201 alpha.h
--- alpha.h	17 Jun 2003 08:06:53 -0000	1.201
+++ alpha.h	27 Jun 2003 17:47:10 -0000
@@ -994,25 +994,14 @@ extern int alpha_memory_latency;
    On Alpha the value is found in $0 for integer functions and
    $f0 for floating-point functions.  */
 
-#define FUNCTION_VALUE(VALTYPE, FUNC)	\
-  gen_rtx_REG (((INTEGRAL_TYPE_P (VALTYPE)			\
-		 && TYPE_PRECISION (VALTYPE) < BITS_PER_WORD)	\
-		|| POINTER_TYPE_P (VALTYPE))			\
-	       ? word_mode : TYPE_MODE (VALTYPE),		\
-	       ((TARGET_FPREGS					\
-		 && (TREE_CODE (VALTYPE) == REAL_TYPE		\
-		     || TREE_CODE (VALTYPE) == COMPLEX_TYPE))	\
-		? 32 : 0))
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+  function_value (VALTYPE, FUNC, VOIDmode)
 
 /* Define how to find the value returned by a library function
    assuming the value has mode MODE.  */
 
-#define LIBCALL_VALUE(MODE)	\
-   gen_rtx_REG (MODE,						\
-		(TARGET_FPREGS					\
-		 && (GET_MODE_CLASS (MODE) == MODE_FLOAT	\
-		     || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
-		 ? 32 : 0))
+#define LIBCALL_VALUE(MODE) \
+  function_value (NULL, NULL, MODE)
 
 /* The definition of this macro implies that there are cases where
    a scalar value cannot be returned in registers.
@@ -1021,10 +1010,7 @@ extern int alpha_memory_latency;
    are integers whose size is larger than 64 bits.  */
 
 #define RETURN_IN_MEMORY(TYPE) \
-  (TYPE_MODE (TYPE) == BLKmode \
-   || TYPE_MODE (TYPE) == TFmode \
-   || TYPE_MODE (TYPE) == TCmode \
-   || (TREE_CODE (TYPE) == INTEGER_TYPE && TYPE_PRECISION (TYPE) > 64))
+  return_in_memory (TYPE, VOIDmode)
 
 /* 1 if N is a possible register number for a function value
    as seen by the caller.  */
@@ -1889,3 +1875,6 @@ do {							\
 
 /* Generate calls to memcpy, etc., not bcopy, etc.  */
 #define TARGET_MEM_FUNCTIONS 1
+
+/* Pass complex arguments independently.  */
+#define SPLIT_COMPLEX_ARGS 1


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