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
This commit is contained in:
Richard Henderson 2004-03-12 02:03:32 -08:00 committed by Richard Henderson
parent ac011d28bb
commit 42ba513004
14 changed files with 130 additions and 60 deletions

View 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.

View 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;

View 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

View 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

View 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;

View 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)

View 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

View 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.,

View File

@ -3794,16 +3794,18 @@ used for this purpose since all function arguments are pushed on the
stack.
@end defmac
@defmac SPLIT_COMPLEX_ARGS
@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.
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
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

View 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);

View 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);

View 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

View 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"

View 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;