re PR target/14547 (Passing _Complex long double does not follow the ABI)
authorRichard Henderson <rth@redhat.com>
Fri, 12 Mar 2004 10:03:32 +0000 (02:03 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 12 Mar 2004 10:03:32 +0000 (02:03 -0800)
        PR target/14547
        * target.h (struct gcc_target): Move calls substructure before
        booleans.  Add split_complex_arg.
        * function.c (assign_parms, split_complex_args): Use it.
        * calls.c (expand_call): Likewise.
        (split_complex_values): Likewise.  Check for splittable types
        before allocating memory.
        (split_complex_types): Likewise.
        * system.h (SPLIT_COMPLEX_ARGS): Poison.
        * expr.h (SPLIT_COMPLEX_ARGS): Remove.
        * target-def.h (TARGET_SPLIT_COMPLEX_ARG): New.
        * config/alpha/alpha.c (alpha_split_complex_arg): New.
        (TARGET_SPLIT_COMPLEX_ARG): New.
        * config/alpha/alpha.h (SPLIT_COMPLEX_ARGS): Remove.
        * config/rs6000/rs6000.c (TARGET_SPLIT_COMPLEX_ARG): New.
        (rs6000_override_options): Zap it for non-AIX.
        (rs6000_function_value): Use targetm.calls.split_complex_arg.
        * config/rs6000/rs6000.h (SPLIT_COMPLEX_ARGS): Remove.
        * config/xtensa/xtensa.c (TARGET_SPLIT_COMPLEX_ARG): New.
        * config/xtensa/xtensa.h (SPLIT_COMPLEX_ARGS): Remove.
        * doc/tm.texi (TARGET_SPLIT_COMPLEX_ARG): Modify from old
        SPLIT_COMPLEX_ARGS entry.

From-SVN: r79376

14 files changed:
gcc/ChangeLog
gcc/calls.c
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/xtensa/xtensa.c
gcc/config/xtensa/xtensa.h
gcc/doc/tm.texi
gcc/expr.h
gcc/function.c
gcc/system.h
gcc/target-def.h
gcc/target.h

index 1c709f47c0d4fb3be77d8f6cb8f17654b5ac5c13..f80b5355b0422ff4f50f2993778a46981db0b348 100644 (file)
@@ -1,3 +1,28 @@
+2004-03-12  Richard Henderson  <rth@redhat.com>
+
+       PR target/14547
+       * target.h (struct gcc_target): Move calls substructure before
+       booleans.  Add split_complex_arg.
+       * function.c (assign_parms, split_complex_args): Use it.
+        * calls.c (expand_call): Likewise.
+        (split_complex_values): Likewise.  Check for splittable types
+        before allocating memory.
+        (split_complex_types): Likewise.
+       * system.h (SPLIT_COMPLEX_ARGS): Poison.
+       * expr.h (SPLIT_COMPLEX_ARGS): Remove.
+       * target-def.h (TARGET_SPLIT_COMPLEX_ARG): New.
+       * config/alpha/alpha.c (alpha_split_complex_arg): New.
+       (TARGET_SPLIT_COMPLEX_ARG): New.
+       * config/alpha/alpha.h (SPLIT_COMPLEX_ARGS): Remove.
+       * config/rs6000/rs6000.c (TARGET_SPLIT_COMPLEX_ARG): New.
+       (rs6000_override_options): Zap it for non-AIX.
+       (rs6000_function_value): Use targetm.calls.split_complex_arg.
+       * config/rs6000/rs6000.h (SPLIT_COMPLEX_ARGS): Remove.
+       * config/xtensa/xtensa.c (TARGET_SPLIT_COMPLEX_ARG): New.
+       * config/xtensa/xtensa.h (SPLIT_COMPLEX_ARGS): Remove.
+       * doc/tm.texi (TARGET_SPLIT_COMPLEX_ARG): Modify from old
+       SPLIT_COMPLEX_ARGS entry.
+
 2004-03-11  Richard Henderson  <rth@redhat.com>
 
        * config/alpha/alpha.c (xfloating_ops, vax_cvt_ops): New.
index 29c06aa47723241ec98f22997a2bc9684b5194a2..e58bd05f8ce771610e35e3b26383731564331c32 100644 (file)
@@ -2347,7 +2347,7 @@ expand_call (tree exp, rtx target, int ignore)
 
   /* Munge the tree to split complex arguments into their imaginary
      and real parts.  */
-  if (SPLIT_COMPLEX_ARGS)
+  if (targetm.calls.split_complex_arg)
     {
       type_arg_types = split_complex_types (TYPE_ARG_TYPES (funtype));
       actparms = split_complex_values (actparms);
@@ -3557,6 +3557,17 @@ split_complex_values (tree values)
 {
   tree p;
 
+  /* Before allocating memory, check for the common case of no complex.  */
+  for (p = values; p; p = TREE_CHAIN (p))
+    {
+      tree type = TREE_TYPE (TREE_VALUE (p));
+      if (type && TREE_CODE (type) == COMPLEX_TYPE
+         && targetm.calls.split_complex_arg (type))
+        goto found;
+    }
+  return values;
+
+ found:
   values = copy_list (values);
 
   for (p = values; p; p = TREE_CHAIN (p))
@@ -3568,7 +3579,8 @@ split_complex_values (tree values)
       if (!complex_type)
        continue;
 
-      if (TREE_CODE (complex_type) == COMPLEX_TYPE)
+      if (TREE_CODE (complex_type) == COMPLEX_TYPE
+         && targetm.calls.split_complex_arg (complex_type))
        {
          tree subtype;
          tree real, imag, next;
@@ -3599,13 +3611,25 @@ split_complex_types (tree types)
 {
   tree p;
 
+  /* Before allocating memory, check for the common case of no complex.  */
+  for (p = types; p; p = TREE_CHAIN (p))
+    {
+      tree type = TREE_VALUE (p);
+      if (TREE_CODE (type) == COMPLEX_TYPE
+         && targetm.calls.split_complex_arg (type))
+        goto found;
+    }
+  return types;
+
+ found:
   types = copy_list (types);
 
   for (p = types; p; p = TREE_CHAIN (p))
     {
       tree complex_type = TREE_VALUE (p);
 
-      if (TREE_CODE (complex_type) == COMPLEX_TYPE)
+      if (TREE_CODE (complex_type) == COMPLEX_TYPE
+         && targetm.calls.split_complex_arg (complex_type))
        {
          tree next, imag;
 
index 37920ad30194610620005280c01f5ddbb3b2e408..c9a87ebf31180c0ef3de33adeb1b7d41222bbe05 100644 (file)
@@ -5889,7 +5889,7 @@ function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, tree type,
   else
     {
 #ifdef ENABLE_CHECKING
-      /* With SPLIT_COMPLEX_ARGS, we shouldn't see any raw complex
+      /* With alpha_split_complex_arg, we shouldn't see any raw complex
         values here.  */
       if (COMPLEX_MODE_P (mode))
        abort ();
@@ -6106,6 +6106,15 @@ function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
   return gen_rtx_REG (mode, regnum);
 }
 
+/* TCmode complex values are passed by invisible reference.  We 
+   should not split these values.  */
+
+static bool
+alpha_split_complex_arg (tree type)
+{
+  return TYPE_MODE (type) != TCmode;
+}
+
 static tree
 alpha_build_builtin_va_list (void)
 {
@@ -10223,6 +10232,8 @@ alpha_init_libfuncs (void)
 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
 #undef TARGET_PRETEND_OUTGOING_VARARGS_NAMED
 #define TARGET_PRETEND_OUTGOING_VARARGS_NAMED hook_bool_CUMULATIVE_ARGS_true
+#undef TARGET_SPLIT_COMPLEX_ARG
+#define TARGET_SPLIT_COMPLEX_ARG alpha_split_complex_arg
 
 #undef TARGET_BUILD_BUILTIN_VA_LIST
 #define TARGET_BUILD_BUILTIN_VA_LIST alpha_build_builtin_va_list
index 16441166f8bcfa60fc1cdd2b4cb3e7db29826b9d..d59797c103fa76806e125a35632e2663fd72cd75 100644 (file)
@@ -1839,6 +1839,3 @@ do {                                                      \
 
 /* Generate calls to memcpy, etc., not bcopy, etc.  */
 #define TARGET_MEM_FUNCTIONS 1
-
-/* Pass complex arguments independently.  */
-#define SPLIT_COMPLEX_ARGS 1
index 6ed984c5fa50d124961b7515863e897dd9dd8d3e..d53c32eea9351bbd64e13577bd980d55893caf49 100644 (file)
@@ -621,6 +621,8 @@ static const char alt_reg_names[][8] =
 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
 #undef TARGET_PRETEND_OUTGOING_VARARGS_NAMED
 #define TARGET_PRETEND_OUTGOING_VARARGS_NAMED hook_bool_CUMULATIVE_ARGS_true
+#undef TARGET_SPLIT_COMPLEX_ARG
+#define TARGET_SPLIT_COMPLEX_ARG hook_bool_tree_true
 
 #undef TARGET_BUILD_BUILTIN_VA_LIST
 #define TARGET_BUILD_BUILTIN_VA_LIST rs6000_build_builtin_va_list
@@ -1006,6 +1008,11 @@ rs6000_override_options (const char *default_cpu)
 
   /* Arrange to save and restore machine status around nested functions.  */
   init_machine_status = rs6000_init_machine_status;
+
+  /* We should always be splitting complex arguments, but we can't break
+     Linux and Darwin ABIs at the moment.  For now, only AIX is fixed.  */
+  if (DEFAULT_ABI != ABI_AIX)
+    targetm.calls.split_complex_arg = NULL;
 }
 
 /* Handle generic options of the form -mfoo=yes/no.
@@ -15970,7 +15977,7 @@ rs6000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
     regno = FP_ARG_RETURN;
   else if (TREE_CODE (valtype) == COMPLEX_TYPE
           && TARGET_HARD_FLOAT
-          && SPLIT_COMPLEX_ARGS)
+          && targetm.calls.split_complex_arg)
     return rs6000_complex_function_value (mode);
   else if (TREE_CODE (valtype) == VECTOR_TYPE && TARGET_ALTIVEC)
     regno = ALTIVEC_ARG_RETURN;
@@ -15992,7 +15999,7 @@ rs6000_libcall_value (enum machine_mode mode)
     regno = FP_ARG_RETURN;
   else if (ALTIVEC_VECTOR_MODE (mode))
     regno = ALTIVEC_ARG_RETURN;
-  else if (COMPLEX_MODE_P (mode) && SPLIT_COMPLEX_ARGS)
+  else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg)
     return rs6000_complex_function_value (mode);
   else
     regno = GP_ARG_RETURN;
index 641e4bbb8af46c09022f0f976ba7315cff7d2da4..d520cb64efda9fd49f08127a6270cdf583844807 100644 (file)
@@ -1846,13 +1846,6 @@ typedef struct rs6000_args
 #define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
   function_arg_boundary (MODE, TYPE)
 
-/* Define to nonzero if complex arguments should be split into their
-   corresponding components.
-
-   This should be set for Linux and Darwin as well, but we can't break
-   the ABIs at the moment.  For now, only AIX gets fixed.  */
-#define SPLIT_COMPLEX_ARGS (DEFAULT_ABI == ABI_AIX)
-
 /* Implement `va_start' for varargs and stdarg.  */
 #define EXPAND_BUILTIN_VA_START(valist, nextarg) \
   rs6000_va_start (valist, nextarg)
index 14db30f4a99b70195ef3c41d008672e60d1756b4..0c88d8539d89c2ed5105ccf87cd1df23688a4fca 100644 (file)
@@ -251,6 +251,8 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
 
 #undef TARGET_RETURN_IN_MEMORY
 #define TARGET_RETURN_IN_MEMORY xtensa_return_in_memory
+#undef TARGET_SPLIT_COMPLEX_ARG
+#define TARGET_SPLIT_COMPLEX_ARG hook_bool_tree_true
 
 #undef TARGET_EXPAND_BUILTIN_SAVEREGS
 #define TARGET_EXPAND_BUILTIN_SAVEREGS xtensa_builtin_saveregs
index 06df746e71bbdd407dc0447481275824f1e5f1c3..3d2432be9e1dbc27b9d5d7a69dab0df0b4759412 100644 (file)
@@ -794,9 +794,6 @@ typedef struct xtensa_args
    && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST                     \
        || TREE_ADDRESSABLE (TYPE)))
 
-/* Pass complex arguments independently.  */
-#define SPLIT_COMPLEX_ARGS 1
-
 /* Profiling Xtensa code is typically done with the built-in profiling
    feature of Tensilica's instruction set simulator, which does not
    require any compiler support.  Profiling code on a real (i.e.,
index f464bea2eaec30634464b53003079eee68dfd335..4b65d900699f12634b17a3710923fc41629dfa92 100644 (file)
@@ -3794,16 +3794,18 @@ used for this purpose since all function arguments are pushed on the
 stack.
 @end defmac
 
-@defmac SPLIT_COMPLEX_ARGS
-
-Define this macro to a nonzero value if complex function arguments
-should be split into their corresponding components.  By default, GCC
-will attempt to pack complex arguments into the target's word size.
-Some ABIs require complex arguments to be split and treated as their
-individual components.  For example, on AIX64, complex floats should
-be passed in a pair of floating point registers, even though a complex
-float would fit in one 64-bit floating point register.
-@end defmac
+@deftypefn {Target Hook} bool TARGET_SPLIT_COMPLEX_ARG (tree @var{type})
+This hook should return true if parameter of type @var{type} are passed
+as two scalar parameters.  By default, GCC will attempt to pack complex
+arguments into the target's word size.  Some ABIs require complex arguments
+to be split and treated as their individual components.  For example, on
+AIX64, complex floats should be passed in a pair of floating point
+registers, even though a complex float would fit in one 64-bit floating
+point register.
+
+The default value of this hook is @code{NULL}, which is treated as always
+false.
+@end deftypefn
 
 @node Scalar Return
 @subsection How Scalar Function Values Are Returned
index d2bbb8850d4c8edffcb289442c92842477e754ad..dd7ac9c6058b85b7fe918ce2e2dcebfbf6547811 100644 (file)
@@ -188,11 +188,6 @@ do {                                                       \
 #define FUNCTION_ARG_BOUNDARY(MODE, TYPE)      PARM_BOUNDARY
 #endif
 
-/* Define to nonzero if complex arguments should be split into their
-   corresponding components.  */
-#ifndef SPLIT_COMPLEX_ARGS
-#define SPLIT_COMPLEX_ARGS 0
-#endif
 tree split_complex_types (tree);
 tree split_complex_values (tree);
 
index 2f68eaa007292eee4a562e8d14d5593b7d6db474..3d48b404a4e81f10c6d9be5aec0b856e80be59b8 100644 (file)
@@ -4349,7 +4349,8 @@ assign_parms (tree fndecl)
   max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
   parm_reg_stack_loc = ggc_alloc_cleared (max_parm_reg * sizeof (rtx));
 
-  if (SPLIT_COMPLEX_ARGS)
+  /* If the target wants to split complex arguments into scalars, do so.  */
+  if (targetm.calls.split_complex_arg)
     fnargs = split_complex_args (fnargs);
 
 #ifdef REG_PARM_STACK_SPACE
@@ -5225,11 +5226,12 @@ assign_parms (tree fndecl)
        }
     }
 
-  if (SPLIT_COMPLEX_ARGS && fnargs != orig_fnargs)
+  if (targetm.calls.split_complex_arg && fnargs != orig_fnargs)
     {
       for (parm = orig_fnargs; parm; parm = TREE_CHAIN (parm))
        {
-         if (TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE)
+         if (TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE
+             && targetm.calls.split_complex_arg (TREE_TYPE (parm)))
            {
              rtx tmp, real, imag;
              enum machine_mode inner = GET_MODE_INNER (DECL_MODE (parm));
@@ -5373,8 +5375,12 @@ split_complex_args (tree args)
 
   /* Before allocating memory, check for the common case of no complex.  */
   for (p = args; p; p = TREE_CHAIN (p))
-    if (TREE_CODE (TREE_TYPE (p)) == COMPLEX_TYPE)
-      goto found;
+    {
+      tree type = TREE_TYPE (p);
+      if (TREE_CODE (type) == COMPLEX_TYPE
+         && targetm.calls.split_complex_arg (type))
+        goto found;
+    }
   return args;
 
  found:
@@ -5383,7 +5389,8 @@ split_complex_args (tree args)
   for (p = args; p; p = TREE_CHAIN (p))
     {
       tree type = TREE_TYPE (p);
-      if (TREE_CODE (type) == COMPLEX_TYPE)
+      if (TREE_CODE (type) == COMPLEX_TYPE
+         && targetm.calls.split_complex_arg (type))
        {
          tree decl;
          tree subtype = TREE_TYPE (type);
index 2e16382ed2b414e022f1e7d8b34a5c63088224dd..b6d972b1a45e63dfe5aa079da9316cff49184d22 100644 (file)
@@ -606,7 +606,7 @@ typedef char _Bool;
        STRUCT_VALUE_INCOMING STRICT_ARGUMENT_NAMING                    \
        PROMOTE_FUNCTION_RETURN PROMOTE_PROTOTYPES STRUCT_VALUE_REGNUM  \
        SETUP_INCOMING_VARARGS EXPAND_BUILTIN_SAVEREGS                  \
-       DEFAULT_SHORT_ENUMS
+       DEFAULT_SHORT_ENUMS SPLIT_COMPLEX_ARGS
 
 /* Other obsolete target macros, or macros that used to be in target
    headers and were not used, and may be obsolete or may never have
index 89af47e12ee3dfed2b7a304dc1c49309db42a193..cfc8a19eb69029d3bc689d68c4d19cbc3f0d2e41 100644 (file)
@@ -346,7 +346,9 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #define TARGET_EXPAND_BUILTIN_SAVEREGS default_expand_builtin_saveregs
 #define TARGET_SETUP_INCOMING_VARARGS default_setup_incoming_varargs
 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_false
-#define TARGET_PRETEND_OUTGOING_VARARGS_NAMED default_pretend_outgoing_varargs_named
+#define TARGET_PRETEND_OUTGOING_VARARGS_NAMED \
+  default_pretend_outgoing_varargs_named
+#define TARGET_SPLIT_COMPLEX_ARG NULL
 
 #define TARGET_CALLS {                                         \
    TARGET_PROMOTE_FUNCTION_ARGS,                               \
@@ -359,6 +361,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    TARGET_SETUP_INCOMING_VARARGS,                              \
    TARGET_STRICT_ARGUMENT_NAMING,                              \
    TARGET_PRETEND_OUTGOING_VARARGS_NAMED,                      \
+   TARGET_SPLIT_COMPLEX_ARG,                                   \
    }
 
 /* The whole shebang.  */
@@ -403,6 +406,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   TARGET_DEFAULT_SHORT_ENUMS,                  \
   TARGET_BUILTIN_SETJMP_FRAME_VALUE,           \
   TARGET_MD_ASM_CLOBBERS,                      \
+  TARGET_CALLS,                                        \
   TARGET_HAVE_NAMED_SECTIONS,                  \
   TARGET_HAVE_CTORS_DTORS,                     \
   TARGET_HAVE_TLS,                             \
@@ -410,7 +414,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   TARGET_TERMINATE_DW2_EH_FRAME_INFO,          \
   TARGET_ASM_FILE_START_APP_OFF,               \
   TARGET_ASM_FILE_START_FILE_DIRECTIVE,                \
-  TARGET_CALLS,                                        \
 }
 
 #include "hooks.h"
index 2387e4dd38a4080b3f74dccee3b4636307dc6752..e33e815ec8640b5f8ffcb962a10e4b02700f290a 100644 (file)
@@ -429,6 +429,30 @@ struct gcc_target
      the port wishes to automatically clobber for all asms.  */
   tree (* md_asm_clobbers) (tree);
 
+  /* Functions relating to calls - argument passing, returns, etc.  */
+  struct calls {
+    bool (*promote_function_args) (tree fntype);
+    bool (*promote_function_return) (tree fntype);
+    bool (*promote_prototypes) (tree fntype);
+    rtx (*struct_value_rtx) (tree fndecl, int incoming);
+    bool (*return_in_memory) (tree type, tree fndecl);
+    bool (*return_in_msb) (tree type);
+    rtx (*expand_builtin_saveregs) (void);
+    /* Returns pretend_argument_size.  */
+    void (*setup_incoming_varargs) (CUMULATIVE_ARGS *ca, enum machine_mode mode,
+                                   tree type, int *pretend_arg_size,
+                                   int second_time);
+    bool (*strict_argument_naming) (CUMULATIVE_ARGS *ca);
+    /* Returns true if we should use
+       targetm.calls.setup_incoming_varargs() and/or
+       targetm.calls.strict_argument_naming().  */
+    bool (*pretend_outgoing_varargs_named) (CUMULATIVE_ARGS *ca);
+
+    /* Given a complex type T, return true if a parameter of type T
+       should be passed as two scalars.  */
+    bool (* split_complex_arg) (tree type);
+  } calls;
+
   /* Leave the boolean fields at the end.  */
 
   /* True if arbitrary sections are supported.  */
@@ -455,24 +479,7 @@ struct gcc_target
      at the beginning of assembly output.  */
   bool file_start_file_directive;
 
-  /* Functions relating to calls - argument passing, returns, etc.  */
-  struct calls {
-    bool (*promote_function_args) (tree fntype);
-    bool (*promote_function_return) (tree fntype);
-    bool (*promote_prototypes) (tree fntype);
-    rtx (*struct_value_rtx) (tree fndecl, int incoming);
-    bool (*return_in_memory) (tree type, tree fndecl);
-    bool (*return_in_msb) (tree type);
-    rtx (*expand_builtin_saveregs) (void);
-    /* Returns pretend_argument_size.  */
-    void (*setup_incoming_varargs) (CUMULATIVE_ARGS *ca, enum machine_mode mode,
-                                   tree type, int *pretend_arg_size, int second_time);
-    bool (*strict_argument_naming) (CUMULATIVE_ARGS *ca);
-    /* Returns true if we should use
-       targetm.calls.setup_incoming_varargs() and/or
-       targetm.calls.strict_argument_naming().  */
-    bool (*pretend_outgoing_varargs_named) (CUMULATIVE_ARGS *ca);
-  } calls;
+  /* Leave the boolean fields at the end.  */
 };
 
 extern struct gcc_target targetm;