aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2004-03-12 02:03:32 -0800
committerRichard Henderson <rth@gcc.gnu.org>2004-03-12 02:03:32 -0800
commit42ba51300418d586a41637d9c1fc72c6078b7c6d (patch)
treebdd3000f3e6489ec11b58de31921ac902908031e /gcc
parentac011d28bb63763829fd3bec7792fe13d58cfac7 (diff)
downloadgcc-42ba51300418d586a41637d9c1fc72c6078b7c6d.zip
gcc-42ba51300418d586a41637d9c1fc72c6078b7c6d.tar.gz
gcc-42ba51300418d586a41637d9c1fc72c6078b7c6d.tar.bz2
re PR target/14547 (Passing _Complex long double does not follow the ABI)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog25
-rw-r--r--gcc/calls.c30
-rw-r--r--gcc/config/alpha/alpha.c13
-rw-r--r--gcc/config/alpha/alpha.h3
-rw-r--r--gcc/config/rs6000/rs6000.c11
-rw-r--r--gcc/config/rs6000/rs6000.h7
-rw-r--r--gcc/config/xtensa/xtensa.c2
-rw-r--r--gcc/config/xtensa/xtensa.h3
-rw-r--r--gcc/doc/tm.texi22
-rw-r--r--gcc/expr.h5
-rw-r--r--gcc/function.c19
-rw-r--r--gcc/system.h2
-rw-r--r--gcc/target-def.h7
-rw-r--r--gcc/target.h43
14 files changed, 131 insertions, 61 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1c709f4..f80b535 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/calls.c b/gcc/calls.c
index 29c06aa..e58bd05 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -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;
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 37920ad..c9a87eb 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -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
diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h
index 1644116..d59797c 100644
--- a/gcc/config/alpha/alpha.h
+++ b/gcc/config/alpha/alpha.h
@@ -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
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 6ed984c..d53c32e 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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;
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 641e4bb..d520cb6 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -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)
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index 14db30f..0c88d85 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -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
diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h
index 06df746..3d2432b 100644
--- a/gcc/config/xtensa/xtensa.h
+++ b/gcc/config/xtensa/xtensa.h
@@ -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.,
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index f464bea..4b65d90 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -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
diff --git a/gcc/expr.h b/gcc/expr.h
index d2bbb88..dd7ac9c 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -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);
diff --git a/gcc/function.c b/gcc/function.c
index 2f68eaa..3d48b40 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -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);
diff --git a/gcc/system.h b/gcc/system.h
index 2e16382..b6d972b 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -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
diff --git a/gcc/target-def.h b/gcc/target-def.h
index 89af47e..cfc8a19 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -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"
diff --git a/gcc/target.h b/gcc/target.h
index 2387e4d..e33e815 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -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;