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
This commit is contained in:
parent
94313f351a
commit
9dff28ab53
@ -1,3 +1,33 @@
|
||||
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.
|
||||
|
12
gcc/calls.c
12
gcc/calls.c
@ -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))
|
||||
|
@ -5089,22 +5089,33 @@ function_arg_padding (mode, type)
|
||||
enum machine_mode mode;
|
||||
tree type;
|
||||
{
|
||||
int size;
|
||||
|
||||
if (mode == BLKmode)
|
||||
if (mode == BLKmode
|
||||
|| (TARGET_64BIT && type && AGGREGATE_TYPE_P (type)))
|
||||
{
|
||||
if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
|
||||
size = int_size_in_bytes (type) * BITS_PER_UNIT;
|
||||
/* Return 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;
|
||||
|
||||
/* 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
|
||||
return upward; /* Don't know if this is right, but */
|
||||
/* same as old definition. */
|
||||
/* 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;
|
||||
}
|
||||
else
|
||||
size = GET_MODE_BITSIZE (mode);
|
||||
if (size < PARM_BOUNDARY)
|
||||
|
||||
if (GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)
|
||||
return downward;
|
||||
else if (size % PARM_BOUNDARY)
|
||||
return upward;
|
||||
else
|
||||
return none;
|
||||
}
|
||||
@ -5196,15 +5207,23 @@ rtx
|
||||
hppa_va_arg (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;
|
||||
|
||||
if (TARGET_64BIT)
|
||||
{
|
||||
/* Every argument in PA64 is passed by value (including large structs).
|
||||
Arguments with size greater than 8 must be aligned 0 MOD 16. */
|
||||
/* Every argument in PA64 is supposed to be passed by value
|
||||
(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)
|
||||
{
|
||||
t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
|
||||
@ -5213,57 +5232,75 @@ hppa_va_arg (valist, type)
|
||||
build_int_2 (-2 * UNITS_PER_WORD, -1));
|
||||
t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
|
||||
TREE_SIDE_EFFECTS (t) = 1;
|
||||
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||
}
|
||||
return std_expand_builtin_va_arg (valist, type);
|
||||
}
|
||||
|
||||
/* Compute the rounded size of the type. */
|
||||
align = PARM_BOUNDARY / BITS_PER_UNIT;
|
||||
size = int_size_in_bytes (type);
|
||||
|
||||
ptr = build_pointer_type (type);
|
||||
|
||||
/* "Large" types are passed by reference. */
|
||||
if (size > 8)
|
||||
{
|
||||
t = build (PREDECREMENT_EXPR, TREE_TYPE (valist), valist,
|
||||
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
|
||||
{
|
||||
t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
|
||||
build_int_2 (-size, -1));
|
||||
|
||||
/* Copied from va-pa.h, but we probably don't need to align
|
||||
to word size, since we generate and preserve that invariant. */
|
||||
t = build (BIT_AND_EXPR, TREE_TYPE (valist), t,
|
||||
build_int_2 ((size > 4 ? -8 : -4), -1));
|
||||
|
||||
t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
|
||||
TREE_SIDE_EFFECTS (t) = 1;
|
||||
|
||||
ofs = (8 - size) % 4;
|
||||
if (ofs)
|
||||
if (size > 0)
|
||||
return std_expand_builtin_va_arg (valist, type);
|
||||
else
|
||||
{
|
||||
t = build (PLUS_EXPR, TREE_TYPE (valist), t, build_int_2 (ofs, 0));
|
||||
ptr = build_pointer_type (type);
|
||||
|
||||
/* Args grow upward. */
|
||||
t = build (POSTINCREMENT_EXPR, TREE_TYPE (valist), valist,
|
||||
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);
|
||||
|
||||
t = build1 (NOP_EXPR, ptr, t);
|
||||
TREE_SIDE_EFFECTS (t) = 1;
|
||||
/* "Large" and variable sized types are passed by reference. */
|
||||
if (size > 8 || size <= 0)
|
||||
{
|
||||
/* Args grow downward. */
|
||||
t = build (PREDECREMENT_EXPR, TREE_TYPE (valist), valist,
|
||||
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
|
||||
{
|
||||
t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
|
||||
build_int_2 (-size, -1));
|
||||
|
||||
/* Copied from va-pa.h, but we probably don't need to align to
|
||||
word size, since we generate and preserve that invariant. */
|
||||
t = build (BIT_AND_EXPR, TREE_TYPE (valist), t,
|
||||
build_int_2 ((size > 4 ? -8 : -4), -1));
|
||||
|
||||
t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
|
||||
TREE_SIDE_EFFECTS (t) = 1;
|
||||
|
||||
ofs = (8 - size) % 4;
|
||||
if (ofs)
|
||||
{
|
||||
t = build (PLUS_EXPR, TREE_TYPE (valist), t,
|
||||
build_int_2 (ofs, 0));
|
||||
TREE_SIDE_EFFECTS (t) = 1;
|
||||
}
|
||||
|
||||
t = build1 (NOP_EXPR, ptr, t);
|
||||
TREE_SIDE_EFFECTS (t) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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)
|
||||
int incoming;
|
||||
{
|
||||
int max_arg_words = (TARGET_64BIT ? 8 : 4);
|
||||
int arg_size = FUNCTION_ARG_SIZE (mode, type);
|
||||
int alignment = 0;
|
||||
int arg_size;
|
||||
int fpr_reg_base;
|
||||
int gpr_reg_base;
|
||||
rtx retval;
|
||||
|
||||
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
|
||||
this routine should return zero. FUNCTION_ARG_PARTIAL_NREGS will
|
||||
handle arguments which are split between regs and stack slots if
|
||||
the ABI mandates split arguments. */
|
||||
if (! TARGET_64BIT)
|
||||
{
|
||||
/* If this arg would be passed partially or totally on the stack, then
|
||||
this routine should return zero. FUNCTION_ARG_PARTIAL_NREGS will
|
||||
handle arguments which are split between regs and stack slots if
|
||||
the ABI mandates split arguments. */
|
||||
if (cum->words + arg_size > max_arg_words
|
||||
|| mode == VOIDmode)
|
||||
/* The 32-bit ABI does not split arguments. */
|
||||
if (cum->words + arg_size > max_arg_words)
|
||||
return NULL_RTX;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (arg_size > 1)
|
||||
alignment = cum->words & 1;
|
||||
if (cum->words + alignment >= max_arg_words
|
||||
|| mode == VOIDmode)
|
||||
if (cum->words + alignment >= max_arg_words)
|
||||
return NULL_RTX;
|
||||
}
|
||||
|
||||
@ -7488,8 +7529,11 @@ function_arg (cum, mode, type, named, incoming)
|
||||
gpr_reg_base = 26 - cum->words;
|
||||
fpr_reg_base = 32 + cum->words;
|
||||
|
||||
/* Arguments wider than one word need special treatment. */
|
||||
if (arg_size > 1)
|
||||
/* Arguments wider than one word and small aggregates need special
|
||||
treatment. */
|
||||
if (arg_size > 1
|
||||
|| mode == BLKmode
|
||||
|| (type && AGGREGATE_TYPE_P (type)))
|
||||
{
|
||||
/* Double-extended precision (80-bit), quad-precision (128-bit)
|
||||
and aggregates including complex numbers are aligned on
|
||||
@ -7497,7 +7541,10 @@ function_arg (cum, mode, type, named, incoming)
|
||||
are associated one-to-one, with general registers r26
|
||||
through r19, and also with floating-point registers fr4
|
||||
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];
|
||||
int i, offset = 0, ub = arg_size;
|
||||
@ -7517,7 +7564,7 @@ function_arg (cum, mode, type, named, incoming)
|
||||
|
||||
return gen_rtx_PARALLEL (mode, gen_rtvec_v (ub, loc));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the argument is larger than a word, then we know precisely
|
||||
@ -7534,6 +7581,34 @@ function_arg (cum, mode, type, named, incoming)
|
||||
gpr_reg_base = 25;
|
||||
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
|
||||
{
|
||||
|
@ -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 one word are double word aligned. */
|
||||
|
||||
/* Arguments larger than eight bytes are passed by invisible reference */
|
||||
#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)
|
||||
|
||||
/* PA64 does not pass anything by invisible reference. */
|
||||
/* 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.
|
||||
|
Loading…
Reference in New Issue
Block a user