From 0f2f44c007550bdf388940b6a09da1eeaa9caa3f Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 21 Apr 2010 09:05:00 +0200 Subject: [PATCH] dwarf2out.c (add_var_loc_to_decl): Add LABEL argument. * 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. From-SVN: r158590 --- gcc/ChangeLog | 8 +++++ gcc/dwarf2out.c | 90 +++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 80 insertions(+), 18 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6f875d4b32e..7376b8bbc19 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2010-04-21 Jakub Jelinek + * 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. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 21a3f75f855..8d569384f30 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -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;