+2017-09-04 Richard Sandiford <richard.sandiford@linaro.org>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
+ * coretypes.h (pad_direction): New enum.
+ * defaults.h (DEFAULT_FUNCTION_ARG_PADDING): Delete.
+ (FUNCTION_ARG_PADDING): Likewise.
+ * target.def (function_arg_padding): New hook.
+ * targhooks.h (default_function_arg_padding): Declare.
+ * targhooks.c (default_function_arg_padding): New function.
+ * doc/tm.texi.in (FUNCTION_ARG_PADDING): Replace with...
+ (TARGET_FUNCTION_ARG_PADDING): ...this.
+ * doc/tm.texi: Regenerate.
+ * calls.c (store_unaligned_arguments_into_pseudos): Use pad_direction
+ instead of direction.
+ (compute_argument_addresses): Likewise.
+ (load_register_parameters): Likewise.
+ (emit_library_call_value_1): Likewise.
+ (store_one_arg): Use targetm.calls.function_arg_padding instead
+ of FUNCTION_ARG_PADDING.
+ (must_pass_in_stack_var_size_or_pad): Likewise.
+ * expr.c (emit_group_load_1): Use pad_direction instead of direction.
+ (emit_group_store): Likewise.
+ (emit_single_push_insn_1): Use targetm.calls.function_arg_padding
+ instead of FUNCTION_ARG_PADDING.
+ (emit_push_insn): Likewise, and propagate enum change throughout
+ function.
+ * function.h (direction): Delete.
+ (locate_and_pad_arg_data::where_pad): Use pad_direction instead
+ of direction.
+ * function.c (assign_parm_find_stack_rtl): Likewise.
+ (assign_parm_setup_block_p): Likewise.
+ (assign_parm_setup_block): Likewise.
+ (gimplify_parameters): Likewise.
+ (locate_and_pad_parm): Use targetm.calls.function_arg_padding
+ instead of FUNCTION_ARG_PADDING, and propagate enum change throughout
+ function.
+ * config/aarch64/aarch64.h (FUNCTION_ARG_PADDING): Delete.
+ (BLOCK_REG_PADDING): Use pad_direction instead of direction.
+ * config/aarch64/aarch64-protos.h (aarch64_pad_arg_upward): Delete.
+ * config/aarch64/aarch64.c (aarch64_pad_arg_upward): Replace with...
+ (aarch64_function_arg_padding): ...this new function.
+ (aarch64_gimplify_va_arg_expr): Use pad_direction instead of direction.
+ (TARGET_FUNCTION_ARG_PADDING): Redefine.
+ * config/arm/arm.h (FUNCTION_ARG_PADDING): Delete.
+ (BLOCK_REG_PADDING): Use pad_direction instead of direction.
+ * config/arm/arm-protos.h (arm_pad_arg_upward): Delete.
+ * config/arm/arm.c (TARGET_FUNCTION_ARG_PADDING): Redefine.
+ (arm_pad_arg_upward): Replace with...
+ (arm_function_arg_padding): ...this new function.
+ * config/c6x/c6x.h (BLOCK_REG_PADDING): Use pad_direction instead
+ of direction.
+ * config/ia64/hpux.h (FUNCTION_ARG_PADDING): Delete.
+ * config/ia64/ia64-protos.h (ia64_hpux_function_arg_padding): Delete.
+ * config/ia64/ia64.c (TARGET_FUNCTION_ARG_PADDING): Redefine.
+ (ia64_hpux_function_arg_padding): Replace with...
+ (ia64_function_arg_padding): ...this new function. Use pad_direction
+ instead of direction. Check for TARGET_HPUX.
+ * config/iq2000/iq2000.h (FUNCTION_ARG_PADDING): Delete.
+ * config/iq2000/iq2000.c (TARGET_FUNCTION_ARG_PADDING): Redefine.
+ (iq2000_function_arg_padding): New function.
+ * config/mips/mips-protos.h (mips_pad_arg_upward): Delete.
+ * config/mips/mips.c (mips_pad_arg_upward): Replace with...
+ (mips_function_arg_padding): ...this new function.
+ (mips_pad_reg_upward): Update accordingly.
+ (TARGET_FUNCTION_ARG_PADDING): Redefine.
+ * config/mips/mips.h (PAD_VARARGS_DOWN): Use
+ targetm.calls.function_arg_padding.
+ (FUNCTION_ARG_PADDING): Delete.
+ (BLOCK_REG_PADDING): Use pad_direction instead of direction.
+ * config/nios2/nios2.h (FUNCTION_ARG_PADDING): Delete.
+ (PAD_VARARGS_DOWN): Use targetm.calls.function_arg_padding.
+ * config/nios2/nios2-protos.h (nios2_function_arg_padding): Delete.
+ (nios2_block_reg_padding): Return pad_direction instead of direction.
+ * config/nios2/nios2.c (nios2_block_reg_padding): Return pad_direction
+ instead of direction.
+ (nios2_function_arg_padding): Likewise. Make static.
+ (TARGET_FUNCTION_ARG_PADDING): Redefine.
+ * config/pa/pa.h (FUNCTION_ARG_PADDING): Delete.
+ (BLOCK_REG_PADDING): Use targetm.calls.function_arg_padding.
+ * config/pa/pa-protos.h (pa_function_arg_padding): Delete.
+ * config/pa/pa.c (TARGET_FUNCTION_ARG_PADDING): Redefine.
+ (pa_function_arg_padding): Make static. Return pad_direction instead
+ of direction.
+ * config/powerpcspe/powerpcspe.h (FUNCTION_ARG_PADDING): Delete.
+ (PAD_VARARGS_DOWN): Use targetm.calls.function_arg_padding.
+ * config/powerpcspe/aix.h (BLOCK_REG_PADDING): Use pad_direction
+ instead of direction. Use targetm.calls.function_arg_padding.
+ * config/powerpcspe/darwin.h (BLOCK_REG_PADDING): Likewise.
+ * config/powerpcspe/freebsd64.h (BLOCK_REG_PADDING): Likewise.
+ * config/powerpcspe/linux64.h (BLOCK_REG_PADDING): Likewise.
+ * config/powerpcspe/powerpcspe-protos.h (function_arg_padding): Delete.
+ * config/powerpcspe/powerpcspe.c (TARGET_FUNCTION_ARG_PADDING):
+ Redefine.
+ (function_arg_padding): Rename to...
+ (rs6000_function_arg_padding): ...this. Make static. Return
+ pad_direction instead of direction.
+ (rs6000_return_in_msb): Use rs6000_function_arg_padding.
+ * config/rs6000/rs6000.h (FUNCTION_ARG_PADDING): Delete.
+ (PAD_VARARGS_DOWN): Use targetm.calls.function_arg_padding.
+ * config/rs6000/aix.h (BLOCK_REG_PADDING): Use pad_direction
+ instead of direction. Use targetm.calls.function_arg_padding.
+ * config/rs6000/darwin.h (BLOCK_REG_PADDING): Likewise.
+ * config/rs6000/freebsd64.h (BLOCK_REG_PADDING): Likewise.
+ * config/rs6000/linux64.h (BLOCK_REG_PADDING): Likewise.
+ * config/rs6000/rs6000-protos.h (function_arg_padding): Delete.
+ * config/rs6000/rs6000.c (TARGET_FUNCTION_ARG_PADDING): Redefine.
+ (function_arg_padding): Rename to...
+ (rs6000_function_arg_padding): ...this. Make static. Return
+ pad_direction instead of direction.
+ (rs6000_return_in_msb): Use rs6000_function_arg_padding.
+ * config/s390/s390.h (FUNCTION_ARG_PADDING): Delete.
+ * config/s390/s390.c (s390_function_arg_padding): New function.
+ (TARGET_FUNCTION_ARG_PADDING): Redefine.
+ * config/sparc/sparc.h (FUNCTION_ARG_PADDING): Delete.
+ * config/sparc/sparc-protos.h (function_arg_padding): Delete.
+ * config/sparc/sparc.c (TARGET_FUNCTION_ARG_PADDING): Redefine.
+ (function_arg_padding): Rename to...
+ (sparc_function_arg_padding): ...this. Make static. Return
+ pad_direction instead of direction.
+ * config/spu/spu.h (FUNCTION_ARG_PADDING): Delete.
+ * config/spu/spu.c (spu_function_arg_padding): New function.
+ (TARGET_FUNCTION_ARG_PADDING): Redefine.
+ * system.h (FUNCTION_ARG_PADDING): Poison.
+
2017-09-04 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
#ifdef BLOCK_REG_PADDING
&& (BLOCK_REG_PADDING (args[i].mode,
TREE_TYPE (args[i].tree_value), 1)
- == downward)
+ == PAD_DOWNWARD)
#else
&& BYTES_BIG_ENDIAN
#endif
}
align = BITS_PER_UNIT;
boundary = args[i].locate.boundary;
- if (args[i].locate.where_pad != downward)
+ if (args[i].locate.where_pad != PAD_DOWNWARD)
align = boundary;
else if (CONST_INT_P (offset))
{
upward on a BYTES_BIG_ENDIAN machine. */
if (size < UNITS_PER_WORD
&& (args[i].locate.where_pad
- == (BYTES_BIG_ENDIAN ? upward : downward)))
+ == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
{
rtx x;
int shift = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
/* Handle a BLKmode that needs shifting. */
if (nregs == 1 && size < UNITS_PER_WORD
#ifdef BLOCK_REG_PADDING
- && args[i].locate.where_pad == downward
+ && args[i].locate.where_pad == PAD_DOWNWARD
#else
&& BYTES_BIG_ENDIAN
#endif
upward on a BYTES_BIG_ENDIAN machine. */
if (size < UNITS_PER_WORD
&& (argvec[argnum].locate.where_pad
- == (BYTES_BIG_ENDIAN ? upward : downward)))
+ == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
{
rtx x;
int shift = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
/* Compute how much space the argument should get:
round up to a multiple of the alignment for arguments. */
- if (none != FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)))
+ if (targetm.calls.function_arg_padding (arg->mode, TREE_TYPE (pval))
+ != PAD_NONE)
used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
/ (PARM_BOUNDARY / BITS_PER_UNIT))
* (PARM_BOUNDARY / BITS_PER_UNIT));
/* Compute the alignment of the pushed argument. */
parm_align = arg->locate.boundary;
- if (FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)) == downward)
+ if (targetm.calls.function_arg_padding (arg->mode, TREE_TYPE (pval))
+ == PAD_DOWNWARD)
{
int pad = used - size;
if (pad)
/* When an argument is padded down, the block is aligned to
PARM_BOUNDARY, but the actual argument isn't. */
- if (FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)) == downward)
+ if (targetm.calls.function_arg_padding (arg->mode, TREE_TYPE (pval))
+ == PAD_DOWNWARD)
{
if (arg->locate.size.var)
parm_align = BITS_PER_UNIT;
a register would put it into the wrong part of the register. */
if (mode == BLKmode
&& int_size_in_bytes (type) % (PARM_BOUNDARY / BITS_PER_UNIT)
- && (FUNCTION_ARG_PADDING (mode, type)
- == (BYTES_BIG_ENDIAN ? upward : downward)))
+ && (targetm.calls.function_arg_padding (mode, type)
+ == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
return true;
return false;
bool aarch64_offset_7bit_signed_scaled_p (machine_mode, HOST_WIDE_INT);
char *aarch64_output_scalar_simd_mov_immediate (rtx, machine_mode);
char *aarch64_output_simd_mov_immediate (rtx, machine_mode, unsigned);
-bool aarch64_pad_arg_upward (machine_mode, const_tree);
bool aarch64_pad_reg_upward (machine_mode, const_tree, bool);
bool aarch64_regno_ok_for_base_p (int, bool);
bool aarch64_regno_ok_for_index_p (int, bool);
return MIN (MAX (alignment, PARM_BOUNDARY), STACK_BOUNDARY);
}
-/* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
-
- Return true if an argument passed on the stack should be padded upwards,
- i.e. if the least-significant byte of the stack slot has useful data.
+/* Implement TARGET_FUNCTION_ARG_PADDING.
Small aggregate types are placed in the lowest memory address.
The related parameter passing rules are B.4, C.3, C.5 and C.14. */
-bool
-aarch64_pad_arg_upward (machine_mode mode, const_tree type)
+static pad_direction
+aarch64_function_arg_padding (machine_mode mode, const_tree type)
{
/* On little-endian targets, the least significant byte of every stack
argument is passed at the lowest byte address of the stack slot. */
if (!BYTES_BIG_ENDIAN)
- return true;
+ return PAD_UPWARD;
/* Otherwise, integral, floating-point and pointer types are padded downward:
the least significant byte of a stack argument is passed at the highest
? (INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type)
|| POINTER_TYPE_P (type))
: (SCALAR_INT_MODE_P (mode) || SCALAR_FLOAT_MODE_P (mode)))
- return false;
+ return PAD_DOWNWARD;
/* Everything else padded upward, i.e. data in first byte of stack slot. */
- return true;
+ return PAD_UPWARD;
}
/* Similarly, for use by BLOCK_REG_PADDING (MODE, TYPE, FIRST).
if (BYTES_BIG_ENDIAN && GET_MODE_SIZE (ag_mode) < UNITS_PER_VREG)
adjust = UNITS_PER_VREG - GET_MODE_SIZE (ag_mode);
}
- else if (BLOCK_REG_PADDING (mode, type, 1) == downward
+ else if (BLOCK_REG_PADDING (mode, type, 1) == PAD_DOWNWARD
&& size < UNITS_PER_VREG)
{
adjust = UNITS_PER_VREG - size;
if (align > 8)
dw_align = true;
- if (BLOCK_REG_PADDING (mode, type, 1) == downward
+ if (BLOCK_REG_PADDING (mode, type, 1) == PAD_DOWNWARD
&& size < UNITS_PER_WORD)
{
adjust = UNITS_PER_WORD - size;
/* String up with arg */
on_stack = build2 (COMPOUND_EXPR, TREE_TYPE (arg), t, arg);
/* Big-endianness related address adjustment. */
- if (BLOCK_REG_PADDING (mode, type, 1) == downward
+ if (BLOCK_REG_PADDING (mode, type, 1) == PAD_DOWNWARD
&& size < UNITS_PER_WORD)
{
t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (arg), arg,
#undef TARGET_FUNCTION_ARG_BOUNDARY
#define TARGET_FUNCTION_ARG_BOUNDARY aarch64_function_arg_boundary
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING aarch64_function_arg_padding
+
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL aarch64_function_ok_for_sibcall
} CUMULATIVE_ARGS;
#endif
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
- (aarch64_pad_arg_upward (MODE, TYPE) ? upward : downward)
-
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- (aarch64_pad_reg_upward (MODE, TYPE, FIRST) ? upward : downward)
+ (aarch64_pad_reg_upward (MODE, TYPE, FIRST) ? PAD_UPWARD : PAD_DOWNWARD)
#define PAD_VARARGS_DOWN 0
#if defined TREE_CODE
extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
-extern bool arm_pad_arg_upward (machine_mode, const_tree);
extern bool arm_pad_reg_upward (machine_mode, tree, int);
#endif
extern int arm_apply_result_size (void);
const_tree, bool);
static void arm_function_arg_advance (cumulative_args_t, machine_mode,
const_tree, bool);
+static pad_direction arm_function_arg_padding (machine_mode, const_tree);
static unsigned int arm_function_arg_boundary (machine_mode, const_tree);
static rtx aapcs_allocate_return_reg (machine_mode, const_tree,
const_tree);
#define TARGET_FUNCTION_ARG arm_function_arg
#undef TARGET_FUNCTION_ARG_ADVANCE
#define TARGET_FUNCTION_ARG_ADVANCE arm_function_arg_advance
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING arm_function_arg_padding
#undef TARGET_FUNCTION_ARG_BOUNDARY
#define TARGET_FUNCTION_ARG_BOUNDARY arm_function_arg_boundary
}
-/* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
- Return true if an argument passed on the stack should be padded upwards,
- i.e. if the least-significant byte has useful data.
- For legacy APCS ABIs we use the default. For AAPCS based ABIs small
- aggregate types are placed in the lowest memory address. */
+/* Implement TARGET_FUNCTION_ARG_PADDING; return PAD_UPWARD if the lowest
+ byte of a stack argument has useful data. For legacy APCS ABIs we use
+ the default. For AAPCS based ABIs small aggregate types are placed
+ in the lowest memory address. */
-bool
-arm_pad_arg_upward (machine_mode mode ATTRIBUTE_UNUSED, const_tree type)
+static pad_direction
+arm_function_arg_padding (machine_mode mode, const_tree type)
{
if (!TARGET_AAPCS_BASED)
- return DEFAULT_FUNCTION_ARG_PADDING(mode, type) == upward;
+ return default_function_arg_padding (mode, type);
if (type && BYTES_BIG_ENDIAN && INTEGRAL_TYPE_P (type))
- return false;
+ return PAD_DOWNWARD;
- return true;
+ return PAD_UPWARD;
}
} CUMULATIVE_ARGS;
#endif
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
- (arm_pad_arg_upward (MODE, TYPE) ? upward : downward)
-
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- (arm_pad_reg_upward (MODE, TYPE, FIRST) ? upward : downward)
+ (arm_pad_reg_upward (MODE, TYPE, FIRST) ? PAD_UPWARD : PAD_DOWNWARD)
/* For AAPCS, padding should never be below the argument. For other ABIs,
* mimic the default. */
c6x_init_cumulative_args (&cum, fntype, libname, n_named_args)
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- (c6x_block_reg_pad_upward (MODE, TYPE, FIRST) ? upward : downward)
+ (c6x_block_reg_pad_upward (MODE, TYPE, FIRST) ? PAD_UPWARD : PAD_DOWNWARD)
#define FUNCTION_ARG_REGNO_P(r) \
(((r) >= REG_A4 && (r) <= REG_A13) || ((r) >= REG_B4 && (r) <= REG_B13))
ASM_OUTPUT_TYPE_DIRECTIVE (FILE, XSTR (FUN, 0), "function"); \
} while (0)
-#undef FUNCTION_ARG_PADDING
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
- ia64_hpux_function_arg_padding ((MODE), (TYPE))
-
#undef PAD_VARARGS_DOWN
#define PAD_VARARGS_DOWN (!AGGREGATE_TYPE_P (type))
extern rtx ia64_return_addr_rtx (HOST_WIDE_INT, rtx);
extern void ia64_split_return_addr_rtx (rtx);
-#ifdef ARGS_SIZE_RTX
-/* expr.h defines ARGS_SIZE_RTX and `enum direction'. */
-extern enum direction ia64_hpux_function_arg_padding (machine_mode, const_tree);
-#endif /* ARGS_SIZE_RTX */
-
extern void ia64_hpux_handle_builtin_pragma (struct cpp_reader *);
extern void ia64_output_function_profiler (FILE *, int);
extern void ia64_profile_hook (int);
machine_mode, const_tree, bool);
static void ia64_function_arg_advance (cumulative_args_t, machine_mode,
const_tree, bool);
+static pad_direction ia64_function_arg_padding (machine_mode, const_tree);
static unsigned int ia64_function_arg_boundary (machine_mode,
const_tree);
static bool ia64_function_ok_for_sibcall (tree, tree);
#define TARGET_FUNCTION_INCOMING_ARG ia64_function_incoming_arg
#undef TARGET_FUNCTION_ARG_ADVANCE
#define TARGET_FUNCTION_ARG_ADVANCE ia64_function_arg_advance
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING ia64_function_arg_padding
#undef TARGET_FUNCTION_ARG_BOUNDARY
#define TARGET_FUNCTION_ARG_BOUNDARY ia64_function_arg_boundary
return ia64_builtins[code];
}
-/* For the HP-UX IA64 aggregate parameters are passed stored in the
+/* Implement TARGET_FUNCTION_ARG_PADDING.
+
+ For the HP-UX IA64 aggregate parameters are passed stored in the
most significant bits of the stack slot. */
-enum direction
-ia64_hpux_function_arg_padding (machine_mode mode, const_tree type)
+static pad_direction
+ia64_function_arg_padding (machine_mode mode, const_tree type)
{
- /* Exception to normal case for structures/unions/etc. */
-
- if (type && AGGREGATE_TYPE_P (type)
- && int_size_in_bytes (type) < UNITS_PER_WORD)
- return upward;
+ /* Exception to normal case for structures/unions/etc. */
+ if (TARGET_HPUX
+ && type
+ && AGGREGATE_TYPE_P (type)
+ && int_size_in_bytes (type) < UNITS_PER_WORD)
+ return PAD_UPWARD;
- /* Fall back to the default. */
- return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
+ /* Fall back to the default. */
+ return default_function_arg_padding (mode, type);
}
/* Emit text to declare externally defined variables and functions, because
machine_mode, const_tree, bool);
static void iq2000_function_arg_advance (cumulative_args_t,
machine_mode, const_tree, bool);
+static pad_direction iq2000_function_arg_padding (machine_mode, const_tree);
static unsigned int iq2000_function_arg_boundary (machine_mode,
const_tree);
static void iq2000_va_start (tree, rtx);
#define TARGET_FUNCTION_ARG iq2000_function_arg
#undef TARGET_FUNCTION_ARG_ADVANCE
#define TARGET_FUNCTION_ARG_ADVANCE iq2000_function_arg_advance
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING iq2000_function_arg_padding
#undef TARGET_FUNCTION_ARG_BOUNDARY
#define TARGET_FUNCTION_ARG_BOUNDARY iq2000_function_arg_boundary
return ret;
}
+/* Implement TARGET_FUNCTION_ARG_PADDING. */
+
+static pad_direction
+iq2000_function_arg_padding (machine_mode mode, const_tree type)
+{
+ return (! BYTES_BIG_ENDIAN
+ ? PAD_UPWARD
+ : ((mode == BLKmode
+ ? (type
+ && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+ && int_size_in_bytes (type) < (PARM_BOUNDARY / BITS_PER_UNIT))
+ : (GET_MODE_BITSIZE (mode) < PARM_BOUNDARY
+ && GET_MODE_CLASS (mode) == MODE_INT))
+ ? PAD_DOWNWARD : PAD_UPWARD));
+}
+
static unsigned int
iq2000_function_arg_boundary (machine_mode mode, const_tree type)
{
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
init_cumulative_args (& CUM, FNTYPE, LIBNAME) \
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
- (! BYTES_BIG_ENDIAN \
- ? upward \
- : (((MODE) == BLKmode \
- ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
- && int_size_in_bytes (TYPE) < (PARM_BOUNDARY / BITS_PER_UNIT))\
- : (GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY \
- && (GET_MODE_CLASS (MODE) == MODE_INT))) \
- ? downward : upward))
-
#define FUNCTION_ARG_REGNO_P(N) \
(((N) >= GP_ARG_FIRST && (N) <= GP_ARG_LAST))
extern void mips_expand_synci_loop (rtx, rtx);
extern void mips_init_cumulative_args (CUMULATIVE_ARGS *, tree);
-extern bool mips_pad_arg_upward (machine_mode, const_tree);
extern bool mips_pad_reg_upward (machine_mode, tree);
extern bool mips_expand_ext_as_unaligned_load (rtx, rtx, HOST_WIDE_INT,
return default_get_reg_raw_mode (regno);
}
-/* Return true if FUNCTION_ARG_PADDING (MODE, TYPE) should return
- upward rather than downward. In other words, return true if the
- first byte of the stack slot has useful data, false if the last
- byte does. */
+/* Implement TARGET_FUNCTION_ARG_PADDING; return PAD_UPWARD if the first
+ byte of the stack slot has useful data, PAD_DOWNWARD if the last byte
+ does. */
-bool
-mips_pad_arg_upward (machine_mode mode, const_tree type)
+static pad_direction
+mips_function_arg_padding (machine_mode mode, const_tree type)
{
/* On little-endian targets, the first byte of every stack argument
is passed in the first byte of the stack slot. */
if (!BYTES_BIG_ENDIAN)
- return true;
+ return PAD_UPWARD;
/* Otherwise, integral types are padded downward: the last byte of a
stack argument is passed in the last byte of the stack slot. */
|| FIXED_POINT_TYPE_P (type))
: (SCALAR_INT_MODE_P (mode)
|| ALL_SCALAR_FIXED_POINT_MODE_P (mode)))
- return false;
+ return PAD_DOWNWARD;
/* Big-endian o64 pads floating-point arguments downward. */
if (mips_abi == ABI_O64)
if (type != 0 ? FLOAT_TYPE_P (type) : GET_MODE_CLASS (mode) == MODE_FLOAT)
- return false;
+ return PAD_DOWNWARD;
/* Other types are padded upward for o32, o64, n32 and n64. */
if (mips_abi != ABI_EABI)
- return true;
+ return PAD_UPWARD;
/* Arguments smaller than a stack slot are padded downward. */
- if (mode != BLKmode)
- return GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY;
- else
- return int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT);
+ if (mode != BLKmode
+ ? GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY
+ : int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
+ return PAD_UPWARD;
+
+ return PAD_DOWNWARD;
}
/* Likewise BLOCK_REG_PADDING (MODE, TYPE, ...). Return !BYTES_BIG_ENDIAN
/* Otherwise, apply the same padding to register arguments as we do
to stack arguments. */
- return mips_pad_arg_upward (mode, type);
+ return mips_function_arg_padding (mode, type) == PAD_UPWARD;
}
/* Return nonzero when an argument must be passed by reference. */
#define TARGET_FUNCTION_ARG mips_function_arg
#undef TARGET_FUNCTION_ARG_ADVANCE
#define TARGET_FUNCTION_ARG_ADVANCE mips_function_arg_advance
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING mips_function_arg_padding
#undef TARGET_FUNCTION_ARG_BOUNDARY
#define TARGET_FUNCTION_ARG_BOUNDARY mips_function_arg_boundary
#undef TARGET_GET_RAW_RESULT_MODE
DATA_ALIGNMENT (TYPE, ALIGN)
#define PAD_VARARGS_DOWN \
- (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
+ (targetm.calls.function_arg_padding (TYPE_MODE (type), type) == PAD_DOWNWARD)
/* Define if operations between registers always perform the operation
on the full register even if a narrower mode is specified. */
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
mips_init_cumulative_args (&CUM, FNTYPE)
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
- (mips_pad_arg_upward (MODE, TYPE) ? upward : downward)
-
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- (mips_pad_reg_upward (MODE, TYPE) ? upward : downward)
+ (mips_pad_reg_upward (MODE, TYPE) ? PAD_UPWARD : PAD_DOWNWARD)
/* True if using EABI and varargs can be passed in floating-point
registers. Under these conditions, we need a more complex form
extern void nios2_adjust_reg_alloc_order (void);
-#ifdef TREE_CODE
-#ifdef ARGS_SIZE_RTX
-/* expr.h defines both ARGS_SIZE_RTX and `enum direction' */
-extern enum direction nios2_function_arg_padding (machine_mode, const_tree);
-extern enum direction nios2_block_reg_padding (machine_mode, tree, int);
-#endif /* ARGS_SIZE_RTX */
-
-#endif /* TREE_CODE */
+extern pad_direction nios2_block_reg_padding (machine_mode, tree, int);
+
#endif /* RTX_CODE */
#endif /* GCC_NIOS2_PROTOS_H */
cum->regs_used += param_size;
}
-enum direction
+static pad_direction
nios2_function_arg_padding (machine_mode mode, const_tree type)
{
/* On little-endian targets, the first byte of every stack argument
is passed in the first byte of the stack slot. */
if (!BYTES_BIG_ENDIAN)
- return upward;
+ return PAD_UPWARD;
/* Otherwise, integral types are padded downward: the last byte of a
stack argument is passed in the last byte of the stack slot. */
if (type != 0
? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
: GET_MODE_CLASS (mode) == MODE_INT)
- return downward;
+ return PAD_DOWNWARD;
/* Arguments smaller than a stack slot are padded downward. */
if (mode != BLKmode)
- return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY) ? upward : downward;
+ return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY
+ ? PAD_UPWARD : PAD_DOWNWARD);
return ((int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
- ? upward : downward);
+ ? PAD_UPWARD : PAD_DOWNWARD);
}
-enum direction
+pad_direction
nios2_block_reg_padding (machine_mode mode, tree type,
int first ATTRIBUTE_UNUSED)
{
#undef TARGET_FUNCTION_ARG_ADVANCE
#define TARGET_FUNCTION_ARG_ADVANCE nios2_function_arg_advance
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING nios2_function_arg_padding
+
#undef TARGET_ARG_PARTIAL_BYTES
#define TARGET_ARG_PARTIAL_BYTES nios2_arg_partial_bytes
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
do { (CUM).regs_used = 0; } while (0)
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
- (nios2_function_arg_padding ((MODE), (TYPE)))
-
#define PAD_VARARGS_DOWN \
- (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
+ (targetm.calls.function_arg_padding (TYPE_MODE (type), type) == PAD_DOWNWARD)
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
(nios2_block_reg_padding ((MODE), (TYPE), (FIRST)))
extern rtx pa_return_addr_rtx (int, rtx);
-#ifdef ARGS_SIZE_RTX
-/* expr.h defines ARGS_SIZE_RTX and `enum direction' */
-#ifdef TREE_CODE
-extern enum direction pa_function_arg_padding (machine_mode, const_tree);
-#endif
-#endif /* ARGS_SIZE_RTX */
extern int pa_insn_refs_are_delayed (rtx_insn *);
extern rtx pa_get_deferred_plabel (rtx);
extern rtx pa_maybe_emit_compare_and_swap_exchange_loop (rtx, rtx, rtx);
const_tree, bool);
static rtx pa_function_arg (cumulative_args_t, machine_mode,
const_tree, bool);
+static pad_direction pa_function_arg_padding (machine_mode, const_tree);
static unsigned int pa_function_arg_boundary (machine_mode, const_tree);
static struct machine_function * pa_init_machine_status (void);
static reg_class_t pa_secondary_reload (bool, rtx, reg_class_t,
#define TARGET_FUNCTION_ARG pa_function_arg
#undef TARGET_FUNCTION_ARG_ADVANCE
#define TARGET_FUNCTION_ARG_ADVANCE pa_function_arg_advance
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING pa_function_arg_padding
#undef TARGET_FUNCTION_ARG_BOUNDARY
#define TARGET_FUNCTION_ARG_BOUNDARY pa_function_arg_boundary
return size <= 0 || size > 8;
}
-enum direction
+/* Implement TARGET_FUNCTION_ARG_PADDING. */
+
+static pad_direction
pa_function_arg_padding (machine_mode mode, const_tree type)
{
if (mode == BLKmode
|| TREE_CODE (type) == COMPLEX_TYPE
|| TREE_CODE (type) == VECTOR_TYPE)))
{
- /* Return none if justification is not required. */
+ /* Return PAD_NONE if justification is not required. */
if (type
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
&& (int_size_in_bytes (type) * BITS_PER_UNIT) % PARM_BOUNDARY == 0)
- return none;
+ return PAD_NONE;
/* The directions set here are ignored when a BLKmode argument larger
than a word is placed in a register. Different code is used for
the stack and in registers should be identical. */
if (TARGET_64BIT)
/* The 64-bit runtime specifies left justification for aggregates. */
- return upward;
+ return PAD_UPWARD;
else
/* The 32-bit runtime architecture specifies right justification.
When the argument is passed on the stack, the argument is padded
with garbage on the left. The HP compiler pads with zeros. */
- return downward;
+ return PAD_DOWNWARD;
}
if (GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)
- return downward;
+ return PAD_DOWNWARD;
else
- return none;
+ return PAD_NONE;
}
\f
the standard parameter passing conventions on the RS6000. That's why
you'll see lots of similar code in rs6000.h. */
-/* If defined, a C expression which determines whether, and in which
- direction, to pad out an argument with extra space. */
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
- pa_function_arg_padding ((MODE), (TYPE))
-
/* Specify padding for the last element of a block move between registers
and memory.
so that there is only one element. This allows the object to be
correctly padded. */
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- pa_function_arg_padding ((MODE), (TYPE))
+ targetm.calls.function_arg_padding ((MODE), (TYPE))
\f
/* On HPPA, we emit profiling code as rtl via PROFILE_HOOK rather than
registers and memory. FIRST is nonzero if this is the only
element. */
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+ (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
/* Indicate that jump tables go in the text section. */
registers and memory. FIRST is nonzero if this is the only
element. */
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+ (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
#define DOUBLE_INT_ASM_OP "\t.quad\t"
registers and memory. FIRST is nonzero if this is the only
element. */
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+ (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
/* FreeBSD doesn't support saving and restoring 64-bit regs with a 32-bit
kernel. This is supported when running on a 64-bit kernel with
registers and memory. FIRST is nonzero if this is the only
element. */
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+ (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
/* Linux doesn't support saving and restoring 64-bit regs in a 32-bit
process. */
unsigned HOST_WIDE_INT);
extern void rs6000_elf_declare_function_name (FILE *, const char *, tree);
extern bool rs6000_elf_in_small_data_p (const_tree);
-#ifdef ARGS_SIZE_RTX
-/* expr.h defines ARGS_SIZE_RTX and `enum direction' */
-extern enum direction function_arg_padding (machine_mode, const_tree);
-#endif /* ARGS_SIZE_RTX */
#endif /* TREE_CODE */
#define min(A,B) ((A) < (B) ? (A) : (B))
#define max(A,B) ((A) > (B) ? (A) : (B))
+static pad_direction rs6000_function_arg_padding (machine_mode, const_tree);
+
/* Structure used to define the rs6000 stack */
typedef struct rs6000_stack {
int reload_completed; /* stack info won't change from here on */
#define TARGET_FUNCTION_ARG_ADVANCE rs6000_function_arg_advance
#undef TARGET_FUNCTION_ARG
#define TARGET_FUNCTION_ARG rs6000_function_arg
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING rs6000_function_arg_padding
#undef TARGET_FUNCTION_ARG_BOUNDARY
#define TARGET_FUNCTION_ARG_BOUNDARY rs6000_function_arg_boundary
return (DEFAULT_ABI == ABI_ELFv2
&& BYTES_BIG_ENDIAN
&& AGGREGATE_TYPE_P (valtype)
- && FUNCTION_ARG_PADDING (TYPE_MODE (valtype), valtype) == upward);
+ && rs6000_function_arg_padding (TYPE_MODE (valtype),
+ valtype) == PAD_UPWARD);
}
#ifdef HAVE_AS_GNU_ATTRIBUTE
return false;
}
-/* 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
- the argument, `downward' to pad below, or `none' to inhibit
- padding.
+/* Implement TARGET_FUNCTION_ARG_PADDING
For the AIX ABI structs are always stored left shifted in their
argument slot. */
-enum direction
-function_arg_padding (machine_mode mode, const_tree type)
+static pad_direction
+rs6000_function_arg_padding (machine_mode mode, const_tree type)
{
#ifndef AGGREGATE_PADDING_FIXED
#define AGGREGATE_PADDING_FIXED 0
if (!AGGREGATE_PADDING_FIXED)
{
/* GCC used to pass structures of the same size as integer types as
- if they were in fact integers, ignoring FUNCTION_ARG_PADDING.
+ if they were in fact integers, ignoring TARGET_FUNCTION_ARG_PADDING.
i.e. Structures of size 1 or 2 (or 4 when TARGET_64BIT) were
passed padded downward, except that -mstrict-align further
muddied the water in that multi-component structures of 2 and 4
size = GET_MODE_SIZE (mode);
if (size == 1 || size == 2 || size == 4)
- return downward;
+ return PAD_DOWNWARD;
}
- return upward;
+ return PAD_UPWARD;
}
if (AGGREGATES_PAD_UPWARD_ALWAYS)
{
if (type != 0 && AGGREGATE_TYPE_P (type))
- return upward;
+ return PAD_UPWARD;
}
/* Fall back to the default. */
- return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
+ return default_function_arg_padding (mode, type);
}
/* If defined, a C expression that gives the alignment boundary, in bits,
init_cumulative_args (&CUM, NULL_TREE, LIBNAME, FALSE, TRUE, \
0, NULL_TREE, MODE)
-/* 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
- the argument, `downward' to pad below, or `none' to inhibit
- padding. */
-
-#define FUNCTION_ARG_PADDING(MODE, TYPE) function_arg_padding (MODE, TYPE)
-
#define PAD_VARARGS_DOWN \
- (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
+ (targetm.calls.function_arg_padding (TYPE_MODE (type), type) == PAD_DOWNWARD)
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
registers and memory. FIRST is nonzero if this is the only
element. */
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+ (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
/* Indicate that jump tables go in the text section. */
registers and memory. FIRST is nonzero if this is the only
element. */
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+ (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
#define DOUBLE_INT_ASM_OP "\t.quad\t"
registers and memory. FIRST is nonzero if this is the only
element. */
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+ (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
/* FreeBSD doesn't support saving and restoring 64-bit regs with a 32-bit
kernel. This is supported when running on a 64-bit kernel with
registers and memory. FIRST is nonzero if this is the only
element. */
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+ (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
/* Linux doesn't support saving and restoring 64-bit regs in a 32-bit
process. */
unsigned HOST_WIDE_INT);
extern void rs6000_elf_declare_function_name (FILE *, const char *, tree);
extern bool rs6000_elf_in_small_data_p (const_tree);
-#ifdef ARGS_SIZE_RTX
-/* expr.h defines ARGS_SIZE_RTX and `enum direction' */
-extern enum direction function_arg_padding (machine_mode, const_tree);
-#endif /* ARGS_SIZE_RTX */
#endif /* TREE_CODE */
#define min(A,B) ((A) < (B) ? (A) : (B))
#define max(A,B) ((A) > (B) ? (A) : (B))
+static pad_direction rs6000_function_arg_padding (machine_mode, const_tree);
+
/* Structure used to define the rs6000 stack */
typedef struct rs6000_stack {
int reload_completed; /* stack info won't change from here on */
#define TARGET_FUNCTION_ARG_ADVANCE rs6000_function_arg_advance
#undef TARGET_FUNCTION_ARG
#define TARGET_FUNCTION_ARG rs6000_function_arg
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING rs6000_function_arg_padding
#undef TARGET_FUNCTION_ARG_BOUNDARY
#define TARGET_FUNCTION_ARG_BOUNDARY rs6000_function_arg_boundary
return (DEFAULT_ABI == ABI_ELFv2
&& BYTES_BIG_ENDIAN
&& AGGREGATE_TYPE_P (valtype)
- && FUNCTION_ARG_PADDING (TYPE_MODE (valtype), valtype) == upward);
+ && (rs6000_function_arg_padding (TYPE_MODE (valtype), valtype)
+ == PAD_UPWARD));
}
#ifdef HAVE_AS_GNU_ATTRIBUTE
return false;
}
-/* 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
- the argument, `downward' to pad below, or `none' to inhibit
- padding.
+/* Implement TARGET_FUNCTION_ARG_PADDING.
For the AIX ABI structs are always stored left shifted in their
argument slot. */
-enum direction
-function_arg_padding (machine_mode mode, const_tree type)
+static pad_direction
+rs6000_function_arg_padding (machine_mode mode, const_tree type)
{
#ifndef AGGREGATE_PADDING_FIXED
#define AGGREGATE_PADDING_FIXED 0
if (!AGGREGATE_PADDING_FIXED)
{
/* GCC used to pass structures of the same size as integer types as
- if they were in fact integers, ignoring FUNCTION_ARG_PADDING.
+ if they were in fact integers, ignoring TARGET_FUNCTION_ARG_PADDING.
i.e. Structures of size 1 or 2 (or 4 when TARGET_64BIT) were
passed padded downward, except that -mstrict-align further
muddied the water in that multi-component structures of 2 and 4
size = GET_MODE_SIZE (mode);
if (size == 1 || size == 2 || size == 4)
- return downward;
+ return PAD_DOWNWARD;
}
- return upward;
+ return PAD_UPWARD;
}
if (AGGREGATES_PAD_UPWARD_ALWAYS)
{
if (type != 0 && AGGREGATE_TYPE_P (type))
- return upward;
+ return PAD_UPWARD;
}
/* Fall back to the default. */
- return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
+ return default_function_arg_padding (mode, type);
}
/* If defined, a C expression that gives the alignment boundary, in bits,
init_cumulative_args (&CUM, NULL_TREE, LIBNAME, FALSE, TRUE, \
0, NULL_TREE, MODE)
-/* 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
- the argument, `downward' to pad below, or `none' to inhibit
- padding. */
-
-#define FUNCTION_ARG_PADDING(MODE, TYPE) function_arg_padding (MODE, TYPE)
-
#define PAD_VARARGS_DOWN \
- (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
+ (targetm.calls.function_arg_padding (TYPE_MODE (type), type) == PAD_DOWNWARD)
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
gcc_unreachable ();
}
+/* Implement TARGET_FUNCTION_ARG_BOUNDARY. Vector arguments are
+ left-justified when placed on the stack during parameter passing. */
+
+static pad_direction
+s390_function_arg_padding (machine_mode mode, const_tree type)
+{
+ if (s390_function_arg_vector (mode, type))
+ return PAD_UPWARD;
+
+ return default_function_arg_padding (mode, type);
+}
+
/* Return true if return values of type TYPE should be returned
in a memory buffer whose address is passed by the caller as
hidden first argument. */
#define TARGET_FUNCTION_ARG s390_function_arg
#undef TARGET_FUNCTION_ARG_ADVANCE
#define TARGET_FUNCTION_ARG_ADVANCE s390_function_arg_advance
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING s390_function_arg_padding
#undef TARGET_FUNCTION_VALUE
#define TARGET_FUNCTION_VALUE s390_function_value
#undef TARGET_LIBCALL_VALUE
#define STACK_SIZE_MODE (Pmode)
-/* Vector arguments are left-justified when placed on the stack during
- parameter passing. */
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
- (s390_function_arg_vector ((MODE), (TYPE)) \
- ? upward \
- : DEFAULT_FUNCTION_ARG_PADDING ((MODE), (TYPE)))
-
#ifndef IN_LIBGCC2
/* Width of a word, in units (bytes). */
extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
#endif
extern unsigned long sparc_type_code (tree);
-#ifdef ARGS_SIZE_RTX
-/* expr.h defines ARGS_SIZE_RTX and `enum direction' */
-extern enum direction function_arg_padding (machine_mode, const_tree);
-#endif /* ARGS_SIZE_RTX */
#endif /* TREE_CODE */
extern void order_regs_for_local_alloc (void);
machine_mode, const_tree, bool);
static rtx sparc_function_incoming_arg (cumulative_args_t,
machine_mode, const_tree, bool);
+static pad_direction sparc_function_arg_padding (machine_mode, const_tree);
static unsigned int sparc_function_arg_boundary (machine_mode,
const_tree);
static int sparc_arg_partial_bytes (cumulative_args_t,
#define TARGET_FUNCTION_ARG sparc_function_arg
#undef TARGET_FUNCTION_INCOMING_ARG
#define TARGET_FUNCTION_INCOMING_ARG sparc_function_incoming_arg
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING sparc_function_arg_padding
#undef TARGET_FUNCTION_ARG_BOUNDARY
#define TARGET_FUNCTION_ARG_BOUNDARY sparc_function_arg_boundary
}
}
-/* Handle the FUNCTION_ARG_PADDING macro.
- For the 64-bit ABI structs are always stored left shifted in their
- argument slot. */
+/* Implement TARGET_FUNCTION_ARG_PADDING. For the 64-bit ABI structs
+ are always stored left shifted in their argument slot. */
-enum direction
-function_arg_padding (machine_mode mode, const_tree type)
+static pad_direction
+sparc_function_arg_padding (machine_mode mode, const_tree type)
{
if (TARGET_ARCH64 && type && AGGREGATE_TYPE_P (type))
- return upward;
+ return PAD_UPWARD;
/* Fall back to the default. */
- return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
+ return default_function_arg_padding (mode, type);
}
/* Handle the TARGET_RETURN_IN_MEMORY target hook.
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
init_cumulative_args (& (CUM), (FNTYPE), (LIBNAME), (FNDECL));
-/* 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 the argument,
- `downward' to pad below, or `none' to inhibit padding. */
-
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
-function_arg_padding ((MODE), (TYPE))
-
\f
/* Generate the special assembly code needed to tell the assembler whatever
it might need to know about the return value of a function.
: HARD_REGNO_NREGS (cum, mode));
}
+/* Implement TARGET_FUNCTION_ARG_PADDING. */
+
+static pad_direction
+spu_function_arg_padding (machine_mode, const_tree)
+{
+ return PAD_UPWARD;
+}
+
/* Variable sized types are passed by reference. */
static bool
spu_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
#undef TARGET_FUNCTION_ARG_ADVANCE
#define TARGET_FUNCTION_ARG_ADVANCE spu_function_arg_advance
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING spu_function_arg_padding
+
#undef TARGET_MUST_PASS_IN_STACK
#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
? (4 - GET_MODE_SIZE (MODE)) \
: 0)
-#define FUNCTION_ARG_PADDING(MODE,TYPE) upward
-
#define PAD_VARARGS_DOWN 0
#define FUNCTION_ARG_REGNO_P(N) ((N) >= (FIRST_ARG_REGNUM) && (N) <= (LAST_ARG_REGNUM))
OPTIMIZE_FOR_SIZE
};
+/* Enumerates a padding direction. */
+enum pad_direction {
+ /* No padding is required. */
+ PAD_NONE,
+
+ /* Insert padding above the data, i.e. at higher memeory addresses
+ when dealing with memory, and at the most significant end when
+ dealing with registers. */
+ PAD_UPWARD,
+
+ /* Insert padding below the data, i.e. at lower memeory addresses
+ when dealing with memory, and at the least significant end when
+ dealing with registers. */
+ PAD_DOWNWARD
+};
+
/* Possible initialization status of a variable. When requested
by the user, this information is tracked and recorded in the DWARF
debug information, along with the variable's location. */
#define SET_RATIO(speed) MOVE_RATIO (speed)
#endif
-/* Supply a default definition for FUNCTION_ARG_PADDING:
- usually pad upward, but pad short args downward on
- big-endian machines. */
-
-#define DEFAULT_FUNCTION_ARG_PADDING(MODE, TYPE) \
- (! BYTES_BIG_ENDIAN \
- ? upward \
- : (((MODE) == BLKmode \
- ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
- && int_size_in_bytes (TYPE) < (PARM_BOUNDARY / BITS_PER_UNIT)) \
- : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY) \
- ? downward : upward))
-
-#ifndef FUNCTION_ARG_PADDING
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
- DEFAULT_FUNCTION_ARG_PADDING ((MODE), (TYPE))
-#endif
-
/* Supply a default definition of STACK_SAVEAREA_MODE for emit_stack_save.
Normally move_insn, so Pmode stack pointer. */
top.
@end defmac
-@defmac FUNCTION_ARG_PADDING (@var{mode}, @var{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
-@code{enum direction}: either @code{upward} to pad above the argument,
-@code{downward} to pad below, or @code{none} to inhibit padding.
+@deftypefn {Target Hook} pad_direction TARGET_FUNCTION_ARG_PADDING (machine_mode @var{mode}, const_tree @var{type})
+This hook determines whether, and in which direction, to pad out
+an argument of mode @var{mode} and type @var{type}. It returns
+@code{PAD_UPWARD} to insert padding above the argument, @code{PAD_DOWNWARD}
+to insert padding below the argument, or @code{PAD_NONE} to inhibit padding.
-The @emph{amount} of padding is not controlled by this macro, but by the
-target hook @code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}. It is
-always just enough to reach the next multiple of that boundary.
+The @emph{amount} of padding is not controlled by this hook, but by
+@code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}. It is always just enough
+to reach the next multiple of that boundary.
-This macro has a default definition which is right for most systems.
+This hook has a default definition that is right for most systems.
For little-endian machines, the default is to pad upward. For
big-endian machines, the default is to pad downward for an argument of
constant size shorter than an @code{int}, and upward otherwise.
-@end defmac
+@end deftypefn
@defmac PAD_VARARGS_DOWN
If defined, a C expression which determines whether the default
top.
@end defmac
-@defmac FUNCTION_ARG_PADDING (@var{mode}, @var{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
-@code{enum direction}: either @code{upward} to pad above the argument,
-@code{downward} to pad below, or @code{none} to inhibit padding.
-
-The @emph{amount} of padding is not controlled by this macro, but by the
-target hook @code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}. It is
-always just enough to reach the next multiple of that boundary.
-
-This macro has a default definition which is right for most systems.
-For little-endian machines, the default is to pad upward. For
-big-endian machines, the default is to pad downward for an argument of
-constant size shorter than an @code{int}, and upward otherwise.
-@end defmac
+@hook TARGET_FUNCTION_ARG_PADDING
@defmac PAD_VARARGS_DOWN
If defined, a C expression which determines whether the default
if (
#ifdef BLOCK_REG_PADDING
BLOCK_REG_PADDING (GET_MODE (orig_src), type, i == start)
- == (BYTES_BIG_ENDIAN ? upward : downward)
+ == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)
#else
BYTES_BIG_ENDIAN
#endif
if (
#ifdef BLOCK_REG_PADDING
BLOCK_REG_PADDING (GET_MODE (orig_dst), type, i == start)
- == (BYTES_BIG_ENDIAN ? upward : downward)
+ == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)
#else
BYTES_BIG_ENDIAN
#endif
then store X into the stack location using an offset. This is
because emit_move_insn does not know how to pad; it does not have
access to type. */
- else if (FUNCTION_ARG_PADDING (mode, type) == downward)
+ else if (targetm.calls.function_arg_padding (mode, type) == PAD_DOWNWARD)
{
unsigned padding_size = rounded_size - GET_MODE_SIZE (mode);
HOST_WIDE_INT offset;
rtx alignment_pad, bool sibcall_p)
{
rtx xinner;
- enum direction stack_direction = STACK_GROWS_DOWNWARD ? downward : upward;
+ pad_direction stack_direction
+ = STACK_GROWS_DOWNWARD ? PAD_DOWNWARD : PAD_UPWARD;
- /* Decide where to pad the argument: `downward' for below,
- `upward' for above, or `none' for don't pad it.
+ /* Decide where to pad the argument: PAD_DOWNWARD for below,
+ PAD_UPWARD for above, or PAD_NONE for don't pad it.
Default is below for small data on big-endian machines; else above. */
- enum direction where_pad = FUNCTION_ARG_PADDING (mode, type);
+ pad_direction where_pad = targetm.calls.function_arg_padding (mode, type);
/* Invert direction if stack is post-decrement.
FIXME: why? */
if (STACK_PUSH_CODE == POST_DEC)
- if (where_pad != none)
- where_pad = (where_pad == downward ? upward : downward);
+ if (where_pad != PAD_NONE)
+ where_pad = (where_pad == PAD_DOWNWARD ? PAD_UPWARD : PAD_DOWNWARD);
xinner = x;
or if padding below and stack grows up.
But if space already allocated, this has already been done. */
if (extra && args_addr == 0
- && where_pad != none && where_pad != stack_direction)
+ && where_pad != PAD_NONE && where_pad != stack_direction)
anti_adjust_stack (GEN_INT (extra));
move_by_pieces (NULL, xinner, INTVAL (size) - used, align, 0);
A single stack adjust will do. */
if (! args_addr)
{
- temp = push_block (size, extra, where_pad == downward);
+ temp = push_block (size, extra, where_pad == PAD_DOWNWARD);
extra = 0;
}
else if (CONST_INT_P (args_so_far))
or if padding below and stack grows up.
But if space already allocated, this has already been done. */
if (extra && args_addr == 0
- && where_pad != none && where_pad != stack_direction)
+ && where_pad != PAD_NONE && where_pad != stack_direction)
anti_adjust_stack (GEN_INT (extra));
/* If we make space by pushing it, we might as well push
or if padding below and stack grows up.
But if space already allocated, this has already been done. */
if (extra && args_addr == 0
- && where_pad != none && where_pad != stack_direction)
+ && where_pad != PAD_NONE && where_pad != stack_direction)
anti_adjust_stack (GEN_INT (extra));
#ifdef PUSH_ROUNDING
is TARGET_FUNCTION_ARG_BOUNDARY. If we're using slot_offset, we're
intentionally forcing upward padding. Otherwise we have to come
up with a guess at the alignment based on OFFSET_RTX. */
- if (data->locate.where_pad != downward || data->entry_parm)
+ if (data->locate.where_pad != PAD_DOWNWARD || data->entry_parm)
align = boundary;
else if (CONST_INT_P (offset_rtx))
{
if (REG_P (data->entry_parm)
&& GET_MODE_SIZE (data->promoted_mode) < UNITS_PER_WORD
&& (BLOCK_REG_PADDING (data->passed_mode, data->passed_type, 1)
- == (BYTES_BIG_ENDIAN ? upward : downward)))
+ == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
return true;
#endif
#ifdef BLOCK_REG_PADDING
&& (size == UNITS_PER_WORD
|| (BLOCK_REG_PADDING (mode, data->passed_type, 1)
- != (BYTES_BIG_ENDIAN ? upward : downward)))
+ != (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
#endif
)
{
gcc_checking_assert (BYTES_BIG_ENDIAN
&& (BLOCK_REG_PADDING (mode,
data->passed_type, 1)
- == upward));
+ == PAD_UPWARD));
int by = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
else if (size != UNITS_PER_WORD
#ifdef BLOCK_REG_PADDING
&& (BLOCK_REG_PADDING (mode, data->passed_type, 1)
- == downward)
+ == PAD_DOWNWARD)
#else
&& BYTES_BIG_ENDIAN
#endif
#ifdef BLOCK_REG_PADDING
gcc_checking_assert (BLOCK_REG_PADDING (GET_MODE (mem),
data->passed_type, 0)
- == upward);
+ == PAD_UPWARD);
#endif
emit_move_insn (mem, entry_parm);
}
rounding affects the initial and starting offsets, but not the argument
size.
- The second, controlled by FUNCTION_ARG_PADDING and PARM_BOUNDARY,
+ The second, controlled by TARGET_FUNCTION_ARG_PADDING and PARM_BOUNDARY,
optionally rounds the size of the parm to PARM_BOUNDARY. The
initial offset is not affected by this rounding, while the size always
is and the starting offset may be. */
struct locate_and_pad_arg_data *locate)
{
tree sizetree;
- enum direction where_pad;
+ pad_direction where_pad;
unsigned int boundary, round_boundary;
int part_size_in_regs;
sizetree
= type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode));
- where_pad = FUNCTION_ARG_PADDING (passed_mode, type);
+ where_pad = targetm.calls.function_arg_padding (passed_mode, type);
boundary = targetm.calls.function_arg_boundary (passed_mode, type);
round_boundary = targetm.calls.function_arg_round_boundary (passed_mode,
type);
{
tree s2 = sizetree;
- if (where_pad != none
+ if (where_pad != PAD_NONE
&& (!tree_fits_uhwi_p (sizetree)
|| (tree_to_uhwi (sizetree) * BITS_PER_UNIT) % round_boundary))
s2 = round_up (s2, round_boundary / BITS_PER_UNIT);
/* Pad_below needs the pre-rounded size to know how much to pad
below. */
locate->offset = locate->slot_offset;
- if (where_pad == downward)
+ if (where_pad == PAD_DOWNWARD)
pad_below (&locate->offset, passed_mode, sizetree);
}
/* Pad_below needs the pre-rounded size to know how much to pad below
so this must be done before rounding up. */
locate->offset = locate->slot_offset;
- if (where_pad == downward)
+ if (where_pad == PAD_DOWNWARD)
pad_below (&locate->offset, passed_mode, sizetree);
- if (where_pad != none
+ if (where_pad != PAD_NONE
&& (!tree_fits_uhwi_p (sizetree)
|| (tree_to_uhwi (sizetree) * BITS_PER_UNIT) % round_boundary))
sizetree = round_up (sizetree, round_boundary / BITS_PER_UNIT);
data structures. */
extern struct machine_function * (*init_machine_status) (void);
-enum direction {none, upward, downward};
-
/* Structure to record the size of a sequence of arguments
as the sum of a tree-expression and a constant. This structure is
also used to store offsets from the stack, which might be negative,
force alignment for the next argument. */
struct args_size alignment_pad;
/* Which way we should pad this arg. */
- enum direction where_pad;
+ pad_direction where_pad;
/* slot_offset is at least this aligned. */
unsigned int boundary;
};
CLEAR_BY_PIECES_P MOVE_BY_PIECES_P SET_BY_PIECES_P \
STORE_BY_PIECES_P TARGET_FLT_EVAL_METHOD \
HARD_REGNO_CALL_PART_CLOBBERED HARD_REGNO_MODE_OK \
- MODES_TIEABLE_P
+ MODES_TIEABLE_P FUNCTION_ARG_PADDING
/* Target macros only used for code built for the target, that have
moved to libgcc-tm.h or have never been present elsewhere. */
(cumulative_args_t ca, machine_mode mode, const_tree type, bool named),
default_function_arg_advance)
+DEFHOOK
+(function_arg_padding,
+ "This hook determines whether, and in which direction, to pad out\n\
+an argument of mode @var{mode} and type @var{type}. It returns\n\
+@code{PAD_UPWARD} to insert padding above the argument, @code{PAD_DOWNWARD}\n\
+to insert padding below the argument, or @code{PAD_NONE} to inhibit padding.\n\
+\n\
+The @emph{amount} of padding is not controlled by this hook, but by\n\
+@code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}. It is always just enough\n\
+to reach the next multiple of that boundary.\n\
+\n\
+This hook has a default definition that is right for most systems.\n\
+For little-endian machines, the default is to pad upward. For\n\
+big-endian machines, the default is to pad downward for an argument of\n\
+constant size shorter than an @code{int}, and upward otherwise.",
+ pad_direction, (machine_mode mode, const_tree type),
+ default_function_arg_padding)
+
/* Return zero if the argument described by the state of CA should
be placed on a stack, or a hard register in which to store the
argument. The values MODE, TYPE, and NAMED describe that
gcc_unreachable ();
}
+/* Default implementation of TARGET_FUNCTION_ARG_PADDING: usually pad
+ upward, but pad short args downward on big-endian machines. */
+
+pad_direction
+default_function_arg_padding (machine_mode mode, const_tree type)
+{
+ if (!BYTES_BIG_ENDIAN)
+ return PAD_UPWARD;
+
+ unsigned HOST_WIDE_INT size;
+ if (mode == BLKmode)
+ {
+ if (!type || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+ return PAD_UPWARD;
+ size = int_size_in_bytes (type);
+ }
+ else
+ size = GET_MODE_SIZE (mode);
+
+ if (size < (PARM_BOUNDARY / BITS_PER_UNIT))
+ return PAD_DOWNWARD;
+
+ return PAD_UPWARD;
+}
+
rtx
default_function_arg (cumulative_args_t ca ATTRIBUTE_UNUSED,
machine_mode mode ATTRIBUTE_UNUSED,
(const_tree, const_tree, const_tree);
extern void default_function_arg_advance
(cumulative_args_t, machine_mode, const_tree, bool);
+extern pad_direction default_function_arg_padding (machine_mode, const_tree);
extern rtx default_function_arg
(cumulative_args_t, machine_mode, const_tree, bool);
extern rtx default_function_incoming_arg