On Sun, Sep 17, 2017 at 10:21:23PM +0930, Alan Modra wrote:
> When -fstack-protector-all or -fsanitize=address, rs6000.h sets
> FRAME_GROWS_DOWNWARD.  This breaks the assumption in
> rs6000_return_addr that the stack link is at frame_pointer+0.

Well, builtin_return_address(N) already works correctly for N>0, getting
the backlink via the frame pointer; it's fetching the return address via
the frame pointer that doesn't work.

Okay for trunk (and backports later) with those comments fixed.  Thanks!


Segher


>       PR target/81996
>       * gcc/config/rs6000/rs6000.c (rs6000_return_addr): Use
>       stack_pointer_rtx for count 0.  Update comments.  Break up
>       large rtl expression.
> 
> diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
> index e611c45..f14392d 100644
> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -24988,24 +24988,23 @@ debug_stack_info (rs6000_stack_t *info)
>  rtx
>  rs6000_return_addr (int count, rtx frame)
>  {
> -  /* Currently we don't optimize very well between prolog and body
> -     code and for PIC code the code can be actually quite bad, so
> -     don't try to be too clever here.  */
> +  /* We can't use get_hard_reg_initial_val for LR when count == 0 if LR
> +     is trashed by the prologue, as it is for PIC on ABI_V4 and Darwin.  */
>    if (count != 0
>        || ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN) && flag_pic))
>      {
>        cfun->machine->ra_needs_full_frame = 1;
>  
> -      return
> -     gen_rtx_MEM
> -       (Pmode,
> -        memory_address
> -        (Pmode,
> -         plus_constant (Pmode,
> -                        copy_to_reg
> -                        (gen_rtx_MEM (Pmode,
> -                                      memory_address (Pmode, frame))),
> -                        RETURN_ADDRESS_OFFSET)));
> +      if (count == 0)
> +     /* FRAME is set to frame_pointer_rtx by the generic code, but that
> +        is good for loading 0(r1) only when !FRAME_GROWS_DOWNWARD.  */
> +     frame = stack_pointer_rtx;
> +      rtx prev_frame_addr = memory_address (Pmode, frame);
> +      rtx prev_frame = copy_to_reg (gen_rtx_MEM (Pmode, prev_frame_addr));
> +      rtx lr_save_off = plus_constant (Pmode,
> +                                    prev_frame, RETURN_ADDRESS_OFFSET);
> +      rtx lr_save_addr = memory_address (Pmode, lr_save_off);
> +      return gen_rtx_MEM (Pmode, lr_save_addr);
>      }
>  
>    cfun->machine->ra_need_lr = 1;

Reply via email to