On January 3, 2019 11:36:00 PM GMT+01:00, Jakub Jelinek <ja...@redhat.com> 
wrote:
>Hi!
>
>The following testcase FAILs on 8.x branch, went latent later on on the
>trunk and I suppose Alex' i386.c ix86_const_not_ok_for_debug_p change
>would
>have prevented it too.
>
>The problem is in what the comment in const_ok_for_output* says, we
>don't do
>sufficient checking of what kind of expressions we accept inside of
>CONST
>and we could have there something that the assembler doesn't really
>like.
>In particular, in the testcase we ended up with
>(const:P (minus:P (const_int -2) (unspec [(symbol_ref ...)]
>UNSPEC_GOTOFF)))
>and as doesn't like -2-.LC0@gotoff.
>
>We already have some hacks in there, like punt on NOT or NEG.  The
>following
>patch extends it, by requiring that the CONST doesn't contain e.g. .LC0
>+ .LC1
>or any kind of labels in the second operand of MINUS (which is like
>negation).  In theory, we could allow .LC0 - .LC1 if both labels are in
>the
>same section, but the patch tries to be safe.
>
>After writing the patch, I've noticed Alex made
>ix86_const_not_ok_for_debug_p
>changes, but I think they aren't enough, they will still fail on e.g.
>all the cases
>where there are SYMBOL_REFs rather than UNSPECs involved, and on the
>other
>side it disallows 16+.LC0@gotoff which happens quite often.
>
>If const_ok_for_output rejects the whole CONST, there is already code
>to try
>to split it up into smaller expressions, so e.g. that .LC0 - .LC1 would
>be
>emitted then as DW_OP_addr .LC0 DW_OP_addr .LC1 DW_OP_minus, this patch
>extends it so that it can handle the UNSPECs that way as well, so the
>above
>would be DW_OP_const1s 0xff DW_OP_addr .LC0@gotoff DW_OP_minus.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk and
>without the i386.c part after a while for 8.x?

OK. 

Richard. 

>2019-01-03  Jakub Jelinek  <ja...@redhat.com>
>
>       PR debug/88635
>       * dwarf2out.c (const_ok_for_output_1): Reject MINUS that contains
>       SYMBOL_REF, CODE_LABEL or UNSPEC in subexpressions of second argument.
>       Reject PLUS that contains SYMBOL_REF, CODE_LABEL or UNSPEC in
>       subexpressions of both operands.
>       (mem_loc_descriptor): Handle UNSPEC if target hook acks it and all the
>       subrtxes are CONSTANT_P.
>       * config/i386/i386.c (ix86_const_not_ok_for_debug_p): Revert
>       2018-11-09 changes.
>
>       * gcc.dg/debug/dwarf2/pr88635.c: New test.
>
>--- gcc/dwarf2out.c.jj 2019-01-03 12:04:45.720730572 +0100
>+++ gcc/dwarf2out.c    2019-01-03 14:35:02.897782400 +0100
>@@ -14464,6 +14464,41 @@ const_ok_for_output_1 (rtx rtl)
>     case NOT:
>     case NEG:
>       return false;
>+    case PLUS:
>+      {
>+      /* Make sure SYMBOL_REFs/UNSPECs are at most in one of the
>+         operands.  */
>+      subrtx_var_iterator::array_type array;
>+      bool first = false;
>+      FOR_EACH_SUBRTX_VAR (iter, array, XEXP (rtl, 0), ALL)
>+        if (SYMBOL_REF_P (*iter)
>+            || LABEL_P (*iter)
>+            || GET_CODE (*iter) == UNSPEC)
>+          {
>+            first = true;
>+            break;
>+          }
>+      if (!first)
>+        return true;
>+      FOR_EACH_SUBRTX_VAR (iter, array, XEXP (rtl, 1), ALL)
>+        if (SYMBOL_REF_P (*iter)
>+            || LABEL_P (*iter)
>+            || GET_CODE (*iter) == UNSPEC)
>+          return false;
>+      return true;
>+      }
>+    case MINUS:
>+      {
>+      /* Disallow negation of SYMBOL_REFs or UNSPECs when they
>+         appear in the second operand of MINUS.  */
>+      subrtx_var_iterator::array_type array;
>+      FOR_EACH_SUBRTX_VAR (iter, array, XEXP (rtl, 1), ALL)
>+        if (SYMBOL_REF_P (*iter)
>+            || LABEL_P (*iter)
>+            || GET_CODE (*iter) == UNSPEC)
>+          return false;
>+      return true;
>+      }
>     default:
>       return true;
>     }
>@@ -15607,6 +15642,7 @@ mem_loc_descriptor (rtx rtl, machine_mod
>        pool.  */
>     case CONST:
>     case SYMBOL_REF:
>+    case UNSPEC:
>       if (!is_a <scalar_int_mode> (mode, &int_mode)
>         || (GET_MODE_SIZE (int_mode) > DWARF2_ADDR_SIZE
> #ifdef POINTERS_EXTEND_UNSIGNED
>@@ -15614,6 +15650,30 @@ mem_loc_descriptor (rtx rtl, machine_mod
> #endif
>             ))
>       break;
>+
>+      if (GET_CODE (rtl) == UNSPEC)
>+      {
>+        /* If delegitimize_address couldn't do anything with the UNSPEC, we
>+           can't express it in the debug info.  This can happen e.g. with
>some
>+           TLS UNSPECs.  Allow UNSPECs formerly from CONST that the backend
>+           approves.  */
>+        bool not_ok = false;
>+        subrtx_var_iterator::array_type array;
>+        FOR_EACH_SUBRTX_VAR (iter, array, rtl, ALL)
>+          if ((*iter != rtl && !CONSTANT_P (*iter))
>+              || !const_ok_for_output_1 (*iter))
>+            {
>+              not_ok = true;
>+              break;
>+            }
>+
>+        if (not_ok)
>+          break;
>+
>+        rtl = gen_rtx_CONST (GET_MODE (rtl), rtl);
>+        goto symref;
>+      }
>+
>       if (GET_CODE (rtl) == SYMBOL_REF
>         && SYMBOL_REF_TLS_MODEL (rtl) != TLS_MODEL_NONE)
>       {
>@@ -16282,7 +16342,6 @@ mem_loc_descriptor (rtx rtl, machine_mod
>     case VEC_CONCAT:
>     case VEC_DUPLICATE:
>     case VEC_SERIES:
>-    case UNSPEC:
>     case HIGH:
>     case FMA:
>     case STRICT_LOW_PART:
>@@ -16291,9 +16350,6 @@ mem_loc_descriptor (rtx rtl, machine_mod
>     case CLRSB:
>     case CLOBBER:
>     case CLOBBER_HIGH:
>-      /* If delegitimize_address couldn't do anything with the UNSPEC,
>we
>-       can't express it in the debug info.  This can happen e.g. with some
>-       TLS UNSPECs.  */
>       break;
> 
>     case CONST_STRING:
>--- gcc/config/i386/i386.c.jj  2019-01-01 12:37:32.382725150 +0100
>+++ gcc/config/i386/i386.c     2019-01-03 14:32:43.050093691 +0100
>@@ -17240,18 +17240,6 @@ ix86_const_not_ok_for_debug_p (rtx x)
>   if (SYMBOL_REF_P (x) && strcmp (XSTR (x, 0), GOT_SYMBOL_NAME) == 0)
>     return true;
> 
>-  /* Reject UNSPECs within expressions.  We could accept symbol@gotoff
>-     + literal_constant, but that would hardly come up in practice,
>-     and it's not worth the trouble of having to reject that as an
>-     operand to pretty much anything else.  */
>-  if (UNARY_P (x)
>-      && GET_CODE (XEXP (x, 0)) == UNSPEC)
>-    return true;
>-  if (BINARY_P (x)
>-      && (GET_CODE (XEXP (x, 0)) == UNSPEC
>-        || GET_CODE (XEXP (x, 1)) == UNSPEC))
>-    return true;
>-
>   return false;
> }
> >
>--- gcc/testsuite/gcc.dg/debug/dwarf2/pr88635.c.jj     2019-01-03
>14:32:43.050093691 +0100
>+++ gcc/testsuite/gcc.dg/debug/dwarf2/pr88635.c        2019-01-03
>14:32:43.050093691 +0100
>@@ -0,0 +1,24 @@
>+/* PR debug/88635 */
>+/* { dg-do assemble } */
>+/* { dg-options "-g -O2" } */
>+/* { dg-additional-options "-fpie" { target pie } } */
>+
>+static void
>+foo (char *b)
>+{
>+  unsigned c = 0;
>+  --c;
>+  do
>+    if (++*b++ == 0)
>+      break;
>+  while (--c);
>+  if (c == 0)
>+    while (*b++)
>+      ;
>+}
>+
>+void
>+bar (void)
>+{
>+  foo ("");
>+}
>
>       Jakub

Reply via email to