re PR debug/49382 (-O2 -g: DW_AT_location at the very first PC is already modified)
authorJakub Jelinek <jakub@redhat.com>
Wed, 15 Jun 2011 09:56:33 +0000 (11:56 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 15 Jun 2011 09:56:33 +0000 (11:56 +0200)
PR debug/49382
* dwarf2out.c (dw_loc_list_node): Add force field.
(add_var_loc_to_decl): For PARM_DECL, attempt to keep
the incoming location in the list, even if it is modified
before first real insn.
(output_loc_list): Emit empty ranges with force flag set.
(dw_loc_list): If first range of a PARM_DECL is empty,
set force flag.

From-SVN: r175076

gcc/ChangeLog
gcc/dwarf2out.c

index 8c055b3d1bf0b5c7d25b1edc7f0fe4bbac257c3c..a4c589fa31092cf1f84e4ec335bb3e075a13f327 100644 (file)
@@ -1,3 +1,14 @@
+2011-06-15  Jakub Jelinek  <jakub@redhat.com>
+
+       PR debug/49382
+       * dwarf2out.c (dw_loc_list_node): Add force field.
+       (add_var_loc_to_decl): For PARM_DECL, attempt to keep
+       the incoming location in the list, even if it is modified
+       before first real insn.
+       (output_loc_list): Emit empty ranges with force flag set.
+       (dw_loc_list): If first range of a PARM_DECL is empty,
+       set force flag.
+
 2011-06-15  Alexander Monakov  <amonakov@ispras.ru>
 
        PR target/49349
index 9ea8a299b1b3ee3744a01c83eb7e43c22d99d8d2..71ba002cb85370f74099a53943b98e3a1975f848 100644 (file)
@@ -4467,6 +4467,9 @@ typedef struct GTY(()) dw_loc_list_struct {
   /* True if this list has been replaced by dw_loc_next.  */
   bool replaced;
   bool emitted;
+  /* True if the range should be emitted even if begin and end
+     are the same.  */
+  bool force;
 } dw_loc_list_node;
 
 static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT);
@@ -8621,7 +8624,30 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
   else
     temp = (var_loc_list *) *slot;
 
-  if (temp->last)
+  /* For PARM_DECLs try to keep around the original incoming value,
+     even if that means we'll emit a zero-range .debug_loc entry.  */
+  if (temp->last
+      && temp->first == temp->last
+      && TREE_CODE (decl) == PARM_DECL
+      && GET_CODE (temp->first->loc) == NOTE
+      && NOTE_VAR_LOCATION_DECL (temp->first->loc) == decl
+      && DECL_INCOMING_RTL (decl)
+      && NOTE_VAR_LOCATION_LOC (temp->first->loc)
+      && GET_CODE (NOTE_VAR_LOCATION_LOC (temp->first->loc))
+        == GET_CODE (DECL_INCOMING_RTL (decl))
+      && prev_real_insn (temp->first->loc) == NULL_RTX
+      && (bitsize != -1
+         || !rtx_equal_p (NOTE_VAR_LOCATION_LOC (temp->first->loc),
+                          NOTE_VAR_LOCATION_LOC (loc_note))
+         || (NOTE_VAR_LOCATION_STATUS (temp->first->loc)
+             != NOTE_VAR_LOCATION_STATUS (loc_note))))
+    {
+      loc = ggc_alloc_cleared_var_loc_node ();
+      temp->first->next = loc;
+      temp->last = loc;
+      loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
+    }
+  else if (temp->last)
     {
       struct var_loc_node *last = temp->last, *unused = NULL;
       rtx *piece_loc = NULL, last_loc_note;
@@ -8667,7 +8693,9 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
            }
          else
            {
-             gcc_assert (temp->first == temp->last);
+             gcc_assert (temp->first == temp->last
+                         || (temp->first->next == temp->last
+                             && TREE_CODE (decl) == PARM_DECL));
              memset (temp->last, '\0', sizeof (*temp->last));
              temp->last->loc = construct_piece_list (loc_note, bitpos, bitsize);
              return temp->last;
@@ -11394,7 +11422,7 @@ output_loc_list (dw_loc_list_ref list_head)
     {
       unsigned long size;
       /* Don't output an entry that starts and ends at the same address.  */
-      if (strcmp (curr->begin, curr->end) == 0)
+      if (strcmp (curr->begin, curr->end) == 0 && !curr->force)
        continue;
       if (!have_multiple_function_sections)
        {
@@ -16090,6 +16118,11 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
              }
 
            *listp = new_loc_list (descr, node->label, endname, secname);
+           if (TREE_CODE (decl) == PARM_DECL
+               && node == loc_list->first
+               && GET_CODE (node->loc) == NOTE
+               && strcmp (node->label, endname) == 0)
+             (*listp)->force = true;
            listp = &(*listp)->dw_loc_next;
 
            if (range_across_switch)