summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>2003-05-02 14:22:09 +0000
committeramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>2003-05-02 14:22:09 +0000
commit241399f6793dac1fdefa6b6c7c33cabe1c4f1cc9 (patch)
tree3499480542d5aee3c1e4cc0cd83f51a439861617
parent30e87df7d5b99e14e55e7f93055e8481ffff587a (diff)
downloadgcc-241399f6793dac1fdefa6b6c7c33cabe1c4f1cc9.tar.gz
* calls.c (struct arg_data): Move offset, slot_offset, size and
alignment_pad to struct locate_and_pad_arg_data. Update all refs. (initialize_argument_information): Adjust call to locate_and_pad_parm. Delete alignment_pad var. Don't calculate slot_offset here. (emit_library_call_value_1): Delete alignment_pad, offset and size vars. Use struct locate_and_pad_arg_data instead. Adjust refs. Adjust call to locate_and_pad_parm. Don't tweak arg size for partial in-regs here. Formatting fixes. * expr.h (struct locate_and_pad_arg_data): New struct. (locate_and_pad_parm): Adjust declaration. * function.c (assign_parms): Localize vars. Use "locate" instead of other arg location vars. Don't invoke FUNCTION_ARG or FUNCTION_INCOMING_ARG unless pretend_named is different from named_arg. Heed MUST_PASS_IN_STACK and set up "partial" before calling locate_and_pad_parm. Adjust locate_and_pad_parm call. Use slot_offset for stack home of reg parms. Correct test for parm passed in memory. Formatting fixes. (locate_and_pad_parm): Add "partial" to params. Replace offset_ptr arg_size_ptr and alignment pad with "locate". Set slot_offset here. Correct initial_offset_ptr handling. Localize vars. Always pad locate->offset even when in_regs. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@66383 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/calls.c170
-rw-r--r--gcc/expr.h30
-rw-r--r--gcc/function.c291
4 files changed, 264 insertions, 251 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1509141d34f..c2b1e8da47f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,27 @@
+2003-05-02 Alan Modra <amodra@bigpond.net.au>
+
+ * calls.c (struct arg_data): Move offset, slot_offset, size and
+ alignment_pad to struct locate_and_pad_arg_data. Update all refs.
+ (initialize_argument_information): Adjust call to locate_and_pad_parm.
+ Delete alignment_pad var. Don't calculate slot_offset here.
+ (emit_library_call_value_1): Delete alignment_pad, offset and size
+ vars. Use struct locate_and_pad_arg_data instead. Adjust refs.
+ Adjust call to locate_and_pad_parm. Don't tweak arg size for
+ partial in-regs here. Formatting fixes.
+ * expr.h (struct locate_and_pad_arg_data): New struct.
+ (locate_and_pad_parm): Adjust declaration.
+ * function.c (assign_parms): Localize vars. Use "locate" instead of
+ other arg location vars. Don't invoke FUNCTION_ARG or
+ FUNCTION_INCOMING_ARG unless pretend_named is different from
+ named_arg. Heed MUST_PASS_IN_STACK and set up "partial" before
+ calling locate_and_pad_parm. Adjust locate_and_pad_parm call.
+ Use slot_offset for stack home of reg parms. Correct test for
+ parm passed in memory. Formatting fixes.
+ (locate_and_pad_parm): Add "partial" to params. Replace offset_ptr
+ arg_size_ptr and alignment pad with "locate". Set slot_offset here.
+ Correct initial_offset_ptr handling. Localize vars. Always pad
+ locate->offset even when in_regs.
+
2003-05-02 Nathan Sidwell <nathan@codesourcery.com>
* Makefile.in (TREE_H): Replace location.h with input.h.
diff --git a/gcc/calls.c b/gcc/calls.c
index 135f949028c..8fb84e9b906 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -98,16 +98,8 @@ struct arg_data
even though pass_on_stack is zero, just because FUNCTION_ARG says so.
pass_on_stack identifies arguments that *cannot* go in registers. */
int pass_on_stack;
- /* Offset of this argument from beginning of stack-args. */
- struct args_size offset;
- /* Similar, but offset to the start of the stack slot. Different from
- OFFSET if this arg pads downward. */
- struct args_size slot_offset;
- /* Size of this argument on the stack, rounded up for any padding it gets,
- parts of the argument passed in registers do not count.
- If REG_PARM_STACK_SPACE is defined, then register parms
- are counted here as well. */
- struct args_size size;
+ /* Some fields packaged up for locate_and_pad_parm. */
+ struct locate_and_pad_arg_data locate;
/* Location on the stack at which parameter should be stored. The store
has already been done if STACK == VALUE. */
rtx stack;
@@ -123,9 +115,6 @@ struct arg_data
word-sized pseudos we made. */
rtx *aligned_regs;
int n_aligned_regs;
- /* The amount that the stack pointer needs to be adjusted to
- force alignment for the next argument. */
- struct args_size alignment_pad;
};
/* A vector of one char per byte of stack space. A byte if nonzero if
@@ -1120,7 +1109,6 @@ initialize_argument_information (num_actuals, args, args_size, n_named_args,
/* Count arg position in order args appear. */
int argpos;
- struct args_size alignment_pad;
int i;
tree p;
@@ -1331,39 +1319,14 @@ initialize_argument_information (num_actuals, args, args_size, n_named_args,
#else
args[i].reg != 0,
#endif
- fndecl, args_size, &args[i].offset,
- &args[i].size, &alignment_pad);
-
-#ifndef ARGS_GROW_DOWNWARD
- args[i].slot_offset = *args_size;
-#endif
-
- args[i].alignment_pad = alignment_pad;
-
- /* If a part of the arg was put into registers,
- don't include that part in the amount pushed. */
- if (reg_parm_stack_space == 0 && ! args[i].pass_on_stack)
- args[i].size.constant -= ((args[i].partial * UNITS_PER_WORD)
- / (PARM_BOUNDARY / BITS_PER_UNIT)
- * (PARM_BOUNDARY / BITS_PER_UNIT));
+ args[i].pass_on_stack ? 0 : args[i].partial,
+ fndecl, args_size, &args[i].locate);
/* Update ARGS_SIZE, the total stack space for args so far. */
- args_size->constant += args[i].size.constant;
- if (args[i].size.var)
- {
- ADD_PARM_SIZE (*args_size, args[i].size.var);
- }
-
- /* Since the slot offset points to the bottom of the slot,
- we must record it after incrementing if the args grow down. */
-#ifdef ARGS_GROW_DOWNWARD
- args[i].slot_offset = *args_size;
-
- args[i].slot_offset.constant = -args_size->constant;
- if (args_size->var)
- SUB_PARM_SIZE (args[i].slot_offset, args_size->var);
-#endif
+ args_size->constant += args[i].locate.size.constant;
+ if (args[i].locate.size.var)
+ ADD_PARM_SIZE (*args_size, args[i].locate.size.var);
/* Increment ARGS_SO_FAR, which has info about which arg-registers
have been used, etc. */
@@ -1616,8 +1579,8 @@ compute_argument_addresses (args, argblock, num_actuals)
for (i = 0; i < num_actuals; i++)
{
- rtx offset = ARGS_SIZE_RTX (args[i].offset);
- rtx slot_offset = ARGS_SIZE_RTX (args[i].slot_offset);
+ rtx offset = ARGS_SIZE_RTX (args[i].locate.offset);
+ rtx slot_offset = ARGS_SIZE_RTX (args[i].locate.slot_offset);
rtx addr;
/* Skip this parm if it will not be passed on the stack. */
@@ -2060,12 +2023,12 @@ check_sibcall_argument_overlap (insn, arg, mark_stored_args_map)
if (mark_stored_args_map)
{
#ifdef ARGS_GROW_DOWNWARD
- low = -arg->slot_offset.constant - arg->size.constant;
+ low = -arg->locate.slot_offset.constant - arg->locate.size.constant;
#else
- low = arg->slot_offset.constant;
+ low = arg->locate.slot_offset.constant;
#endif
- for (high = low + arg->size.constant; low < high; low++)
+ for (high = low + arg->locate.size.constant; low < high; low++)
SET_BIT (stored_args_map, low);
}
return insn != NULL_RTX;
@@ -3364,7 +3327,7 @@ expand_call (exp, target, ignore)
emit_move_insn (stack_area, args[i].save_area);
else
emit_block_move (stack_area, args[i].save_area,
- GEN_INT (args[i].size.constant),
+ GEN_INT (args[i].locate.size.constant),
BLOCK_OP_CALL_PARM);
}
@@ -3513,7 +3476,6 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
rtx fun;
int inc;
int count;
- struct args_size alignment_pad;
rtx argblock = 0;
CUMULATIVE_ARGS args_so_far;
struct arg
@@ -3522,8 +3484,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
enum machine_mode mode;
rtx reg;
int partial;
- struct args_size offset;
- struct args_size size;
+ struct locate_and_pad_arg_data locate;
rtx save_area;
};
struct arg *argvec;
@@ -3683,12 +3644,11 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
#else
argvec[count].reg != 0,
#endif
- NULL_TREE, &args_size, &argvec[count].offset,
- &argvec[count].size, &alignment_pad);
+ 0, NULL_TREE, &args_size, &argvec[count].locate);
if (argvec[count].reg == 0 || argvec[count].partial != 0
|| reg_parm_stack_space > 0)
- args_size.constant += argvec[count].size.constant;
+ args_size.constant += argvec[count].locate.size.constant;
FUNCTION_ARG_ADVANCE (args_so_far, Pmode, (tree) 0, 1);
@@ -3802,18 +3762,15 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
#else
argvec[count].reg != 0,
#endif
- NULL_TREE, &args_size, &argvec[count].offset,
- &argvec[count].size, &alignment_pad);
+ argvec[count].partial,
+ NULL_TREE, &args_size, &argvec[count].locate);
- if (argvec[count].size.var)
+ if (argvec[count].locate.size.var)
abort ();
- if (reg_parm_stack_space == 0 && argvec[count].partial)
- argvec[count].size.constant -= argvec[count].partial * UNITS_PER_WORD;
-
if (argvec[count].reg == 0 || argvec[count].partial != 0
|| reg_parm_stack_space > 0)
- args_size.constant += argvec[count].size.constant;
+ args_size.constant += argvec[count].locate.size.constant;
FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree) 0, 1);
}
@@ -3951,11 +3908,11 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
#ifdef ARGS_GROW_DOWNWARD
/* stack_slot is negative, but we want to index stack_usage_map
with positive values. */
- upper_bound = -argvec[argnum].offset.constant + 1;
- lower_bound = upper_bound - argvec[argnum].size.constant;
+ upper_bound = -argvec[argnum].locate.offset.constant + 1;
+ lower_bound = upper_bound - argvec[argnum].locate.size.constant;
#else
- lower_bound = argvec[argnum].offset.constant;
- upper_bound = lower_bound + argvec[argnum].size.constant;
+ lower_bound = argvec[argnum].locate.offset.constant;
+ upper_bound = lower_bound + argvec[argnum].locate.size.constant;
#endif
i = lower_bound;
@@ -3968,19 +3925,16 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
if (i < upper_bound)
{
- /* We need to make a save area. See what mode we can make
- it. */
+ /* We need to make a save area. */
+ unsigned int size
+ = argvec[argnum].locate.size.constant * BITS_PER_UNIT;
enum machine_mode save_mode
- = mode_for_size (argvec[argnum].size.constant
- * BITS_PER_UNIT,
- MODE_INT, 1);
+ = mode_for_size (size, MODE_INT, 1);
+ rtx adr
+ = plus_constant (argblock,
+ argvec[argnum].locate.offset.constant);
rtx stack_area
- = gen_rtx_MEM
- (save_mode,
- memory_address
- (save_mode,
- plus_constant (argblock,
- argvec[argnum].offset.constant)));
+ = gen_rtx_MEM (save_mode, memory_address (save_mode, adr));
argvec[argnum].save_area = gen_reg_rtx (save_mode);
emit_move_insn (argvec[argnum].save_area, stack_area);
@@ -3989,8 +3943,9 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
emit_push_insn (val, mode, NULL_TREE, NULL_RTX, PARM_BOUNDARY,
partial, reg, 0, argblock,
- GEN_INT (argvec[argnum].offset.constant),
- reg_parm_stack_space, ARGS_SIZE_RTX (alignment_pad));
+ GEN_INT (argvec[argnum].locate.offset.constant),
+ reg_parm_stack_space,
+ ARGS_SIZE_RTX (argvec[argnum].locate.alignment_pad));
/* Now mark the segment we just used. */
if (ACCUMULATE_OUTGOING_ARGS)
@@ -4195,12 +4150,10 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
if (argvec[count].save_area)
{
enum machine_mode save_mode = GET_MODE (argvec[count].save_area);
- rtx stack_area
- = gen_rtx_MEM (save_mode,
- memory_address
- (save_mode,
- plus_constant (argblock,
- argvec[count].offset.constant)));
+ rtx adr = plus_constant (argblock,
+ argvec[count].locate.offset.constant);
+ rtx stack_area = gen_rtx_MEM (save_mode,
+ memory_address (save_mode, adr));
emit_move_insn (stack_area, argvec[count].save_area);
}
@@ -4327,14 +4280,14 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
else
upper_bound = 0;
- lower_bound = upper_bound - arg->size.constant;
+ lower_bound = upper_bound - arg->locate.size.constant;
#else
if (GET_CODE (XEXP (arg->stack_slot, 0)) == PLUS)
lower_bound = INTVAL (XEXP (XEXP (arg->stack_slot, 0), 1));
else
lower_bound = 0;
- upper_bound = lower_bound + arg->size.constant;
+ upper_bound = lower_bound + arg->locate.size.constant;
#endif
i = lower_bound;
@@ -4347,13 +4300,11 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
if (i < upper_bound)
{
- /* We need to make a save area. See what mode we can make it. */
- enum machine_mode save_mode
- = mode_for_size (arg->size.constant * BITS_PER_UNIT, MODE_INT, 1);
- rtx stack_area
- = gen_rtx_MEM (save_mode,
- memory_address (save_mode,
- XEXP (arg->stack_slot, 0)));
+ /* We need to make a save area. */
+ unsigned int size = arg->locate.size.constant * BITS_PER_UNIT;
+ enum machine_mode save_mode = mode_for_size (size, MODE_INT, 1);
+ rtx adr = memory_address (save_mode, XEXP (arg->stack_slot, 0));
+ rtx stack_area = gen_rtx_MEM (save_mode, adr);
if (save_mode == BLKmode)
{
@@ -4481,8 +4432,8 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
This can either be done with push or copy insns. */
emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX,
PARM_BOUNDARY, partial, reg, used - size, argblock,
- ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
- ARGS_SIZE_RTX (arg->alignment_pad));
+ ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space,
+ ARGS_SIZE_RTX (arg->locate.alignment_pad));
/* Unless this is a partially-in-register argument, the argument is now
in the stack. */
@@ -4504,16 +4455,17 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
/* Round its size up to a multiple
of the allocation unit for arguments. */
- if (arg->size.var != 0)
+ if (arg->locate.size.var != 0)
{
excess = 0;
- size_rtx = ARGS_SIZE_RTX (arg->size);
+ size_rtx = ARGS_SIZE_RTX (arg->locate.size);
}
else
{
/* PUSH_ROUNDING has no effect on us, because
emit_push_insn for BLKmode is careful to avoid it. */
- excess = (arg->size.constant - int_size_in_bytes (TREE_TYPE (pval))
+ excess = (arg->locate.size.constant
+ - int_size_in_bytes (TREE_TYPE (pval))
+ partial * UNITS_PER_WORD);
size_rtx = expand_expr (size_in_bytes (TREE_TYPE (pval)),
NULL_RTX, TYPE_MODE (sizetype), 0);
@@ -4527,7 +4479,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
PARM_BOUNDARY, but the actual argument isn't. */
if (FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)) == downward)
{
- if (arg->size.var)
+ if (arg->locate.size.var)
parm_align = BITS_PER_UNIT;
else if (excess)
{
@@ -4539,7 +4491,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
if ((flags & ECF_SIBCALL) && GET_CODE (arg->value) == MEM)
{
/* emit_push_insn might not work properly if arg->value and
- argblock + arg->offset areas overlap. */
+ argblock + arg->locate.offset areas overlap. */
rtx x = arg->value;
int i = 0;
@@ -4553,17 +4505,17 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
i = INTVAL (XEXP (XEXP (x, 0), 1));
/* expand_call should ensure this */
- if (arg->offset.var || GET_CODE (size_rtx) != CONST_INT)
+ if (arg->locate.offset.var || GET_CODE (size_rtx) != CONST_INT)
abort ();
- if (arg->offset.constant > i)
+ if (arg->locate.offset.constant > i)
{
- if (arg->offset.constant < i + INTVAL (size_rtx))
+ if (arg->locate.offset.constant < i + INTVAL (size_rtx))
sibcall_failure = 1;
}
- else if (arg->offset.constant < i)
+ else if (arg->locate.offset.constant < i)
{
- if (i < arg->offset.constant + INTVAL (size_rtx))
+ if (i < arg->locate.offset.constant + INTVAL (size_rtx))
sibcall_failure = 1;
}
}
@@ -4571,8 +4523,8 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
parm_align, partial, reg, excess, argblock,
- ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
- ARGS_SIZE_RTX (arg->alignment_pad));
+ ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space,
+ ARGS_SIZE_RTX (arg->locate.alignment_pad));
/* Unless this is a partially-in-register argument, the argument is now
in the stack.
diff --git a/gcc/expr.h b/gcc/expr.h
index 7e157cdf302..dfd83d43c23 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -63,6 +63,8 @@ enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM = 2, EXPAND_SUM,
more information. */
#define OK_DEFER_POP (inhibit_defer_pop -= 1)
+enum direction {none, upward, downward};
+
#ifdef TREE_CODE /* Don't lose if tree.h not included. */
/* Structure to record the size of a sequence of arguments
as the sum of a tree-expression and a constant. This structure is
@@ -74,6 +76,24 @@ struct args_size
HOST_WIDE_INT constant;
tree var;
};
+
+/* Package up various arg related fields of struct args for
+ locate_and_pad_parm. */
+struct locate_and_pad_arg_data
+{
+ /* Size of this argument on the stack, rounded up for any padding it
+ gets. If REG_PARM_STACK_SPACE is defined, then register parms are
+ counted here, otherwise they aren't. */
+ struct args_size size;
+ /* Offset of this argument from beginning of stack-args. */
+ struct args_size offset;
+ /* Offset to the start of the stack slot. Different from OFFSET
+ if this arg pads downward. */
+ struct args_size slot_offset;
+ /* The amount that the stack pointer needs to be adjusted to
+ force alignment for the next argument. */
+ struct args_size alignment_pad;
+};
#endif
/* Add the value of the tree INC to the `struct args_size' TO. */
@@ -119,8 +139,6 @@ do { \
usually pad upward, but pad short args downward on
big-endian machines. */
-enum direction {none, upward, downward}; /* Value has this type. */
-
#ifndef FUNCTION_ARG_PADDING
#define FUNCTION_ARG_PADDING(MODE, TYPE) \
(! BYTES_BIG_ENDIAN \
@@ -570,11 +588,9 @@ extern rtx expand_shift PARAMS ((enum tree_code, enum machine_mode, rtx, tree,
rtx, int));
extern rtx expand_divmod PARAMS ((int, enum tree_code, enum machine_mode, rtx,
rtx, rtx, int));
-extern void locate_and_pad_parm PARAMS ((enum machine_mode, tree, int, tree,
- struct args_size *,
- struct args_size *,
- struct args_size *,
- struct args_size *));
+extern void locate_and_pad_parm PARAMS ((enum machine_mode, tree, int, int,
+ tree, struct args_size *,
+ struct locate_and_pad_arg_data *));
extern rtx expand_inline_function PARAMS ((tree, tree, rtx, int, tree, rtx));
/* Return the CODE_LABEL rtx for a LABEL_DECL, creating it if necessary. */
diff --git a/gcc/function.c b/gcc/function.c
index 6e52d7e1ddb..5684392b5e9 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -4340,12 +4340,7 @@ assign_parms (fndecl)
tree fndecl;
{
tree parm;
- rtx entry_parm = 0;
- rtx stack_parm = 0;
CUMULATIVE_ARGS args_so_far;
- enum machine_mode promoted_mode, passed_mode;
- enum machine_mode nominal_mode, promoted_nominal_mode;
- int unsignedp;
/* Total space needed so far for args on the stack,
given as a constant and a tree-expression. */
struct args_size stack_args_size;
@@ -4359,8 +4354,8 @@ assign_parms (fndecl)
#ifdef SETUP_INCOMING_VARARGS
int varargs_setup = 0;
#endif
+ int reg_parm_stack_space = 0;
rtx conversion_insns = 0;
- struct args_size alignment_pad;
/* Nonzero if function takes extra anonymous args.
This means the last named arg must be on the stack
@@ -4407,6 +4402,14 @@ assign_parms (fndecl)
max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
parm_reg_stack_loc = (rtx *) ggc_alloc_cleared (max_parm_reg * sizeof (rtx));
+#ifdef REG_PARM_STACK_SPACE
+#ifdef MAYBE_REG_PARM_STACK_SPACE
+ reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
+#else
+ reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
+#endif
+#endif
+
#ifdef INIT_CUMULATIVE_INCOMING_ARGS
INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, NULL_RTX);
#else
@@ -4419,14 +4422,19 @@ assign_parms (fndecl)
for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
{
- struct args_size stack_offset;
- struct args_size arg_size;
+ rtx entry_parm;
+ rtx stack_parm;
+ enum machine_mode promoted_mode, passed_mode;
+ enum machine_mode nominal_mode, promoted_nominal_mode;
+ int unsignedp;
+ struct locate_and_pad_arg_data locate;
int passed_pointer = 0;
int did_conversion = 0;
tree passed_type = DECL_ARG_TYPE (parm);
tree nominal_type = TREE_TYPE (parm);
- int pretend_named;
int last_named = 0, named_arg;
+ int in_regs;
+ int partial = 0;
/* Set LAST_NAMED if this is last named arg before last
anonymous args. */
@@ -4490,7 +4498,7 @@ assign_parms (fndecl)
|| TREE_ADDRESSABLE (passed_type)
#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
|| FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, passed_mode,
- passed_type, named_arg)
+ passed_type, named_arg)
#endif
)
{
@@ -4560,27 +4568,52 @@ assign_parms (fndecl)
it came in a register so that REG_PARM_STACK_SPACE isn't skipped.
In this case, we call FUNCTION_ARG with NAMED set to 1 instead of
0 as it was the previous time. */
-
- pretend_named = named_arg || PRETEND_OUTGOING_VARARGS_NAMED;
- locate_and_pad_parm (promoted_mode, passed_type,
+ in_regs = entry_parm != 0;
#ifdef STACK_PARMS_IN_REG_PARM_AREA
- 1,
-#else
+ in_regs = 1;
+#endif
+ if (!in_regs && !named_arg)
+ {
+ int pretend_named = PRETEND_OUTGOING_VARARGS_NAMED;
+ if (pretend_named)
+ {
#ifdef FUNCTION_INCOMING_ARG
- FUNCTION_INCOMING_ARG (args_so_far, promoted_mode,
- passed_type,
- pretend_named) != 0,
+ in_regs = FUNCTION_INCOMING_ARG (args_so_far, promoted_mode,
+ passed_type,
+ pretend_named) != 0;
#else
- FUNCTION_ARG (args_so_far, promoted_mode,
- passed_type,
- pretend_named) != 0,
+ in_regs = FUNCTION_ARG (args_so_far, promoted_mode,
+ passed_type,
+ pretend_named) != 0;
#endif
+ }
+ }
+
+ /* If this parameter was passed both in registers and in the stack,
+ use the copy on the stack. */
+ if (MUST_PASS_IN_STACK (promoted_mode, passed_type))
+ entry_parm = 0;
+
+#ifdef FUNCTION_ARG_PARTIAL_NREGS
+ if (entry_parm)
+ partial = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, promoted_mode,
+ passed_type, named_arg);
#endif
- fndecl, &stack_args_size, &stack_offset, &arg_size,
- &alignment_pad);
+
+ memset (&locate, 0, sizeof (locate));
+ locate_and_pad_parm (promoted_mode, passed_type, in_regs,
+ entry_parm ? partial : 0, fndecl,
+ &stack_args_size, &locate);
{
- rtx offset_rtx = ARGS_SIZE_RTX (stack_offset);
+ rtx offset_rtx;
+
+ /* If we're passing this arg using a reg, make its stack home
+ the aligned stack slot. */
+ if (entry_parm)
+ offset_rtx = ARGS_SIZE_RTX (locate.slot_offset);
+ else
+ offset_rtx = ARGS_SIZE_RTX (locate.offset);
if (offset_rtx == const0_rtx)
stack_parm = gen_rtx_MEM (promoted_mode, internal_arg_pointer);
@@ -4597,12 +4630,6 @@ assign_parms (fndecl)
set_reg_attrs_for_parm (entry_parm, stack_parm);
}
- /* If this parameter was passed both in registers and in the stack,
- use the copy on the stack. */
- if (MUST_PASS_IN_STACK (promoted_mode, passed_type))
- entry_parm = 0;
-
-#ifdef FUNCTION_ARG_PARTIAL_NREGS
/* If this parm was passed part in regs and part in memory,
pretend it arrived entirely in memory
by pushing the register-part onto the stack.
@@ -4611,39 +4638,31 @@ assign_parms (fndecl)
we could put it together in a pseudoreg directly,
but for now that's not worth bothering with. */
- if (entry_parm)
+ if (partial)
{
- int nregs = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, promoted_mode,
- passed_type, named_arg);
-
- if (nregs > 0)
- {
-#if defined (REG_PARM_STACK_SPACE) && !defined (MAYBE_REG_PARM_STACK_SPACE)
- /* When REG_PARM_STACK_SPACE is nonzero, stack space for
- split parameters was allocated by our caller, so we
- won't be pushing it in the prolog. */
- if (REG_PARM_STACK_SPACE (fndecl) == 0)
+#ifndef MAYBE_REG_PARM_STACK_SPACE
+ /* When REG_PARM_STACK_SPACE is nonzero, stack space for
+ split parameters was allocated by our caller, so we
+ won't be pushing it in the prolog. */
+ if (reg_parm_stack_space)
#endif
- current_function_pretend_args_size
- = (((nregs * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
- / (PARM_BOUNDARY / BITS_PER_UNIT)
- * (PARM_BOUNDARY / BITS_PER_UNIT));
+ current_function_pretend_args_size
+ = (((partial * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
+ / (PARM_BOUNDARY / BITS_PER_UNIT)
+ * (PARM_BOUNDARY / BITS_PER_UNIT));
- /* Handle calls that pass values in multiple non-contiguous
- locations. The Irix 6 ABI has examples of this. */
- if (GET_CODE (entry_parm) == PARALLEL)
- emit_group_store (validize_mem (stack_parm), entry_parm,
- int_size_in_bytes (TREE_TYPE (parm)));
+ /* Handle calls that pass values in multiple non-contiguous
+ locations. The Irix 6 ABI has examples of this. */
+ if (GET_CODE (entry_parm) == PARALLEL)
+ emit_group_store (validize_mem (stack_parm), entry_parm,
+ int_size_in_bytes (TREE_TYPE (parm)));
- else
- move_block_from_reg (REGNO (entry_parm),
- validize_mem (stack_parm), nregs,
- int_size_in_bytes (TREE_TYPE (parm)));
+ else
+ move_block_from_reg (REGNO (entry_parm), validize_mem (stack_parm),
+ partial, int_size_in_bytes (TREE_TYPE (parm)));
- entry_parm = stack_parm;
- }
+ entry_parm = stack_parm;
}
-#endif
/* If we didn't decide this parm came in a register,
by default it came on the stack. */
@@ -4674,9 +4693,9 @@ assign_parms (fndecl)
#endif
)
{
- stack_args_size.constant += arg_size.constant;
- if (arg_size.var)
- ADD_PARM_SIZE (stack_args_size, arg_size.var);
+ stack_args_size.constant += locate.size.constant;
+ if (locate.size.var)
+ ADD_PARM_SIZE (stack_args_size, locate.size.var);
}
else
/* No stack slot was pushed for this parm. */
@@ -4700,7 +4719,7 @@ assign_parms (fndecl)
/* If parm was passed in memory, and we need to convert it on entry,
don't store it back in that same slot. */
- if (entry_parm != 0
+ if (entry_parm == stack_parm
&& nominal_mode != BLKmode && nominal_mode != passed_mode)
stack_parm = 0;
@@ -5023,7 +5042,7 @@ assign_parms (fndecl)
&& ! did_conversion
&& stack_parm != 0
&& GET_CODE (stack_parm) == MEM
- && stack_offset.var == 0
+ && locate.offset.var == 0
&& reg_mentioned_p (virtual_incoming_args_rtx,
XEXP (stack_parm, 0)))
{
@@ -5109,7 +5128,8 @@ assign_parms (fndecl)
{
stack_parm
= assign_stack_local (GET_MODE (entry_parm),
- GET_MODE_SIZE (GET_MODE (entry_parm)), 0);
+ GET_MODE_SIZE (GET_MODE (entry_parm)),
+ 0);
set_mem_attributes (stack_parm, parm, 1);
}
@@ -5280,8 +5300,11 @@ promoted_input_arg (regno, pmode, punsignedp)
INITIAL_OFFSET_PTR points to the current offset into the stacked
arguments.
- The starting offset and size for this parm are returned in *OFFSET_PTR
- and *ARG_SIZE_PTR, respectively.
+ The starting offset and size for this parm are returned in
+ LOCATE->OFFSET and LOCATE->SIZE, respectively. When IN_REGS is
+ nonzero, the offset is that of stack slot, which is returned in
+ LOCATE->SLOT_OFFSET. LOCATE->ALIGNMENT_PAD is the amount of
+ padding required from the initial offset ptr to the stack slot.
IN_REGS is nonzero if the argument will be passed in registers. It will
never be set if REG_PARM_STACK_SPACE is not defined.
@@ -5298,45 +5321,39 @@ promoted_input_arg (regno, pmode, punsignedp)
initial offset is not affected by this rounding, while the size always
is and the starting offset may be. */
-/* offset_ptr will be negative for ARGS_GROW_DOWNWARD case;
- initial_offset_ptr is positive because locate_and_pad_parm's
+/* LOCATE->OFFSET will be negative for ARGS_GROW_DOWNWARD case;
+ INITIAL_OFFSET_PTR is positive because locate_and_pad_parm's
callers pass in the total size of args so far as
- initial_offset_ptr. arg_size_ptr is always positive. */
+ INITIAL_OFFSET_PTR. LOCATE->SIZE is always positive. */
void
-locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
- initial_offset_ptr, offset_ptr, arg_size_ptr,
- alignment_pad)
+locate_and_pad_parm (passed_mode, type, in_regs, partial, fndecl,
+ initial_offset_ptr, locate)
enum machine_mode passed_mode;
tree type;
- int in_regs ATTRIBUTE_UNUSED;
+ int in_regs;
+ int partial;
tree fndecl ATTRIBUTE_UNUSED;
struct args_size *initial_offset_ptr;
- struct args_size *offset_ptr;
- struct args_size *arg_size_ptr;
- struct args_size *alignment_pad;
-
+ struct locate_and_pad_arg_data *locate;
{
- tree sizetree
- = 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
+ tree sizetree;
+ enum direction where_pad;
+ int boundary;
+ int reg_parm_stack_space = 0;
+ int part_size_in_regs;
#ifdef REG_PARM_STACK_SPACE
+#ifdef MAYBE_REG_PARM_STACK_SPACE
+ reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
+#else
+ reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
+#endif
+
/* If we have found a stack parm before we reach the end of the
area reserved for registers, skip that area. */
if (! in_regs)
{
- int reg_parm_stack_space = 0;
-
-#ifdef MAYBE_REG_PARM_STACK_SPACE
- reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
-#else
- reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
-#endif
if (reg_parm_stack_space > 0)
{
if (initial_offset_ptr->var)
@@ -5352,54 +5369,56 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
}
#endif /* REG_PARM_STACK_SPACE */
- arg_size_ptr->var = 0;
- arg_size_ptr->constant = 0;
- alignment_pad->var = 0;
- alignment_pad->constant = 0;
+ part_size_in_regs = 0;
+ if (reg_parm_stack_space == 0)
+ part_size_in_regs = ((partial * UNITS_PER_WORD)
+ / (PARM_BOUNDARY / BITS_PER_UNIT)
+ * (PARM_BOUNDARY / BITS_PER_UNIT));
+
+ sizetree
+ = type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode));
+ where_pad = FUNCTION_ARG_PADDING (passed_mode, type);
+ boundary = FUNCTION_ARG_BOUNDARY (passed_mode, type);
#ifdef ARGS_GROW_DOWNWARD
+ locate->slot_offset.constant = -initial_offset_ptr->constant;
if (initial_offset_ptr->var)
- {
- offset_ptr->constant = 0;
- offset_ptr->var = size_binop (MINUS_EXPR, ssize_int (0),
- initial_offset_ptr->var);
- }
- else
- {
- offset_ptr->constant = -initial_offset_ptr->constant;
- offset_ptr->var = 0;
- }
+ locate->slot_offset.var = size_binop (MINUS_EXPR, ssize_int (0),
+ initial_offset_ptr->var);
- if (where_pad != none
- && (!host_integerp (sizetree, 1)
- || (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % PARM_BOUNDARY))
- s2 = round_up (s2, PARM_BOUNDARY / BITS_PER_UNIT);
- SUB_PARM_SIZE (*offset_ptr, s2);
+ {
+ tree s2 = sizetree;
+ if (where_pad != none
+ && (!host_integerp (sizetree, 1)
+ || (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % PARM_BOUNDARY))
+ s2 = round_up (s2, PARM_BOUNDARY / BITS_PER_UNIT);
+ SUB_PARM_SIZE (locate->slot_offset, s2);
+ }
+
+ locate->slot_offset.constant += part_size_in_regs;
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 (&locate->slot_offset, boundary,
+ &locate->alignment_pad);
+ locate->size.constant = (-initial_offset_ptr->constant
+ - locate->slot_offset.constant);
if (initial_offset_ptr->var)
- arg_size_ptr->var = size_binop (MINUS_EXPR,
- size_binop (MINUS_EXPR,
- ssize_int (0),
- initial_offset_ptr->var),
- offset_ptr->var);
-
- else
- 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);
+ locate->size.var = size_binop (MINUS_EXPR,
+ size_binop (MINUS_EXPR,
+ ssize_int (0),
+ initial_offset_ptr->var),
+ locate->slot_offset.var);
+
+ /* Pad_below needs the pre-rounded size to know how much to pad
+ below. */
+ locate->offset = locate->slot_offset;
+ if (where_pad == downward)
+ pad_below (&locate->offset, passed_mode, sizetree);
#else /* !ARGS_GROW_DOWNWARD */
if (!in_regs
@@ -5407,8 +5426,9 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
|| REG_PARM_STACK_SPACE (fndecl) > 0
#endif
)
- pad_to_arg_alignment (initial_offset_ptr, boundary, alignment_pad);
- *offset_ptr = *initial_offset_ptr;
+ pad_to_arg_alignment (initial_offset_ptr, boundary,
+ &locate->alignment_pad);
+ locate->slot_offset = *initial_offset_ptr;
#ifdef PUSH_ROUNDING
if (passed_mode != BLKmode)
@@ -5417,18 +5437,18 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
/* Pad_below needs the pre-rounded size to know how much to pad below
so this must be done before rounding up. */
- if (where_pad == downward
- /* However, BLKmode args passed in regs have their padding done elsewhere.
- The stack slot must be able to hold the entire register. */
- && !(in_regs && passed_mode == BLKmode))
- pad_below (offset_ptr, passed_mode, sizetree);
+ locate->offset = locate->slot_offset;
+ if (where_pad == downward)
+ pad_below (&locate->offset, passed_mode, sizetree);
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);
- ADD_PARM_SIZE (*arg_size_ptr, sizetree);
+ ADD_PARM_SIZE (locate->size, sizetree);
+
+ locate->size.constant -= part_size_in_regs;
#endif /* ARGS_GROW_DOWNWARD */
}
@@ -5467,7 +5487,8 @@ pad_to_arg_alignment (offset_ptr, boundary, alignment_pad)
#endif
(ARGS_SIZE_TREE (*offset_ptr),
boundary / BITS_PER_UNIT);
- offset_ptr->constant = 0; /*?*/
+ /* ARGS_SIZE_TREE includes constant term. */
+ offset_ptr->constant = 0;
if (boundary > PARM_BOUNDARY && boundary > STACK_BOUNDARY)
alignment_pad->var = size_binop (MINUS_EXPR, offset_ptr->var,
save_var);