diff options
author | John David Anglin <dave@hiauly1.hia.nrc.ca> | 2002-09-17 03:30:37 +0000 |
---|---|---|
committer | John David Anglin <danglin@gcc.gnu.org> | 2002-09-17 03:30:37 +0000 |
commit | 9dff28ab5386ec651699c6245823e3e2c68d1c64 (patch) | |
tree | 9562fab54c7f71944f468dd8ea88012248c2545e /gcc | |
parent | 94313f351a9d53ae192d425c82b023b895827009 (diff) | |
download | gcc-9dff28ab5386ec651699c6245823e3e2c68d1c64.zip gcc-9dff28ab5386ec651699c6245823e3e2c68d1c64.tar.gz gcc-9dff28ab5386ec651699c6245823e3e2c68d1c64.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 30 | ||||
-rw-r--r-- | gcc/calls.c | 12 | ||||
-rw-r--r-- | gcc/config/pa/pa-64.h | 13 | ||||
-rw-r--r-- | gcc/config/pa/pa.c | 205 | ||||
-rw-r--r-- | gcc/config/pa/pa.h | 86 | ||||
-rw-r--r-- | gcc/function.c | 27 |
6 files changed, 260 insertions, 113 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 06a2ff9..abaa25a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/calls.c b/gcc/calls.c index 665868f..578bd98 100644 --- a/gcc/calls.c +++ b/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)); diff --git a/gcc/config/pa/pa-64.h b/gcc/config/pa/pa-64.h index 82ce3ef..646f5f1 100644 --- a/gcc/config/pa/pa-64.h +++ b/gcc/config/pa/pa-64.h @@ -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)) diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 2d65539..e9679a7 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -5089,22 +5089,33 @@ function_arg_padding (mode, type) enum machine_mode mode; tree type; { - int size; - - if (mode == BLKmode) - { - if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) - size = int_size_in_bytes (type) * BITS_PER_UNIT; + if (mode == BLKmode + || (TARGET_64BIT && type && AGGREGATE_TYPE_P (type))) + { + /* 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); + if (size > 0) + return std_expand_builtin_va_arg (valist, type); + else + { + 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; + /* 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; + 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; + t = build1 (INDIRECT_REF, ptr, t); + TREE_SIDE_EFFECTS (t) = 1; + } } - else + else /* !TARGET_64BIT */ { - t = build (PLUS_EXPR, TREE_TYPE (valist), valist, - build_int_2 (-size, -1)); + ptr = build_pointer_type (type); - /* 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)); + /* "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; - t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t); - TREE_SIDE_EFFECTS (t) = 1; + pptr = build_pointer_type (ptr); + t = build1 (NOP_EXPR, pptr, 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)); + 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; + 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 { diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index 04e417f..aeef60f 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -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; diff --git a/gcc/function.c b/gcc/function.c index 424f06c..edc1581 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -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. |