diff options
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r-- | gcc/dwarf2out.c | 836 |
1 files changed, 413 insertions, 423 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 5193da79dff..6c5951cd6c9 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -1,3 +1,4 @@ +/* APPLE LOCAL file mainline 4.2 2006-04-26 4498201 */ /* Output Dwarf2 format symbol table information from GCC. APPLE LOCAL begin mainline 2006-03-16 dwarf 4383509 Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -3216,12 +3217,24 @@ size_of_loc_descr (dw_loc_descr_ref loc) static unsigned long size_of_locs (dw_loc_descr_ref loc) { + dw_loc_descr_ref l; unsigned long size; - for (size = 0; loc != NULL; loc = loc->dw_loc_next) + /* If there are no skip or bra opcodes, don't fill in the dw_loc_addr + field, to avoid writing to a PCH file. */ + for (size = 0, l = loc; l != NULL; l = l->dw_loc_next) { - loc->dw_loc_addr = size; - size += size_of_loc_descr (loc); + if (l->dw_loc_opc == DW_OP_skip || l->dw_loc_opc == DW_OP_bra) + break; + size += size_of_loc_descr (l); + } + if (! l) + return size; + + for (size = 0, l = loc; l != NULL; l = l->dw_loc_next) + { + l->dw_loc_addr = size; + size += size_of_loc_descr (l); } return size; @@ -3649,18 +3662,22 @@ dw_separate_line_info_entry; typedef struct dw_attr_struct GTY(()) { enum dwarf_attribute dw_attr; - dw_attr_ref dw_attr_next; + /* remove field dw_attr_next */ dw_val_node dw_attr_val; } dw_attr_node; -/* The Debugging Information Entry (DIE) structure */ +DEF_VEC_GC_O(dw_attr_node); + +/* The Debugging Information Entry (DIE) structure. DIEs form a tree. + The children of each node form a circular list linked by + die_sib. die_child points to the node *before* the "first" child node. */ typedef struct die_struct GTY(()) { enum dwarf_tag die_tag; char *die_symbol; - dw_attr_ref die_attr; + VEC(dw_attr_node) * die_attr; dw_die_ref die_parent; dw_die_ref die_child; dw_die_ref die_sib; @@ -3672,6 +3689,15 @@ typedef struct die_struct GTY(()) } die_node; +/* Evaluate 'expr' while 'c' is set to each child of DIE in order. */ +#define FOR_EACH_CHILD(die, c, expr) do { \ + c = die->die_child; \ + if (c) do { \ + c = c->die_sib; \ + expr; \ + } while (c != die->die_child); \ +} while (0) + /* The pubname structure */ typedef struct pubname_struct GTY(()) @@ -3994,8 +4020,7 @@ static bool is_fortran (void); static bool is_ada (void); static void remove_AT (dw_die_ref, enum dwarf_attribute); static void remove_child_TAG (dw_die_ref, enum dwarf_tag); -static inline void free_die (dw_die_ref); -static void remove_children (dw_die_ref); +/* free_die, remove_children removed */ static void add_child_die (dw_die_ref, dw_die_ref); static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree); static dw_die_ref lookup_type_die (tree); @@ -4011,8 +4036,6 @@ static void add_var_loc_to_decl (tree, struct var_loc_node *); static void print_spaces (FILE *); static void print_die (dw_die_ref, FILE *); static void print_dwarf_line_table (FILE *); -static void reverse_die_lists (dw_die_ref); -static void reverse_all_dies (dw_die_ref); static dw_die_ref push_new_compile_unit (dw_die_ref, dw_die_ref); static dw_die_ref pop_compile_unit (dw_die_ref); static void loc_checksum (dw_loc_descr_ref, struct md5_ctx *); @@ -4826,17 +4849,18 @@ decl_class_context (tree decl) return context; } -/* Add an attribute/value pair to a DIE. We build the lists up in reverse - addition order, and correct that in reverse_all_dies. */ +/* Add an attribute/value pair to a DIE. */ static inline void add_dwarf_attr (dw_die_ref die, dw_attr_ref attr) { - if (die != NULL && attr != NULL) - { - attr->dw_attr_next = die->die_attr; - die->die_attr = attr; - } + /* Maybe this should be an assert? */ + if (die == NULL) + return; + + if (die->die_attr == NULL) + die->die_attr = VEC_alloc (dw_attr_node, 1); + VEC_safe_push (dw_attr_node, die->die_attr, attr); } static inline enum dw_val_class @@ -4850,13 +4874,12 @@ AT_class (dw_attr_ref a) static inline void add_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int flag) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_flag; - attr->dw_attr_val.v.val_flag = flag; - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_flag; + attr.dw_attr_val.v.val_flag = flag; + add_dwarf_attr (die, &attr); } static inline unsigned @@ -4871,13 +4894,12 @@ AT_flag (dw_attr_ref a) static inline void add_AT_int (dw_die_ref die, enum dwarf_attribute attr_kind, HOST_WIDE_INT int_val) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_const; - attr->dw_attr_val.v.val_int = int_val; - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_const; + attr.dw_attr_val.v.val_int = int_val; + add_dwarf_attr (die, &attr); } static inline HOST_WIDE_INT @@ -4893,13 +4915,12 @@ static inline void add_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned HOST_WIDE_INT unsigned_val) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_unsigned_const; - attr->dw_attr_val.v.val_unsigned = unsigned_val; - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_unsigned_const; + attr.dw_attr_val.v.val_unsigned = unsigned_val; + add_dwarf_attr (die, &attr); } static inline unsigned HOST_WIDE_INT @@ -4915,14 +4936,13 @@ static inline void add_AT_long_long (dw_die_ref die, enum dwarf_attribute attr_kind, long unsigned int val_hi, long unsigned int val_low) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_long_long; - attr->dw_attr_val.v.val_long_long.hi = val_hi; - attr->dw_attr_val.v.val_long_long.low = val_low; - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_long_long; + attr.dw_attr_val.v.val_long_long.hi = val_hi; + attr.dw_attr_val.v.val_long_long.low = val_low; + add_dwarf_attr (die, &attr); } /* Add a floating point attribute value to a DIE and return it. */ @@ -4931,15 +4951,14 @@ static inline void add_AT_vec (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int length, unsigned int elt_size, unsigned char *array) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_vec; - attr->dw_attr_val.v.val_vec.length = length; - attr->dw_attr_val.v.val_vec.elt_size = elt_size; - attr->dw_attr_val.v.val_vec.array = array; - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_vec; + attr.dw_attr_val.v.val_vec.length = length; + attr.dw_attr_val.v.val_vec.elt_size = elt_size; + attr.dw_attr_val.v.val_vec.array = array; + add_dwarf_attr (die, &attr); } /* Hash and equality functions for debug_str_hash. */ @@ -4962,7 +4981,7 @@ debug_str_eq (const void *x1, const void *x2) static inline void add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; struct indirect_string_node *node; void **slot; @@ -4978,11 +4997,10 @@ add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str) node->str = ggc_strdup (str); node->refcount++; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_str; - attr->dw_attr_val.v.val_str = node; - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_str; + attr.dw_attr_val.v.val_str = node; + add_dwarf_attr (die, &attr); } static inline const char * @@ -5034,14 +5052,13 @@ AT_string_form (dw_attr_ref a) static inline void add_AT_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind, dw_die_ref targ_die) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_die_ref; - attr->dw_attr_val.v.val_die_ref.die = targ_die; - attr->dw_attr_val.v.val_die_ref.external = 0; - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_die_ref; + attr.dw_attr_val.v.val_die_ref.die = targ_die; + attr.dw_attr_val.v.val_die_ref.external = 0; + add_dwarf_attr (die, &attr); } /* Add an AT_specification attribute to a DIE, and also make the back @@ -5083,13 +5100,12 @@ set_AT_ref_external (dw_attr_ref a, int i) static inline void add_AT_fde_ref (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int targ_fde) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_fde_ref; - attr->dw_attr_val.v.val_fde_index = targ_fde; - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_fde_ref; + attr.dw_attr_val.v.val_fde_index = targ_fde; + add_dwarf_attr (die, &attr); } /* Add a location description attribute value to a DIE. */ @@ -5097,13 +5113,12 @@ add_AT_fde_ref (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int tar static inline void add_AT_loc (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_descr_ref loc) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_loc; - attr->dw_attr_val.v.val_loc = loc; - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_loc; + attr.dw_attr_val.v.val_loc = loc; + add_dwarf_attr (die, &attr); } static inline dw_loc_descr_ref @@ -5116,13 +5131,12 @@ AT_loc (dw_attr_ref a) static inline void add_AT_loc_list (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_list_ref loc_list) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_loc_list; - attr->dw_attr_val.v.val_loc_list = loc_list; - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_loc_list; + attr.dw_attr_val.v.val_loc_list = loc_list; + add_dwarf_attr (die, &attr); /* APPLE LOCAL mainline 4.2 2006-01-02 4386366 */ have_location_lists = true; } @@ -5139,13 +5153,12 @@ AT_loc_list (dw_attr_ref a) static inline void add_AT_addr (dw_die_ref die, enum dwarf_attribute attr_kind, rtx addr) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_addr; - attr->dw_attr_val.v.val_addr = addr; - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_addr; + attr.dw_attr_val.v.val_addr = addr; + add_dwarf_attr (die, &attr); } static inline rtx @@ -5160,13 +5173,12 @@ AT_addr (dw_attr_ref a) static inline void add_AT_lbl_id (dw_die_ref die, enum dwarf_attribute attr_kind, const char *lbl_id) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_lbl_id; - attr->dw_attr_val.v.val_lbl_id = xstrdup (lbl_id); - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_lbl_id; + attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_id); + add_dwarf_attr (die, &attr); } /* APPLE LOCAL begin mainline 2006-03-16 dwarf 4383509 */ @@ -5177,13 +5189,12 @@ static inline void add_AT_lineptr (dw_die_ref die, enum dwarf_attribute attr_kind, const char *label) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_lineptr; - attr->dw_attr_val.v.val_lbl_id = xstrdup (label); - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_lineptr; + attr.dw_attr_val.v.val_lbl_id = xstrdup (label); + add_dwarf_attr (die, &attr); } /* Add a section offset attribute value to a DIE, an offset into the @@ -5193,13 +5204,12 @@ static inline void add_AT_macptr (dw_die_ref die, enum dwarf_attribute attr_kind, const char *label) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_macptr; - attr->dw_attr_val.v.val_lbl_id = xstrdup (label); - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_macptr; + attr.dw_attr_val.v.val_lbl_id = xstrdup (label); + add_dwarf_attr (die, &attr); } /* APPLE LOCAL end mainline 2006-03-16 dwarf 4383509 */ @@ -5209,13 +5219,12 @@ static inline void add_AT_offset (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned HOST_WIDE_INT offset) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_offset; - attr->dw_attr_val.v.val_offset = offset; - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_offset; + attr.dw_attr_val.v.val_offset = offset; + add_dwarf_attr (die, &attr); } /* Add an range_list attribute value to a DIE. */ @@ -5224,13 +5233,12 @@ static void add_AT_range_list (dw_die_ref die, enum dwarf_attribute attr_kind, long unsigned int offset) { - dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); + dw_attr_node attr; - attr->dw_attr_next = NULL; - attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_range_list; - attr->dw_attr_val.v.val_offset = offset; - add_dwarf_attr (die, attr); + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_range_list; + attr.dw_attr_val.v.val_offset = offset; + add_dwarf_attr (die, &attr); } static inline const char * @@ -5250,20 +5258,21 @@ static dw_attr_ref get_AT (dw_die_ref die, enum dwarf_attribute attr_kind) { dw_attr_ref a; + unsigned ix; dw_die_ref spec = NULL; - if (die != NULL) - { - for (a = die->die_attr; a != NULL; a = a->dw_attr_next) - if (a->dw_attr == attr_kind) - return a; - else if (a->dw_attr == DW_AT_specification - || a->dw_attr == DW_AT_abstract_origin) - spec = AT_ref (a); + if (! die) + return NULL; - if (spec) - return get_AT (spec, attr_kind); - } + for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++) + if (a->dw_attr == attr_kind) + return a; + else if (a->dw_attr == DW_AT_specification + || a->dw_attr == DW_AT_abstract_origin) + spec = AT_ref (a); + + if (spec) + return get_AT (spec, attr_kind); return NULL; } @@ -5391,127 +5400,103 @@ is_ada (void) return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83; } -/* Free up the memory used by A. */ - -static inline void free_AT (dw_attr_ref); -static inline void -free_AT (dw_attr_ref a) -{ - if (AT_class (a) == dw_val_class_str) - if (a->dw_attr_val.v.val_str->refcount) - a->dw_attr_val.v.val_str->refcount--; -} +/* Remove free_AT */ /* Remove the specified attribute if present. */ static void remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind) { - dw_attr_ref *p; - dw_attr_ref removed = NULL; + dw_attr_ref a; + unsigned ix; - if (die != NULL) - { - for (p = &(die->die_attr); *p; p = &((*p)->dw_attr_next)) - if ((*p)->dw_attr == attr_kind) - { - removed = *p; - *p = (*p)->dw_attr_next; - break; - } + if (! die) + return; - if (removed != 0) - free_AT (removed); - } -} + for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++) + if (a->dw_attr == attr_kind) + { + if (AT_class (a) == dw_val_class_str) + if (a->dw_attr_val.v.val_str->refcount) + a->dw_attr_val.v.val_str->refcount--; -/* Remove child die whose die_tag is specified tag. */ + /* VEC_ordered_remove should help reduce the number of abbrevs + that are needed. */ + VEC_ordered_remove (dw_attr_node, die->die_attr, ix); + return; + } +} +/* Remove CHILD from its parent. PREV must have the property that + PREV->DIE_SIB == CHILD. Does not alter CHILD. */ static void -remove_child_TAG (dw_die_ref die, enum dwarf_tag tag) +remove_child_with_prev (dw_die_ref child, dw_die_ref prev) { - dw_die_ref current, prev, next; - current = die->die_child; - prev = NULL; - while (current != NULL) + gcc_assert (child->die_parent == prev->die_parent); + gcc_assert (prev->die_sib == child); + if (prev == child) { - if (current->die_tag == tag) - { - next = current->die_sib; - if (prev == NULL) - die->die_child = next; - else - prev->die_sib = next; - free_die (current); - current = next; - } - else - { - prev = current; - current = current->die_sib; - } + gcc_assert (child->die_parent->die_child == child); + prev = NULL; } + else + prev->die_sib = child->die_sib; + if (child->die_parent->die_child == child) + child->die_parent->die_child = prev; } -/* Free up the memory used by DIE. */ - -static inline void -free_die (dw_die_ref die) -{ - remove_children (die); -} - -/* Discard the children of this DIE. */ +/* Remove child DIE whose die_tag is TAG. Do nothing if no child + matches TAG. */ static void -remove_children (dw_die_ref die) +remove_child_TAG (dw_die_ref die, enum dwarf_tag tag) { - dw_die_ref child_die = die->die_child; - - die->die_child = NULL; - - while (child_die != NULL) - { - dw_die_ref tmp_die = child_die; - dw_attr_ref a; - - child_die = child_die->die_sib; - - for (a = tmp_die->die_attr; a != NULL;) - { - dw_attr_ref tmp_a = a; - - a = a->dw_attr_next; - free_AT (tmp_a); - } - - free_die (tmp_die); - } + dw_die_ref c; + + c = die->die_child; + if (c) do { + dw_die_ref prev = c; + c = c->die_sib; + while (c->die_tag == tag) + { + remove_child_with_prev (c, prev); + /* Might have removed every child. */ + if (c == c->die_sib) + return; + c = c->die_sib; + } + } while (c != die->die_child); } -/* Add a child DIE below its parent. We build the lists up in reverse - addition order, and correct that in reverse_all_dies. */ +/* Add a CHILD_DIE as the last child of DIE. */ -static inline void +static void add_child_die (dw_die_ref die, dw_die_ref child_die) { - if (die != NULL && child_die != NULL) - { - gcc_assert (die != child_die); + /* FIXME this should probably be an assert. */ + if (! die || ! child_die) + return; + gcc_assert (die != child_die); - child_die->die_parent = die; - child_die->die_sib = die->die_child; - die->die_child = child_die; + child_die->die_parent = die; + if (die->die_child) + { + child_die->die_sib = die->die_child->die_sib; + die->die_child->die_sib = child_die; } + else + child_die->die_sib = child_die; + die->die_child = child_die; } /* Move CHILD, which must be a child of PARENT or the DIE for which PARENT - is the specification, to the front of PARENT's list of children. */ + is the specification, to the end of PARENT's list of children. + This is done by removing and re-adding it. */ static void splice_child_die (dw_die_ref parent, dw_die_ref child) { - dw_die_ref *p; + dw_die_ref p; /* We want the declaration DIE from inside the class, not the specification DIE at toplevel. */ @@ -5526,17 +5511,15 @@ splice_child_die (dw_die_ref parent, dw_die_ref child) gcc_assert (child->die_parent == parent || (child->die_parent == get_AT_ref (parent, DW_AT_specification))); - - for (p = &(child->die_parent->die_child); *p; p = &((*p)->die_sib)) - if (*p == child) + + for (p = child->die_parent->die_child; ; p = p->die_sib) + if (p->die_sib == child) { - *p = child->die_sib; + remove_child_with_prev (child, p); break; } - child->die_parent = parent; - child->die_sib = parent->die_child; - parent->die_child = child; + add_child_die (parent, child); } /* Return a pointer to a newly created DIE node. */ @@ -5702,6 +5685,7 @@ print_die (dw_die_ref die, FILE *outfile) { dw_attr_ref a; dw_die_ref c; + unsigned ix; print_spaces (outfile); fprintf (outfile, "DIE %4lu: %s\n", @@ -5710,7 +5694,7 @@ print_die (dw_die_ref die, FILE *outfile) fprintf (outfile, " abbrev id: %lu", die->die_abbrev); fprintf (outfile, " offset: %lu\n", die->die_offset); - for (a = die->die_attr; a != NULL; a = a->dw_attr_next) + for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++) { print_spaces (outfile); fprintf (outfile, " %s: ", dwarf_attr_name (a->dw_attr)); @@ -5784,9 +5768,7 @@ print_die (dw_die_ref die, FILE *outfile) if (die->die_child != NULL) { print_indent += 4; - for (c = die->die_child; c != NULL; c = c->die_sib) - print_die (c, outfile); - + FOR_EACH_CHILD (die, c, print_die (c, outfile)); print_indent -= 4; } if (print_indent == 0) @@ -5836,52 +5818,6 @@ debug_dwarf (void) print_dwarf_line_table (stderr); } -/* We build up the lists of children and attributes by pushing new ones - onto the beginning of the list. Reverse the lists for DIE so that - they are in order of addition. */ - -static void -reverse_die_lists (dw_die_ref die) -{ - dw_die_ref c, cp, cn; - dw_attr_ref a, ap, an; - - for (a = die->die_attr, ap = 0; a; a = an) - { - an = a->dw_attr_next; - a->dw_attr_next = ap; - ap = a; - } - - die->die_attr = ap; - - for (c = die->die_child, cp = 0; c; c = cn) - { - cn = c->die_sib; - c->die_sib = cp; - cp = c; - } - - die->die_child = cp; -} - -/* reverse_die_lists only reverses the single die you pass it. Since we used to - reverse all dies in add_sibling_attributes, which runs through all the dies, - it would reverse all the dies. Now, however, since we don't call - reverse_die_lists in add_sibling_attributes, we need a routine to - recursively reverse all the dies. This is that routine. */ - -static void -reverse_all_dies (dw_die_ref die) -{ - dw_die_ref c; - - reverse_die_lists (die); - - for (c = die->die_child; c; c = c->die_sib) - reverse_all_dies (c); -} - /* Start a new compilation unit DIE for an include file. OLD_UNIT is the CU for the enclosing include file, if any. BINCL_DIE is the DW_TAG_GNU_BINCL DIE that marks the start of the DIEs for this include file. */ @@ -5997,6 +5933,7 @@ die_checksum (dw_die_ref die, struct md5_ctx *ctx, int *mark) { dw_die_ref c; dw_attr_ref a; + unsigned ix; /* To avoid infinite recursion. */ if (die->die_mark) @@ -6008,11 +5945,10 @@ die_checksum (dw_die_ref die, struct md5_ctx *ctx, int *mark) CHECKSUM (die->die_tag); - for (a = die->die_attr; a; a = a->dw_attr_next) + for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++) attr_checksum (a, ctx, mark); - for (c = die->die_child; c; c = c->die_sib) - die_checksum (c, ctx, mark); + FOR_EACH_CHILD (die, c, die_checksum (c, ctx, mark)); } #undef CHECKSUM @@ -6118,7 +6054,8 @@ static int same_die_p (dw_die_ref die1, dw_die_ref die2, int *mark) { dw_die_ref c1, c2; - dw_attr_ref a1, a2; + dw_attr_ref a1; + unsigned ix; /* To avoid infinite recursion. */ if (die1->die_mark) @@ -6128,21 +6065,36 @@ same_die_p (dw_die_ref die1, dw_die_ref die2, int *mark) if (die1->die_tag != die2->die_tag) return 0; - for (a1 = die1->die_attr, a2 = die2->die_attr; - a1 && a2; - a1 = a1->dw_attr_next, a2 = a2->dw_attr_next) - if (!same_attr_p (a1, a2, mark)) - return 0; - if (a1 || a2) + if (VEC_length (dw_attr_node, die1->die_attr) + != VEC_length (dw_attr_node, die2->die_attr)) return 0; - - for (c1 = die1->die_child, c2 = die2->die_child; - c1 && c2; - c1 = c1->die_sib, c2 = c2->die_sib) - if (!same_die_p (c1, c2, mark)) + + for (ix = 0; VEC_iterate (dw_attr_node, die1->die_attr, ix, a1); ix++) + if (!same_attr_p (a1, VEC_index (dw_attr_node, die2->die_attr, ix), mark)) return 0; - if (c1 || c2) - return 0; + + c1 = die1->die_child; + c2 = die2->die_child; + if (! c1) + { + if (c2) + return 0; + } + else + for (;;) + { + if (!same_die_p (c1, c2, mark)) + return 0; + c1 = c1->die_sib; + c2 = c2->die_sib; + if (c1 == die1->die_child) + { + if (c2 == die2->die_child) + break; + else + return 0; + } + } return 1; } @@ -6306,8 +6258,7 @@ assign_symbol_names (dw_die_ref die) die->die_symbol = gen_internal_sym ("LDIE"); } - for (c = die->die_child; c != NULL; c = c->die_sib) - assign_symbol_names (c); + FOR_EACH_CHILD (die, c, assign_symbol_names (c)); } struct cu_hash_table_entry @@ -6405,41 +6356,34 @@ record_comdat_symbol_number (dw_die_ref cu, htab_t htable, unsigned int sym_num) static void break_out_includes (dw_die_ref die) { - dw_die_ref *ptr; + dw_die_ref c; dw_die_ref unit = NULL; limbo_die_node *node, **pnode; htab_t cu_hash_table; - for (ptr = &(die->die_child); *ptr;) - { - dw_die_ref c = *ptr; - - if (c->die_tag == DW_TAG_GNU_BINCL || c->die_tag == DW_TAG_GNU_EINCL - || (unit && is_comdat_die (c))) - { - /* This DIE is for a secondary CU; remove it from the main one. */ - *ptr = c->die_sib; - - if (c->die_tag == DW_TAG_GNU_BINCL) - { - unit = push_new_compile_unit (unit, c); - free_die (c); - } - else if (c->die_tag == DW_TAG_GNU_EINCL) - { - unit = pop_compile_unit (unit); - free_die (c); - } - else - add_child_die (unit, c); - } - else - { - /* Leave this DIE in the main CU. */ - ptr = &(c->die_sib); - continue; - } - } + c = die->die_child; + if (c) do { + dw_die_ref prev = c; + c = c->die_sib; + while (c->die_tag == DW_TAG_GNU_BINCL || c->die_tag == DW_TAG_GNU_EINCL + || (unit && is_comdat_die (c))) + { + dw_die_ref next = c->die_sib; + + /* This DIE is for a secondary CU; remove it from the main one. */ + remove_child_with_prev (c, prev); + + if (c->die_tag == DW_TAG_GNU_BINCL) + unit = push_new_compile_unit (unit, c); + else if (c->die_tag == DW_TAG_GNU_EINCL) + unit = pop_compile_unit (unit); + else + add_child_die (unit, c); + c = next; + if (c == die->die_child) + break; + } + } while (c != die->die_child); #if 0 /* We can only use this in debugging, since the frontend doesn't check @@ -6480,13 +6424,13 @@ add_sibling_attributes (dw_die_ref die) { dw_die_ref c; - if (die->die_tag != DW_TAG_compile_unit - && die->die_sib && die->die_child != NULL) - /* Add the sibling link to the front of the attribute list. */ + if (! die->die_child) + return; + + if (die->die_parent && die != die->die_parent->die_child) add_AT_die_ref (die, DW_AT_sibling, die->die_sib); - for (c = die->die_child; c != NULL; c = c->die_sib) - add_sibling_attributes (c); + FOR_EACH_CHILD (die, c, add_sibling_attributes (c)); } /* Output all location lists for the DIE and its children. */ @@ -6495,15 +6439,14 @@ static void output_location_lists (dw_die_ref die) { dw_die_ref c; - dw_attr_ref d_attr; - - for (d_attr = die->die_attr; d_attr; d_attr = d_attr->dw_attr_next) - if (AT_class (d_attr) == dw_val_class_loc_list) - output_loc_list (AT_loc_list (d_attr)); + dw_attr_ref a; + unsigned ix; - for (c = die->die_child; c != NULL; c = c->die_sib) - output_location_lists (c); + for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++) + if (AT_class (a) == dw_val_class_loc_list) + output_loc_list (AT_loc_list (a)); + FOR_EACH_CHILD (die, c, output_location_lists (c)); } /* The format of each DIE (and its attribute value pairs) is encoded in an @@ -6517,44 +6460,48 @@ build_abbrev_table (dw_die_ref die) unsigned long abbrev_id; unsigned int n_alloc; dw_die_ref c; - dw_attr_ref d_attr, a_attr; + dw_attr_ref a; + unsigned ix; /* Scan the DIE references, and mark as external any that refer to DIEs from other CUs (i.e. those which are not marked). */ - for (d_attr = die->die_attr; d_attr; d_attr = d_attr->dw_attr_next) - if (AT_class (d_attr) == dw_val_class_die_ref - && AT_ref (d_attr)->die_mark == 0) + for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++) + if (AT_class (a) == dw_val_class_die_ref + && AT_ref (a)->die_mark == 0) { - gcc_assert (AT_ref (d_attr)->die_symbol); + gcc_assert (AT_ref (a)->die_symbol); - set_AT_ref_external (d_attr, 1); + set_AT_ref_external (a, 1); } for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id) { dw_die_ref abbrev = abbrev_die_table[abbrev_id]; - - if (abbrev->die_tag == die->die_tag) + dw_attr_ref die_a, abbrev_a; + unsigned ix; + bool ok = true; + + if (abbrev->die_tag != die->die_tag) + continue; + if ((abbrev->die_child != NULL) != (die->die_child != NULL)) + continue; + + if (VEC_length (dw_attr_node, abbrev->die_attr) + != VEC_length (dw_attr_node, die->die_attr)) + continue; + + for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, die_a); ix++) { - if ((abbrev->die_child != NULL) == (die->die_child != NULL)) + abbrev_a = VEC_index (dw_attr_node, abbrev->die_attr, ix); + if ((abbrev_a->dw_attr != die_a->dw_attr) + || (value_format (abbrev_a) != value_format (die_a))) { - a_attr = abbrev->die_attr; - d_attr = die->die_attr; - - while (a_attr != NULL && d_attr != NULL) - { - if ((a_attr->dw_attr != d_attr->dw_attr) - || (value_format (a_attr) != value_format (d_attr))) - break; - - a_attr = a_attr->dw_attr_next; - d_attr = d_attr->dw_attr_next; - } - - if (a_attr == NULL && d_attr == NULL) - break; + ok = false; + break; } } + if (ok) + break; } if (abbrev_id >= abbrev_die_table_in_use) @@ -6575,8 +6522,7 @@ build_abbrev_table (dw_die_ref die) } die->die_abbrev = abbrev_id; - for (c = die->die_child; c != NULL; c = c->die_sib) - build_abbrev_table (c); + FOR_EACH_CHILD (die, c, build_abbrev_table (c)); } /* Return the power-of-two number of bytes necessary to represent VALUE. */ @@ -6605,9 +6551,10 @@ size_of_die (dw_die_ref die) { unsigned long size = 0; dw_attr_ref a; + unsigned ix; size += size_of_uleb128 (die->die_abbrev); - for (a = die->die_attr; a != NULL; a = a->dw_attr_next) + for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++) { switch (AT_class (a)) { @@ -6693,8 +6640,7 @@ calc_die_sizes (dw_die_ref die) die->die_offset = next_die_offset; next_die_offset += size_of_die (die); - for (c = die->die_child; c != NULL; c = c->die_sib) - calc_die_sizes (c); + FOR_EACH_CHILD (die, c, calc_die_sizes (c)); if (die->die_child != NULL) /* Count the null byte used to terminate sibling lists. */ @@ -6714,8 +6660,7 @@ mark_dies (dw_die_ref die) gcc_assert (!die->die_mark); die->die_mark = 1; - for (c = die->die_child; c; c = c->die_sib) - mark_dies (c); + FOR_EACH_CHILD (die, c, mark_dies (c)); } /* Clear the marks for a die and its children. */ @@ -6728,8 +6673,7 @@ unmark_dies (dw_die_ref die) gcc_assert (die->die_mark); die->die_mark = 0; - for (c = die->die_child; c; c = c->die_sib) - unmark_dies (c); + FOR_EACH_CHILD (die, c, unmark_dies (c)); } /* Clear the marks for a die, its children and referred dies. */ @@ -6739,15 +6683,15 @@ unmark_all_dies (dw_die_ref die) { dw_die_ref c; dw_attr_ref a; + unsigned ix; if (!die->die_mark) return; die->die_mark = 0; - for (c = die->die_child; c; c = c->die_sib) - unmark_all_dies (c); + FOR_EACH_CHILD (die, c, unmark_all_dies (c)); - for (a = die->die_attr; a; a = a->dw_attr_next) + for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++) if (AT_class (a) == dw_val_class_die_ref) unmark_all_dies (AT_ref (a)); } @@ -6886,11 +6830,11 @@ output_abbrev_section (void) { unsigned long abbrev_id; - dw_attr_ref a_attr; - for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id) { dw_die_ref abbrev = abbrev_die_table[abbrev_id]; + unsigned ix; + dw_attr_ref a_attr; dw2_asm_output_data_uleb128 (abbrev_id, "(abbrev code)"); dw2_asm_output_data_uleb128 (abbrev->die_tag, "(TAG: %s)", @@ -6901,8 +6845,8 @@ output_abbrev_section (void) else dw2_asm_output_data (1, DW_children_no, "DW_children_no"); - for (a_attr = abbrev->die_attr; a_attr != NULL; - a_attr = a_attr->dw_attr_next) + for (ix = 0; VEC_iterate (dw_attr_node, abbrev->die_attr, ix, a_attr); + ix++) { dw2_asm_output_data_uleb128 (a_attr->dw_attr, "(%s)", dwarf_attr_name (a_attr->dw_attr)); @@ -7031,6 +6975,7 @@ output_die (dw_die_ref die) dw_attr_ref a; dw_die_ref c; unsigned long size; + unsigned ix; /* If someone in another CU might refer to us, set up a symbol for them to point to. */ @@ -7040,7 +6985,7 @@ output_die (dw_die_ref die) dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (0x%lx) %s)", die->die_offset, dwarf_tag_name (die->die_tag)); - for (a = die->die_attr; a != NULL; a = a->dw_attr_next) + for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++) { const char *name = dwarf_attr_name (a->dw_attr); @@ -7217,8 +7162,7 @@ output_die (dw_die_ref die) } } - for (c = die->die_child; c != NULL; c = c->die_sib) - output_die (c); + FOR_EACH_CHILD (die, c, output_die (c)); /* Add null byte to terminate sibling list. */ if (die->die_child != NULL) @@ -10205,7 +10149,7 @@ containing_function_has_frame_base (tree decl) { tree declcontext = decl_function_context (decl); dw_die_ref context; - dw_attr_ref attr; + /* Delete 'attr' */ if (!declcontext) return false; @@ -10214,9 +10158,8 @@ containing_function_has_frame_base (tree decl) if (!context) return false; - for (attr = context->die_attr; attr; attr = attr->dw_attr_next) - if (attr->dw_attr == DW_AT_frame_base) - return true; + if (get_AT (context, DW_AT_frame_base)) + return true; return false; } @@ -13694,7 +13637,18 @@ output_indirect_string (void **h, void *v ATTRIBUTE_UNUSED) return 1; } +#if ENABLE_ASSERT_CHECKING +/* Verify that all marks are clear. */ +static void +verify_marks_clear (dw_die_ref die) +{ + dw_die_ref c; + + gcc_assert (! die->die_mark); + FOR_EACH_CHILD (die, c, verify_marks_clear (c)); +} +#endif /* ENABLE_ASSERT_CHECKING */ /* Clear the marks for a die and its children. Be cool if the mark isn't set. */ @@ -13703,12 +13657,11 @@ static void prune_unmark_dies (dw_die_ref die) { dw_die_ref c; - die->die_mark = 0; - for (c = die->die_child; c; c = c->die_sib) - prune_unmark_dies (c); + if (die->die_mark) + die->die_mark = 0; + FOR_EACH_CHILD (die, c, prune_unmark_dies (c)); } - /* Given DIE that we're marking as used, find any other dies it references as attributes and mark them as used. */ @@ -13716,8 +13669,9 @@ static void prune_unused_types_walk_attribs (dw_die_ref die) { dw_attr_ref a; + unsigned ix; - for (a = die->die_attr; a != NULL; a = a->dw_attr_next) + for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++) { if (a->dw_attr_val.val_class == dw_val_class_die_ref) { @@ -13731,6 +13685,10 @@ prune_unused_types_walk_attribs (dw_die_ref die) a->dw_attr_val.v.val_unsigned = maybe_emit_file (a->dw_attr_val.v.val_unsigned); } + /* Set the string's refcount to 0 so that prune_unused_types_mark + accounts properly for it. */ + if (AT_class (a) == dw_val_class_str) + a->dw_attr_val.v.val_str->refcount = 0; } } @@ -13768,16 +13726,12 @@ prune_unused_types_mark (dw_die_ref die, int dokids) Remember that we've walked the kids. */ die->die_mark = 2; - /* Walk them. */ - for (c = die->die_child; c; c = c->die_sib) - { - /* If this is an array type, we need to make sure our - kids get marked, even if they're types. */ - if (die->die_tag == DW_TAG_array_type) - prune_unused_types_mark (c, 1); - else - prune_unused_types_walk (c); - } + /* If this is an array type, we need to make sure our + kids get marked, even if they're types. */ + if (die->die_tag == DW_TAG_array_type) + FOR_EACH_CHILD (die, c, prune_unused_types_mark (c, 1)); + else + FOR_EACH_CHILD (die, c, prune_unused_types_walk (c)); } } @@ -13827,38 +13781,74 @@ prune_unused_types_walk (dw_die_ref die) prune_unused_types_walk_attribs (die); /* Mark children. */ - for (c = die->die_child; c; c = c->die_sib) - prune_unused_types_walk (c); + FOR_EACH_CHILD (die, c, prune_unused_types_walk (c)); } +/* Increment the string counts on strings referred to from DIE's + attributes. */ + +static void +prune_unused_types_update_strings (dw_die_ref die) +{ + dw_attr_ref a; + unsigned ix; + + for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++) + if (AT_class (a) == dw_val_class_str) + { + struct indirect_string_node *s = a->dw_attr_val.v.val_str; + s->refcount++; + /* Avoid unnecessarily putting strings that are used less than + twice in the hash table. */ + if (s->refcount == 2 + || (s->refcount == 1 + && (DEBUG_STR_SECTION_FLAGS & SECTION_MERGE) != 0)) + { + void ** slot; + slot = htab_find_slot_with_hash (debug_str_hash, s->str, + htab_hash_string (s->str), + INSERT); + gcc_assert (*slot == NULL); + *slot = s; + } + } +} /* Remove from the tree DIE any dies that aren't marked. */ static void prune_unused_types_prune (dw_die_ref die) { - dw_die_ref c, p, n; + dw_die_ref c; gcc_assert (die->die_mark); - p = NULL; - for (c = die->die_child; c; c = n) - { - n = c->die_sib; - if (c->die_mark) - { - prune_unused_types_prune (c); - p = c; - } - else + if (! die->die_child) + return; + + c = die->die_child; + do { + dw_die_ref prev = c; + for (c = c->die_sib; ! c->die_mark; c = c->die_sib) + if (c == die->die_child) { - if (p) - p->die_sib = n; + /* No marked children between 'prev' and the end of the list. */ + if (prev == c) + /* No marked children at all. */ + die->die_child = NULL; else - die->die_child = n; - free_die (c); + { + prev->die_sib = c->die_sib; + die->die_child = prev; + } + return; } - } + + if (c != prev->die_sib) + prev->die_sib = c; + prune_unused_types_update_strings (c); + prune_unused_types_prune (c); + } while (c != die->die_child); } @@ -13870,10 +13860,12 @@ prune_unused_types (void) unsigned int i; limbo_die_node *node; - /* Clear all the marks. */ - prune_unmark_dies (comp_unit_die); +#if ENABLE_ASSERT_CHECKING + /* All the marks should already be clear. */ + verify_marks_clear (comp_unit_die); for (node = limbo_die_list; node; node = node->next) - prune_unmark_dies (node->die); + verify_marks_clear (node->die); +#endif /* ENABLE_ASSERT_CHECKING */ /* Set the mark on nodes that are actually used. */ prune_unused_types_walk (comp_unit_die); @@ -13887,7 +13879,9 @@ prune_unused_types (void) for (i = 0; i < arange_table_in_use; i++) prune_unused_types_mark (arange_table[i], 1); - /* Get rid of nodes that aren't marked. */ + /* Get rid of nodes that aren't marked; and update the string counts. */ + if (debug_str_hash) + htab_empty (debug_str_hash); prune_unused_types_prune (comp_unit_die); for (node = limbo_die_list; node; node = node->next) prune_unused_types_prune (node->die); @@ -13984,10 +13978,6 @@ dwarf2out_finish (const char *filename) emit full debugging info for them. */ retry_incomplete_types (); - /* We need to reverse all the dies before break_out_includes, or - we'll see the end of an include file before the beginning. */ - reverse_all_dies (comp_unit_die); - if (flag_eliminate_unused_debug_types) prune_unused_types (); |