[patch] fix PR middle-end/35616, sibcall miscompilation

Richard Guenther richard.guenther@gmail.com
Tue Mar 18 16:57:00 GMT 2008


On Tue, Mar 18, 2008 at 5:03 PM, Michael Matz <matz@suse.de> wrote:
> Hi,
>
>  as seen in the bugreport expand_call fails to ensure that the call address
>  doesn't overlap with the arguments for sibcalls (it checks all
>  inter-argument overlap and disables sibcalls then, but if the arguments
>  don't overlap, but one of them overlaps the call address it's clobbered as
>  in the testcase).
>
>  Regstrapping in progress on i686 and x86_64.  Okay for trunk if this
>  passes?  What with 4.3?

Ok for trunk and all open branches.

Thanks,
Richard.

>
>  Ciao,
>  Michael.
>         PR middle-end/35616
>         * calls.c (expand_call): Check overlap of arguments with call
>         address for sibcalls.
>
>         * gcc.dg/pr35616.c: New test.
>
>  Index: gcc/calls.c
>  ===================================================================
>  --- gcc/calls.c (revision 133304)
>  +++ gcc/calls.c (working copy)
>  @@ -2326,7 +2326,7 @@ expand_call (tree exp, rtx target, int i
>        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 i
>             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 i
>                    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
>  Index: gcc/testsuite/gcc.dg/pr35616.c
>  ===================================================================
>  --- gcc/testsuite/gcc.dg/pr35616.c      (revision 0)
>  +++ gcc/testsuite/gcc.dg/pr35616.c      (revision 0)
>  @@ -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;
>  +}
>



More information about the Gcc-patches mailing list