* 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.
From-SVN: r84606
+2004-07-13 Richard Henderson <rth@redhat.com>
+
+ * 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 <aheading@jpmorgan.com>
* configure.ac (gcc_cv_as_offsetable_lo10: Fix a typo.
= 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
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;
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
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)
{
/* 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;
/* 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,
\f
#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. */
# 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
(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,
#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
\
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) \
#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 \
{ \
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)
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)
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)
#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)
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
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))
#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
/*}}}*/
/*{{{ 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
{
int size;
- if (MUST_PASS_IN_STACK (mode, type))
+ if (targetm.calls.must_pass_in_stack (mode, type))
return 0;
if (type && mode == BLKmode)
/*}}}*/ \f
/*{{{ 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))
#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
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);
\f
/* Initialize the GCC target structure. */
#undef TARGET_ASM_FUNCTION_PROLOGUE
#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
}
\f
+/* 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. */
return BITS_PER_WORD;
}
-\f
-/* 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,
}
\f
-
-/* 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
#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
\f
-/* 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)
/* 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)
#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 */
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);
#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
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. */
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))
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)
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),
#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
#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. */
/* 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
#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
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
#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
#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
target_flags |= M340_BIT;
}
\f
-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. */
{
int size;
- if (MUST_PASS_IN_STACK (mode, type))
+ if (targetm.calls.must_pass_in_stack (mode, type))
return 0;
if (type && mode == BLKmode)
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);
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
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))
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.
#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;
\f
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;
/* 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;
(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. */
: 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))
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);
#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 \
#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
#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. */
#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. */
#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. */
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. */
#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
}
}
\f
+/* 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
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);
}
#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
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);
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) \
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) \
#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
#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.
{
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);
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);
#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
/* 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 ();
? 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.,
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
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
@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
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. */
/* 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)
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
#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, \
TARGET_STRICT_ARGUMENT_NAMING, \
TARGET_PRETEND_OUTGOING_VARARGS_NAMED, \
TARGET_SPLIT_COMPLEX_ARG, \
+ TARGET_MUST_PASS_IN_STACK \
}
/* 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. */
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. */