OSDN Git Service

* dwarf2out.c (add_var_loc_to_decl): Add LABEL argument. Drop
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 21 Apr 2010 07:05:00 +0000 (07:05 +0000)
committerMasaki Muranaka <monaka@monami-software.com>
Sun, 23 May 2010 01:08:02 +0000 (10:08 +0900)
last chain entry if it starts with the still current label.
(add_location_or_const_value_attribute): Check that
loc_list->first->next is NULL instead of comparing ->first with
->last.
(dwarf2out_var_location): Pass last_label resp. last_postcall_label
to add_var_loc_to_decl.

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

gcc/ChangeLog
gcc/dwarf2out.c

index 6f875d4..7376b8b 100644 (file)
@@ -1,5 +1,13 @@
 2010-04-21  Jakub Jelinek  <jakub@redhat.com>
 
+       * dwarf2out.c (add_var_loc_to_decl): Add LABEL argument.  Drop
+       last chain entry if it starts with the still current label.
+       (add_location_or_const_value_attribute): Check that
+       loc_list->first->next is NULL instead of comparing ->first with
+       ->last.
+       (dwarf2out_var_location): Pass last_label resp. last_postcall_label
+       to add_var_loc_to_decl.
+
        * dwarf2out.c (output_call_frame_info): For dw_cie_version
        >= 4 add also address size and segment size fields into CIE
        header.
index 21a3f75..8d56938 100644 (file)
@@ -5748,8 +5748,12 @@ struct GTY ((chain_next ("%h.next"))) var_loc_node {
 struct GTY (()) var_loc_list_def {
   struct var_loc_node * GTY (()) first;
 
-  /* Do not mark the last element of the chained list because
-     it is marked through the chain.  */
+  /* Pointer to the last but one or last element of the
+     chained list.  If the list is empty, both first and
+     last are NULL, if the list contains just one node
+     or the last node certainly is not redundant, it points
+     to the last node, otherwise points to the last but one.
+     Do not mark it for GC because it is marked through the chain.  */
   struct var_loc_node * GTY ((skip ("%h"))) last;
 
   /* DECL_UID of the variable decl.  */
@@ -5991,7 +5995,7 @@ static hashval_t decl_loc_table_hash (const void *);
 static int decl_loc_table_eq (const void *, const void *);
 static var_loc_list *lookup_decl_loc (const_tree);
 static void equate_decl_number_to_die (tree, dw_die_ref);
-static struct var_loc_node *add_var_loc_to_decl (tree, rtx);
+static struct var_loc_node *add_var_loc_to_decl (tree, rtx, const char *);
 static void print_spaces (FILE *);
 static void print_die (dw_die_ref, FILE *);
 static void print_dwarf_line_table (FILE *);
@@ -7755,7 +7759,7 @@ equate_decl_number_to_die (tree decl, dw_die_ref decl_die)
 /* Add a variable location node to the linked list for DECL.  */
 
 static struct var_loc_node *
-add_var_loc_to_decl (tree decl, rtx loc_note)
+add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
 {
   unsigned int decl_id = DECL_UID (decl);
   var_loc_list *temp;
@@ -7774,23 +7778,62 @@ add_var_loc_to_decl (tree decl, rtx loc_note)
 
   if (temp->last)
     {
+      struct var_loc_node *last = temp->last, *unused = NULL;
+      if (last->next)
+       {
+         last = last->next;
+         gcc_assert (last->next == NULL);
+       }
+      /* TEMP->LAST here is either pointer to the last but one or
+        last element in the chained list, LAST is pointer to the
+        last element.  */
+      /* If the last note doesn't cover any instructions, remove it.  */
+      if (label && strcmp (last->label, label) == 0)
+       {
+         if (temp->last != last)
+           {
+             temp->last->next = NULL;
+             unused = last;
+             last = temp->last;
+             gcc_assert (strcmp (last->label, label) != 0);
+           }
+         else
+           {
+             gcc_assert (temp->first == temp->last);
+             memset (temp->last, '\0', sizeof (*temp->last));
+             return temp->last;
+           }
+       }
       /* If the current location is the same as the end of the list,
         and either both or neither of the locations is uninitialized,
         we have nothing to do.  */
-      if ((!rtx_equal_p (NOTE_VAR_LOCATION_LOC (temp->last->var_loc_note),
+      if ((!rtx_equal_p (NOTE_VAR_LOCATION_LOC (last->var_loc_note),
                         NOTE_VAR_LOCATION_LOC (loc_note)))
-         || ((NOTE_VAR_LOCATION_STATUS (temp->last->var_loc_note)
+         || ((NOTE_VAR_LOCATION_STATUS (last->var_loc_note)
               != NOTE_VAR_LOCATION_STATUS (loc_note))
-             && ((NOTE_VAR_LOCATION_STATUS (temp->last->var_loc_note)
+             && ((NOTE_VAR_LOCATION_STATUS (last->var_loc_note)
                   == VAR_INIT_STATUS_UNINITIALIZED)
                  || (NOTE_VAR_LOCATION_STATUS (loc_note)
                      == VAR_INIT_STATUS_UNINITIALIZED))))
        {
-         /* Add LOC to the end of list and update LAST.  */
-         loc = GGC_CNEW (struct var_loc_node);
-         temp->last->next = loc;
-         temp->last = loc;
+         /* Add LOC to the end of list and update LAST.  If the last
+            element of the list has been removed above, reuse its
+            memory for the new node, otherwise allocate a new one.  */
+         if (unused)
+           {
+             loc = unused;
+             memset (loc, '\0', sizeof (*loc));
+           }
+         else
+           loc = GGC_CNEW (struct var_loc_node);
+         last->next = loc;
+         /* Ensure TEMP->LAST will point either to the new last but one
+            element of the chain, or to the last element in it.  */
+         if (last != temp->last)
+           temp->last = last;
        }
+      else if (unused)
+       ggc_free (unused);
     }
   else
     {
@@ -15925,7 +15968,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
   loc_list = lookup_decl_loc (decl);
   if (loc_list
       && loc_list->first
-      && loc_list->first == loc_list->last
+      && loc_list->first->next == NULL
       && NOTE_VAR_LOCATION (loc_list->first->var_loc_note)
       && NOTE_VAR_LOCATION_LOC (loc_list->first->var_loc_note))
     {
@@ -20384,22 +20427,33 @@ dwarf2out_var_location (rtx loc_note)
   if (next_real == NULL_RTX)
     return;
 
+  /* If there were any real insns between note we processed last time
+     and this note (or if it is the first note), clear
+     last_{,postcall_}label so that they are not reused this time.  */
+  if (last_var_location_insn == NULL_RTX
+      || last_var_location_insn != next_real
+      || last_in_cold_section_p != in_cold_section_p)
+    {
+      last_label = NULL;
+      last_postcall_label = NULL;
+    }
+
   decl = NOTE_VAR_LOCATION_DECL (loc_note);
-  newloc = add_var_loc_to_decl (decl, loc_note);
+  newloc = add_var_loc_to_decl (decl, loc_note,
+                               NOTE_DURING_CALL_P (loc_note)
+                               ? last_postcall_label : last_label);
   if (newloc == NULL)
     return;
 
   /* If there were no real insns between note we processed last time
-     and this note, use the label we emitted last time.  */
-  if (last_var_location_insn == NULL_RTX
-      || last_var_location_insn != next_real
-      || last_in_cold_section_p != in_cold_section_p)
+     and this note, use the label we emitted last time.  Otherwise
+     create a new label and emit it.  */
+  if (last_label == NULL)
     {
       ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", loclabel_num);
       ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LVL", loclabel_num);
       loclabel_num++;
       last_label = ggc_strdup (loclabel);
-      last_postcall_label = NULL;
     }
   newloc->var_loc_note = loc_note;
   newloc->next = NULL;