re PR middle-end/35616 (Incorrect code while O2 compling)

PR middle-end/35616
        * calls.c (expand_call): Check overlap of arguments with call
        address for sibcalls.

        * gcc.dg/pr35616.c: New test.

From-SVN: r133348
This commit is contained in:
Michael Matz 2008-03-19 19:15:03 +00:00 committed by Michael Matz
parent ac05557cc7
commit 05e6ee933e
4 changed files with 63 additions and 1 deletions

View File

@ -1,3 +1,9 @@
2008-03-19 Michael Matz <matz@suse.de>
PR middle-end/35616
* calls.c (expand_call): Check overlap of arguments with call
address for sibcalls.
2008-03-19 Uros Bizjak <ubizjak@gmail.com>
PR target/35496

View File

@ -2326,7 +2326,7 @@ expand_call (tree exp, rtx target, int ignore)
int save_pending_stack_adjust = 0;
int save_stack_pointer_delta = 0;
rtx insns;
rtx before_call, next_arg_reg;
rtx before_call, next_arg_reg, after_args;
if (pass == 0)
{
@ -2756,6 +2756,7 @@ expand_call (tree exp, rtx target, int ignore)
use_reg (&call_fusage, struct_value);
}
after_args = get_last_insn ();
funexp = prepare_call_address (funexp, static_chain_value,
&call_fusage, reg_parm_seen, pass == 0);
@ -2790,6 +2791,13 @@ expand_call (tree exp, rtx target, int ignore)
next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
flags, & args_so_far);
/* If the call setup or the call itself overlaps with anything
of the argument setup we probably clobbered our call address.
In that case we can't do sibcalls. */
if (pass == 0
&& check_sibcall_argument_overlap (after_args, 0, 0))
sibcall_failure = 1;
/* If a non-BLKmode value is returned at the most significant end
of a register, shift the register right by the appropriate amount
and update VALREG accordingly. BLKmode values are handled by the

View File

@ -1,3 +1,8 @@
2008-03-19 Michael Matz <matz@suse.de>
PR middle-end/35616
* gcc.dg/pr35616.c: New test.
2008-03-19 Daniel Franke <franke.daniel@gmail.com>
PR fortran/35152

View File

@ -0,0 +1,43 @@
/* { dg-do run } */
/* { dg-options "-O2" } */
typedef void (*listener_fun)(
int a,
int b,
int c);
struct data_t
{
int a;
listener_fun listener;
int b;
int c;
int d;
};
extern void abort(void);
void function_calling_listener (struct data_t data);
void function_calling_listener (struct data_t data)
{
data.listener(data.a, data.c, data.d);
}
void my_listener(int a, int b, int c)
{
if (a != 42 || b != 44 || c != 45)
abort ();
}
int main()
{
struct data_t d;
d.a = 42;
d.b = 43;
d.c = 44;
d.d = 45;
d.listener = my_listener;
function_calling_listener (d);
return 0;
}