s390.c (s390_function_arg_float): New function.
authorUlrich Weigand <uweigand@de.ibm.com>
Sun, 11 May 2003 20:01:01 +0000 (20:01 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Sun, 11 May 2003 20:01:01 +0000 (20:01 +0000)
* config/s390/s390.c (s390_function_arg_float): New function.
(s390_function_arg_pass_by_reference): Use it.
(s390_function_arg_advance): Likewise.
(s390_function_arg): Likewise.
(s390_va_arg): Likewise

From-SVN: r66696

gcc/ChangeLog
gcc/config/s390/s390.c

index f9104ce0cf6beb2b8957ee2261c4479077d545ab..6ff7d82183b201c74fcf9c753de3ed56dcc9dca1 100644 (file)
@@ -1,3 +1,11 @@
+2003-05-11  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * config/s390/s390.c (s390_function_arg_float): New function.
+       (s390_function_arg_pass_by_reference): Use it.
+       (s390_function_arg_advance): Likewise.
+       (s390_function_arg): Likewise.
+       (s390_va_arg): Likewise
+
 2003-05-11  Nathan Sidwell  <nathan@codesourcery.com>
 
        * coverage.h (coverage_counter_alloc): New function.
index 2a4938152aae5e34cc0f91775c39f3fca7fdc846..4c290a4ac4343ae5a0574b68f87dcc72a14140a8 100644 (file)
@@ -211,6 +211,7 @@ static rtx restore_fpr PARAMS ((rtx, int, int));
 static rtx save_gprs PARAMS ((rtx, int, int, int));
 static rtx restore_gprs PARAMS ((rtx, int, int, int));
 static int s390_function_arg_size PARAMS ((enum machine_mode, tree));
+static bool s390_function_arg_float PARAMS ((enum machine_mode, tree));
 static struct machine_function * s390_init_machine_status PARAMS ((void));
  
 /* Return true if SET either doesn't set the CC register, or else
@@ -5699,6 +5700,48 @@ s390_function_arg_size (mode, type)
   abort ();
 }
 
+/* Return true if a function argument of type TYPE and mode MODE
+   is to be passed in a floating-point register, if available.  */
+
+static bool
+s390_function_arg_float (mode, type)
+     enum machine_mode mode;
+     tree type;
+{
+  /* Soft-float changes the ABI: no floating-point registers are used.  */
+  if (TARGET_SOFT_FLOAT)
+    return false;
+
+  /* No type info available for some library calls ...  */
+  if (!type)
+    return mode == SFmode || mode == DFmode;
+
+  /* The ABI says that record types with a single member are treated
+     just like that member would be.  */
+  while (TREE_CODE (type) == RECORD_TYPE)
+    {
+      tree field, single = NULL_TREE;
+
+      for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+       {
+         if (TREE_CODE (field) != FIELD_DECL)
+           continue;
+
+         if (single == NULL_TREE)
+           single = TREE_TYPE (field);
+         else
+           return false;
+       }
+
+      if (single == NULL_TREE)
+       return false;
+      else
+       type = single;
+    }
+
+  return TREE_CODE (type) == REAL_TYPE;
+}
+
 /* 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,
@@ -5715,14 +5758,15 @@ s390_function_arg_pass_by_reference (mode, type)
   if (type)
     {
       if (AGGREGATE_TYPE_P (type) &&
-          size != 1 && size != 2 && size != 4 && size != 8)
+          size != 1 && size != 2 && size != 4 && size != 8
+         && !s390_function_arg_float (mode, type))
         return 1;
 
       if (TREE_CODE (type) == COMPLEX_TYPE)
         return 1;
     }
+    
   return 0;
-
 }
 
 /* Update the data in CUM to advance over an argument of mode MODE and
@@ -5738,13 +5782,13 @@ s390_function_arg_advance (cum, mode, type, named)
      tree type;
      int named ATTRIBUTE_UNUSED;
 {
-  if (! TARGET_SOFT_FLOAT && (mode == DFmode || mode == SFmode))
+  if (s390_function_arg_pass_by_reference (mode, type))
     {
-      cum->fprs++;
+      cum->gprs += 1;
     }
-  else if (s390_function_arg_pass_by_reference (mode, type))
+  else if (s390_function_arg_float (mode, type))
     {
-      cum->gprs += 1;
+      cum->fprs += 1;
     }
   else
     {
@@ -5782,7 +5826,7 @@ s390_function_arg (cum, mode, type, named)
   if (s390_function_arg_pass_by_reference (mode, type))
       return 0;
 
-  if (! TARGET_SOFT_FLOAT && (mode == DFmode || mode == SFmode))
+  if (s390_function_arg_float (mode, type))
     {
       if (cum->fprs + 1 > (TARGET_64BIT? 4 : 2))
        return 0;
@@ -5996,7 +6040,7 @@ s390_va_arg (valist, type)
       size = UNITS_PER_WORD;
       max_reg = 4;
     }
-  else if (FLOAT_TYPE_P (type) && ! TARGET_SOFT_FLOAT)
+  else if (s390_function_arg_float (TYPE_MODE (type), type))
     {
       if (TARGET_DEBUG_ARG)
        {