re PR debug/82718 (Bad DWARF5 .debug_loclists generation)
authorJakub Jelinek <jakub@redhat.com>
Tue, 21 Nov 2017 07:59:03 +0000 (08:59 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 21 Nov 2017 07:59:03 +0000 (08:59 +0100)
PR debug/82718
* dwarf2out.c (dw_loc_list): If crtl->has_bb_partition, temporarily
set in_cold_section_p to the partition containing loc_list->first.
When seeing loc_list->last_before_switch node, update secname and
perform range_across_switch second partition handling only after that.

* gcc.dg/debug/dwarf2/pr82718-1.c: New test.
* gcc.dg/debug/dwarf2/pr82718-2.c: New test.

From-SVN: r254989

gcc/ChangeLog
gcc/dwarf2out.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/debug/dwarf2/pr82718-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/debug/dwarf2/pr82718-2.c [new file with mode: 0644]

index 1c3aaede5ec0a945c88f8a56e6c636e28ee3989b..207e6f32b2e0dc000dd75eec4f76cc7db12274c9 100644 (file)
@@ -1,5 +1,11 @@
 2017-11-21  Jakub Jelinek  <jakub@redhat.com>
 
+       PR debug/82718
+       * dwarf2out.c (dw_loc_list): If crtl->has_bb_partition, temporarily
+       set in_cold_section_p to the partition containing loc_list->first.
+       When seeing loc_list->last_before_switch node, update secname and
+       perform range_across_switch second partition handling only after that.
+
        PR debug/82933
        * run-rtl-passes.c: Include debug.h.
        (run_rtl_passes): Call debug_hooks->assembly_start.
index 7fd6ae37fd27cd0604f0bc4d559aff64098e7591..89e119c3dcad352925e34c5880e16af4c59cdca7 100644 (file)
@@ -16366,92 +16366,111 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
      This means we have to special case the last node, and generate
      a range of [last location start, end of function label].  */
 
-  secname = secname_for_decl (decl);
+  if (cfun && crtl->has_bb_partition)
+    {
+      bool save_in_cold_section_p = in_cold_section_p;
+      in_cold_section_p = first_function_block_is_cold;
+      if (loc_list->last_before_switch == NULL)
+       in_cold_section_p = !in_cold_section_p;
+      secname = secname_for_decl (decl);
+      in_cold_section_p = save_in_cold_section_p;
+    }
+  else
+    secname = secname_for_decl (decl);
 
   for (node = loc_list->first; node; node = node->next)
-    if (GET_CODE (node->loc) == EXPR_LIST
-       || NOTE_VAR_LOCATION_LOC (node->loc) != NULL_RTX)
-      {
-       if (GET_CODE (node->loc) == EXPR_LIST)
-         {
-           /* This requires DW_OP_{,bit_}piece, which is not usable
-              inside DWARF expressions.  */
-           if (want_address != 2)
-             continue;
-           descr = dw_sra_loc_expr (decl, node->loc);
-           if (descr == NULL)
-             continue;
-         }
-       else
-         {
-           initialized = NOTE_VAR_LOCATION_STATUS (node->loc);
-           varloc = NOTE_VAR_LOCATION (node->loc);
-           descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
-         }
-       if (descr)
-         {
-           bool range_across_switch = false;
-           /* If section switch happens in between node->label
-              and node->next->label (or end of function) and
-              we can't emit it as a single entry list,
-              emit two ranges, first one ending at the end
-              of first partition and second one starting at the
-              beginning of second partition.  */
-           if (node == loc_list->last_before_switch
-               && (node != loc_list->first || loc_list->first->next)
-               && current_function_decl)
-             {
-               endname = cfun->fde->dw_fde_end;
-               range_across_switch = true;
-             }
-           /* The variable has a location between NODE->LABEL and
-              NODE->NEXT->LABEL.  */
-           else if (node->next)
-             endname = node->next->label;
-           /* If the variable has a location at the last label
-              it keeps its location until the end of function.  */
-           else if (!current_function_decl)
-             endname = text_end_label;
-           else
-             {
-               ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
-                                            current_function_funcdef_no);
-               endname = ggc_strdup (label_id);
-             }
+    {
+      bool range_across_switch = false;
+      if (GET_CODE (node->loc) == EXPR_LIST
+         || NOTE_VAR_LOCATION_LOC (node->loc) != NULL_RTX)
+       {
+         if (GET_CODE (node->loc) == EXPR_LIST)
+           {
+             descr = NULL;
+             /* This requires DW_OP_{,bit_}piece, which is not usable
+                inside DWARF expressions.  */
+             if (want_address == 2)
+               descr = dw_sra_loc_expr (decl, node->loc);
+           }
+         else
+           {
+             initialized = NOTE_VAR_LOCATION_STATUS (node->loc);
+             varloc = NOTE_VAR_LOCATION (node->loc);
+             descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
+           }
+         if (descr)
+           {
+             /* If section switch happens in between node->label
+                and node->next->label (or end of function) and
+                we can't emit it as a single entry list,
+                emit two ranges, first one ending at the end
+                of first partition and second one starting at the
+                beginning of second partition.  */
+             if (node == loc_list->last_before_switch
+                 && (node != loc_list->first || loc_list->first->next)
+                 && current_function_decl)
+               {
+                 endname = cfun->fde->dw_fde_end;
+                 range_across_switch = true;
+               }
+             /* The variable has a location between NODE->LABEL and
+                NODE->NEXT->LABEL.  */
+             else if (node->next)
+               endname = node->next->label;
+             /* If the variable has a location at the last label
+                it keeps its location until the end of function.  */
+             else if (!current_function_decl)
+               endname = text_end_label;
+             else
+               {
+                 ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
+                                              current_function_funcdef_no);
+                 endname = ggc_strdup (label_id);
+               }
 
-           *listp = new_loc_list (descr, node->label, endname, secname);
-           if (TREE_CODE (decl) == PARM_DECL
-               && node == loc_list->first
-               && NOTE_P (node->loc)
-               && strcmp (node->label, endname) == 0)
-             (*listp)->force = true;
-           listp = &(*listp)->dw_loc_next;
+             *listp = new_loc_list (descr, node->label, endname, secname);
+             if (TREE_CODE (decl) == PARM_DECL
+                 && node == loc_list->first
+                 && NOTE_P (node->loc)
+                 && strcmp (node->label, endname) == 0)
+               (*listp)->force = true;
+             listp = &(*listp)->dw_loc_next;
+           }
+       }
 
-           if (range_across_switch)
-             {
-               if (GET_CODE (node->loc) == EXPR_LIST)
-                 descr = dw_sra_loc_expr (decl, node->loc);
-               else
-                 {
-                   initialized = NOTE_VAR_LOCATION_STATUS (node->loc);
-                   varloc = NOTE_VAR_LOCATION (node->loc);
-                   descr = dw_loc_list_1 (decl, varloc, want_address,
-                                          initialized);
-                 }
-               gcc_assert (descr);
-               /* The variable has a location between NODE->LABEL and
-                  NODE->NEXT->LABEL.  */
-               if (node->next)
-                 endname = node->next->label;
-               else
-                 endname = cfun->fde->dw_fde_second_end;
-               *listp = new_loc_list (descr,
-                                      cfun->fde->dw_fde_second_begin,
-                                      endname, secname);
-               listp = &(*listp)->dw_loc_next;
-             }
-         }
-      }
+      if (cfun
+         && crtl->has_bb_partition
+         && node == loc_list->last_before_switch)
+       {
+         bool save_in_cold_section_p = in_cold_section_p;
+         in_cold_section_p = !first_function_block_is_cold;
+         secname = secname_for_decl (decl);
+         in_cold_section_p = save_in_cold_section_p;
+       }
+
+      if (range_across_switch)
+       {
+         if (GET_CODE (node->loc) == EXPR_LIST)
+           descr = dw_sra_loc_expr (decl, node->loc);
+         else
+           {
+             initialized = NOTE_VAR_LOCATION_STATUS (node->loc);
+             varloc = NOTE_VAR_LOCATION (node->loc);
+             descr = dw_loc_list_1 (decl, varloc, want_address,
+                                    initialized);
+           }
+         gcc_assert (descr);
+         /* The variable has a location between NODE->LABEL and
+            NODE->NEXT->LABEL.  */
+         if (node->next)
+           endname = node->next->label;
+         else
+           endname = cfun->fde->dw_fde_second_end;
+         *listp = new_loc_list (descr, cfun->fde->dw_fde_second_begin,
+                                endname, secname);
+         listp = &(*listp)->dw_loc_next;
+       }
+    }
 
   /* Try to avoid the overhead of a location list emitting a location
      expression instead, but only if we didn't have more than one
index 32fce8c44216efb8fa71040f888e1f8ce7c54c15..ca2206c575cb6a4e17c79566716afffccf09577f 100644 (file)
@@ -1,5 +1,9 @@
 2017-11-21  Jakub Jelinek  <jakub@redhat.com>
 
+       PR debug/82718
+       * gcc.dg/debug/dwarf2/pr82718-1.c: New test.
+       * gcc.dg/debug/dwarf2/pr82718-2.c: New test.
+
        PR debug/82933
        * gcc.dg/rtl/x86_64/pr82933.c: New test.
 
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr82718-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr82718-1.c
new file mode 100644 (file)
index 0000000..1ed92bf
--- /dev/null
@@ -0,0 +1,41 @@
+/* PR debug/82718 */
+/* { dg-do assemble } */
+/* { dg-options "-O2 -gdwarf-5" } */
+
+extern int e;
+extern long foo (int, void *, unsigned long, unsigned long);
+struct S
+{
+  int f;
+  unsigned long t, s;
+};
+
+static inline long
+bv (int x, void *y, unsigned long z, unsigned long w)
+{
+  long a = 0;
+  do
+    {
+      long g;
+      do
+       g = (long int) (foo (x, y + a, z - a, w + a));
+      while (g == -1L && e == 9959);
+      if (g <= 0)
+       return g < 0 ? g : a;
+      a += g;
+    }
+  while ((unsigned long) a < z);
+  return a;
+}
+
+const char *
+baz (struct S *x)
+{
+  unsigned long h = 8;
+  char *j = 0;
+  unsigned long z = x->f;
+  if (__builtin_expect (!!((unsigned long) bv (x->f, j, z, x->t + h + 10) != z), 0))
+    return 0;
+  x->s = z;
+  return j;
+}
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr82718-2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr82718-2.c
new file mode 100644 (file)
index 0000000..85279e1
--- /dev/null
@@ -0,0 +1,12 @@
+/* PR debug/82718 */
+/* { dg-do assemble } */
+/* { dg-options "-O2 -gdwarf-5" } */
+
+extern int bar (void);
+
+int
+foo (int x)
+{
+  if (bar ())
+    __builtin_abort ();
+}