This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] Fix bug in cleaning parameters after function call
- From: Josef Zlomek <zlomj9am at artax dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 12 Dec 2003 09:15:13 +0100
- Subject: [patch] Fix bug in cleaning parameters after function call
Hello,
when compiling attached testcase on i686 I noticed that the stack adjustment
in the block containing the last call to foo2 is different when
reached from different edges.
The problem is that when there is one call immediatelly followed by the second
and the second call has 16 bytes (= stack alignment)
the arguments of the first call are not cleaned up.
The reason is that the condition in expand_call is wrong.
The code emitting stack cleanup is in a block
where adjusted_args_size.constant != unadjusted_args_size.
When emiting the second call (which has 16 bytes of parameters)
adjusted_args_size.constant == unadjusted_args_size == 16
and thus the block is not entered.
My patch fixes the logic to emit the stack cleanup when pending_stack_adjust>0
even when adjusted_args_size.constant == unadjusted_args_size.
Interesting part of example in detail:
pseudo code as it is now: as it should be:
sp -= 12; sp -= 12
pushl arg1 pushl arg1
call foo1 call foo1
// cleanup missing sp += 16 // cleanup stack
pushl arg4 // because of call
pushl arg3 sp -= 0 // aligning
pushl arg2 pushl arg4
pushl arg1 pushl arg3
call foo3 pushl arg2
pushl arg1
call foo3
// sp += 16 and sp -= 0 is emitted combined together
Bootstrapped/regtested mainline and 3.3 branch on i686 and x86-64.
OK for mainline and 3.3 branch?
Josef
extern void *foo1(void *a);
extern void *foo4(const char *a, int b);
__attribute__ ((__noreturn__))
extern void foo2 (char *expr, char *file, int line, char *fn);
int foo (const char *name)
{
void *dm, *status;
dm = foo4 (name, 1);
if (dm == 0)
foo2 ("0", "c", 3907, __PRETTY_FUNCTION__);
status = foo1 (dm);
if (status)
{
foo1 (dm);
foo2 ("0", "c", 3918, __PRETTY_FUNCTION__);
}
return 0;
}
2003-12-12 Josef Zlomek <zlomekj@suse.cz>
* calls.c (expand_call): Fix logic to emit stack cleanup when
pending_stack_adjust > 0.
Index: calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.308
diff -c -7 -p -r1.308 calls.c
*** calls.c 8 Dec 2003 10:33:46 -0000 1.308
--- calls.c 12 Dec 2003 08:10:43 -0000
*************** expand_call (tree exp, rtx target, int i
*** 2955,2985 ****
}
}
compute_argument_addresses (args, argblock, num_actuals);
/* If we push args individually in reverse order, perform stack alignment
before the first push (the last arg). */
! if (PUSH_ARGS_REVERSED && argblock == 0
! && adjusted_args_size.constant != unadjusted_args_size)
{
/* When the stack adjustment is pending, we get better code
by combining the adjustments. */
if (pending_stack_adjust
&& ! (flags & ECF_LIBCALL_BLOCK)
&& ! inhibit_defer_pop)
{
pending_stack_adjust
= (combine_pending_stack_adjustment_and_call
(unadjusted_args_size,
&adjusted_args_size,
preferred_unit_stack_boundary));
do_pending_stack_adjust ();
}
! else if (argblock == 0)
anti_adjust_stack (GEN_INT (adjusted_args_size.constant
- unadjusted_args_size));
}
/* Now that the stack is properly aligned, pops can't safely
be deferred during the evaluation of the arguments. */
NO_DEFER_POP;
--- 2955,2985 ----
}
}
compute_argument_addresses (args, argblock, num_actuals);
/* If we push args individually in reverse order, perform stack alignment
before the first push (the last arg). */
! if (PUSH_ARGS_REVERSED && argblock == 0)
{
/* When the stack adjustment is pending, we get better code
by combining the adjustments. */
if (pending_stack_adjust
&& ! (flags & ECF_LIBCALL_BLOCK)
&& ! inhibit_defer_pop)
{
pending_stack_adjust
= (combine_pending_stack_adjustment_and_call
(unadjusted_args_size,
&adjusted_args_size,
preferred_unit_stack_boundary));
do_pending_stack_adjust ();
}
! else if (argblock == 0
! && adjusted_args_size.constant != unadjusted_args_size)
anti_adjust_stack (GEN_INT (adjusted_args_size.constant
- unadjusted_args_size));
}
/* Now that the stack is properly aligned, pops can't safely
be deferred during the evaluation of the arguments. */
NO_DEFER_POP;