This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: Problem with stack-adjustment code
>>>>> "Jan" == Jan Hubicka <jhub6202@ss1000.ms.mff.cuni.cz> writes:
Jan> Mark, I am aware of this problem. The patch to fix it is at:
By the time I got your message, I already had this patch put together.
Since it fixes my test case, survived a i686-pc-linux-gnu
bootstrap/test and makes sense to me, I checked it in. However, you
or Richard may well conclude I blew it. I will be off email much of
today, so I will trust the other maintainers to back this out, if
appropriate.
The bottom line is that I don't think this code:
! args_size.constant = (unadjusted_args_size
! + ((pending_stack_adjust
! + args_size.constant
! - unadjusted_args_size)
! % (preferred_stack_boundary
! / BITS_PER_UNIT)));
! adjust = (pending_stack_adjust - args_size.constant
was quite right since it didn't have to do with stack_pointer_delta,
which is the thing that tells us how unaligned the stack is at the
moment.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2000-04-27 Mark Mitchell <mark@codesourcery.com>
* calls.c (combine_pending_stack_adjustment_and_call): New function.
(expand_call): Use it.
Index: calls.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/calls.c,v
retrieving revision 1.125
diff -c -p -r1.125 calls.c
*** calls.c 2000/04/26 00:43:09 1.125
--- calls.c 2000/04/27 16:42:36
*************** static int special_function_p PARAMS (
*** 210,215 ****
--- 210,217 ----
static int flags_from_decl_or_type PARAMS ((tree));
static rtx try_to_integrate PARAMS ((tree, tree, rtx,
int, tree, rtx));
+ static void combine_pending_stack_adjustment_and_call
+ PARAMS ((int, struct args_size *, int));
#ifdef REG_PARM_STACK_SPACE
static rtx save_fixed_argument_area PARAMS ((int, rtx, int *, int *));
*************** try_to_integrate (fndecl, actparms, targ
*** 1855,1860 ****
--- 1857,1920 ----
return (rtx) (HOST_WIDE_INT) - 1;
}
+ /* We need to pop PENDING_STACK_ADJUST bytes. But, if the arguments
+ wouldn't fill up an even multiple of PREFERRED_UNIT_STACK_BOUNDARY
+ bytes, then we would need to push some additional bytes to pad the
+ arguments. So, we adjust the stack pointer by an amount that will
+ leave the stack under-aligned by UNADJUSTED_ARGS_SIZE bytes. Then,
+ when the arguments are pushed the stack will be perfectly aligned.
+ ARGS_SIZE->CONSTANT is set to the number of bytes that should be
+ popped after the call. */
+
+ static void
+ combine_pending_stack_adjustment_and_call (unadjusted_args_size,
+ args_size,
+ preferred_unit_stack_boundary)
+ int unadjusted_args_size;
+ struct args_size *args_size;
+ int preferred_unit_stack_boundary;
+ {
+ /* The number of bytes to pop so that the stack will be
+ under-aligned by UNADJUSTED_ARGS_SIZE bytes. */
+ HOST_WIDE_INT adjustment;
+ /* The alignment of the stack after the arguments are pushed, if we
+ just pushed the arguments without adjust the stack here. */
+ HOST_WIDE_INT unadjusted_alignment;
+
+ unadjusted_alignment
+ = ((stack_pointer_delta + unadjusted_args_size)
+ % preferred_unit_stack_boundary);
+
+ /* We want to get rid of as many of the PENDING_STACK_ADJUST bytes
+ as possible -- leaving just enough left to cancel out the
+ UNADJUSTED_ALIGNMENT. In other words, we want to ensure that the
+ PENDING_STACK_ADJUST is non-negative, and congruent to
+ -UNADJUSTED_ALIGNMENT modulo the PREFERRED_UNIT_STACK_BOUNDARY. */
+
+ /* Begin by trying to pop all the bytes. */
+ unadjusted_alignment
+ = (unadjusted_alignment
+ - (pending_stack_adjust % preferred_unit_stack_boundary));
+ adjustment = pending_stack_adjust;
+ /* Push enough additional bytes that the stack will be aligned
+ after the arguments are pushed. */
+ if (unadjusted_alignment >= 0)
+ adjustment -= preferred_unit_stack_boundary - unadjusted_alignment;
+ else
+ adjustment += unadjusted_alignment;
+
+ /* Now, sets ARGS_SIZE->CONSTANT so that we pop the right number of
+ bytes after the call. The right number is the entire
+ PENDING_STACK_ADJUST less our ADJUSTMENT plus the amount required
+ by the arguments in the first place. */
+ args_size->constant
+ = pending_stack_adjust - adjustment + unadjusted_args_size;
+
+ /* Push the right number of bytes. */
+ pending_stack_adjust = adjustment;
+ do_pending_stack_adjust ();
+ }
+
/* Generate all the code for a function call
and return an rtx for its value.
Store the value in TARGET (specified as an rtx) if convenient.
*************** expand_call (exp, target, ignore)
*** 1966,1972 ****
rtx call_fusage;
register tree p;
register int i;
! int preferred_stack_boundary;
/* The value of the function call can be put in a hard register. But
if -fcheck-memory-usage, code which invokes functions (and thus
--- 2026,2035 ----
rtx call_fusage;
register tree p;
register int i;
! /* The alignment of the stack, in bits. */
! HOST_WIDE_INT preferred_stack_boundary;
! /* The alignment of the stack, in bytes. */
! HOST_WIDE_INT preferred_unit_stack_boundary;
/* The value of the function call can be put in a hard register. But
if -fcheck-memory-usage, code which invokes functions (and thus
*************** expand_call (exp, target, ignore)
*** 2207,2217 ****
--- 2270,2282 ----
if (fndecl && DECL_NAME (fndecl))
name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
+ /* Figure out the amount to which the stack should be aligned. */
#ifdef PREFERRED_STACK_BOUNDARY
preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
#else
preferred_stack_boundary = STACK_BOUNDARY;
#endif
+ preferred_unit_stack_boundary = preferred_stack_boundary / BITS_PER_UNIT;
/* Ensure current function's preferred stack boundary is at least
what we need. We don't have to increase alignment for recursive
*************** expand_call (exp, target, ignore)
*** 2657,2677 ****
{
/* When the stack adjustment is pending, we get better code
by combining the adjustments. */
! if (pending_stack_adjust && ! (flags & (ECF_CONST | ECF_PURE))
&& ! inhibit_defer_pop)
! {
! int adjust;
! args_size.constant = (unadjusted_args_size
! + ((pending_stack_adjust
! + args_size.constant
! - unadjusted_args_size)
! % (preferred_stack_boundary
! / BITS_PER_UNIT)));
! adjust = (pending_stack_adjust - args_size.constant
! + unadjusted_args_size);
! adjust_stack (GEN_INT (adjust));
! pending_stack_adjust = 0;
! }
else if (argblock == 0)
anti_adjust_stack (GEN_INT (args_size.constant
- unadjusted_args_size));
--- 2722,2734 ----
{
/* When the stack adjustment is pending, we get better code
by combining the adjustments. */
! if (pending_stack_adjust
! && ! (flags & (ECF_CONST | ECF_PURE))
&& ! inhibit_defer_pop)
! combine_pending_stack_adjustment_and_call
! (unadjusted_args_size,
! &args_size,
! preferred_unit_stack_boundary);
else if (argblock == 0)
anti_adjust_stack (GEN_INT (args_size.constant
- unadjusted_args_size));