OSDN Git Service

* config/alpha/alpha.c (function_arg): Don't pass small aggregates
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 27 Jun 2003 17:52:03 +0000 (17:52 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 27 Jun 2003 17:52:03 +0000 (17:52 +0000)
        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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@68591 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.h

index a86f0a8..9d71ea6 100644 (file)
@@ -1,4 +1,16 @@
-2003-06-13  Ulrich Weigand  <uweigand@de.ibm.com>
+2003-06-27  Richard Henderson  <rth@redhat.com>
+
+       * 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.
+
+2003-06-27  Ulrich Weigand  <uweigand@de.ibm.com>
 
         * ggc-page.c (inverse_table): Change type of mult to size_t.
         (compute_inverse): Compute inverse using size_t, not unsigned int.
index 3a342eb..0e14e6b 100644 (file)
@@ -135,6 +135,9 @@ extern void alpha_setup_incoming_varargs (CUMULATIVE_ARGS, enum machine_mode,
 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 1d1be31..d1b884f 100644 (file)
@@ -5864,14 +5864,25 @@ function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, tree type,
   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 machine_mode mode, tree type,
       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 machine_mode mode, tree type,
            }
        }
     }
-#else
+#elif TARGET_ABI_OSF
     {
       if (cum >= 6)
        return NULL_RTX;
@@ -5963,12 +5973,119 @@ function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, tree type,
       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 7ba7b15..267d292 100644 (file)
@@ -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