DWARF: add abstract origin links on lexical blocks DIEs
authorPierre-Marie de Rodat <derodat@adacore.com>
Tue, 10 May 2016 08:03:49 +0000 (08:03 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Tue, 10 May 2016 08:03:49 +0000 (08:03 +0000)
Track from which abstract lexical block concrete ones come from in DWARF
so that debuggers can inherit the former from the latter. This enables
debuggers to properly handle the following case:

  * function Child2 is nested in a lexical block, itself nested in
    function Child1;
  * function Child1 is inlined into some call site;
  * function Child2 is never inlined.

Here, Child2 is described in DWARF only in the abstract instance of
Child1. So when debuggers decode Child1's concrete instances, they need
to fetch the definition for Child2 in the corresponding abstract
instance: the DW_AT_abstract_origin link on the lexical block that
embeds Child1 enables them to do that.

Bootstrapped and regtested on x86_64-linux.

gcc/ChangeLog:

* dwarf2out.c (add_abstract_origin_attribute): Adjust
documentation comment.  For BLOCK nodes, add a
DW_AT_abstract_origin attribute that points to the DIE generated
for the origin BLOCK.
(gen_lexical_block_die): Call add_abstract_origin_attribute for
blocks from inlined functions.

gcc/testsuite/Changelog:

* gcc.dg/debug/dwarf2/nested_fun.c: New testcase.

From-SVN: r236065

gcc/ChangeLog
gcc/dwarf2out.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/debug/dwarf2/nested_fun.c [new file with mode: 0644]

index 687ab97b4502916f3e6542c1b50d26dc10748a19..fb9b6a7f4166b0de6e9b96f3de5157526c7c646f 100644 (file)
@@ -1,3 +1,12 @@
+2016-05-10  Pierre-Marie de Rodat  <derodat@adacore.com>
+
+       * dwarf2out.c (add_abstract_origin_attribute): Adjust
+       documentation comment.  For BLOCK nodes, add a
+       DW_AT_abstract_origin attribute that points to the DIE generated
+       for the origin BLOCK.
+       (gen_lexical_block_die): Call add_abstract_origin_attribute for
+       blocks from inlined functions.
+
 2016-05-10  Alan Modra  <amodra@gmail.com>
 
        PR target/70947
index fb3f7b9eb3c12a1568ef55d602a1e97b694128c6..da95e19849dfb58ce195244660c8b247bbb92a66 100644 (file)
@@ -18621,15 +18621,16 @@ add_prototyped_attribute (dw_die_ref die, tree func_type)
 }
 
 /* Add an 'abstract_origin' attribute below a given DIE.  The DIE is found
-   by looking in either the type declaration or object declaration
-   equate table.  */
+   by looking in the type declaration, the object declaration equate table or
+   the block mapping.  */
 
 static inline dw_die_ref
 add_abstract_origin_attribute (dw_die_ref die, tree origin)
 {
   dw_die_ref origin_die = NULL;
 
-  if (TREE_CODE (origin) != FUNCTION_DECL)
+  if (TREE_CODE (origin) != FUNCTION_DECL
+      && TREE_CODE (origin) != BLOCK)
     {
       /* We may have gotten separated from the block for the inlined
         function, if we're in an exception handler or some such; make
@@ -18651,6 +18652,8 @@ add_abstract_origin_attribute (dw_die_ref die, tree origin)
     origin_die = lookup_decl_die (origin);
   else if (TYPE_P (origin))
     origin_die = lookup_type_die (origin);
+  else if (TREE_CODE (origin) == BLOCK)
+    origin_die = BLOCK_DIE (origin);
 
   /* XXX: Functions that are never lowered don't always have correct block
      trees (in the case of java, they simply have no block tree, in some other
@@ -21467,6 +21470,10 @@ gen_lexical_block_die (tree stmt, dw_die_ref context_die)
          BLOCK_DIE (stmt) = stmt_die;
          old_die = NULL;
        }
+
+      tree origin = block_ultimate_origin (stmt);
+      if (origin != NULL_TREE && origin != stmt)
+       add_abstract_origin_attribute (stmt_die, origin);
     }
 
   if (old_die)
index 29a9709e6ca639b20ac48164ba8238a843269807..f144648aae8e68a9cef871e396b82dfacbed4acb 100644 (file)
@@ -1,3 +1,7 @@
+2016-05-10  Pierre-Marie de Rodat  <derodat@adacore.com>
+
+       * gcc.dg/debug/dwarf2/nested_fun.c: New testcase.
+
 2016-05-09  Uros Bizjak  <ubizjak@gmail.com>
 
        * gcc.target/i386/fabsneg-1.c New test.
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/nested_fun.c b/gcc/testsuite/gcc.dg/debug/dwarf2/nested_fun.c
new file mode 100644 (file)
index 0000000..c783ac0
--- /dev/null
@@ -0,0 +1,65 @@
+/* As part of inlining, a BLOCK (described as DW_TAG_lexical_block DIE's) may
+   be present both as an abstract instance and a concrete one in the DWARF
+   output.  This testcase attempts to make sure that the concrete ones refer to
+   the abstract ones thanks to the DW_AT_abstract_origin attribute.
+
+   Such a back-link enables debuggers to make entities present in the abstract
+   instance only available in concrete ones.  */
+
+/* { dg-options "-O2 -g -std=gnu99 -gdwarf -dA" } */
+/* { dg-final { scan-assembler-times "\\(DIE \\(0x.*\\) DW_TAG_lexical_block\\)\[^)\]*DW_AT_abstract_origin" 1 } } */
+
+extern void *create (const char *);
+extern void destroy (void *);
+extern void do_nothing (char);
+
+struct string
+{
+  const char *data;
+  int lb;
+  int ub;
+};
+
+int
+main (void)
+{
+  void *o1 = create ("foo");
+
+  void
+  parent (void)
+  {
+    {
+      void *o2 = create ("bar");
+
+      int
+      child (struct string s)
+      {
+       int i = s.lb;
+
+       if (s.lb <= s.ub)
+         while (1)
+           {
+             char c = s.data[i - s.lb];
+             do_nothing (c);
+             if (c == 'o')
+               return 1;
+             if (i == s.ub)
+               break;
+             ++i;
+           }
+       return 0;
+      }
+
+      int r;
+
+      r = child ((struct string) {"baz", 1, 3});
+      r = child ((struct string) {"qux", 2, 4});
+      r = child ((struct string) {"foobar", 1, 6});
+    }
+
+    do_nothing (0);
+  }
+
+  parent ();
+  return 0;
+}