From: rth Date: Tue, 13 Jul 2004 07:45:09 +0000 (+0000) Subject: * target-def.h (TARGET_MUST_PASS_IN_STACK): New. X-Git-Tag: upstream/4.9.2~69588 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0336f0f0a448f834556a8efb0cf4161c2e2a38d2;p=platform%2Fupstream%2Flinaro-gcc.git * target-def.h (TARGET_MUST_PASS_IN_STACK): New. * target.h (struct gcc_target): Add calls.must_pass_in_stack. * expr.h (MUST_PASS_IN_STACK): Remove. * system.h (MUST_PASS_IN_STACK): Poison. * tree.h (must_pass_in_stack_var_size): Declare. (must_pass_in_stack_var_size_or_pad): Declare. * calls.c (must_pass_in_stack_var_size): New. (must_pass_in_stack_var_size_or_pad): Rename from default_must_pass_in_stack. * config/alpha/alpha.c (unicosmk_must_pass_in_stack): New. (TARGET_MUST_PASS_IN_STACK): New. * config/alpha/unicosmk.h (MUST_PASS_IN_STACK): Remove. * config/fr30/fr30.c (fr30_must_pass_in_stack): New. (TARGET_MUST_PASS_IN_STACK): New. * config/fr30/fr30.h (MUST_PASS_IN_STACK): Remove. * config/frv/frv.c (frv_must_pass_in_stack): New. (TARGET_MUST_PASS_IN_STACK): New. * config/frv/frv.h (MUST_PASS_IN_STACK): Remove. * config/i386/i386-protos.h (ix86_must_pass_in_stack): Remove. * config/i386/i386.c (TARGET_MUST_PASS_IN_STACK): New. (ix86_must_pass_in_stack): Make static. * config/i386/i386.h (MUST_PASS_IN_STACK): Remove. * config/ia64/ia64.c (TARGET_MUST_PASS_IN_STACK): New. * config/ia64/ia64.h (MUST_PASS_IN_STACK): Remove. * config/m32r/m32r.c (TARGET_MUST_PASS_IN_STACK): New. * config/m32r/m32r.h (MUST_PASS_IN_STACK): Remove. * config/mcore/mcore-protos.h (mcore_must_pass_on_stack): Remove. * config/mcore/mcore.c (TARGET_MUST_PASS_IN_STACK): New. (mcore_must_pass_on_stack): Remove. * config/mcore/mcore.h (MUST_PASS_IN_STACK): Remove. * config/mips/mips.c (TARGET_MUST_PASS_IN_STACK): New. * config/mips/mips.h (MUST_PASS_IN_STACK): Remove. * config/pa/pa.c (TARGET_MUST_PASS_IN_STACK): New. * config/pa/pa.h (MUST_PASS_IN_STACK): Remove. * config/rs6000/aix.h (MUST_PASS_IN_STACK): Remove. * config/rs6000/linux64.h (MUST_PASS_IN_STACK): Remove. * config/rs6000/rs6000.c (rs6000_must_pass_in_stack): New. (TARGET_MUST_PASS_IN_STACK): New. * config/sh/sh.c (TARGET_MUST_PASS_IN_STACK): New. * config/sh/sh.h (MUST_PASS_IN_STACK): Remove. * config/sparc/sparc.c (TARGET_MUST_PASS_IN_STACK): New. * config/sparc/sparc.h (MUST_PASS_IN_STACK): Remove. * config/xtensa/xtensa.c (TARGET_MUST_PASS_IN_STACK): New. * config/xtensa/xtensa.h (MUST_PASS_IN_STACK): Remove. * doc/tm.texi (TARGET_MUST_PASS_IN_STACK): Update from MUST_PASS_IN_STACK. * calls.c, function.c, config/alpha/alpha.c, config/alpha/alpha.h, config/alpha/unicosmk.h, config/alpha/vms.h, config/c4x/c4x.c, config/cris/cris.h, config/fr30/fr30.c, config/fr30/fr30.h, config/frv/frv.c, config/i386/i386.c, config/iq2000/iq2000.c, config/mcore/mcore.c, config/mcore/mcore.h, config/mips/mips.c, config/mmix/mmix.c, config/mmix/mmix.h, config/rs6000/rs6000.c, config/sh/sh.c, config/sh/sh.h, config/stormy16/stormy16.c, config/xtensa/xtensa.c: Use target hook. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@84606 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8372af0..6c2ef13 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,61 @@ +2004-07-13 Richard Henderson + + * target-def.h (TARGET_MUST_PASS_IN_STACK): New. + * target.h (struct gcc_target): Add calls.must_pass_in_stack. + * expr.h (MUST_PASS_IN_STACK): Remove. + * system.h (MUST_PASS_IN_STACK): Poison. + * tree.h (must_pass_in_stack_var_size): Declare. + (must_pass_in_stack_var_size_or_pad): Declare. + * calls.c (must_pass_in_stack_var_size): New. + (must_pass_in_stack_var_size_or_pad): Rename from + default_must_pass_in_stack. + * config/alpha/alpha.c (unicosmk_must_pass_in_stack): New. + (TARGET_MUST_PASS_IN_STACK): New. + * config/alpha/unicosmk.h (MUST_PASS_IN_STACK): Remove. + * config/fr30/fr30.c (fr30_must_pass_in_stack): New. + (TARGET_MUST_PASS_IN_STACK): New. + * config/fr30/fr30.h (MUST_PASS_IN_STACK): Remove. + * config/frv/frv.c (frv_must_pass_in_stack): New. + (TARGET_MUST_PASS_IN_STACK): New. + * config/frv/frv.h (MUST_PASS_IN_STACK): Remove. + * config/i386/i386-protos.h (ix86_must_pass_in_stack): Remove. + * config/i386/i386.c (TARGET_MUST_PASS_IN_STACK): New. + (ix86_must_pass_in_stack): Make static. + * config/i386/i386.h (MUST_PASS_IN_STACK): Remove. + * config/ia64/ia64.c (TARGET_MUST_PASS_IN_STACK): New. + * config/ia64/ia64.h (MUST_PASS_IN_STACK): Remove. + * config/m32r/m32r.c (TARGET_MUST_PASS_IN_STACK): New. + * config/m32r/m32r.h (MUST_PASS_IN_STACK): Remove. + * config/mcore/mcore-protos.h (mcore_must_pass_on_stack): Remove. + * config/mcore/mcore.c (TARGET_MUST_PASS_IN_STACK): New. + (mcore_must_pass_on_stack): Remove. + * config/mcore/mcore.h (MUST_PASS_IN_STACK): Remove. + * config/mips/mips.c (TARGET_MUST_PASS_IN_STACK): New. + * config/mips/mips.h (MUST_PASS_IN_STACK): Remove. + * config/pa/pa.c (TARGET_MUST_PASS_IN_STACK): New. + * config/pa/pa.h (MUST_PASS_IN_STACK): Remove. + * config/rs6000/aix.h (MUST_PASS_IN_STACK): Remove. + * config/rs6000/linux64.h (MUST_PASS_IN_STACK): Remove. + * config/rs6000/rs6000.c (rs6000_must_pass_in_stack): New. + (TARGET_MUST_PASS_IN_STACK): New. + * config/sh/sh.c (TARGET_MUST_PASS_IN_STACK): New. + * config/sh/sh.h (MUST_PASS_IN_STACK): Remove. + * config/sparc/sparc.c (TARGET_MUST_PASS_IN_STACK): New. + * config/sparc/sparc.h (MUST_PASS_IN_STACK): Remove. + * config/xtensa/xtensa.c (TARGET_MUST_PASS_IN_STACK): New. + * config/xtensa/xtensa.h (MUST_PASS_IN_STACK): Remove. + * doc/tm.texi (TARGET_MUST_PASS_IN_STACK): Update from + MUST_PASS_IN_STACK. + + * calls.c, function.c, config/alpha/alpha.c, config/alpha/alpha.h, + config/alpha/unicosmk.h, config/alpha/vms.h, config/c4x/c4x.c, + config/cris/cris.h, config/fr30/fr30.c, config/fr30/fr30.h, + config/frv/frv.c, config/i386/i386.c, config/iq2000/iq2000.c, + config/mcore/mcore.c, config/mcore/mcore.h, config/mips/mips.c, + config/mmix/mmix.c, config/mmix/mmix.h, config/rs6000/rs6000.c, + config/sh/sh.c, config/sh/sh.h, config/stormy16/stormy16.c, + config/xtensa/xtensa.c: Use target hook. + 2004-07-13 Anthony Heading * configure.ac (gcc_cv_as_offsetable_lo10: Fix a typo. diff --git a/gcc/calls.c b/gcc/calls.c index c54ab48..e128162 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1097,7 +1097,7 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, = FUNCTION_ARG_PARTIAL_NREGS (*args_so_far, mode, type, argpos < n_named_args); - args[i].pass_on_stack = MUST_PASS_IN_STACK (mode, type); + args[i].pass_on_stack = targetm.calls.must_pass_in_stack (mode, type); /* If FUNCTION_ARG returned a (parallel [(expr_list (nil) ...) ...]), it means that we are to pass this arg in the register(s) designated @@ -4445,24 +4445,33 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags, return sibcall_failure; } -/* Nonzero if we do not know how to pass TYPE solely in registers. - We cannot do so in the following cases: +/* Nonzero if we do not know how to pass TYPE solely in registers. */ - - if the type has variable size - - if the type is marked as addressable (it is required to be constructed - into the stack) - - if the padding and mode of the type is such that a copy into a register - would put it into the wrong part of the register. +bool +must_pass_in_stack_var_size (enum machine_mode mode ATTRIBUTE_UNUSED, + tree type) +{ + if (!type) + return false; + + /* If the type has variable size... */ + if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + return true; - Which padding can't be supported depends on the byte endianness. + /* If the type is marked as addressable (it is required + to be constructed into the stack)... */ + if (TREE_ADDRESSABLE (type)) + return true; + + return false; +} - A value in a register is implicitly padded at the most significant end. - On a big-endian machine, that is the lower end in memory. - So a value padded in memory at the upper end can't go in a register. - For a little-endian machine, the reverse is true. */ +/* Another version of the TARGET_MUST_PASS_IN_STACK hook. This one + takes trailing padding of a structure into account. */ +/* ??? Should be able to merge these two by examining BLOCK_REG_PADDING. */ bool -default_must_pass_in_stack (enum machine_mode mode, tree type) +must_pass_in_stack_var_size_or_pad (enum machine_mode mode, tree type) { if (!type) return false; diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 19bf341..422d6c6 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -5842,7 +5842,8 @@ function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, tree type, return alpha_arg_info_reg_val (cum); num_args = cum.num_args; - if (num_args >= 6 || MUST_PASS_IN_STACK (mode, type)) + if (num_args >= 6 + || targetm.calls.must_pass_in_stack (mode, type)) return NULL_RTX; } #elif TARGET_ABI_UNICOSMK @@ -5885,8 +5886,9 @@ function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, tree type, size = ALPHA_ARG_SIZE (mode, type, named); num_args = cum.num_reg_words; - if (MUST_PASS_IN_STACK (mode, type) - || cum.num_reg_words + size > 6 || cum.force_stack) + if (cum.force_stack + || cum.num_reg_words + size > 6 + || targetm.calls.must_pass_in_stack (mode, type)) return NULL_RTX; else if (type && TYPE_MODE (type) == BLKmode) { @@ -5918,7 +5920,7 @@ function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, tree type, /* VOID is passed as a special flag for "last argument". */ if (type == void_type_node) basereg = 16; - else if (MUST_PASS_IN_STACK (mode, type)) + else if (targetm.calls.must_pass_in_stack (mode, type)) return NULL_RTX; else if (FUNCTION_ARG_PASS_BY_REFERENCE (cum, mode, type, named)) basereg = 16; @@ -6232,7 +6234,7 @@ alpha_gimplify_va_arg_1 (tree type, tree base, tree offset, tree *pre_p) /* If the type could not be passed in registers, skip the block reserved for the registers. */ - if (MUST_PASS_IN_STACK (TYPE_MODE (type), type)) + if (targetm.calls.must_pass_in_stack (TYPE_MODE (type), type)) { t = fold_convert (TREE_TYPE (offset), build_int_2 (6*8, 0)); t = build (MODIFY_EXPR, TREE_TYPE (offset), offset, @@ -9285,6 +9287,24 @@ alpha_use_linkage (rtx linkage ATTRIBUTE_UNUSED, #if TARGET_ABI_UNICOSMK +/* This evaluates to true if we do not know how to pass TYPE solely in + registers. This is the case for all arguments that do not fit in two + registers. */ + +static bool +unicosmk_must_pass_in_stack (enum machine_mode mode, tree type) +{ + if (type == NULL) + return false; + + if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + return true; + if (TREE_ADDRESSABLE (type)) + return true; + + return ALPHA_ARG_SIZE (mode, type, 0) > 2; +} + /* Define the offset between two registers, one to be eliminated, and the other its replacement, at the start of a routine. */ @@ -10078,6 +10098,8 @@ alpha_init_libfuncs (void) # define TARGET_ASM_UNIQUE_SECTION unicosmk_unique_section # undef TARGET_ASM_GLOBALIZE_LABEL # define TARGET_ASM_GLOBALIZE_LABEL hook_void_FILEptr_constcharptr +# undef TARGET_MUST_PASS_IN_STACK +# define TARGET_MUST_PASS_IN_STACK unicosmk_must_pass_in_stack #endif #undef TARGET_ASM_ALIGNED_HI_OP diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index 8dbdeb0..e142e5e 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -1040,10 +1040,9 @@ extern int alpha_memory_latency; (TYPE is null for libcalls where that information may not be available.) */ #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - if (MUST_PASS_IN_STACK (MODE, TYPE)) \ - (CUM) = 6; \ - else \ - (CUM) += ALPHA_ARG_SIZE (MODE, TYPE, NAMED) + ((CUM) += \ + (targetm.calls.must_pass_in_stack (MODE, TYPE)) \ + ? 6 : ALPHA_ARG_SIZE (MODE, TYPE, NAMED)) /* Determine where to put an argument to a function. Value is zero to push the argument on the stack, diff --git a/gcc/config/alpha/unicosmk.h b/gcc/config/alpha/unicosmk.h index d1dfe91..7c9a607 100644 --- a/gcc/config/alpha/unicosmk.h +++ b/gcc/config/alpha/unicosmk.h @@ -124,15 +124,6 @@ Boston, MA 02111-1307, USA. */ #define STACK_PARMS_IN_REG_PARM_AREA -/* This evaluates to nonzero if we do not know how to pass TYPE solely in - registers. This is the case for all arguments that do not fit in two - registers. */ - -#define MUST_PASS_IN_STACK(MODE,TYPE) \ - ((TYPE) != 0 \ - && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ - || (TREE_ADDRESSABLE (TYPE) || ALPHA_ARG_SIZE (MODE, TYPE, 0) > 2))) - /* Define a data type for recording info about an argument list during the scan of that argument list. This data type should hold all necessary information about the function itself @@ -198,8 +189,9 @@ do { \ \ size = ALPHA_ARG_SIZE (MODE, TYPE, NAMED); \ \ - if (size > 2 || MUST_PASS_IN_STACK (MODE, TYPE) \ - || (CUM).num_reg_words + size > 6) \ + if (size > 2 \ + || (CUM).num_reg_words + size > 6 \ + || targetm.calls.must_pass_in_stack (MODE, TYPE)) \ (CUM).force_stack = 1; \ \ if (! (CUM).force_stack) \ diff --git a/gcc/config/alpha/vms.h b/gcc/config/alpha/vms.h index f7058f3..b062d61 100644 --- a/gcc/config/alpha/vms.h +++ b/gcc/config/alpha/vms.h @@ -179,7 +179,7 @@ typedef struct {int num_args; enum avms_arg_type atypes[6];} avms_arg_info; #undef FUNCTION_ARG_ADVANCE #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - if (MUST_PASS_IN_STACK (MODE, TYPE)) \ + if (targetm.calls.must_pass_in_stack (MODE, TYPE)) \ (CUM).num_args += 6; \ else \ { \ diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c index dff0da4..bc384ee 100644 --- a/gcc/config/c4x/c4x.c +++ b/gcc/config/c4x/c4x.c @@ -575,7 +575,7 @@ c4x_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname) if ((mode = TYPE_MODE (type))) { - if (! MUST_PASS_IN_STACK (mode, type)) + if (! targetm.calls.must_pass_in_stack (mode, type)) { /* Look for float, double, or long double argument. */ if (mode == QFmode || mode == HFmode) @@ -612,7 +612,7 @@ c4x_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, if (! TARGET_MEMPARM && named && type - && ! MUST_PASS_IN_STACK (mode, type)) + && ! targetm.calls.must_pass_in_stack (mode, type)) { /* Look for float, double, or long double argument. */ if (mode == QFmode || mode == HFmode) @@ -678,7 +678,7 @@ c4x_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, if (! TARGET_MEMPARM && named && type - && ! MUST_PASS_IN_STACK (mode, type)) + && ! targetm.calls.must_pass_in_stack (mode, type)) { /* Look for float, double, or long double argument. */ if (mode == QFmode || mode == HFmode) diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h index 3eabb51..252992b 100644 --- a/gcc/config/cris/cris.h +++ b/gcc/config/cris/cris.h @@ -961,7 +961,7 @@ enum reg_class {NO_REGS, ALL_REGS, LIM_REG_CLASSES}; #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ (((CUM).regs == (CRIS_MAX_ARGS_IN_REGS - 1) \ - && !MUST_PASS_IN_STACK (MODE, TYPE) \ + && !targetm.calls.must_pass_in_stack (MODE, TYPE) \ && CRIS_FUNCTION_ARG_SIZE (MODE, TYPE) > 4 \ && CRIS_FUNCTION_ARG_SIZE (MODE, TYPE) <= 8) \ ? 1 : 0) @@ -970,7 +970,7 @@ enum reg_class {NO_REGS, ALL_REGS, LIM_REG_CLASSES}; bytes long. If you tweak this, don't forget to adjust cris_expand_builtin_va_arg. */ #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ - (MUST_PASS_IN_STACK (MODE, TYPE) \ + (targetm.calls.must_pass_in_stack (MODE, TYPE) \ || CRIS_FUNCTION_ARG_SIZE (MODE, TYPE) > 8) \ /* Contrary to what you'd believe, defining FUNCTION_ARG_CALLEE_COPIES diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c index d0213d2..017acfd 100644 --- a/gcc/config/fr30/fr30.c +++ b/gcc/config/fr30/fr30.c @@ -124,6 +124,7 @@ static struct fr30_frame_info zero_frame_info; static void fr30_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int); static tree fr30_gimplify_va_arg_expr (tree, tree, tree *, tree *); +static bool fr30_must_pass_in_stack (enum machine_mode, tree); #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM)) #define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM)) @@ -152,9 +153,11 @@ static tree fr30_gimplify_va_arg_expr (tree, tree, tree *, tree *); #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true - #undef TARGET_SETUP_INCOMING_VARARGS #define TARGET_SETUP_INCOMING_VARARGS fr30_setup_incoming_varargs +#undef TARGET_MUST_PASS_IN_STACK +#define TARGET_MUST_PASS_IN_STACK fr30_must_pass_in_stack + #undef TARGET_GIMPLIFY_VA_ARG_EXPR #define TARGET_GIMPLIFY_VA_ARG_EXPR fr30_gimplify_va_arg_expr @@ -664,6 +667,19 @@ fr30_print_operand (FILE *file, rtx x, int code) /*}}}*/ /*{{{ Function arguments */ +/* Return true if we should pass an argument on the stack rather than + in registers. */ + +static bool +fr30_must_pass_in_stack (enum machine_mode mode, tree type) +{ + if (mode == BLKmode) + return true; + if (type == NULL) + return false; + return AGGREGATE_TYPE_P (type); +} + /* Compute the number of word sized registers needed to hold a function argument of mode INT_MODE and tree type TYPE. */ int @@ -671,7 +687,7 @@ fr30_num_arg_regs (enum machine_mode mode, tree type) { int size; - if (MUST_PASS_IN_STACK (mode, type)) + if (targetm.calls.must_pass_in_stack (mode, type)) return 0; if (type && mode == BLKmode) diff --git a/gcc/config/fr30/fr30.h b/gcc/config/fr30/fr30.h index 1260075..b8bec8e 100644 --- a/gcc/config/fr30/fr30.h +++ b/gcc/config/fr30/fr30.h @@ -651,46 +651,13 @@ enum reg_class /*}}}*/ /*{{{ Function Arguments in Registers. */ -/* Nonzero if we do not know how to pass TYPE solely in registers. - We cannot do so in the following cases: - - - if the type has variable size - - if the type is marked as addressable (it is required to be constructed - into the stack) - - if the type is a structure or union. */ - -#define MUST_PASS_IN_STACK(MODE, TYPE) \ - (((MODE) == BLKmode) \ - || ((TYPE) != NULL \ - && TYPE_SIZE (TYPE) != NULL \ - && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ - || TREE_CODE (TYPE) == RECORD_TYPE \ - || TREE_CODE (TYPE) == UNION_TYPE \ - || TREE_CODE (TYPE) == QUAL_UNION_TYPE \ - || TREE_ADDRESSABLE (TYPE)))) - /* The number of register assigned to holding function arguments. */ #define FR30_NUM_ARG_REGS 4 -/* A C expression that controls whether a function argument is passed in a - register, and which register. - - The usual way to make the ANSI library `stdarg.h' work on a machine where - some arguments are usually passed in registers, is to cause nameless - arguments to be passed on the stack instead. This is done by making - `FUNCTION_ARG' return 0 whenever NAMED is 0. - - You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of - this macro to determine if this argument is of a type that must be passed in - the stack. If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG' - returns nonzero for such an argument, the compiler will abort. If - `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the - stack and then loaded into a register. */ - #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ ( (NAMED) == 0 ? NULL_RTX \ - : MUST_PASS_IN_STACK (MODE, TYPE) ? NULL_RTX \ + : targetm.calls.must_pass_in_stack (MODE, TYPE) ? NULL_RTX \ : (CUM) >= FR30_NUM_ARG_REGS ? NULL_RTX \ : gen_rtx_REG (MODE, CUM + FIRST_ARG_REGNUM)) @@ -727,18 +694,8 @@ enum reg_class #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ fr30_function_arg_partial_nregs (CUM, MODE, TYPE, NAMED) -/* A C expression that indicates when an argument must be passed by reference. - If nonzero for an argument, a copy of that argument is made in memory and a - pointer to the argument is passed instead of the argument itself. The - pointer is passed in whatever way is appropriate for passing a pointer to - that type. - - On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable - definition of this macro might be: - #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ - MUST_PASS_IN_STACK (MODE, TYPE) */ #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ - MUST_PASS_IN_STACK (MODE, TYPE) + targetm.calls.must_pass_in_stack (MODE, TYPE) /* A C statement (sans semicolon) for initializing the variable CUM for the state at the beginning of the argument list. The variable has type diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c index 9866320..4d05bd4 100644 --- a/gcc/config/frv/frv.c +++ b/gcc/config/frv/frv.c @@ -287,6 +287,7 @@ static void frv_output_const_unspec (FILE *, static bool frv_function_ok_for_sibcall (tree, tree); static rtx frv_struct_value_rtx (tree, int); static tree frv_gimplify_va_arg_expr (tree, tree, tree *, tree *); +static bool frv_must_pass_in_stack (enum machine_mode mode, tree type); /* Initialize the GCC target structure. */ #undef TARGET_ASM_FUNCTION_PROLOGUE @@ -327,6 +328,8 @@ static tree frv_gimplify_va_arg_expr (tree, tree, tree *, tree *); #undef TARGET_STRUCT_VALUE_RTX #define TARGET_STRUCT_VALUE_RTX frv_struct_value_rtx +#undef TARGET_MUST_PASS_IN_STACK +#define TARGET_MUST_PASS_IN_STACK frv_must_pass_in_stack #undef TARGET_EXPAND_BUILTIN_SAVEREGS #define TARGET_EXPAND_BUILTIN_SAVEREGS frv_expand_builtin_saveregs @@ -3026,6 +3029,19 @@ frv_init_cumulative_args (CUMULATIVE_ARGS *cum, } +/* Return true if we should pass an argument on the stack rather than + in registers. */ + +static bool +frv_must_pass_in_stack (enum machine_mode mode, tree type) +{ + if (mode == BLKmode) + return true; + if (type == NULL) + return false; + return AGGREGATE_TYPE_P (type); +} + /* If defined, a C expression that gives the alignment boundary, in bits, of an argument with the specified mode and type. If it is not defined, `PARM_BOUNDARY' is used for all arguments. */ @@ -3037,37 +3053,6 @@ frv_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED, return BITS_PER_WORD; } - -/* A C expression that controls whether a function argument is passed in a - register, and which register. - - The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes (in a way - defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE) all of the previous - arguments so far passed in registers; MODE, the machine mode of the argument; - TYPE, the data type of the argument as a tree node or 0 if that is not known - (which happens for C support library functions); and NAMED, which is 1 for an - ordinary argument and 0 for nameless arguments that correspond to `...' in the - called function's prototype. - - The value of the expression should either be a `reg' RTX for the hard - register in which to pass the argument, or zero to pass the argument on the - stack. - - For machines like the VAX and 68000, where normally all arguments are - pushed, zero suffices as a definition. - - The usual way to make the ANSI library `stdarg.h' work on a machine where - some arguments are usually passed in registers, is to cause nameless - arguments to be passed on the stack instead. This is done by making - `FUNCTION_ARG' return 0 whenever NAMED is 0. - - You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of - this macro to determine if this argument is of a type that must be passed in - the stack. If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG' - returns nonzero for such an argument, the compiler will abort. If - `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the - stack and then loaded into a register. */ - rtx frv_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, @@ -3177,25 +3162,13 @@ frv_function_arg_partial_nregs (CUMULATIVE_ARGS *cum, } - -/* A C expression that indicates when an argument must be passed by reference. - If nonzero for an argument, a copy of that argument is made in memory and a - pointer to the argument is passed instead of the argument itself. The - pointer is passed in whatever way is appropriate for passing a pointer to - that type. - - On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable - definition of this macro might be - #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ - MUST_PASS_IN_STACK (MODE, TYPE) */ - int frv_function_arg_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, enum machine_mode mode, tree type, int named ATTRIBUTE_UNUSED) { - return MUST_PASS_IN_STACK (mode, type); + return targetm.calls.must_pass_in_stack (mode, type); } /* If defined, a C expression that indicates when it is the called function's diff --git a/gcc/config/frv/frv.h b/gcc/config/frv/frv.h index 29d22e4..493ebc7 100644 --- a/gcc/config/frv/frv.h +++ b/gcc/config/frv/frv.h @@ -1860,58 +1860,10 @@ struct machine_function GTY(()) #define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0 -/* Function Arguments in Registers. */ - -/* Nonzero if we do not know how to pass TYPE solely in registers. - We cannot do so in the following cases: - - - if the type has variable size - - if the type is marked as addressable (it is required to be constructed - into the stack) - - if the type is a structure or union. */ - -#define MUST_PASS_IN_STACK(MODE,TYPE) \ - (((MODE) == BLKmode) \ - || ((TYPE) != 0 \ - && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ - || TREE_CODE (TYPE) == RECORD_TYPE \ - || TREE_CODE (TYPE) == UNION_TYPE \ - || TREE_CODE (TYPE) == QUAL_UNION_TYPE \ - || TREE_ADDRESSABLE (TYPE)))) - /* The number of register assigned to holding function arguments. */ #define FRV_NUM_ARG_REGS 6 -/* A C expression that controls whether a function argument is passed in a - register, and which register. - - The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes (in a way - defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE) all of the previous - arguments so far passed in registers; MODE, the machine mode of the argument; - TYPE, the data type of the argument as a tree node or 0 if that is not known - (which happens for C support library functions); and NAMED, which is 1 for an - ordinary argument and 0 for nameless arguments that correspond to `...' in the - called function's prototype. - - The value of the expression should either be a `reg' RTX for the hard - register in which to pass the argument, or zero to pass the argument on the - stack. - - For machines like the VAX and 68000, where normally all arguments are - pushed, zero suffices as a definition. - - The usual way to make the ANSI library `stdarg.h' work on a machine where - some arguments are usually passed in registers, is to cause nameless - arguments to be passed on the stack instead. This is done by making - `FUNCTION_ARG' return 0 whenever NAMED is 0. - - You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of - this macro to determine if this argument is of a type that must be passed in - the stack. If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG' - returns nonzero for such an argument, the compiler will abort. If - `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the - stack and then loaded into a register. */ #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ frv_function_arg (&CUM, MODE, TYPE, NAMED, FALSE) @@ -1949,16 +1901,6 @@ struct machine_function GTY(()) /* extern int frv_function_arg_partial_nregs (CUMULATIVE_ARGS, int, Tree, int); */ -/* A C expression that indicates when an argument must be passed by reference. - If nonzero for an argument, a copy of that argument is made in memory and a - pointer to the argument is passed instead of the argument itself. The - pointer is passed in whatever way is appropriate for passing a pointer to - that type. - - On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable - definition of this macro might be - #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ - MUST_PASS_IN_STACK (MODE, TYPE) */ #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ frv_function_arg_pass_by_reference (&CUM, MODE, TYPE, NAMED) diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 6cf6fe2..7fb122d 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -216,7 +216,6 @@ extern int x86_field_alignment (tree, int); #endif extern rtx ix86_tls_get_addr (void); -extern bool ix86_must_pass_in_stack (enum machine_mode mode, tree); extern void ix86_expand_vector_init (rtx, rtx); /* In winnt.c */ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index dafc60a..9b6e30e 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -928,6 +928,7 @@ static int extended_reg_mentioned_1 (rtx *, void *); static bool ix86_rtx_costs (rtx, int, int, int *); static int min_insn_size (rtx); static tree ix86_md_asm_clobbers (tree clobbers); +static bool ix86_must_pass_in_stack (enum machine_mode mode, tree type); #if defined (DO_GLOBAL_CTORS_BODY) && defined (HAS_INIT_SECTION) static void ix86_svr3_asm_out_constructor (rtx, int); @@ -1071,6 +1072,8 @@ static void init_ext_80387_constants (void); #define TARGET_STRUCT_VALUE_RTX ix86_struct_value_rtx #undef TARGET_SETUP_INCOMING_VARARGS #define TARGET_SETUP_INCOMING_VARARGS ix86_setup_incoming_varargs +#undef TARGET_MUST_PASS_IN_STACK +#define TARGET_MUST_PASS_IN_STACK ix86_must_pass_in_stack #undef TARGET_GIMPLIFY_VA_ARG_EXPR #define TARGET_GIMPLIFY_VA_ARG_EXPR ix86_gimplify_va_arg @@ -1905,6 +1908,16 @@ ix86_function_arg_regno_p (int regno) return false; } +/* Return if we do not know how to pass TYPE solely in registers. */ + +static bool +ix86_must_pass_in_stack (enum machine_mode mode, tree type) +{ + if (must_pass_in_stack_var_size_or_pad (mode, type)) + return true; + return (!TARGET_64BIT && type && mode == TImode); +} + /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. For a library call, FNTYPE is 0. */ @@ -2060,7 +2073,7 @@ classify_argument (enum machine_mode mode, tree type, return 0; if (mode != VOIDmode - && MUST_PASS_IN_STACK (mode, type)) + && targetm.calls.must_pass_in_stack (mode, type)) return 0; if (type && AGGREGATE_TYPE_P (type)) @@ -15848,15 +15861,6 @@ x86_emit_floatuns (rtx operands[2]) emit_label (donelab); } -/* Return if we do not know how to pass TYPE solely in registers. */ -bool -ix86_must_pass_in_stack (enum machine_mode mode, tree type) -{ - if (default_must_pass_in_stack (mode, type)) - return true; - return (!TARGET_64BIT && type && mode == TImode); -} - /* Initialize vector TARGET via VALS. */ void ix86_expand_vector_init (rtx target, rtx vals) diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 631922b..33cd861 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1662,13 +1662,6 @@ enum reg_class which. */ #define REG_PARM_STACK_SPACE(FNDECL) 0 -/* Define as a C expression that evaluates to nonzero if we do not know how - to pass TYPE solely in registers. The file expr.h defines a - definition that is usually appropriate, refer to expr.h for additional - documentation. If `REG_PARM_STACK_SPACE' is defined, the argument will be - computed in the stack and then loaded into a register. */ -#define MUST_PASS_IN_STACK(MODE, TYPE) ix86_must_pass_in_stack ((MODE), (TYPE)) - /* Value is the number of bytes of arguments automatically popped when returning from a subroutine call. FUNDECL is the declaration node of the function (as a tree), diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 3f03cab..51e410e 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -402,11 +402,12 @@ static const struct attribute_spec ia64_attribute_table[] = #define TARGET_STRUCT_VALUE_RTX ia64_struct_value_rtx #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY ia64_return_in_memory - #undef TARGET_SETUP_INCOMING_VARARGS #define TARGET_SETUP_INCOMING_VARARGS ia64_setup_incoming_varargs #undef TARGET_STRICT_ARGUMENT_NAMING #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true +#undef TARGET_MUST_PASS_IN_STACK +#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size #undef TARGET_GIMPLIFY_VA_ARG_EXPR #define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index 930266c..0e649e3 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -1328,13 +1328,6 @@ enum reg_class #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ ia64_function_arg_pass_by_reference (&CUM, MODE, TYPE, NAMED) -/* Nonzero if we do not know how to pass TYPE solely in registers. */ - -#define MUST_PASS_IN_STACK(MODE, TYPE) \ - ((TYPE) != 0 \ - && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ - || TREE_ADDRESSABLE (TYPE))) - /* A C type for declaring a variable that is used as the first argument of `FUNCTION_ARG' and other related values. For some target machines, the type `int' suffices and can hold the number of bytes of argument so far. */ diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c index ab7a7b5..ac9b5d1 100644 --- a/gcc/config/iq2000/iq2000.c +++ b/gcc/config/iq2000/iq2000.c @@ -2498,7 +2498,7 @@ function_arg_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, /* We must pass by reference if we would be both passing in registers and the stack. This is because any subsequent partial arg would be handled incorrectly in this case. */ - if (cum && MUST_PASS_IN_STACK (mode, type)) + if (cum && targetm.calls.must_pass_in_stack (mode, type)) { /* Don't pass the actual CUM to FUNCTION_ARG, because we would get double copies of any offsets generated for small structs diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c index 871369a..9bc3313 100644 --- a/gcc/config/m32r/m32r.c +++ b/gcc/config/m32r/m32r.c @@ -137,12 +137,13 @@ static tree m32r_gimplify_va_arg_expr (tree, tree, tree *, tree *); #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true - #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY m32r_return_in_memory - #undef TARGET_SETUP_INCOMING_VARARGS #define TARGET_SETUP_INCOMING_VARARGS m32r_setup_incoming_varargs +#undef TARGET_MUST_PASS_IN_STACK +#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size + #undef TARGET_GIMPLIFY_VA_ARG_EXPR #define TARGET_GIMPLIFY_VA_ARG_EXPR m32r_gimplify_va_arg_expr diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h index 4a2e01f..6300967 100644 --- a/gcc/config/m32r/m32r.h +++ b/gcc/config/m32r/m32r.h @@ -1033,12 +1033,6 @@ extern enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER]; SIZE is the number of bytes of arguments passed on the stack. */ #define RETURN_POPS_ARGS(DECL, FUNTYPE, SIZE) 0 -/* Nonzero if we do not know how to pass TYPE solely in registers. */ -#define MUST_PASS_IN_STACK(MODE, TYPE) \ - ((TYPE) != 0 \ - && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ - || TREE_ADDRESSABLE (TYPE))) - /* Define a data type for recording info about an argument list during the scan of that argument list. This data type should hold all necessary information about the function itself diff --git a/gcc/config/mcore/mcore-protos.h b/gcc/config/mcore/mcore-protos.h index 05272e7..ede6f93 100644 --- a/gcc/config/mcore/mcore-protos.h +++ b/gcc/config/mcore/mcore-protos.h @@ -38,7 +38,6 @@ extern int mcore_naked_function_p (void); #ifdef HAVE_MACHINE_MODES extern int mcore_function_arg_partial_nregs (CUMULATIVE_ARGS, enum machine_mode, tree, int); extern int mcore_num_arg_regs (enum machine_mode, tree); -extern int mcore_must_pass_on_stack (enum machine_mode, tree); #endif /* HAVE_MACHINE_MODES */ #ifdef RTX_CODE diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c index 97d06d0..7bad189 100644 --- a/gcc/config/mcore/mcore.c +++ b/gcc/config/mcore/mcore.c @@ -192,6 +192,8 @@ static bool mcore_return_in_memory (tree, tree); #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY mcore_return_in_memory +#undef TARGET_MUST_PASS_IN_STACK +#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size #undef TARGET_SETUP_INCOMING_VARARGS #define TARGET_SETUP_INCOMING_VARARGS mcore_setup_incoming_varargs @@ -3001,20 +3003,6 @@ mcore_override_options (void) target_flags |= M340_BIT; } -int -mcore_must_pass_on_stack (enum machine_mode mode ATTRIBUTE_UNUSED, tree type) -{ - if (type == NULL) - return 0; - - /* If the argument can have its address taken, it must - be placed on the stack. */ - if (TREE_ADDRESSABLE (type)) - return 1; - - return 0; -} - /* Compute the number of word sized registers needed to hold a function argument of mode MODE and type TYPE. */ @@ -3023,7 +3011,7 @@ mcore_num_arg_regs (enum machine_mode mode, tree type) { int size; - if (MUST_PASS_IN_STACK (mode, type)) + if (targetm.calls.must_pass_in_stack (mode, type)) return 0; if (type && mode == BLKmode) @@ -3118,7 +3106,7 @@ mcore_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, if (! named) return 0; - if (MUST_PASS_IN_STACK (mode, type)) + if (targetm.calls.must_pass_in_stack (mode, type)) return 0; arg_reg = ROUND_REG (cum, mode); @@ -3146,7 +3134,7 @@ mcore_function_arg_partial_nregs (CUMULATIVE_ARGS cum, enum machine_mode mode, if (named == 0) return 0; - if (MUST_PASS_IN_STACK (mode, type)) + if (targetm.calls.must_pass_in_stack (mode, type)) return 0; /* REG is not the *hardware* register number of the register that holds diff --git a/gcc/config/mcore/mcore.h b/gcc/config/mcore/mcore.h index b6e5d87..b026c14 100644 --- a/gcc/config/mcore/mcore.h +++ b/gcc/config/mcore/mcore.h @@ -662,9 +662,6 @@ extern const enum reg_class reg_class_from_letter[]; On the MCore, only r4 can return results. */ #define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == FIRST_RET_REG) -#define MUST_PASS_IN_STACK(MODE,TYPE) \ - mcore_must_pass_on_stack (MODE, TYPE) - /* 1 if N is a possible register number for function argument passing. */ #define FUNCTION_ARG_REGNO_P(REGNO) \ ((REGNO) >= FIRST_PARM_REG && (REGNO) < (NPARM_REGS + FIRST_PARM_REG)) @@ -721,7 +718,7 @@ extern const enum reg_class reg_class_from_letter[]; the argument itself. The pointer is passed in whatever way is appropriate for passing a pointer to that type. */ #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ - MUST_PASS_IN_STACK (MODE, TYPE) + targetm.calls.must_pass_in_stack (MODE, TYPE) /* For an arg passed partly in registers and partly in memory, this is the number of registers used. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index cad6e8d..cb470b4 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -738,6 +738,8 @@ const struct mips_cpu_info mips_cpu_info_table[] = { #define TARGET_SETUP_INCOMING_VARARGS mips_setup_incoming_varargs #undef TARGET_STRICT_ARGUMENT_NAMING #define TARGET_STRICT_ARGUMENT_NAMING mips_strict_argument_naming +#undef TARGET_MUST_PASS_IN_STACK +#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size struct gcc_target targetm = TARGET_INITIALIZER; @@ -3552,7 +3554,7 @@ mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode, even_reg_p = true; } - if (mips_abi != ABI_EABI && MUST_PASS_IN_STACK (mode, type)) + if (mips_abi != ABI_EABI && targetm.calls.must_pass_in_stack (mode, type)) /* This argument must be passed on the stack. Eat up all the remaining registers. */ info->reg_offset = MAX_ARGS_IN_REGISTERS; @@ -4284,7 +4286,7 @@ mips_va_arg (tree valist, tree type) /* If arguments of type TYPE must be passed on the stack, set MIN_OFFSET to the offset of the first stack parameter. */ - if (!MUST_PASS_IN_STACK (TYPE_MODE (type), type)) + if (!targetm.calls.must_pass_in_stack (TYPE_MODE (type), type)) min_offset = 0; else if (TARGET_NEWABI) min_offset = current_function_pretend_args_size; diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 829168d..04e6ee4 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -2364,14 +2364,6 @@ typedef struct mips_args { (mips_abi == ABI_EABI && (NAMED) \ && FUNCTION_ARG_PASS_BY_REFERENCE (CUM, MODE, TYPE, NAMED)) -/* Modified version of the macro in expr.h. Only return true if - the type has a variable size or if the front end requires it - to be passed by reference. */ -#define MUST_PASS_IN_STACK(MODE,TYPE) \ - ((TYPE) != 0 \ - && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ - || TREE_ADDRESSABLE (TYPE))) - /* True if using EABI and varargs can be passed in floating-point registers. Under these conditions, we need a more complex form of va_list, which tracks GPR, FPR and stack arguments separately. */ diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c index 9c7fb62..569acc2 100644 --- a/gcc/config/mmix/mmix.c +++ b/gcc/config/mmix/mmix.c @@ -578,7 +578,7 @@ mmix_function_arg (const CUMULATIVE_ARGS *argsp, : NULL_RTX; return (argsp->regs < MMIX_MAX_ARGS_IN_REGS - && !MUST_PASS_IN_STACK (mode, type) + && !targetm.calls.must_pass_in_stack (mode, type) && (GET_MODE_BITSIZE (mode) <= 64 || argsp->lib || TARGET_LIBFUNC)) @@ -599,10 +599,10 @@ mmix_function_arg_pass_by_reference (const CUMULATIVE_ARGS *argsp, tree type, int named ATTRIBUTE_UNUSED) { - /* FIXME: Check: I'm not sure the MUST_PASS_IN_STACK check is + /* FIXME: Check: I'm not sure the must_pass_in_stack check is necessary. */ return - MUST_PASS_IN_STACK (mode, type) + targetm.calls.must_pass_in_stack (mode, type) || (MMIX_FUNCTION_ARG_SIZE (mode, type) > 8 && !TARGET_LIBFUNC && !argsp->lib); diff --git a/gcc/config/mmix/mmix.h b/gcc/config/mmix/mmix.h index 7d2ca84..5d68fa7 100644 --- a/gcc/config/mmix/mmix.h +++ b/gcc/config/mmix/mmix.h @@ -740,7 +740,7 @@ typedef struct { int regs; int lib; } CUMULATIVE_ARGS; #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ ((CUM).regs \ - = ((MUST_PASS_IN_STACK (MODE, TYPE)) \ + = ((targetm.calls.must_pass_in_stack (MODE, TYPE)) \ || (MMIX_FUNCTION_ARG_SIZE (MODE, TYPE) > 8 \ && !TARGET_LIBFUNC && !(CUM).lib)) \ ? (MMIX_MAX_ARGS_IN_REGS) + 1 \ diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index ccc8f28..bbc27bd 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -265,6 +265,8 @@ static size_t n_deferred_plabels = 0; #define TARGET_STRUCT_VALUE_RTX pa_struct_value_rtx #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY pa_return_in_memory +#undef TARGET_MUST_PASS_IN_STACK +#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size #undef TARGET_EXPAND_BUILTIN_SAVEREGS #define TARGET_EXPAND_BUILTIN_SAVEREGS hppa_builtin_saveregs diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index f82e09b..dd6f356 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -890,12 +890,6 @@ struct hppa_args {int words, nargs_prototype, incoming, indirect; }; #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ function_arg (&CUM, MODE, TYPE, NAMED) -/* Nonzero if we do not know how to pass TYPE solely in registers. */ -#define MUST_PASS_IN_STACK(MODE,TYPE) \ - ((TYPE) != 0 \ - && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ - || TREE_ADDRESSABLE (TYPE))) - /* For an arg passed partly in registers and partly in memory, this is the number of registers used. For args passed entirely in registers or entirely in memory, zero. */ diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h index 8875207..38196d7 100644 --- a/gcc/config/rs6000/aix.h +++ b/gcc/config/rs6000/aix.h @@ -183,13 +183,6 @@ #define AGGREGATE_PADDING_FIXED 1 #define AGGREGATES_PAD_UPWARD_ALWAYS 1 -/* We don't want anything in the reg parm area being passed on the - stack. */ -#define MUST_PASS_IN_STACK(MODE, TYPE) \ - ((TYPE) != 0 \ - && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ - || TREE_ADDRESSABLE (TYPE))) - /* Specify padding for the last element of a block move between registers and memory. FIRST is nonzero if this is the only element. */ diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index a63cb5f..5ebc19c 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -259,16 +259,6 @@ #define AGGREGATE_PADDING_FIXED TARGET_64BIT #define AGGREGATES_PAD_UPWARD_ALWAYS 0 -/* We don't want anything in the reg parm area being passed on the - stack. */ -#define MUST_PASS_IN_STACK(MODE, TYPE) \ - ((TARGET_64BIT \ - && (TYPE) != 0 \ - && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ - || TREE_ADDRESSABLE (TYPE))) \ - || (!TARGET_64BIT \ - && default_must_pass_in_stack ((MODE), (TYPE)))) - /* Specify padding for the last element of a block move between registers and memory. FIRST is nonzero if this is the only element. */ diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 0722ed7..ea81e8b 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -744,6 +744,7 @@ static tree get_prev_label (tree function_name); static tree rs6000_build_builtin_va_list (void); static tree rs6000_gimplify_va_arg (tree, tree, tree *, tree *); +static bool rs6000_must_pass_in_stack (enum machine_mode, tree); /* Hash table stuff for keeping track of TOC entries. */ @@ -948,6 +949,8 @@ static const char alt_reg_names[][8] = #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_MUST_PASS_IN_STACK +#define TARGET_MUST_PASS_IN_STACK rs6000_must_pass_in_stack #undef TARGET_BUILD_BUILTIN_VA_LIST #define TARGET_BUILD_BUILTIN_VA_LIST rs6000_build_builtin_va_list @@ -4525,6 +4528,17 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, } } +/* Return true if TYPE must be passed on the stack and not in registers. */ + +static bool +rs6000_must_pass_in_stack (enum machine_mode mode, tree type) +{ + if (DEFAULT_ABI == ABI_AIX || TARGET_64BIT) + return must_pass_in_stack_var_size (mode, type); + else + return must_pass_in_stack_var_size_or_pad (mode, type); +} + /* If defined, a C expression which determines whether, and in which direction, to pad out an argument with extra space. The value should be of type `enum direction': either `upward' to pad above @@ -5261,7 +5275,7 @@ setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode, save_area = virtual_incoming_args_rtx; cfun->machine->sysv_varargs_p = 0; - if (MUST_PASS_IN_STACK (mode, type)) + if (targetm.calls.must_pass_in_stack (mode, type)) first_reg_offset += rs6000_arg_size (TYPE_MODE (type), type); } diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index dc16c61..4003f16 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -436,6 +436,8 @@ static tree sh_gimplify_va_arg_expr (tree, tree, tree *, tree *); #define TARGET_STRICT_ARGUMENT_NAMING sh_strict_argument_naming #undef TARGET_PRETEND_OUTGOING_VARARGS_NAMED #define TARGET_PRETEND_OUTGOING_VARARGS_NAMED sh_pretend_outgoing_varargs_named +#undef TARGET_MUST_PASS_IN_STACK +#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size #undef TARGET_BUILD_BUILTIN_VA_LIST #define TARGET_BUILD_BUILTIN_VA_LIST sh_build_builtin_va_list @@ -6316,7 +6318,7 @@ sh_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, HOST_WIDE_INT size, rsize; tree tmp, pptr_type_node; tree addr, lab_over, result = NULL; - int pass_by_ref = MUST_PASS_IN_STACK (TYPE_MODE (type), type); + int pass_by_ref = targetm.calls.must_pass_in_stack (TYPE_MODE (type), type); if (pass_by_ref) type = build_pointer_type (type); diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 360ba4a..a76bda1 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -1725,14 +1725,6 @@ extern enum reg_class reg_class_from_letter[]; On SHcompact, the call trampoline pops arguments off the stack. */ #define CALL_POPS_ARGS(CUM) (TARGET_SHCOMPACT ? (CUM).stack_regs * 8 : 0) -/* Nonzero if we do not know how to pass TYPE solely in registers. - Values that come in registers with inconvenient padding are stored - to memory at the function start. */ - -#define MUST_PASS_IN_STACK(MODE,TYPE) \ - ((TYPE) != 0 \ - && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ - || TREE_ADDRESSABLE (TYPE))) /* Some subroutine macros specific to this machine. */ #define BASE_RETURN_VALUE_REG(MODE) \ @@ -2046,7 +2038,7 @@ struct sh_args { registers are passed by reference, so that an SHmedia trampoline loads them into the full 64-bits registers. */ #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM,MODE,TYPE,NAMED) \ - (MUST_PASS_IN_STACK ((MODE), (TYPE)) \ + (targetm.calls.must_pass_in_stack ((MODE), (TYPE)) \ || SHCOMPACT_BYREF ((CUM), (MODE), (TYPE), (NAMED))) #define SHCOMPACT_BYREF(CUM, MODE, TYPE, NAMED) \ diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index e87b29e..8f73f1b 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -434,6 +434,8 @@ enum processor_type sparc_cpu; #define TARGET_STRUCT_VALUE_RTX sparc_struct_value_rtx #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY sparc_return_in_memory +#undef TARGET_MUST_PASS_IN_STACK +#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size #undef TARGET_EXPAND_BUILTIN_SAVEREGS #define TARGET_EXPAND_BUILTIN_SAVEREGS sparc_builtin_saveregs diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index d0f75d2..18de27f8 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -1713,13 +1713,6 @@ init_cumulative_args (& (CUM), (FNTYPE), (LIBNAME), (FNDECL)); #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ function_arg_advance (& (CUM), (MODE), (TYPE), (NAMED)) -/* Nonzero if we do not know how to pass TYPE solely in registers. */ - -#define MUST_PASS_IN_STACK(MODE,TYPE) \ - ((TYPE) != 0 \ - && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ - || TREE_ADDRESSABLE (TYPE))) - /* Determine where to put an argument to a function. Value is zero to push the argument on the stack, or a hard register in which to store the argument. diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c index e2fbf02..7f2a2fe 100644 --- a/gcc/config/stormy16/stormy16.c +++ b/gcc/config/stormy16/stormy16.c @@ -1229,7 +1229,7 @@ xstormy16_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, { if (mode == VOIDmode) return const0_rtx; - if (MUST_PASS_IN_STACK (mode, type) + if (targetm.calls.must_pass_in_stack (mode, type) || cum + XSTORMY16_WORD_SIZE (type, mode) > NUM_ARGUMENT_REGISTERS) return 0; return gen_rtx_REG (mode, cum + 2); @@ -1325,7 +1325,7 @@ xstormy16_expand_builtin_va_arg (tree valist, tree type, tree *pre_p, count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count, NULL_TREE); - must_stack = MUST_PASS_IN_STACK (TYPE_MODE (type), type); + must_stack = targetm.calls.must_pass_in_stack (TYPE_MODE (type), type); size_tree = round_up (size_in_bytes (type), UNITS_PER_WORD); gimplify_expr (&size_tree, pre_p, NULL, is_gimple_val, fb_rvalue); diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index f21930d..b3bd840 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -255,6 +255,8 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] = #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_MUST_PASS_IN_STACK +#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size #undef TARGET_EXPAND_BUILTIN_SAVEREGS #define TARGET_EXPAND_BUILTIN_SAVEREGS xtensa_builtin_saveregs @@ -2540,13 +2542,13 @@ xtensa_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, /* Check if the argument is in registers: if ((AP).__va_ndx <= __MAX_ARGS_IN_REGISTERS * 4 - && !MUST_PASS_IN_STACK (type)) + && !must_pass_in_stack (type)) __array = (AP).__va_reg; */ array = create_tmp_var (ptr_type_node, NULL); lab_over = NULL; - if (!MUST_PASS_IN_STACK (VOIDmode, type)) + if (!targetm.calls.must_pass_in_stack (TYPE_MODE (type), type)) { lab_false = create_artificial_label (); lab_over = create_artificial_label (); diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h index 41e64c6..1321448 100644 --- a/gcc/config/xtensa/xtensa.h +++ b/gcc/config/xtensa/xtensa.h @@ -774,22 +774,6 @@ typedef struct xtensa_args ? PARM_BOUNDARY \ : GET_MODE_ALIGNMENT (MODE))) -/* Nonzero if we do not know how to pass TYPE solely in registers. - We cannot do so in the following cases: - - - if the type has variable size - - if the type is marked as addressable (it is required to be constructed - into the stack) - - This differs from the default in that it does not check if the padding - and mode of the type are such that a copy into a register would put it - into the wrong part of the register. */ - -#define MUST_PASS_IN_STACK(MODE, TYPE) \ - ((TYPE) != 0 \ - && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ - || TREE_ADDRESSABLE (TYPE))) - /* 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 3bc86f3..28dfe7d 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -3669,9 +3669,9 @@ where some arguments are usually passed in registers, is to cause nameless arguments to be passed on the stack instead. This is done by making @code{FUNCTION_ARG} return 0 whenever @var{named} is 0. -@cindex @code{MUST_PASS_IN_STACK}, and @code{FUNCTION_ARG} +@cindex @code{TARGET_MUST_PASS_IN_STACK}, and @code{FUNCTION_ARG} @cindex @code{REG_PARM_STACK_SPACE}, and @code{FUNCTION_ARG} -You may use the macro @code{MUST_PASS_IN_STACK (@var{mode}, @var{type})} +You may use the hook @code{targetm.calls.must_pass_in_stack} in the definition of this macro to determine if this argument is of a type that must be passed in the stack. If @code{REG_PARM_STACK_SPACE} is not defined and @code{FUNCTION_ARG} returns nonzero for such an @@ -3680,12 +3680,12 @@ defined, the argument will be computed in the stack and then loaded into a register. @end defmac -@defmac MUST_PASS_IN_STACK (@var{mode}, @var{type}) -Define as a C expression that evaluates to nonzero if we do not know how -to pass TYPE solely in registers. The file @file{expr.h} defines a +@deftypefn {Target Hook} bool TARGET_MUST_PASS_IN_STACK (enum machine_mode @var{mode}, tree @var{type}) +This target hook should return @code{true} if we should not pass @var{type} +solely in registers. The file @file{expr.h} defines a definition that is usually appropriate, refer to @file{expr.h} for additional documentation. -@end defmac +@end deftypefn @defmac FUNCTION_INCOMING_ARG (@var{cum}, @var{mode}, @var{type}, @var{named}) Define this macro if the target machine has ``register windows'', so @@ -3734,7 +3734,7 @@ definition of this macro might be @smallexample #define FUNCTION_ARG_PASS_BY_REFERENCE\ (CUM, MODE, TYPE, NAMED) \ - MUST_PASS_IN_STACK (MODE, TYPE) + targetm.calls.must_pass_in_stack (MODE, TYPE) @end smallexample @c this is *still* too long. --mew 5feb93 @end defmac diff --git a/gcc/expr.h b/gcc/expr.h index 55106a2..687b6e3 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -218,12 +218,6 @@ do { \ tree split_complex_types (tree); tree split_complex_values (tree); -/* Nonzero if we do not know how to pass TYPE solely in registers. */ -extern bool default_must_pass_in_stack (enum machine_mode, tree); -#ifndef MUST_PASS_IN_STACK -#define MUST_PASS_IN_STACK(MODE,TYPE) default_must_pass_in_stack(MODE, TYPE) -#endif - /* Supply a default definition of STACK_SAVEAREA_MODE for emit_stack_save. Normally move_insn, so Pmode stack pointer. */ diff --git a/gcc/function.c b/gcc/function.c index 19549b1..19698f9 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -2356,7 +2356,8 @@ assign_parm_find_entry_rtl (struct assign_parm_data_all *all, /* If this parameter was passed both in registers and in the stack, use the copy on the stack. */ - if (MUST_PASS_IN_STACK (data->promoted_mode, data->passed_type)) + if (targetm.calls.must_pass_in_stack (data->promoted_mode, + data->passed_type)) entry_parm = 0; if (entry_parm) diff --git a/gcc/system.h b/gcc/system.h index 367c51e..ce8f3ec 100644 --- a/gcc/system.h +++ b/gcc/system.h @@ -584,7 +584,8 @@ extern int snprintf (char *, size_t, const char *, ...); PROMOTE_FUNCTION_RETURN PROMOTE_PROTOTYPES STRUCT_VALUE_REGNUM \ SETUP_INCOMING_VARARGS EXPAND_BUILTIN_SAVEREGS \ DEFAULT_SHORT_ENUMS SPLIT_COMPLEX_ARGS MD_ASM_CLOBBERS \ - HANDLE_PRAGMA_REDEFINE_EXTNAME HANDLE_PRAGMA_EXTERN_PREFIX + HANDLE_PRAGMA_REDEFINE_EXTNAME HANDLE_PRAGMA_EXTERN_PREFIX \ + MUST_PASS_IN_STACK /* 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 14943da..329e44b 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -364,6 +364,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define TARGET_LATE_RTL_PROLOGUE_EPILOGUE false +#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size_or_pad + #define TARGET_CALLS { \ TARGET_PROMOTE_FUNCTION_ARGS, \ TARGET_PROMOTE_FUNCTION_RETURN, \ @@ -376,6 +378,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. TARGET_STRICT_ARGUMENT_NAMING, \ TARGET_PRETEND_OUTGOING_VARARGS_NAMED, \ TARGET_SPLIT_COMPLEX_ARG, \ + TARGET_MUST_PASS_IN_STACK \ } diff --git a/gcc/target.h b/gcc/target.h index befe67b..2c38dc5 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -462,6 +462,12 @@ struct gcc_target /* 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); + + /* Return true if type T, mode MODE, may not be passed in registers, + but must be passed on the stack. */ + /* ??? This predicate should be applied strictly after pass-by-reference. + Need audit to verify that this is the case. */ + bool (* must_pass_in_stack) (enum machine_mode mode, tree t); } calls; /* Functions specific to the C++ frontend. */ diff --git a/gcc/tree.h b/gcc/tree.h index 75f4f28..d2b06b3 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3567,6 +3567,8 @@ extern int call_expr_flags (tree); extern int setjmp_call_p (tree); extern bool alloca_call_p (tree); +extern bool must_pass_in_stack_var_size (enum machine_mode, tree); +extern bool must_pass_in_stack_var_size_or_pad (enum machine_mode, tree); /* In attribs.c. */