sparc.c (function_arg_slotno): Handle aggregate types other than record and union...
authorEric Botcazou <ebotcazou@libertysurf.fr>
Tue, 11 Apr 2006 16:25:46 +0000 (18:25 +0200)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Tue, 11 Apr 2006 16:25:46 +0000 (16:25 +0000)
* config/sparc/sparc.c (function_arg_slotno) <BLKmode>: Handle
aggregate types other than record and union types.
(function_arg): Likewise.
(function_arg_pass_by_reference): In 64-bit mode, return 0 for
small arrays.
(function_value): In 64-bit mode, return objects that require it
in FP registers.

From-SVN: r112859

gcc/ChangeLog
gcc/config/sparc/sparc.c

index 3d0cd8be1d7fe871a30c63f1e99dc7c8e8f2b35d..0cf5ae0d1e58b6a4baab018e27d0e12eca6cfc9c 100644 (file)
@@ -1,3 +1,13 @@
+2006-04-11  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * config/sparc/sparc.c (function_arg_slotno) <BLKmode>: Handle
+       aggregate types other than record and union types.
+       (function_arg): Likewise.
+       (function_arg_pass_by_reference): In 64-bit mode, return 0 for
+       small arrays.
+       (function_value): In 64-bit mode, return objects that require it
+       in FP registers.
+
 2006-04-11  Roger Sayle  <roger@eyesopen.com>
 
        * dwarf2out.c (premark_used_types): Remove problematic prototype.
index e880226412e0b726465c7de4f52c90a074ee9b6b..578f91668b1c5db44655b69a34d7ae116fe0d37d 100644 (file)
@@ -4559,7 +4559,10 @@ function_arg_slotno (const struct sparc_args *cum, enum machine_mode mode,
 
       gcc_assert (mode == BLKmode);
 
-      if (TARGET_ARCH32 || !type || (TREE_CODE (type) == UNION_TYPE))
+      if (TARGET_ARCH32
+         || !type
+         || (TREE_CODE (type) != VECTOR_TYPE
+             && TREE_CODE (type) != RECORD_TYPE))
        {
          if (slotno >= SPARC_INT_ARG_MAX)
            return -1;
@@ -5073,62 +5076,58 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode,
                 : SPARC_OUTGOING_INT_ARG_FIRST);
   int slotno, regno, padding;
   enum mode_class mclass = GET_MODE_CLASS (mode);
-  rtx reg;
 
   slotno = function_arg_slotno (cum, mode, type, named, incoming_p,
                                &regno, &padding);
-
   if (slotno == -1)
     return 0;
 
-  if (TARGET_ARCH32)
+  /* Vector types deserve special treatment because they are polymorphic wrt
+     their mode, depending upon whether VIS instructions are enabled.  */
+  if (type && TREE_CODE (type) == VECTOR_TYPE)
     {
-      reg = gen_rtx_REG (mode, regno);
-      return reg;
+      HOST_WIDE_INT size = int_size_in_bytes (type);
+      gcc_assert ((TARGET_ARCH32 && size <= 8)
+                 || (TARGET_ARCH64 && size <= 16));
+
+      if (mode == BLKmode)
+       return function_arg_vector_value (size,
+                                         TYPE_MODE (TREE_TYPE (type)),
+                                         SPARC_FP_ARG_FIRST + 2*slotno);
+      else
+       mclass = MODE_FLOAT;
     }
-    
-  if (type && TREE_CODE (type) == RECORD_TYPE)
-    {
-      /* Structures up to 16 bytes in size are passed in arg slots on the
-        stack and are promoted to registers where possible.  */
 
-      gcc_assert (int_size_in_bytes (type) <= 16);
+  if (TARGET_ARCH32)
+    return gen_rtx_REG (mode, regno);
 
-      return function_arg_record_value (type, mode, slotno, named, regbase);
-    }
-  else if (type && TREE_CODE (type) == UNION_TYPE)
+  /* Structures up to 16 bytes in size are passed in arg slots on the stack
+     and are promoted to registers if possible.  */
+  if (type && TREE_CODE (type) == RECORD_TYPE)
     {
       HOST_WIDE_INT size = int_size_in_bytes (type);
-
       gcc_assert (size <= 16);
 
-      return function_arg_union_value (size, mode, slotno, regno);
+      return function_arg_record_value (type, mode, slotno, named, regbase);
     }
-  else if (type && TREE_CODE (type) == VECTOR_TYPE)
+
+  /* Unions up to 16 bytes in size are passed in integer registers.  */
+  else if (type && TREE_CODE (type) == UNION_TYPE)
     {
-      /* Vector types deserve special treatment because they are
-        polymorphic wrt their mode, depending upon whether VIS
-        instructions are enabled.  */
       HOST_WIDE_INT size = int_size_in_bytes (type);
-
       gcc_assert (size <= 16);
 
-      if (mode == BLKmode)
-       return function_arg_vector_value (size,
-                                         TYPE_MODE (TREE_TYPE (type)),
-                                         SPARC_FP_ARG_FIRST + 2*slotno);
-      else
-       mclass = MODE_FLOAT;
+      return function_arg_union_value (size, mode, slotno, regno);
     }
 
   /* v9 fp args in reg slots beyond the int reg slots get passed in regs
      but also have the slot allocated for them.
      If no prototype is in scope fp values in register slots get passed
      in two places, either fp regs and int regs or fp regs and memory.  */
-  if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
-      && SPARC_FP_REG_P (regno))
+  else if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
+          && SPARC_FP_REG_P (regno))
     {
-      reg = gen_rtx_REG (mode, regno);
+      rtx reg = gen_rtx_REG (mode, regno);
       if (cum->prototype_p || cum->libcall_p)
        {
          /* "* 2" because fp reg numbers are recorded in 4 byte
@@ -5189,13 +5188,18 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode,
            }
        }
     }
-  else
+
+  /* All other aggregate types are passed in an integer register in a mode
+     corresponding to the size of the type.  */
+  else if (type && AGGREGATE_TYPE_P (type))
     {
-      /* Scalar or complex int.  */
-      reg = gen_rtx_REG (mode, regno);
+      HOST_WIDE_INT size = int_size_in_bytes (type);
+      gcc_assert (size <= 16);
+
+      mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
     }
 
-  return reg;
+  return gen_rtx_REG (mode, regno);
 }
 
 /* For an arg passed partly in registers and partly in memory,
@@ -5271,7 +5275,6 @@ sparc_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
                         bool named ATTRIBUTE_UNUSED)
 {
   if (TARGET_ARCH32)
-    {
     /* Original SPARC 32-bit ABI says that structures and unions,
        and quad-precision floats are passed by reference.  For Pascal,
        also pass arrays by reference.  All other base types are passed
@@ -5286,19 +5289,17 @@ sparc_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
        integers are passed like floats of the same size, that is in
        registers up to 8 bytes.  Pass all vector floats by reference
        like structure and unions.  */
-      return ((type && (AGGREGATE_TYPE_P (type) || VECTOR_FLOAT_TYPE_P (type)))
-             || mode == SCmode
-             /* Catch CDImode, TFmode, DCmode and TCmode.  */
-             || GET_MODE_SIZE (mode) > 8
-             || (type
-                 && TREE_CODE (type) == VECTOR_TYPE
-                 && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8));
-    }
+    return ((type && (AGGREGATE_TYPE_P (type) || VECTOR_FLOAT_TYPE_P (type)))
+           || mode == SCmode
+           /* Catch CDImode, TFmode, DCmode and TCmode.  */
+           || GET_MODE_SIZE (mode) > 8
+           || (type
+               && TREE_CODE (type) == VECTOR_TYPE
+               && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8));
   else
-    {
     /* Original SPARC 64-bit ABI says that structures and unions
        smaller than 16 bytes are passed in registers, as well as
-       all other base types.  For Pascal, pass arrays by reference.
+       all other base types.
        
        Extended ABI (as implemented by the Sun compiler) says that
        complex floats are passed in registers up to 16 bytes.  Pass
@@ -5309,13 +5310,11 @@ sparc_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
        integers are passed like floats of the same size, that is in
        registers (up to 16 bytes).  Pass all vector floats like structure
        and unions.  */
-      return ((type && TREE_CODE (type) == ARRAY_TYPE)
-             || (type
-                 && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == VECTOR_TYPE)
-                 && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 16)
-             /* Catch CTImode and TCmode.  */
-             || GET_MODE_SIZE (mode) > 16);
-    }
+    return ((type
+            && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == VECTOR_TYPE)
+            && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 16)
+           /* Catch CTImode and TCmode.  */
+           || GET_MODE_SIZE (mode) > 16);
 }
 
 /* Handle the FUNCTION_ARG_ADVANCE macro.
@@ -5499,13 +5498,11 @@ function_value (tree type, enum machine_mode mode, int incoming_p)
   enum mode_class mclass = GET_MODE_CLASS (mode);
   int regno;
 
+  /* Vector types deserve special treatment because they are polymorphic wrt
+     their mode, depending upon whether VIS instructions are enabled.  */
   if (type && TREE_CODE (type) == VECTOR_TYPE)
     {
-      /* Vector types deserve special treatment because they are
-        polymorphic wrt their mode, depending upon whether VIS
-        instructions are enabled.  */
       HOST_WIDE_INT size = int_size_in_bytes (type);
-
       gcc_assert ((TARGET_ARCH32 && size <= 8)
                  || (TARGET_ARCH64 && size <= 32));
 
@@ -5516,34 +5513,41 @@ function_value (tree type, enum machine_mode mode, int incoming_p)
       else
        mclass = MODE_FLOAT;
     }
-  else if (type && TARGET_ARCH64)
+
+  if (TARGET_ARCH64 && type)
     {
+      /* Structures up to 32 bytes in size are returned in registers.  */
       if (TREE_CODE (type) == RECORD_TYPE)
        {
-         /* Structures up to 32 bytes in size are passed in registers,
-            promoted to fp registers where possible.  */
-
-         gcc_assert (int_size_in_bytes (type) <= 32);
+         HOST_WIDE_INT size = int_size_in_bytes (type);
+         gcc_assert (size <= 32);
 
          return function_arg_record_value (type, mode, 0, 1, regbase);
        }
+
+      /* Unions up to 32 bytes in size are returned in integer registers.  */
       else if (TREE_CODE (type) == UNION_TYPE)
        {
          HOST_WIDE_INT size = int_size_in_bytes (type);
-
          gcc_assert (size <= 32);
 
          return function_arg_union_value (size, mode, 0, regbase);
        }
+
+      /* Objects that require it are returned in FP registers.  */
+      else if (mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
+       ;
+
+      /* All other aggregate types are returned in an integer register in a
+        mode corresponding to the size of the type.  */
       else if (AGGREGATE_TYPE_P (type))
        {
          /* All other aggregate types are passed in an integer register
             in a mode corresponding to the size of the type.  */
-         HOST_WIDE_INT bytes = int_size_in_bytes (type);
-
-         gcc_assert (bytes <= 32);
+         HOST_WIDE_INT size = int_size_in_bytes (type);
+         gcc_assert (size <= 32);
 
-         mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 0);
+         mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
 
          /* ??? We probably should have made the same ABI change in
             3.4.0 as the one we made for unions.   The latter was
@@ -5555,17 +5559,17 @@ function_value (tree type, enum machine_mode mode, int incoming_p)
             try to be unduly clever, and simply follow the ABI
             for unions in that case.  */
          if (mode == BLKmode)
-           return function_arg_union_value (bytes, mode, 0, regbase);
+           return function_arg_union_value (size, mode, 0, regbase);
          else
            mclass = MODE_INT;
        }
-      else if (mclass == MODE_INT
-              && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+
+      /* This must match PROMOTE_FUNCTION_MODE.  */
+      else if (mclass == MODE_INT && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
        mode = word_mode;
     }
 
-  if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
-      && TARGET_FPU)
+  if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT) && TARGET_FPU)
     regno = SPARC_FP_ARG_FIRST;
   else
     regno = regbase;