re PR debug/56154 (Bad .debug_loc generated for some code)
authorJakub Jelinek <jakub@redhat.com>
Thu, 7 Feb 2013 14:48:39 +0000 (15:48 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 7 Feb 2013 14:48:39 +0000 (15:48 +0100)
PR debug/56154
* dwarf2out.c (dwarf2_debug_hooks): Set end_function hook to
dwarf2out_end_function.
(in_first_function_p, maybe_at_text_label_p,
first_loclabel_num_not_at_text_label): New variables.
(dwarf2out_var_location): In the first function find out
lowest loclabel_num N where .LVLN is known not to be equal
to .Ltext0.
(find_empty_loc_ranges_at_text_label, dwarf2out_end_function): New
functions.

* gcc.dg/guality/pr56154-1.c: New test.
* gcc.dg/guality/pr56154-2.c: New test.
* gcc.dg/guality/pr56154-3.c: New test.
* gcc.dg/guality/pr56154-4.c: New test.
* gcc.dg/guality/pr56154-aux.c: New file.

From-SVN: r195850

gcc/ChangeLog
gcc/dwarf2out.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/guality/pr56154-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/guality/pr56154-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/guality/pr56154-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/guality/pr56154-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/guality/pr56154-aux.c [new file with mode: 0644]

index b7914b5..a1ad361 100644 (file)
@@ -1,3 +1,16 @@
+2013-02-07  Jakub Jelinek  <jakub@redhat.com>
+
+       PR debug/56154
+       * dwarf2out.c (dwarf2_debug_hooks): Set end_function hook to
+       dwarf2out_end_function.
+       (in_first_function_p, maybe_at_text_label_p,
+       first_loclabel_num_not_at_text_label): New variables.
+       (dwarf2out_var_location): In the first function find out
+       lowest loclabel_num N where .LVLN is known not to be equal
+       to .Ltext0.
+       (find_empty_loc_ranges_at_text_label, dwarf2out_end_function): New
+       functions.
+
 2013-02-07  Eric Botcazou  <ebotcazou@adacore.com>
 
        PR rtl-optimization/56178
index 06cfb18..13c31ad 100644 (file)
@@ -2351,6 +2351,7 @@ static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree,
 static void dwarf2out_abstract_function (tree);
 static void dwarf2out_var_location (rtx);
 static void dwarf2out_begin_function (tree);
+static void dwarf2out_end_function (unsigned int);
 static void dwarf2out_set_name (tree, tree);
 
 /* The debug hooks structure.  */
@@ -2378,7 +2379,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
 #endif
   dwarf2out_end_epilogue,
   dwarf2out_begin_function,
-  debug_nothing_int,           /* end_function */
+  dwarf2out_end_function,      /* end_function */
   dwarf2out_function_decl,     /* function_decl */
   dwarf2out_global_decl,
   dwarf2out_type_decl,         /* type_decl */
@@ -20627,6 +20628,14 @@ dwarf2out_set_name (tree decl, tree name)
     add_name_attribute (die, dname);
 }
 
+/* True if before or during processing of the first function being emitted.  */
+static bool in_first_function_p = true;
+/* True if loc_note during dwarf2out_var_location call might still be
+   before first real instruction at address equal to .Ltext0.  */
+static bool maybe_at_text_label_p = true;
+/* One above highest N where .LVLN label might be equal to .Ltext0 label.  */
+static unsigned int first_loclabel_num_not_at_text_label;
+
 /* Called by the final INSN scan whenever we see a var location.  We
    use it to drop labels in the right places, and throw the location in
    our lookup table.  */
@@ -20734,6 +20743,45 @@ dwarf2out_var_location (rtx loc_note)
       ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LVL", loclabel_num);
       loclabel_num++;
       last_label = ggc_strdup (loclabel);
+      /* See if loclabel might be equal to .Ltext0.  If yes,
+        bump first_loclabel_num_not_at_text_label.  */
+      if (!have_multiple_function_sections
+         && in_first_function_p
+         && maybe_at_text_label_p)
+       {
+         static rtx last_start;
+         rtx insn;
+         for (insn = loc_note; insn; insn = previous_insn (insn))
+           if (insn == last_start)
+             break;
+           else if (!NONDEBUG_INSN_P (insn))
+             continue;
+           else
+             {
+               rtx body = PATTERN (insn);
+               if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER)
+                 continue;
+               /* Inline asm could occupy zero bytes.  */
+               else if (GET_CODE (body) == ASM_INPUT
+                        || asm_noperands (body) >= 0)
+                 continue;
+#ifdef HAVE_attr_length
+               else if (get_attr_min_length (insn) == 0)
+                 continue;
+#endif
+               else
+                 {
+                   /* Assume insn has non-zero length.  */
+                   maybe_at_text_label_p = false;
+                   break;
+                 }
+             }
+         if (maybe_at_text_label_p)
+           {
+             last_start = loc_note;
+             first_loclabel_num_not_at_text_label = loclabel_num;
+           }
+       }
     }
 
   if (!var_loc_p)
@@ -20903,6 +20951,59 @@ dwarf2out_begin_function (tree fun)
   set_cur_line_info_table (sec);
 }
 
+/* Helper function of dwarf2out_end_function, called only after emitting
+   the very first function into assembly.  Check if some .debug_loc range
+   might end with a .LVL* label that could be equal to .Ltext0.
+   In that case we must force using absolute addresses in .debug_loc ranges,
+   because this range could be .LVLN-.Ltext0 .. .LVLM-.Ltext0 for
+   .LVLN == .LVLM == .Ltext0, thus 0 .. 0, which is a .debug_loc
+   list terminator.
+   Set have_multiple_function_sections to true in that case and
+   terminate htab traversal.  */
+
+static int
+find_empty_loc_ranges_at_text_label (void **slot, void *)
+{
+  var_loc_list *entry;
+  struct var_loc_node *node;
+
+  entry = (var_loc_list *) *slot;
+  node = entry->first;
+  if (node && node->next && node->next->label)
+    {
+      unsigned int i;
+      const char *label = node->next->label;
+      char loclabel[MAX_ARTIFICIAL_LABEL_BYTES];
+
+      for (i = 0; i < first_loclabel_num_not_at_text_label; i++)
+       {
+         ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", i);
+         if (strcmp (label, loclabel) == 0)
+           {
+             have_multiple_function_sections = true;
+             return 0;
+           }
+       }
+    }
+  return 1;
+}
+
+/* Hook called after emitting a function into assembly.
+   This does something only for the very first function emitted.  */
+
+static void
+dwarf2out_end_function (unsigned int)
+{
+  if (in_first_function_p
+      && !have_multiple_function_sections
+      && first_loclabel_num_not_at_text_label
+      && decl_loc_table)
+    htab_traverse (decl_loc_table, find_empty_loc_ranges_at_text_label,
+                  NULL);
+  in_first_function_p = false;
+  maybe_at_text_label_p = false;
+}
+
 /* Add OPCODE+VAL as an entry at the end of the opcode array in TABLE.  */
 
 static void
index ffa9cc3..c024e08 100644 (file)
@@ -1,5 +1,12 @@
 2013-02-07  Jakub Jelinek  <jakub@redhat.com>
 
+       PR debug/56154
+       * gcc.dg/guality/pr56154-1.c: New test.
+       * gcc.dg/guality/pr56154-2.c: New test.
+       * gcc.dg/guality/pr56154-3.c: New test.
+       * gcc.dg/guality/pr56154-4.c: New test.
+       * gcc.dg/guality/pr56154-aux.c: New file.
+
        PR tree-optimization/55789
        * g++.dg/ipa/inline-3.C: Use cleanup-ipa-dump instead of
        cleanup-tree-dump.
diff --git a/gcc/testsuite/gcc.dg/guality/pr56154-1.c b/gcc/testsuite/gcc.dg/guality/pr56154-1.c
new file mode 100644 (file)
index 0000000..4f02bc9
--- /dev/null
@@ -0,0 +1,29 @@
+/* PR debug/56154 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+/* { dg-additional-sources "pr56154-aux.c" } */
+
+#include "../nop.h"
+
+union U { int a, b; };
+volatile int z;
+
+__attribute__((noinline, noclone)) int
+foo (int fd, union U x)
+{
+  int result = x.a != 0;
+  if (fd != 0)
+    result = x.a == 0;
+  asm (NOP : : : "memory");      /* { dg-final { gdb-test pr56154-1.c:17 "x.a" "4" } } */
+  z = x.a;
+  x.a = 6;
+  asm (NOP : : : "memory");      /* { dg-final { gdb-test pr56154-1.c:20 "x.a" "6" } } */
+  return result;
+}
+
+void
+test_main (void)
+{
+  union U u = { .a = 4 };
+  foo (0, u);
+}
diff --git a/gcc/testsuite/gcc.dg/guality/pr56154-2.c b/gcc/testsuite/gcc.dg/guality/pr56154-2.c
new file mode 100644 (file)
index 0000000..6c1d5d9
--- /dev/null
@@ -0,0 +1,39 @@
+/* PR debug/56154 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+/* { dg-additional-sources "pr56154-aux.c" } */
+
+#include "../nop.h"
+
+extern void abort (void);
+
+__attribute__((noinline, noclone)) int
+foo (int x)
+{
+  asm ("");
+  x++;
+  asm ("");
+  x++;
+  asm ("");
+  x++;
+  asm ("");
+  x++;
+  asm ("");
+  x++;
+  asm ("");
+  x++;
+  asm ("");
+  x++;
+  asm ("");
+  x++;
+  asm (NOP : : : "memory");
+  asm (NOP : : : "memory");    /* { dg-final { gdb-test pr56154-2.c:30 "x" "28" } } */
+  return x;
+}
+
+void
+test_main (void)
+{
+  if (foo (20) != 28)
+    abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/guality/pr56154-3.c b/gcc/testsuite/gcc.dg/guality/pr56154-3.c
new file mode 100644 (file)
index 0000000..095dce9
--- /dev/null
@@ -0,0 +1,31 @@
+/* PR debug/56154 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+/* { dg-additional-sources "pr56154-aux.c" } */
+
+#include "../nop.h"
+
+extern void abort (void);
+
+__attribute__((noinline, noclone)) int
+foo (int x)
+{
+  x++;
+  x++;
+  x++;
+  x++;
+  x++;
+  x++;
+  x++;
+  x++;
+  asm (NOP : : : "memory");
+  asm (NOP : : : "memory");    /* { dg-final { gdb-test pr56154-3.c:22 "x" "28" } } */
+  return x;
+}
+
+void
+test_main (void)
+{
+  if (foo (20) != 28)
+    abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/guality/pr56154-4.c b/gcc/testsuite/gcc.dg/guality/pr56154-4.c
new file mode 100644 (file)
index 0000000..bfe7338
--- /dev/null
@@ -0,0 +1,34 @@
+/* PR debug/56154 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+/* { dg-additional-sources "pr56154-aux.c" } */
+
+#include "../nop.h"
+
+extern void abort (void);
+
+volatile int z;
+
+__attribute__((noinline, noclone)) int
+foo (int x)
+{
+  z = 6;
+  x++;
+  x++;
+  x++;
+  x++;
+  x++;
+  x++;
+  x++;
+  x++;
+  asm (NOP : : : "memory");
+  asm (NOP : : : "memory");    /* { dg-final { gdb-test pr56154-4.c:25 "x" "28" } } */
+  return x;
+}
+
+void
+test_main (void)
+{
+  if (foo (20) != 28)
+    abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/guality/pr56154-aux.c b/gcc/testsuite/gcc.dg/guality/pr56154-aux.c
new file mode 100644 (file)
index 0000000..131173c
--- /dev/null
@@ -0,0 +1,11 @@
+/* PR debug/56154 */
+/* { dg-do compile } */
+
+extern void test_main (void);
+
+int
+main ()
+{
+  test_main ();
+  return 0;
+}