* expr.c (emit_push_insn): New argument alignment_pad.
Update all callers. Adjust stack pointer based on alignment pad.
* function.c (pad_to_arg_alignment): New argument alignment_pad.
Update all callers. Track alignment_pad if boundary > PARM_BOUNDARY.
(locate_and_pad_parm): New argument alignment_pad. Update all
callers.
* expr.h (emit_push_insn): Update prototype.
(locate_and_pad_parm): Update prototype.
* calls.c (arg_data): Add new field alignment_pad.
(initialize_argument_information): Initialize alignment_pad.
From-SVN: r30257
+Fri Oct 29 08:03:57 1999 Catherine Moore <clm@cygnus.com>
+
+ * expr.c (emit_push_insn): New argument alignment_pad.
+ Update all callers. Adjust stack pointer based on alignment pad.
+ * function.c (pad_to_arg_alignment): New argument alignment_pad.
+ Update all callers. Track alignment_pad if boundary > PARM_BOUNDARY.
+ (locate_and_pad_parm): New argument alignment_pad. Update all
+ callers.
+ * expr.h (emit_push_insn): Update prototype.
+ (locate_and_pad_parm): Update prototype.
+ * calls.c (arg_data): Add new field alignment_pad.
+ (initialize_argument_information): Initialize alignment_pad.
+
Fri Oct 29 02:51:35 1999 Mark Mitchell <mark@codesourcery.com>
* except.c (free_eh_nesting_info): Free the info itself.
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;
};
#ifdef ACCUMULATE_OUTGOING_ARGS
/* Count arg position in order args appear. */
int argpos;
+ struct args_size alignment_pad;
int i;
tree p;
args[i].reg != 0,
#endif
fndecl, args_size, &args[i].offset,
- &args[i].size);
+ &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)
locate_and_pad_parm (mode, NULL_TREE,
argvec[count].reg && argvec[count].partial == 0,
NULL_TREE, &args_size, &argvec[count].offset,
- &argvec[count].size);
+ &argvec[count].size, &alignment_pad);
if (argvec[count].size.var)
abort ();
#endif
emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0,
argblock, GEN_INT (argvec[argnum].offset.constant),
- reg_parm_stack_space);
+ reg_parm_stack_space, ARGS_SIZE_RTX (alignment_pad));
#ifdef ACCUMULATE_OUTGOING_ARGS
/* Now mark the segment we just used. */
rtx fun;
int inc;
int count;
+ struct args_size alignment_pad;
rtx argblock = 0;
CUMULATIVE_ARGS args_so_far;
struct arg { rtx value; enum machine_mode mode; rtx reg; int partial;
locate_and_pad_parm (Pmode, NULL_TREE,
argvec[count].reg && argvec[count].partial == 0,
NULL_TREE, &args_size, &argvec[count].offset,
- &argvec[count].size);
+ &argvec[count].size, &alignment_pad);
if (argvec[count].reg == 0 || argvec[count].partial != 0
locate_and_pad_parm (mode, NULL_TREE,
argvec[count].reg && argvec[count].partial == 0,
NULL_TREE, &args_size, &argvec[count].offset,
- &argvec[count].size);
+ &argvec[count].size, &alignment_pad);
if (argvec[count].size.var)
abort ();
#endif
emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0,
argblock, GEN_INT (argvec[argnum].offset.constant),
- reg_parm_stack_space);
+ reg_parm_stack_space, ARGS_SIZE_RTX (alignment_pad));
#ifdef ACCUMULATE_OUTGOING_ARGS
/* Now mark the segment we just used. */
highest_outgoing_arg_in_use = initial_highest_arg_in_use;
stack_usage_map = initial_stack_usage_map;
#endif
+ struct args_size alignment_pad;
return value;
}
This can either be done with push or copy insns. */
emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX, 0,
partial, reg, used - size, argblock,
- ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space);
+ ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
+ ARGS_SIZE_RTX (arg->alignment_pad));
+
}
else
{
emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
TYPE_ALIGN (TREE_TYPE (pval)) / BITS_PER_UNIT, partial,
reg, excess, argblock, ARGS_SIZE_RTX (arg->offset),
- reg_parm_stack_space);
+ reg_parm_stack_space,
+ ARGS_SIZE_RTX (arg->alignment_pad));
}
void
emit_push_insn (x, mode, type, size, align, partial, reg, extra,
- args_addr, args_so_far, reg_parm_stack_space)
+ args_addr, args_so_far, reg_parm_stack_space,
+ alignment_pad)
register rtx x;
enum machine_mode mode;
tree type;
rtx args_addr;
rtx args_so_far;
int reg_parm_stack_space;
+ rtx alignment_pad;
{
rtx xinner;
enum direction stack_direction
0, args_addr,
GEN_INT (args_offset + ((i - not_stack + skip)
* UNITS_PER_WORD)),
- reg_parm_stack_space);
+ reg_parm_stack_space, alignment_pad);
}
else
{
if (extra && args_addr == 0 && where_pad == stack_direction)
anti_adjust_stack (GEN_INT (extra));
+
+ if (alignment_pad)
+ anti_adjust_stack (alignment_pad);
}
\f
/* Expand an assignment that stores the value of FROM into TO.
#ifdef TREE_CODE
/* Generate code to push something onto the stack, given its mode and type. */
extern void emit_push_insn PROTO((rtx, enum machine_mode, tree, rtx, int,
- int, rtx, int, rtx, rtx, int));
+ int, rtx, int, rtx, rtx, int, rtx));
/* Emit library call. */
extern void emit_library_call PVPROTO((rtx orgfun, int no_queue,
extern rtx expand_shift PROTO((enum tree_code, enum machine_mode, rtx, tree, rtx, int));
extern rtx expand_divmod PROTO((int, enum tree_code, enum machine_mode, rtx, rtx, rtx, int));
-extern void locate_and_pad_parm PROTO((enum machine_mode, tree, int, tree, struct args_size *, struct args_size *, struct args_size *));
+extern void locate_and_pad_parm PROTO((enum machine_mode, tree, int, tree, struct args_size *, struct args_size *, struct args_size *, struct args_size *));
extern rtx expand_inline_function PROTO((tree, tree, rtx, int, tree, rtx));
/* Return the CODE_LABEL rtx for a LABEL_DECL, creating it if necessary. */
extern rtx label_rtx PROTO((tree));
static void instantiate_decl PROTO((rtx, int, int));
static int instantiate_virtual_regs_1 PROTO((rtx *, rtx, int));
static void delete_handlers PROTO((void));
-static void pad_to_arg_alignment PROTO((struct args_size *, int));
+static void pad_to_arg_alignment PROTO((struct args_size *, int, struct args_size *));
#ifndef ARGS_GROW_DOWNWARD
static void pad_below PROTO((struct args_size *, enum machine_mode,
tree));
int varargs_setup = 0;
#endif
rtx conversion_insns = 0;
+ struct args_size alignment_pad;
/* Nonzero if the last arg is named `__builtin_va_alist',
which is used on some machines for old-fashioned non-ANSI varargs.h;
pretend_named) != 0,
#endif
#endif
- fndecl, &stack_args_size, &stack_offset, &arg_size);
+ fndecl, &stack_args_size, &stack_offset, &arg_size,
+ &alignment_pad);
{
rtx offset_rtx = ARGS_SIZE_RTX (stack_offset);
void
locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
- initial_offset_ptr, offset_ptr, arg_size_ptr)
+ initial_offset_ptr, offset_ptr, arg_size_ptr,
+ alignment_pad)
enum machine_mode passed_mode;
tree type;
int in_regs;
struct args_size *initial_offset_ptr;
struct args_size *offset_ptr;
struct args_size *arg_size_ptr;
+ struct args_size *alignment_pad;
+
{
tree sizetree
= type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode));
sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
SUB_PARM_SIZE (*offset_ptr, sizetree);
if (where_pad != downward)
- pad_to_arg_alignment (offset_ptr, boundary);
+ pad_to_arg_alignment (offset_ptr, boundary, alignment_pad);
if (initial_offset_ptr->var)
{
arg_size_ptr->var = size_binop (MINUS_EXPR,
- offset_ptr->constant);
}
#else /* !ARGS_GROW_DOWNWARD */
- pad_to_arg_alignment (initial_offset_ptr, boundary);
+ pad_to_arg_alignment (initial_offset_ptr, boundary, alignment_pad);
*offset_ptr = *initial_offset_ptr;
#ifdef PUSH_ROUNDING
BOUNDARY is measured in bits, but must be a multiple of a storage unit. */
static void
-pad_to_arg_alignment (offset_ptr, boundary)
+pad_to_arg_alignment (offset_ptr, boundary, alignment_pad)
struct args_size *offset_ptr;
int boundary;
+ struct args_size *alignment_pad;
{
+ tree save_var;
+ HOST_WIDE_INT save_constant;
+
int boundary_in_bytes = boundary / BITS_PER_UNIT;
+ if (boundary > PARM_BOUNDARY)
+ {
+ save_var = offset_ptr->var;
+ save_constant = offset_ptr->constant;
+ }
+
+ alignment_pad->var = NULL_TREE;
+ alignment_pad->constant = 0;
+ /* END CYGNUS LOCAL */
+
if (boundary > BITS_PER_UNIT)
{
if (offset_ptr->var)
(ARGS_SIZE_TREE (*offset_ptr),
boundary / BITS_PER_UNIT);
offset_ptr->constant = 0; /*?*/
+ if (boundary > PARM_BOUNDARY)
+ alignment_pad->var = size_binop (MINUS_EXPR, offset_ptr->var, save_var);
}
else
offset_ptr->constant =
#else
CEIL_ROUND (offset_ptr->constant, boundary_in_bytes);
#endif
+ if (boundary > PARM_BOUNDARY)
+ alignment_pad->constant = offset_ptr->constant - save_constant;
}
}