calls.c (struct arg_data): Move offset, slot_offset, size and alignment_pad to struct locate_and_pad_arg_data.

* 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.

From-SVN: r66383
This commit is contained in:
Alan Modra 2003-05-02 14:22:09 +00:00 committed by Alan Modra
parent 5ca5a6554e
commit e79498768f
4 changed files with 263 additions and 250 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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. */

View File

@ -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);
locate->size.var = size_binop (MINUS_EXPR,
size_binop (MINUS_EXPR,
ssize_int (0),
initial_offset_ptr->var),
locate->slot_offset.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);
/* 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);