On Tue, 5 Mar 2013, Jakub Jelinek wrote:

> Hi!
> 
> cselib (probably among others) isn't prepared to handle arbitrarily
> complex debug insns.  The debug insns are usually created from debug stmts
> which shouldn't have unbound complexity, but with TER we can actually end up
> with arbitrarily large debug insns.
> 
> This patch fixes that up during expansion, by splitting subexpressions of
> too large debug insn expressions into their own debug temporaries.
> 
> So far bootstrapped/regtested on x86_64-linux and i686-linux without the
> first two hunks (it caused one failure on the latter because of invalid RTL
> sharing), I'm going to bootstrap/regtest it again, ok for trunk if it
> passes?

Works for me.

Richard.

> 2013-03-05  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR debug/56510
>       * cfgexpand.c (expand_debug_parm_decl): Call copy_rtx on incoming.
>       (avoid_complex_debug_insns): New function.
>       (expand_debug_locations): Call it.
> 
>       * gcc.dg/pr56510.c: New test.
> 
> --- gcc/cfgexpand.c.jj        2013-03-05 15:12:15.071565689 +0100
> +++ gcc/cfgexpand.c   2013-03-05 17:21:55.683602432 +0100
> @@ -2622,6 +2622,8 @@ expand_debug_parm_decl (tree decl)
>             reg = gen_raw_REG (GET_MODE (reg), OUTGOING_REGNO (REGNO (reg)));
>             incoming = replace_equiv_address_nv (incoming, reg);
>           }
> +       else
> +         incoming = copy_rtx (incoming);
>       }
>  #endif
>  
> @@ -2637,7 +2639,7 @@ expand_debug_parm_decl (tree decl)
>         || (GET_CODE (XEXP (incoming, 0)) == PLUS
>             && XEXP (XEXP (incoming, 0), 0) == virtual_incoming_args_rtx
>             && CONST_INT_P (XEXP (XEXP (incoming, 0), 1)))))
> -    return incoming;
> +    return copy_rtx (incoming);
>  
>    return NULL_RTX;
>  }
> @@ -3704,6 +3706,54 @@ expand_debug_source_expr (tree exp)
>    return op0;
>  }
>  
> +/* Ensure INSN_VAR_LOCATION_LOC (insn) doesn't have unbound complexity.
> +   Allow 4 levels of rtl nesting for most rtl codes, and if we see anything
> +   deeper than that, create DEBUG_EXPRs and emit DEBUG_INSNs before INSN.  */
> +
> +static void
> +avoid_complex_debug_insns (rtx insn, rtx *exp_p, int depth)
> +{
> +  rtx exp = *exp_p;
> +  if (exp == NULL_RTX)
> +    return;
> +  if ((OBJECT_P (exp) && !MEM_P (exp)) || GET_CODE (exp) == CLOBBER)
> +    return;
> +
> +  if (depth == 4)
> +    {
> +      /* Create DEBUG_EXPR (and DEBUG_EXPR_DECL).  */
> +      rtx dval = make_debug_expr_from_rtl (exp);
> +
> +      /* Emit a debug bind insn before INSN.  */
> +      rtx bind = gen_rtx_VAR_LOCATION (GET_MODE (exp),
> +                                    DEBUG_EXPR_TREE_DECL (dval), exp,
> +                                    VAR_INIT_STATUS_INITIALIZED);
> +
> +      emit_debug_insn_before (bind, insn);
> +      *exp_p = dval;
> +      return;
> +    }
> +
> +  const char *format_ptr = GET_RTX_FORMAT (GET_CODE (exp));
> +  int i, j;
> +  for (i = 0; i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
> +    switch (*format_ptr++)
> +      {
> +      case 'e':
> +     avoid_complex_debug_insns (insn, &XEXP (exp, i), depth + 1);
> +     break;
> +
> +      case 'E':
> +      case 'V':
> +     for (j = 0; j < XVECLEN (exp, i); j++)
> +       avoid_complex_debug_insns (insn, &XVECEXP (exp, i, j), depth + 1);
> +     break;
> +
> +      default:
> +     break;
> +      }
> +}
> +
>  /* Expand the _LOCs in debug insns.  We run this after expanding all
>     regular insns, so that any variables referenced in the function
>     will have their DECL_RTLs set.  */
> @@ -3724,7 +3774,7 @@ expand_debug_locations (void)
>      if (DEBUG_INSN_P (insn))
>        {
>       tree value = (tree)INSN_VAR_LOCATION_LOC (insn);
> -     rtx val;
> +     rtx val, prev_insn, insn2;
>       enum machine_mode mode;
>  
>       if (value == NULL_TREE)
> @@ -3753,6 +3803,9 @@ expand_debug_locations (void)
>         }
>  
>       INSN_VAR_LOCATION_LOC (insn) = val;
> +     prev_insn = PREV_INSN (insn);
> +     for (insn2 = insn; insn2 != prev_insn; insn2 = PREV_INSN (insn2))
> +       avoid_complex_debug_insns (insn2, &INSN_VAR_LOCATION_LOC (insn2), 0);
>        }
>  
>    flag_strict_aliasing = save_strict_alias;
> --- gcc/testsuite/gcc.dg/pr56510.c.jj 2013-03-05 16:57:54.498939220 +0100
> +++ gcc/testsuite/gcc.dg/pr56510.c    2013-03-05 16:57:54.499939214 +0100
> @@ -0,0 +1,37 @@
> +/* PR debug/56510 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -g" } */
> +
> +struct S { unsigned long s1; void **s2[0]; };
> +void **a, **b, **c, **d, **e, **f;
> +
> +static void **
> +baz (long x, long y)
> +{
> +  void **s = f;
> +  *f = (void **) (y << 8 | (x & 0xff));
> +  f += y + 1;
> +  return s;
> +}
> +
> +void bar (void);
> +void
> +foo (void)
> +{
> +  void **g = b[4];
> +  a = b[2];
> +  b = b[1];
> +  g[2] = e;
> +  void **h
> +    = ((void **************************)
> +       
> a)[1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][66];
> +  void **i = ((struct S *) h)->s2[4];
> +  d = baz (4, 3);
> +  d[1] = b;
> +  d[2] = a;
> +  d[3] = bar;
> +  b = d;
> +  g[1] = i[2];
> +  a = g;
> +  ((void (*) (void)) (i[1])) ();
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imend

Reply via email to