DWARF: fix loc. descr. generation for DW_AT_static_link
authorpmderodat <pmderodat@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 26 Nov 2015 14:56:24 +0000 (14:56 +0000)
committerpmderodat <pmderodat@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 26 Nov 2015 14:56:24 +0000 (14:56 +0000)
gcc/ChangeLog:

PR debug/53927
* tree-nested.c (finalize_nesting_tree_1): Append a field to
hold the frame base address.
* dwarf2out.c (gen_subprogram_die): Generate for
DW_AT_static_link a location description that computes the value
of this field.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@230968 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/dwarf2out.c
gcc/tree-nested.c

index da80e71..07ed7ba 100644 (file)
@@ -1,3 +1,12 @@
+2015-11-26  Pierre-Marie de Rodat  <derodat@adacore.com>
+
+       PR debug/53927
+       * tree-nested.c (finalize_nesting_tree_1): Append a field to
+       hold the frame base address.
+       * dwarf2out.c (gen_subprogram_die): Generate for
+       DW_AT_static_link a location description that computes the value
+       of this field.
+
 2015-11-26  Tom de Vries  <tom@codesourcery.com>
 
        revert:
index d46a671..add2204 100644 (file)
@@ -19113,9 +19113,23 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       compute_frame_pointer_to_fb_displacement (cfa_fb_offset);
 
       if (fun->static_chain_decl)
-       add_AT_location_description
-         (subr_die, DW_AT_static_link,
-          loc_list_from_tree (fun->static_chain_decl, 2, NULL));
+       {
+         /* DWARF requires here a location expression that computes the
+            address of the enclosing subprogram's frame base.  The machinery
+            in tree-nested.c is supposed to store this specific address in the
+            last field of the FRAME record.  */
+         const tree frame_type
+           = TREE_TYPE (TREE_TYPE (fun->static_chain_decl));
+         const tree fb_decl = tree_last (TYPE_FIELDS (frame_type));
+
+         tree fb_expr
+           = build1 (INDIRECT_REF, frame_type, fun->static_chain_decl);
+         fb_expr = build3 (COMPONENT_REF, TREE_TYPE (fb_decl),
+                           fb_expr, fb_decl, NULL_TREE);
+
+         add_AT_location_description (subr_die, DW_AT_static_link,
+                                      loc_list_from_tree (fb_expr, 0, NULL));
+       }
     }
 
   /* Generate child dies for template paramaters.  */
index 6bc5016..280d29b 100644 (file)
@@ -2722,10 +2722,10 @@ fold_mem_refs (tree *const &e, void *data ATTRIBUTE_UNUSED)
   return true;
 }
 
-/* Do "everything else" to clean up or complete state collected by the
-   various walking passes -- lay out the types and decls, generate code
-   to initialize the frame decl, store critical expressions in the
-   struct function for rtl to find.  */
+/* Do "everything else" to clean up or complete state collected by the various
+   walking passes -- create a field to hold the frame base address, lay out the
+   types and decls, generate code to initialize the frame decl, store critical
+   expressions in the struct function for rtl to find.  */
 
 static void
 finalize_nesting_tree_1 (struct nesting_info *root)
@@ -2741,20 +2741,70 @@ finalize_nesting_tree_1 (struct nesting_info *root)
      out at this time.  */
   if (root->frame_type)
     {
+      /* Debugging information needs to compute the frame base address of the
+        parent frame out of the static chain from the nested frame.
+
+        The static chain is the address of the FRAME record, so one could
+        imagine it would be possible to compute the frame base address just
+        adding a constant offset to this address.  Unfortunately, this is not
+        possible: if the FRAME object has alignment constraints that are
+        stronger than the stack, then the offset between the frame base and
+        the FRAME object will be dynamic.
+
+        What we do instead is to append a field to the FRAME object that holds
+        the frame base address: then debug info just has to fetch this
+        field.  */
+
+      /* Debugging information will refer to the CFA as the frame base
+        address: we will do the same here.  */
+      const tree frame_addr_fndecl
+        = builtin_decl_explicit (BUILT_IN_DWARF_CFA);
+
+      /* Create a field in the FRAME record to hold the frame base address for
+        this stack frame.  Since it will be used only by the debugger, put it
+        at the end of the record in order not to shift all other offsets.  */
+      tree fb_decl = make_node (FIELD_DECL);
+
+      DECL_NAME (fb_decl) = get_identifier ("FRAME_BASE.PARENT");
+      TREE_TYPE (fb_decl) = ptr_type_node;
+      TREE_ADDRESSABLE (fb_decl) = 1;
+      DECL_CONTEXT (fb_decl) = root->frame_type;
+      TYPE_FIELDS (root->frame_type) = chainon (TYPE_FIELDS (root->frame_type),
+                                               fb_decl);
+
       /* In some cases the frame type will trigger the -Wpadded warning.
         This is not helpful; suppress it. */
       int save_warn_padded = warn_padded;
-      tree *adjust;
-
       warn_padded = 0;
       layout_type (root->frame_type);
       warn_padded = save_warn_padded;
       layout_decl (root->frame_decl, 0);
 
+      /* Initialize the frame base address field.  If the builtin we need is
+        not available, set it to NULL so that debugging information does not
+        reference junk.  */
+      tree fb_ref = build3 (COMPONENT_REF, TREE_TYPE (fb_decl),
+                           root->frame_decl, fb_decl, NULL_TREE);
+      tree fb_tmp;
+
+      if (frame_addr_fndecl != NULL_TREE)
+       {
+         gcall *fb_gimple = gimple_build_call (frame_addr_fndecl, 1,
+                                               integer_zero_node);
+         gimple_stmt_iterator gsi = gsi_last (stmt_list);
+
+         fb_tmp = init_tmp_var_with_call (root, &gsi, fb_gimple);
+       }
+      else
+       fb_tmp = build_int_cst (TREE_TYPE (fb_ref), 0);
+      gimple_seq_add_stmt (&stmt_list,
+                          gimple_build_assign (fb_ref, fb_tmp));
+
       /* Remove root->frame_decl from root->new_local_var_chain, so
         that we can declare it also in the lexical blocks, which
         helps ensure virtual regs that end up appearing in its RTL
         expression get substituted in instantiate_virtual_regs().  */
+      tree *adjust;
       for (adjust = &root->new_local_var_chain;
           *adjust != root->frame_decl;
           adjust = &DECL_CHAIN (*adjust))