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> 2002-09-16 Richard Henderson <rth@redhat.com>
* real.c (do_fix_trunc): New. * real.c (do_fix_trunc): New.
......
...@@ -4491,6 +4491,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) ...@@ -4491,6 +4491,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
{ {
/* BLKmode, at least partly to be pushed. */ /* BLKmode, at least partly to be pushed. */
unsigned int default_align = PARM_BOUNDARY;
int excess; int excess;
rtx size_rtx; rtx size_rtx;
...@@ -4498,6 +4499,13 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) ...@@ -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 If part is passed in registers, PARTIAL says how much
and emit_push_insn will take care of putting it there. */ 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 /* Round its size up to a multiple
of the allocation unit for arguments. */ of the allocation unit for arguments. */
...@@ -4573,7 +4581,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) ...@@ -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); rtx size_rtx1 = GEN_INT (reg_parm_stack_space - arg->offset.constant);
emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx1, 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, partial, reg, excess, argblock,
ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space, ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
ARGS_SIZE_RTX (arg->alignment_pad)); ARGS_SIZE_RTX (arg->alignment_pad));
...@@ -4582,7 +4590,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) ...@@ -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, 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, partial, reg, excess, argblock,
ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space, ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
ARGS_SIZE_RTX (arg->alignment_pad)); ARGS_SIZE_RTX (arg->alignment_pad));
......
...@@ -88,8 +88,11 @@ Boston, MA 02111-1307, USA. */ ...@@ -88,8 +88,11 @@ Boston, MA 02111-1307, USA. */
#undef STATIC_CHAIN_REGNUM #undef STATIC_CHAIN_REGNUM
#define STATIC_CHAIN_REGNUM 31 #define STATIC_CHAIN_REGNUM 31
/* Nonzero if we do not know how to pass TYPE solely in registers. */ /* If defined, a C expression which determines whether the default
#define MUST_PASS_IN_STACK(MODE,TYPE) \ implementation of va_arg will attempt to pad down before reading the
((TYPE) != 0 \ next argument, if that argument is smaller than its aligned space as
&& (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ controlled by PARM_BOUNDARY. If this macro is not defined, all such
|| TREE_ADDRESSABLE (TYPE))) 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))
...@@ -5089,22 +5089,33 @@ function_arg_padding (mode, type) ...@@ -5089,22 +5089,33 @@ function_arg_padding (mode, type)
enum machine_mode mode; enum machine_mode mode;
tree type; tree type;
{ {
int size; if (mode == BLKmode
|| (TARGET_64BIT && type && AGGREGATE_TYPE_P (type)))
if (mode == BLKmode)
{ {
if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) /* Return none if justification is not required. */
size = int_size_in_bytes (type) * BITS_PER_UNIT; if (type
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
&& (int_size_in_bytes (type) * BITS_PER_UNIT) % PARM_BOUNDARY == 0)
return 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 registers. This makes it difficult to have a
consistent data representation for both the stack and registers.
For both runtimes, the justification and padding for arguments on
the stack and in registers should be identical. */
if (TARGET_64BIT)
/* The 64-bit runtime specifies left justification for aggregates. */
return upward;
else else
return upward; /* Don't know if this is right, but */ /* The 32-bit runtime architecture specifies right justification.
/* same as old definition. */ 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;
} }
else
size = GET_MODE_BITSIZE (mode); if (GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)
if (size < PARM_BOUNDARY)
return downward; return downward;
else if (size % PARM_BOUNDARY)
return upward;
else else
return none; return none;
} }
...@@ -5196,15 +5207,23 @@ rtx ...@@ -5196,15 +5207,23 @@ rtx
hppa_va_arg (valist, type) hppa_va_arg (valist, type)
tree valist, type; tree valist, type;
{ {
HOST_WIDE_INT align, size, ofs; HOST_WIDE_INT size = int_size_in_bytes (type);
HOST_WIDE_INT ofs;
tree t, ptr, pptr; tree t, ptr, pptr;
if (TARGET_64BIT) if (TARGET_64BIT)
{ {
/* Every argument in PA64 is passed by value (including large structs). /* Every argument in PA64 is supposed to be passed by value
Arguments with size greater than 8 must be aligned 0 MOD 16. */ (including large structs). However, as a GCC extension, we
pass zero and variable sized arguments by reference. Empty
structures are a GCC extension not supported by the HP
compilers. Thus, passing them by reference isn't likely
to conflict with the ABI. For variable sized arguments,
GCC doesn't have the infrastructure to allocate these to
registers. */
/* Arguments with a size greater than 8 must be aligned 0 MOD 16. */
size = int_size_in_bytes (type);
if (size > UNITS_PER_WORD) if (size > UNITS_PER_WORD)
{ {
t = build (PLUS_EXPR, TREE_TYPE (valist), valist, t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
...@@ -5215,18 +5234,34 @@ hppa_va_arg (valist, type) ...@@ -5215,18 +5234,34 @@ hppa_va_arg (valist, type)
TREE_SIDE_EFFECTS (t) = 1; TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
} }
if (size > 0)
return std_expand_builtin_va_arg (valist, type); return std_expand_builtin_va_arg (valist, type);
} else
{
ptr = build_pointer_type (type);
/* Compute the rounded size of the type. */ /* Args grow upward. */
align = PARM_BOUNDARY / BITS_PER_UNIT; t = build (POSTINCREMENT_EXPR, TREE_TYPE (valist), valist,
size = int_size_in_bytes (type); build_int_2 (POINTER_SIZE / BITS_PER_UNIT, 0));
TREE_SIDE_EFFECTS (t) = 1;
pptr = build_pointer_type (ptr);
t = build1 (NOP_EXPR, pptr, t);
TREE_SIDE_EFFECTS (t) = 1;
t = build1 (INDIRECT_REF, ptr, t);
TREE_SIDE_EFFECTS (t) = 1;
}
}
else /* !TARGET_64BIT */
{
ptr = build_pointer_type (type); ptr = build_pointer_type (type);
/* "Large" types are passed by reference. */ /* "Large" and variable sized types are passed by reference. */
if (size > 8) if (size > 8 || size <= 0)
{ {
/* Args grow downward. */
t = build (PREDECREMENT_EXPR, TREE_TYPE (valist), valist, t = build (PREDECREMENT_EXPR, TREE_TYPE (valist), valist,
build_int_2 (POINTER_SIZE / BITS_PER_UNIT, 0)); build_int_2 (POINTER_SIZE / BITS_PER_UNIT, 0));
TREE_SIDE_EFFECTS (t) = 1; TREE_SIDE_EFFECTS (t) = 1;
...@@ -5243,8 +5278,8 @@ hppa_va_arg (valist, type) ...@@ -5243,8 +5278,8 @@ hppa_va_arg (valist, type)
t = build (PLUS_EXPR, TREE_TYPE (valist), valist, t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
build_int_2 (-size, -1)); build_int_2 (-size, -1));
/* Copied from va-pa.h, but we probably don't need to align /* Copied from va-pa.h, but we probably don't need to align to
to word size, since we generate and preserve that invariant. */ word size, since we generate and preserve that invariant. */
t = build (BIT_AND_EXPR, TREE_TYPE (valist), t, t = build (BIT_AND_EXPR, TREE_TYPE (valist), t,
build_int_2 ((size > 4 ? -8 : -4), -1)); build_int_2 ((size > 4 ? -8 : -4), -1));
...@@ -5254,16 +5289,18 @@ hppa_va_arg (valist, type) ...@@ -5254,16 +5289,18 @@ hppa_va_arg (valist, type)
ofs = (8 - size) % 4; ofs = (8 - size) % 4;
if (ofs) if (ofs)
{ {
t = build (PLUS_EXPR, TREE_TYPE (valist), t, build_int_2 (ofs, 0)); t = build (PLUS_EXPR, TREE_TYPE (valist), t,
build_int_2 (ofs, 0));
TREE_SIDE_EFFECTS (t) = 1; TREE_SIDE_EFFECTS (t) = 1;
} }
t = build1 (NOP_EXPR, ptr, t); t = build1 (NOP_EXPR, ptr, t);
TREE_SIDE_EFFECTS (t) = 1; TREE_SIDE_EFFECTS (t) = 1;
} }
}
/* Calculate! */ /* Calculate! */
return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL); return expand_expr (t, NULL_RTX, VOIDmode, EXPAND_NORMAL);
} }
...@@ -7446,28 +7483,32 @@ function_arg (cum, mode, type, named, incoming) ...@@ -7446,28 +7483,32 @@ function_arg (cum, mode, type, named, incoming)
int incoming; int incoming;
{ {
int max_arg_words = (TARGET_64BIT ? 8 : 4); int max_arg_words = (TARGET_64BIT ? 8 : 4);
int arg_size = FUNCTION_ARG_SIZE (mode, type);
int alignment = 0; int alignment = 0;
int arg_size;
int fpr_reg_base; int fpr_reg_base;
int gpr_reg_base; int gpr_reg_base;
rtx retval; rtx retval;
if (! TARGET_64BIT) if (mode == VOIDmode)
{ return NULL_RTX;
arg_size = FUNCTION_ARG_SIZE (mode, type);
/* If this arg would be passed partially or totally on the stack, then /* If this arg would be passed partially or totally on the stack, then
this routine should return zero. FUNCTION_ARG_PARTIAL_NREGS will this routine should return zero. FUNCTION_ARG_PARTIAL_NREGS will
handle arguments which are split between regs and stack slots if handle arguments which are split between regs and stack slots if
the ABI mandates split arguments. */ the ABI mandates split arguments. */
if (cum->words + arg_size > max_arg_words if (! TARGET_64BIT)
|| mode == VOIDmode) {
/* The 32-bit ABI does not split arguments. */
if (cum->words + arg_size > max_arg_words)
return NULL_RTX; return NULL_RTX;
} }
else else
{ {
if (arg_size > 1) if (arg_size > 1)
alignment = cum->words & 1; alignment = cum->words & 1;
if (cum->words + alignment >= max_arg_words if (cum->words + alignment >= max_arg_words)
|| mode == VOIDmode)
return NULL_RTX; return NULL_RTX;
} }
...@@ -7488,8 +7529,11 @@ function_arg (cum, mode, type, named, incoming) ...@@ -7488,8 +7529,11 @@ function_arg (cum, mode, type, named, incoming)
gpr_reg_base = 26 - cum->words; gpr_reg_base = 26 - cum->words;
fpr_reg_base = 32 + cum->words; fpr_reg_base = 32 + cum->words;
/* Arguments wider than one word need special treatment. */ /* Arguments wider than one word and small aggregates need special
if (arg_size > 1) treatment. */
if (arg_size > 1
|| mode == BLKmode
|| (type && AGGREGATE_TYPE_P (type)))
{ {
/* Double-extended precision (80-bit), quad-precision (128-bit) /* Double-extended precision (80-bit), quad-precision (128-bit)
and aggregates including complex numbers are aligned on and aggregates including complex numbers are aligned on
...@@ -7497,7 +7541,10 @@ function_arg (cum, mode, type, named, incoming) ...@@ -7497,7 +7541,10 @@ function_arg (cum, mode, type, named, incoming)
are associated one-to-one, with general registers r26 are associated one-to-one, with general registers r26
through r19, and also with floating-point registers fr4 through r19, and also with floating-point registers fr4
through fr11. Arguments larger than one word are always through fr11. Arguments larger than one word are always
passed in general registers. */ passed in general registers.
Using a PARALLEL with a word mode register results in left
justified data on a big-endian target. */
rtx loc[8]; rtx loc[8];
int i, offset = 0, ub = arg_size; int i, offset = 0, ub = arg_size;
...@@ -7534,6 +7581,34 @@ function_arg (cum, mode, type, named, incoming) ...@@ -7534,6 +7581,34 @@ function_arg (cum, mode, type, named, incoming)
gpr_reg_base = 25; gpr_reg_base = 25;
fpr_reg_base = 34; fpr_reg_base = 34;
} }
/* Structures 5 to 8 bytes in size are passed in the general
registers in the same manner as other non floating-point
objects. The data is right-justified and zero-extended
to 64 bits.
This is magic. Normally, using a PARALLEL results in left
justified data on a big-endian target. However, using a
single double-word register provides the required right
justication for 5 to 8 byte structures. This has nothing
to do with the direction of padding specified for the argument.
It has to do with how the data is widened and shifted into
and from the register.
Aside from adding load_multiple and store_multiple patterns,
this is the only way that I have found to obtain right
justification of BLKmode data when it has a size greater
than one word. Splitting the operation into two SImode loads
or returning a DImode REG results in left justified data. */
if (mode == BLKmode)
{
rtx loc[1];
loc[0] = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (DImode, gpr_reg_base),
const0_rtx);
return gen_rtx_PARALLEL (mode, gen_rtvec_v (1, loc));
}
} }
else else
{ {
......
...@@ -407,7 +407,7 @@ extern int target_flags; ...@@ -407,7 +407,7 @@ extern int target_flags;
/* Largest alignment required for any stack parameter, in bits. /* Largest alignment required for any stack parameter, in bits.
Don't define this if it is equal to PARM_BOUNDARY */ 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; /* Boundary (in *bits*) on which stack pointer is always aligned;
certain optimizations in combine depend on this. certain optimizations in combine depend on this.
...@@ -506,9 +506,13 @@ extern struct rtx_def *hppa_pic_save_rtx PARAMS ((void)); ...@@ -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. 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 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 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) \ #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 /* Register in which address to store a structure value
is passed to a function. */ is passed to a function. */
...@@ -681,7 +685,7 @@ extern struct rtx_def *hppa_pic_save_rtx PARAMS ((void)); ...@@ -681,7 +685,7 @@ extern struct rtx_def *hppa_pic_save_rtx PARAMS ((void));
otherwise, FUNC is 0. */ otherwise, FUNC is 0. */
/* On the HP-PA the value is found in register(s) 28(-29), unless /* 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 /* This must perform the same promotions as PROMOTE_MODE, else
PROMOTE_FUNCTION_RETURN will not work correctly. */ PROMOTE_FUNCTION_RETURN will not work correctly. */
...@@ -690,7 +694,9 @@ extern struct rtx_def *hppa_pic_save_rtx PARAMS ((void)); ...@@ -690,7 +694,9 @@ extern struct rtx_def *hppa_pic_save_rtx PARAMS ((void));
&& TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \ && TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
|| POINTER_TYPE_P (VALTYPE)) \ || POINTER_TYPE_P (VALTYPE)) \
? word_mode : TYPE_MODE (VALTYPE), \ ? word_mode : TYPE_MODE (VALTYPE), \
TREE_CODE (VALTYPE) == REAL_TYPE && !TARGET_SOFT_FLOAT ? 32 : 28) (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 /* Define how to find the value returned by a library function
assuming the value has mode MODE. */ assuming the value has mode MODE. */
...@@ -745,7 +751,9 @@ struct hppa_args {int words, nargs_prototype, indirect; }; ...@@ -745,7 +751,9 @@ struct hppa_args {int words, nargs_prototype, indirect; };
(CUM).indirect = 0, \ (CUM).indirect = 0, \
(CUM).nargs_prototype = 1000 (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) \ #define FUNCTION_ARG_SIZE(MODE, TYPE) \
((((MODE) != BLKmode \ ((((MODE) != BLKmode \
...@@ -817,6 +825,12 @@ struct hppa_args {int words, nargs_prototype, indirect; }; ...@@ -817,6 +825,12 @@ struct hppa_args {int words, nargs_prototype, indirect; };
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
function_arg (&CUM, MODE, TYPE, NAMED, 0) 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) \ #define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
function_arg (&CUM, MODE, TYPE, NAMED, 1) function_arg (&CUM, MODE, TYPE, NAMED, 1)
...@@ -833,33 +847,37 @@ struct hppa_args {int words, nargs_prototype, indirect; }; ...@@ -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 bits, of an argument with the specified mode and type. If it is
not defined, `PARM_BOUNDARY' is used for all arguments. */ not defined, `PARM_BOUNDARY' is used for all arguments. */
/* Arguments larger than one word are double word aligned. */
#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ #define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
(((TYPE) != 0) \ (((TYPE) \
? ((integer_zerop (TYPE_SIZE (TYPE)) \ ? (integer_zerop (TYPE_SIZE (TYPE)) \
|| ! TREE_CONSTANT (TYPE_SIZE (TYPE))) \ || !TREE_CONSTANT (TYPE_SIZE (TYPE)) \
? BITS_PER_UNIT \ || int_size_in_bytes (TYPE) <= UNITS_PER_WORD) \
: (((int_size_in_bytes (TYPE)) + UNITS_PER_WORD - 1) \ : GET_MODE_SIZE(MODE) <= UNITS_PER_WORD) \
/ UNITS_PER_WORD) * BITS_PER_WORD) \ ? PARM_BOUNDARY : MAX_PARM_BOUNDARY)
: ((GET_MODE_ALIGNMENT(MODE) <= PARM_BOUNDARY) \
? PARM_BOUNDARY : GET_MODE_ALIGNMENT(MODE))) /* In the 32-bit runtime, arguments larger than eight bytes are passed
by invisible reference. As a GCC extension, we also pass anything
/* Arguments larger than eight bytes are passed by invisible reference */ with a zero or variable size by reference.
/* PA64 does not pass anything by invisible 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) \ #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
(TARGET_64BIT \ (TARGET_64BIT \
? 0 \ ? ((TYPE) && int_size_in_bytes (TYPE) <= 0) \
: (((TYPE) && int_size_in_bytes (TYPE) > 8) \ : (((TYPE) && (int_size_in_bytes (TYPE) > 8 \
|| int_size_in_bytes (TYPE) <= 0)) \
|| ((MODE) && GET_MODE_SIZE (MODE) > 8))) || ((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) \ #define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \
(TARGET_64BIT \ FUNCTION_ARG_PASS_BY_REFERENCE (CUM, MODE, TYPE, NAMED)
? 0 \
: (((TYPE) && int_size_in_bytes (TYPE) > 8) \
|| ((MODE) && GET_MODE_SIZE (MODE) > 8)))
extern GTY(()) rtx hppa_compare_op0; extern GTY(()) rtx hppa_compare_op0;
......
...@@ -255,10 +255,8 @@ static int instantiate_virtual_regs_1 PARAMS ((rtx *, rtx, int)); ...@@ -255,10 +255,8 @@ static int instantiate_virtual_regs_1 PARAMS ((rtx *, rtx, int));
static void delete_handlers PARAMS ((void)); static void delete_handlers PARAMS ((void));
static void pad_to_arg_alignment PARAMS ((struct args_size *, int, static void pad_to_arg_alignment PARAMS ((struct args_size *, int,
struct args_size *)); struct args_size *));
#ifndef ARGS_GROW_DOWNWARD
static void pad_below PARAMS ((struct args_size *, enum machine_mode, static void pad_below PARAMS ((struct args_size *, enum machine_mode,
tree)); tree));
#endif
static rtx round_trampoline_addr PARAMS ((rtx)); static rtx round_trampoline_addr PARAMS ((rtx));
static rtx adjust_trampoline_addr PARAMS ((rtx)); static rtx adjust_trampoline_addr PARAMS ((rtx));
static tree *identify_blocks_1 PARAMS ((rtx, tree *, tree *, tree *)); static tree *identify_blocks_1 PARAMS ((rtx, tree *, tree *, tree *));
...@@ -5244,6 +5242,9 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl, ...@@ -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)); = type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode));
enum direction where_pad = FUNCTION_ARG_PADDING (passed_mode, type); enum direction where_pad = FUNCTION_ARG_PADDING (passed_mode, type);
int boundary = FUNCTION_ARG_BOUNDARY (passed_mode, type); int boundary = FUNCTION_ARG_BOUNDARY (passed_mode, type);
#ifdef ARGS_GROW_DOWNWARD
tree s2 = sizetree;
#endif
#ifdef REG_PARM_STACK_SPACE #ifdef REG_PARM_STACK_SPACE
/* If we have found a stack parm before we reach the end of the /* 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, ...@@ -5289,13 +5290,20 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
offset_ptr->constant = -initial_offset_ptr->constant; offset_ptr->constant = -initial_offset_ptr->constant;
offset_ptr->var = 0; offset_ptr->var = 0;
} }
if (where_pad != none if (where_pad != none
&& (!host_integerp (sizetree, 1) && (!host_integerp (sizetree, 1)
|| (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % PARM_BOUNDARY)) || (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % PARM_BOUNDARY))
sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT); s2 = round_up (s2, PARM_BOUNDARY / BITS_PER_UNIT);
SUB_PARM_SIZE (*offset_ptr, sizetree); SUB_PARM_SIZE (*offset_ptr, s2);
if (where_pad != downward)
if (!in_regs
#ifdef REG_PARM_STACK_SPACE
|| REG_PARM_STACK_SPACE (fndecl) > 0
#endif
)
pad_to_arg_alignment (offset_ptr, boundary, alignment_pad); pad_to_arg_alignment (offset_ptr, boundary, alignment_pad);
if (initial_offset_ptr->var) if (initial_offset_ptr->var)
arg_size_ptr->var = size_binop (MINUS_EXPR, arg_size_ptr->var = size_binop (MINUS_EXPR,
size_binop (MINUS_EXPR, size_binop (MINUS_EXPR,
...@@ -5307,6 +5315,13 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl, ...@@ -5307,6 +5315,13 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
arg_size_ptr->constant = (-initial_offset_ptr->constant arg_size_ptr->constant = (-initial_offset_ptr->constant
- 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 */ #else /* !ARGS_GROW_DOWNWARD */
if (!in_regs if (!in_regs
#ifdef REG_PARM_STACK_SPACE #ifdef REG_PARM_STACK_SPACE
...@@ -5392,7 +5407,6 @@ pad_to_arg_alignment (offset_ptr, boundary, alignment_pad) ...@@ -5392,7 +5407,6 @@ pad_to_arg_alignment (offset_ptr, boundary, alignment_pad)
} }
} }
#ifndef ARGS_GROW_DOWNWARD
static void static void
pad_below (offset_ptr, passed_mode, sizetree) pad_below (offset_ptr, passed_mode, sizetree)
struct args_size *offset_ptr; struct args_size *offset_ptr;
...@@ -5420,7 +5434,6 @@ pad_below (offset_ptr, passed_mode, sizetree) ...@@ -5420,7 +5434,6 @@ pad_below (offset_ptr, passed_mode, sizetree)
} }
} }
} }
#endif
/* Walk the tree of blocks describing the binding levels within a function /* Walk the tree of blocks describing the binding levels within a function
and warn about uninitialized variables. 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