diff options
author | Richard Henderson <rth@redhat.com> | 2004-03-12 02:03:32 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2004-03-12 02:03:32 -0800 |
commit | 42ba51300418d586a41637d9c1fc72c6078b7c6d (patch) | |
tree | bdd3000f3e6489ec11b58de31921ac902908031e /gcc | |
parent | ac011d28bb63763829fd3bec7792fe13d58cfac7 (diff) | |
download | gcc-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/ChangeLog | 25 | ||||
-rw-r--r-- | gcc/calls.c | 30 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 13 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.h | 3 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 11 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.h | 7 | ||||
-rw-r--r-- | gcc/config/xtensa/xtensa.c | 2 | ||||
-rw-r--r-- | gcc/config/xtensa/xtensa.h | 3 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 22 | ||||
-rw-r--r-- | gcc/expr.h | 5 | ||||
-rw-r--r-- | gcc/function.c | 19 | ||||
-rw-r--r-- | gcc/system.h | 2 | ||||
-rw-r--r-- | gcc/target-def.h | 7 | ||||
-rw-r--r-- | gcc/target.h | 43 |
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 @@ -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; |