s390-protos.h (s390_function_value): Declare.
authorUlrich Weigand <uweigand@de.ibm.com>
Thu, 6 Nov 2003 21:35:10 +0000 (21:35 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Thu, 6 Nov 2003 21:35:10 +0000 (21:35 +0000)
* config/s390/s390-protos.h (s390_function_value): Declare.
* config/s390/s390.c (TARGET_RETURN_IN_MEMORY): Define.
(s390_return_in_memory): New function.
(s390_function_value): New function.
(s390_function_arg_float): Return false for all arguments larger
than 8 bytes.
(s390_function_arg_pass_by_reference): Likewise.  Return true for
all vector arguments.
(s390_function_arg_integer): New function.
(s390_function_arg_advance): Call it.  Add sanity checks.
(s390_function_arg): Likewise.
* config/s390/s390.h (FUNCTION_VALUE): Call s390_function_value.
(LIBCALL_VALUE): Likewise.
(RET_REG): Remove.
(RETURN_IN_MEMORY): Remove.

From-SVN: r73314

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

index fbb999c..9279d35 100644 (file)
@@ -1,3 +1,21 @@
+2003-11-06  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * config/s390/s390-protos.h (s390_function_value): Declare.
+       * config/s390/s390.c (TARGET_RETURN_IN_MEMORY): Define.
+       (s390_return_in_memory): New function.
+       (s390_function_value): New function.
+       (s390_function_arg_float): Return false for all arguments larger
+       than 8 bytes.
+       (s390_function_arg_pass_by_reference): Likewise.  Return true for
+       all vector arguments.
+       (s390_function_arg_integer): New function.
+       (s390_function_arg_advance): Call it.  Add sanity checks.
+       (s390_function_arg): Likewise.
+       * config/s390/s390.h (FUNCTION_VALUE): Call s390_function_value.
+       (LIBCALL_VALUE): Likewise.
+       (RET_REG): Remove.
+       (RETURN_IN_MEMORY): Remove.
+
 2003-11-06  Richard Sandiford  <rsandifo@redhat.com>
 
        * config/mips/mips-protos.h (mips_initial_elimination_offset): Change
index cad75e0..1ab6b09 100644 (file)
@@ -99,6 +99,7 @@ extern void s390_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
                                       tree, int);
 #ifdef RTX_CODE
 extern rtx s390_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+extern rtx s390_function_value (tree, enum machine_mode);
 extern void s390_va_start (tree, rtx);
 extern rtx s390_va_arg (tree, tree);
 #endif /* RTX_CODE */
index ede221e..6d94d3d 100644 (file)
@@ -60,6 +60,7 @@ static void s390_select_rtx_section (enum machine_mode, rtx,
 static void s390_encode_section_info (tree, rtx, int);
 static bool s390_cannot_force_const_mem (rtx);
 static rtx s390_delegitimize_address (rtx);
+static bool s390_return_in_memory (tree, tree);
 static void s390_init_builtins (void);
 static rtx s390_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
 static void s390_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
@@ -107,6 +108,9 @@ static tree s390_build_builtin_va_list (void);
 #undef TARGET_DELEGITIMIZE_ADDRESS
 #define TARGET_DELEGITIMIZE_ADDRESS s390_delegitimize_address
 
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY s390_return_in_memory
+
 #undef  TARGET_INIT_BUILTINS
 #define TARGET_INIT_BUILTINS s390_init_builtins
 #undef  TARGET_EXPAND_BUILTIN
@@ -6009,6 +6013,10 @@ s390_function_arg_size (enum machine_mode mode, tree type)
 static bool
 s390_function_arg_float (enum machine_mode mode, tree type)
 {
+  int size = s390_function_arg_size (mode, type);
+  if (size > 8)
+    return false;
+
   /* Soft-float changes the ABI: no floating-point registers are used.  */
   if (TARGET_SOFT_FLOAT)
     return false;
@@ -6043,6 +6051,39 @@ s390_function_arg_float (enum machine_mode mode, tree type)
   return TREE_CODE (type) == REAL_TYPE;
 }
 
+/* Return true if a function argument of type TYPE and mode MODE
+   is to be passed in an integer register, or a pair of integer
+   registers, if available.  */
+
+static bool
+s390_function_arg_integer (enum machine_mode mode, tree type)
+{
+  int size = s390_function_arg_size (mode, type);
+  if (size > 8)
+    return false;
+
+  /* No type info available for some library calls ...  */
+  if (!type)
+    return GET_MODE_CLASS (mode) == MODE_INT
+          || (TARGET_SOFT_FLOAT &&  GET_MODE_CLASS (mode) == MODE_FLOAT);
+
+  /* We accept small integral (and similar) types.  */
+  if (INTEGRAL_TYPE_P (type)
+      || POINTER_TYPE_P (type) 
+      || TREE_CODE (type) == OFFSET_TYPE
+      || (TARGET_SOFT_FLOAT && TREE_CODE (type) == REAL_TYPE))
+    return true;
+
+  /* We also accept structs of size 1, 2, 4, 8 that are not
+     passed in floating-point registers.  */  
+  if (AGGREGATE_TYPE_P (type)
+      && exact_log2 (size) >= 0
+      && !s390_function_arg_float (mode, type))
+    return true;
+
+  return false;
+}
+
 /* Return 1 if a function argument of type TYPE and mode MODE
    is to be passed by reference.  The ABI specifies that only
    structures of size 1, 2, 4, or 8 bytes are passed by value,
@@ -6053,15 +6094,16 @@ int
 s390_function_arg_pass_by_reference (enum machine_mode mode, tree type)
 {
   int size = s390_function_arg_size (mode, type);
+  if (size > 8)
+    return true;
 
   if (type)
     {
-      if (AGGREGATE_TYPE_P (type) &&
-          size != 1 && size != 2 && size != 4 && size != 8
-         && !s390_function_arg_float (mode, type))
+      if (AGGREGATE_TYPE_P (type) && exact_log2 (size) < 0)
         return 1;
 
-      if (TREE_CODE (type) == COMPLEX_TYPE)
+      if (TREE_CODE (type) == COMPLEX_TYPE
+         || TREE_CODE (type) == VECTOR_TYPE)
         return 1;
     }
 
@@ -6086,11 +6128,13 @@ s390_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
     {
       cum->fprs += 1;
     }
-  else
+  else if (s390_function_arg_integer (mode, type))
     {
       int size = s390_function_arg_size (mode, type);
       cum->gprs += ((size + UNITS_PER_WORD-1) / UNITS_PER_WORD);
     }
+  else
+    abort ();
 }
 
 /* Define where to put the arguments to a function.
@@ -6126,7 +6170,7 @@ s390_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
       else
        return gen_rtx (REG, mode, cum->fprs + 16);
     }
-  else
+  else if (s390_function_arg_integer (mode, type))
     {
       int size = s390_function_arg_size (mode, type);
       int n_gprs = (size + UNITS_PER_WORD-1) / UNITS_PER_WORD;
@@ -6136,6 +6180,68 @@ s390_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
       else
        return gen_rtx (REG, mode, cum->gprs + 2);
     }
+
+  /* After the real arguments, expand_call calls us once again
+     with a void_type_node type.  Whatever we return here is
+     passed as operand 2 to the call expanders.
+
+     We don't need this feature ...  */
+  else if (type == void_type_node)
+    return const0_rtx;
+
+  abort ();
+}
+
+/* Return true if return values of type TYPE should be returned
+   in a memory buffer whose address is passed by the caller as
+   hidden first argument.  */
+
+static bool
+s390_return_in_memory (tree type, tree fundecl ATTRIBUTE_UNUSED)
+{
+  /* We accept small integral (and similar) types.  */
+  if (INTEGRAL_TYPE_P (type)
+      || POINTER_TYPE_P (type) 
+      || TREE_CODE (type) == OFFSET_TYPE
+      || TREE_CODE (type) == REAL_TYPE)
+    return int_size_in_bytes (type) > 8;
+
+  /* Aggregates and similar constructs are always returned
+     in memory.  */
+  if (AGGREGATE_TYPE_P (type)
+      || TREE_CODE (type) == COMPLEX_TYPE
+      || TREE_CODE (type) == VECTOR_TYPE)
+    return true;
+
+  /* ??? 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;
+}
+
+/* Define where to return a (scalar) value of type TYPE.
+   If TYPE is null, define where to return a (scalar)
+   value of mode MODE from a libcall.  */
+
+rtx
+s390_function_value (tree type, enum machine_mode mode)
+{
+  if (type)
+    {
+      int unsignedp = TREE_UNSIGNED (type);
+      mode = promote_mode (type, TYPE_MODE (type), &unsignedp, 1);
+    }
+
+  if (GET_MODE_CLASS (mode) != MODE_INT 
+      && GET_MODE_CLASS (mode) != MODE_FLOAT)
+    abort ();
+  if (GET_MODE_SIZE (mode) > 8)
+    abort ();
+
+  if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
+    return gen_rtx_REG (mode, 16);
+  else
+    return gen_rtx_REG (mode, 2);
 }
 
 
index 63fd3ee..e3eaf91 100644 (file)
@@ -707,34 +707,15 @@ CUMULATIVE_ARGS;
 
 /* Scalar return values.  */
 
-/* We return scalars in general purpose register 2 for integral values,
-   and floating point register 0 for fp values.  */
-#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),               \
-              TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_HARD_FLOAT ? 16 : 2)
-
-/* Define how to find the value returned by a library function assuming
-   the value has mode MODE.  */
-#define RET_REG(MODE) ((GET_MODE_CLASS (MODE) == MODE_INT       \
-                       || TARGET_SOFT_FLOAT ) ? 2 : 16)
-#define LIBCALL_VALUE(MODE)  gen_rtx (REG, MODE, RET_REG (MODE))
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+  s390_function_value ((VALTYPE), VOIDmode)
+
+#define LIBCALL_VALUE(MODE) \
+  s390_function_value (NULL, (MODE))
 
 /* Only gpr 2 and fpr 0 are ever used as return registers.  */
 #define FUNCTION_VALUE_REGNO_P(N) ((N) == 2 || (N) == 16)
 
-
-/* Aggregate return values.  */
-
-/* The definition of this macro implies that there are cases where
-   a scalar value cannot be returned in registers.  */
-#define RETURN_IN_MEMORY(type)                                 \
-  (TYPE_MODE (type) == BLKmode ||                              \
-   GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_INT  ||   \
-   GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT)
-
 /* Structure value address is passed as invisible first argument (gpr 2).  */
 #define STRUCT_VALUE 0