Commit 9dff28ab by John David Anglin Committed by John David Anglin

calls.c (store_one_arg): Set default alignment for BLKmode arguments to BITS_PER_UNIT when...

	* calls.c (store_one_arg): Set default alignment for BLKmode arguments
	to BITS_PER_UNIT when ARGS_GROW_DOWNWARD and the padding direction is
	downward.
	* function.c (pad_below):  Always compile.
	(locate_and_pad_parm): If defined ARGS_GROW_DOWNWARD, pad argument to
	alignment when it is not in a register or REG_PARM_STACK_SPACE is true.
	Pad below when the argument is not in a register and the padding
	direction is downward.
	* pa-64.h (MUST_PASS_IN_STACK): Move define to pa.h.
	(PAD_VARARGS_DOWN): Define.
	* pa.c (function_arg_padding): Revise padding directions to make them
	compatible with the 32 and 64-bit runtime architecture documentation.
	(hppa_va_arg):  Add code to handle variable and size zero arguments
	passed by reference on TARGET_64BIT.  Reformat.
	(function_arg): Use a PARALLEL for BLKmode and aggregates args on
	TARGET_64BIT.  Use a DImode PARALLEL for BLKmode args 5 to 8 bytes
	wide when !TARGET_64BIT.  Move forward check for mode==VOIDmode.
	Add comments.
	* pa.h (MAX_PARM_BOUNDARY): Correct define for TARGET_64BIT.
	(RETURN_IN_MEMORY): Return size zero types in memory.
	(FUNCTION_VALUE): Return TFmode in general registers.
	(MUST_PASS_IN_STACK): Define.
	(FUNCTION_ARG_BOUNDARY): Simplify.
	(FUNCTION_ARG_PASS_BY_REFERENCE): Pass variable and zero sized types
	by reference.
	(FUNCTION_ARG_CALLEE_COPIES): Define to FUNCTION_ARG_PASS_BY_REFERENCE.

From-SVN: r57226
parent 94313f35
2002-09-16 John David Anglin <dave@hiauly1.hia.nrc.ca>
* calls.c (store_one_arg): Set default alignment for BLKmode arguments
to BITS_PER_UNIT when ARGS_GROW_DOWNWARD and the padding direction is
downward.
* function.c (pad_below): Always compile.
(locate_and_pad_parm): If defined ARGS_GROW_DOWNWARD, pad argument to
alignment when it is not in a register or REG_PARM_STACK_SPACE is true.
Pad below when the argument is not in a register and the padding
direction is downward.
* pa-64.h (MUST_PASS_IN_STACK): Move define to pa.h.
(PAD_VARARGS_DOWN): Define.
* pa.c (function_arg_padding): Revise padding directions to make them
compatible with the 32 and 64-bit runtime architecture documentation.
(hppa_va_arg): Add code to handle variable and size zero arguments
passed by reference on TARGET_64BIT. Reformat.
(function_arg): Use a PARALLEL for BLKmode and aggregates args on
TARGET_64BIT. Use a DImode PARALLEL for BLKmode args 5 to 8 bytes
wide when !TARGET_64BIT. Move forward check for mode==VOIDmode.
Add comments.
* pa.h (MAX_PARM_BOUNDARY): Correct define for TARGET_64BIT.
(RETURN_IN_MEMORY): Return size zero types in memory.
(FUNCTION_VALUE): Return TFmode in general registers.
(MUST_PASS_IN_STACK): Define.
(FUNCTION_ARG_BOUNDARY): Simplify.
(FUNCTION_ARG_PASS_BY_REFERENCE): Pass variable and zero sized types
by reference.
(FUNCTION_ARG_CALLEE_COPIES): Define to FUNCTION_ARG_PASS_BY_REFERENCE.
2002-09-16 Richard Henderson <rth@redhat.com>
* real.c (do_fix_trunc): New.
......
......@@ -4491,6 +4491,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
{
/* BLKmode, at least partly to be pushed. */
unsigned int default_align = PARM_BOUNDARY;
int excess;
rtx size_rtx;
......@@ -4498,6 +4499,13 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
If part is passed in registers, PARTIAL says how much
and emit_push_insn will take care of putting it there. */
#ifdef ARGS_GROW_DOWNWARD
/* When an argument is padded down, the block is not aligned to
PARM_BOUNDARY. */
if (FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)) == downward)
default_align = BITS_PER_UNIT;
#endif
/* Round its size up to a multiple
of the allocation unit for arguments. */
......@@ -4573,7 +4581,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
{
rtx size_rtx1 = GEN_INT (reg_parm_stack_space - arg->offset.constant);
emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx1,
MAX (PARM_BOUNDARY, TYPE_ALIGN (TREE_TYPE (pval))),
MAX (default_align, TYPE_ALIGN (TREE_TYPE (pval))),
partial, reg, excess, argblock,
ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
ARGS_SIZE_RTX (arg->alignment_pad));
......@@ -4582,7 +4590,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
MAX (PARM_BOUNDARY, TYPE_ALIGN (TREE_TYPE (pval))),
MAX (default_align, TYPE_ALIGN (TREE_TYPE (pval))),
partial, reg, excess, argblock,
ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
ARGS_SIZE_RTX (arg->alignment_pad));
......
......@@ -88,8 +88,11 @@ Boston, MA 02111-1307, USA. */
#undef STATIC_CHAIN_REGNUM
#define STATIC_CHAIN_REGNUM 31
/* 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)))
/* If defined, a C expression which determines whether the default
implementation of va_arg will attempt to pad down before reading the
next argument, if that argument is smaller than its aligned space as
controlled by PARM_BOUNDARY. If this macro is not defined, all such
arguments are padded down when BYTES_BIG_ENDIAN is true. We don't
want aggregrates padded down. */
#define PAD_VARARGS_DOWN (!AGGREGATE_TYPE_P (type))
......@@ -407,7 +407,7 @@ extern int target_flags;
/* Largest alignment required for any stack parameter, in bits.
Don't define this if it is equal to PARM_BOUNDARY */
#define MAX_PARM_BOUNDARY 64
#define MAX_PARM_BOUNDARY (2 * PARM_BOUNDARY)
/* Boundary (in *bits*) on which stack pointer is always aligned;
certain optimizations in combine depend on this.
......@@ -506,9 +506,13 @@ extern struct rtx_def *hppa_pic_save_rtx PARAMS ((void));
PA64 ABI says that objects larger than 128 bits are returned in memory.
Note, int_size_in_bytes can return -1 if the size of the object is
variable or larger than the maximum value that can be expressed as
a HOST_WIDE_INT. */
a HOST_WIDE_INT. It can also return zero for an empty type. The
simplest way to handle variable and empty types is to pass them in
memory. This avoids problems in defining the boundaries of argument
slots, allocating registers, etc. */
#define RETURN_IN_MEMORY(TYPE) \
((unsigned HOST_WIDE_INT) int_size_in_bytes (TYPE) > (TARGET_64BIT ? 16 : 8))
(int_size_in_bytes (TYPE) > (TARGET_64BIT ? 16 : 8) \
|| int_size_in_bytes (TYPE) <= 0)
/* Register in which address to store a structure value
is passed to a function. */
......@@ -681,16 +685,18 @@ extern struct rtx_def *hppa_pic_save_rtx PARAMS ((void));
otherwise, FUNC is 0. */
/* On the HP-PA the value is found in register(s) 28(-29), unless
the mode is SF or DF. Then the value is returned in fr4 (32, ) */
the mode is SF or DF. Then the value is returned in fr4 (32). */
/* This must perform the same promotions as PROMOTE_MODE, else
PROMOTE_FUNCTION_RETURN will not work correctly. */
#define FUNCTION_VALUE(VALTYPE, FUNC) \
gen_rtx_REG (((INTEGRAL_TYPE_P (VALTYPE) \
&& TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
|| POINTER_TYPE_P (VALTYPE)) \
? word_mode : TYPE_MODE (VALTYPE), \
TREE_CODE (VALTYPE) == REAL_TYPE && !TARGET_SOFT_FLOAT ? 32 : 28)
#define FUNCTION_VALUE(VALTYPE, FUNC) \
gen_rtx_REG (((INTEGRAL_TYPE_P (VALTYPE) \
&& TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
|| POINTER_TYPE_P (VALTYPE)) \
? word_mode : TYPE_MODE (VALTYPE), \
(TREE_CODE (VALTYPE) == REAL_TYPE \
&& TYPE_MODE (VALTYPE) != TFmode \
&& !TARGET_SOFT_FLOAT) ? 32 : 28)
/* Define how to find the value returned by a library function
assuming the value has mode MODE. */
......@@ -745,7 +751,9 @@ struct hppa_args {int words, nargs_prototype, indirect; };
(CUM).indirect = 0, \
(CUM).nargs_prototype = 1000
/* Figure out the size in words of the function argument. */
/* Figure out the size in words of the function argument. The size
returned by this macro should always be greater than zero because
we pass variable and zero sized objects by reference. */
#define FUNCTION_ARG_SIZE(MODE, TYPE) \
((((MODE) != BLKmode \
......@@ -817,6 +825,12 @@ struct hppa_args {int words, nargs_prototype, indirect; };
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
function_arg (&CUM, MODE, TYPE, NAMED, 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 FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
function_arg (&CUM, MODE, TYPE, NAMED, 1)
......@@ -833,33 +847,37 @@ struct hppa_args {int words, nargs_prototype, indirect; };
bits, of an argument with the specified mode and type. If it is
not defined, `PARM_BOUNDARY' is used for all arguments. */
#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
(((TYPE) != 0) \
? ((integer_zerop (TYPE_SIZE (TYPE)) \
|| ! TREE_CONSTANT (TYPE_SIZE (TYPE))) \
? BITS_PER_UNIT \
: (((int_size_in_bytes (TYPE)) + UNITS_PER_WORD - 1) \
/ UNITS_PER_WORD) * BITS_PER_WORD) \
: ((GET_MODE_ALIGNMENT(MODE) <= PARM_BOUNDARY) \
? PARM_BOUNDARY : GET_MODE_ALIGNMENT(MODE)))
/* Arguments larger than eight bytes are passed by invisible reference */
/* PA64 does not pass anything by invisible reference. */
/* Arguments larger than one word are double word aligned. */
#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
(((TYPE) \
? (integer_zerop (TYPE_SIZE (TYPE)) \
|| !TREE_CONSTANT (TYPE_SIZE (TYPE)) \
|| int_size_in_bytes (TYPE) <= UNITS_PER_WORD) \
: GET_MODE_SIZE(MODE) <= UNITS_PER_WORD) \
? PARM_BOUNDARY : MAX_PARM_BOUNDARY)
/* In the 32-bit runtime, arguments larger than eight bytes are passed
by invisible reference. As a GCC extension, we also pass anything
with a zero or variable size by reference.
The 64-bit runtime does not describe passing any types by invisible
reference. The internals of GCC can't currently handle passing
empty structures, and zero or variable length arrays when they are
not passed entirely on the stack or by reference. Thus, as a GCC
extension, we pass these types by reference. The HP compiler doesn't
support these types, so hopefully there shouldn't be any compatibility
issues. This may have to be revisited when HP releases a C99 compiler
or updates the ABI. */
#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
(TARGET_64BIT \
? 0 \
: (((TYPE) && int_size_in_bytes (TYPE) > 8) \
? ((TYPE) && int_size_in_bytes (TYPE) <= 0) \
: (((TYPE) && (int_size_in_bytes (TYPE) > 8 \
|| int_size_in_bytes (TYPE) <= 0)) \
|| ((MODE) && GET_MODE_SIZE (MODE) > 8)))
/* PA64 does not pass anything by invisible reference.
This should be undef'ed for 64bit, but we'll see if this works. The
problem is that we can't test TARGET_64BIT from the preprocessor. */
#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \
(TARGET_64BIT \
? 0 \
: (((TYPE) && int_size_in_bytes (TYPE) > 8) \
|| ((MODE) && GET_MODE_SIZE (MODE) > 8)))
#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \
FUNCTION_ARG_PASS_BY_REFERENCE (CUM, MODE, TYPE, NAMED)
extern GTY(()) rtx hppa_compare_op0;
......
......@@ -255,10 +255,8 @@ static int instantiate_virtual_regs_1 PARAMS ((rtx *, rtx, int));
static void delete_handlers PARAMS ((void));
static void pad_to_arg_alignment PARAMS ((struct args_size *, int,
struct args_size *));
#ifndef ARGS_GROW_DOWNWARD
static void pad_below PARAMS ((struct args_size *, enum machine_mode,
tree));
#endif
static rtx round_trampoline_addr PARAMS ((rtx));
static rtx adjust_trampoline_addr PARAMS ((rtx));
static tree *identify_blocks_1 PARAMS ((rtx, tree *, tree *, tree *));
......@@ -5244,6 +5242,9 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
= type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode));
enum direction where_pad = FUNCTION_ARG_PADDING (passed_mode, type);
int boundary = FUNCTION_ARG_BOUNDARY (passed_mode, type);
#ifdef ARGS_GROW_DOWNWARD
tree s2 = sizetree;
#endif
#ifdef REG_PARM_STACK_SPACE
/* If we have found a stack parm before we reach the end of the
......@@ -5289,13 +5290,20 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
offset_ptr->constant = -initial_offset_ptr->constant;
offset_ptr->var = 0;
}
if (where_pad != none
&& (!host_integerp (sizetree, 1)
|| (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % PARM_BOUNDARY))
sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
SUB_PARM_SIZE (*offset_ptr, sizetree);
if (where_pad != downward)
s2 = round_up (s2, PARM_BOUNDARY / BITS_PER_UNIT);
SUB_PARM_SIZE (*offset_ptr, s2);
if (!in_regs
#ifdef REG_PARM_STACK_SPACE
|| REG_PARM_STACK_SPACE (fndecl) > 0
#endif
)
pad_to_arg_alignment (offset_ptr, boundary, alignment_pad);
if (initial_offset_ptr->var)
arg_size_ptr->var = size_binop (MINUS_EXPR,
size_binop (MINUS_EXPR,
......@@ -5307,6 +5315,13 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
arg_size_ptr->constant = (-initial_offset_ptr->constant
- offset_ptr->constant);
/* Pad_below needs the pre-rounded size to know how much to pad below.
We only pad parameters which are not in registers as they have their
padding done elsewhere. */
if (where_pad == downward
&& !in_regs)
pad_below (offset_ptr, passed_mode, sizetree);
#else /* !ARGS_GROW_DOWNWARD */
if (!in_regs
#ifdef REG_PARM_STACK_SPACE
......@@ -5392,7 +5407,6 @@ pad_to_arg_alignment (offset_ptr, boundary, alignment_pad)
}
}
#ifndef ARGS_GROW_DOWNWARD
static void
pad_below (offset_ptr, passed_mode, sizetree)
struct args_size *offset_ptr;
......@@ -5420,7 +5434,6 @@ pad_below (offset_ptr, passed_mode, sizetree)
}
}
}
#endif
/* Walk the tree of blocks describing the binding levels within a function
and warn about uninitialized variables.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment