From 51e8c210a0a7978cee3fb255d68bf67ff7f70827 Mon Sep 17 00:00:00 2001 From: rakdver Date: Sun, 27 Oct 2002 09:14:04 +0000 Subject: [PATCH] * Makefile.in (dwarf2out.o): Add dependendcy on hashtab.h. * dwarf2out.c: Include hashtab.h. (is_main_source): New static variable. (attr_checksum, die_checksum): Modified to handle die references. (same_loc_p, same_dw_val_p, same_attr_p, same_die_p, same_die_p_wrap, unmark_all_dies, htab_cu_hash, htab_cu_eq, htab_cu_del, check_duplicate_cu, record_comdat_symbol_number): New static functions. (output_comp_unit, compute_section_prefix, is_type_die, break_out_includes, mark_dies, unmark_dies, dwarf2out_start_source_file): Modified. * toplev.c (rest_of_decl_compilation): Call of dwarf2out_decl for type declarations added. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@58578 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 14 ++ gcc/Makefile.in | 2 +- gcc/dwarf2out.c | 401 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- gcc/toplev.c | 11 ++ 4 files changed, 402 insertions(+), 26 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 61f3bfb..ef1dbff 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2002-10-27 Zdenek Dvorak + + * Makefile.in (dwarf2out.o): Add dependendcy on hashtab.h. + * dwarf2out.c: Include hashtab.h. + (is_main_source): New static variable. + (attr_checksum, die_checksum): Modified to handle die references. + (same_loc_p, same_dw_val_p, same_attr_p, same_die_p, same_die_p_wrap, + unmark_all_dies, htab_cu_hash, htab_cu_eq, htab_cu_del, check_duplicate_cu, + record_comdat_symbol_number): New static functions. + (output_comp_unit, compute_section_prefix, is_type_die, break_out_includes, + mark_dies, unmark_dies, dwarf2out_start_source_file): Modified. + * toplev.c (rest_of_decl_compilation): Call of dwarf2out_decl for type + declarations added. + 2002-10-26 Kazu Hirata * config/h8300/h8300.c (initial_offset): Change to diff --git a/gcc/Makefile.in b/gcc/Makefile.in index eb4596e..e97c302 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1455,7 +1455,7 @@ dwarfout.o : dwarfout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) dwarf.h \ dwarf2out.o : dwarf2out.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) dwarf2.h \ debug.h flags.h insn-config.h reload.h output.h diagnostic.h real.h \ hard-reg-set.h $(REGS_H) $(EXPR_H) libfuncs.h toplev.h dwarf2out.h varray.h \ - $(GGC_H) except.h dwarf2asm.h $(TM_P_H) langhooks.h gt-dwarf2out.h + $(GGC_H) except.h dwarf2asm.h $(TM_P_H) langhooks.h $(HASHTAB_H) gt-dwarf2out.h dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) flags.h $(RTL_H) $(TREE_H) \ output.h dwarf2asm.h $(TM_P_H) $(GGC_H) vmsdbgout.o : vmsdbgout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) flags.h \ diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index b8bf06b..ed2a0ec 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -62,6 +62,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "target.h" #include "langhooks.h" #include "hashtable.h" +#include "hashtab.h" #ifdef DWARF2_DEBUGGING_INFO static void dwarf2out_source_line PARAMS ((unsigned int, const char *)); @@ -3333,6 +3334,10 @@ static unsigned long next_die_offset; /* Record the root of the DIE's built for the current compilation unit. */ static dw_die_ref comp_unit_die; +/* We need special handling in dwarf2out_start_source_file if it is + first one. */ +static int is_main_source; + /* A list of DIEs with a NULL parent waiting to be relocated. */ static limbo_die_node *limbo_die_list = 0; @@ -3569,15 +3574,29 @@ static dw_die_ref pop_compile_unit PARAMS ((dw_die_ref)); static void loc_checksum PARAMS ((dw_loc_descr_ref, struct md5_ctx *)); static void attr_checksum PARAMS ((dw_attr_ref, - struct md5_ctx *)); + struct md5_ctx *, + int *)); static void die_checksum PARAMS ((dw_die_ref, - struct md5_ctx *)); + struct md5_ctx *, + int *)); +static int same_loc_p PARAMS ((dw_loc_descr_ref, + dw_loc_descr_ref, int *)); +static int same_dw_val_p PARAMS ((dw_val_node *, dw_val_node *, + int *)); +static int same_attr_p PARAMS ((dw_attr_ref, dw_attr_ref, int *)); +static int same_die_p PARAMS ((dw_die_ref, dw_die_ref, int *)); +static int same_die_p_wrap PARAMS ((dw_die_ref, dw_die_ref)); static void compute_section_prefix PARAMS ((dw_die_ref)); static int is_type_die PARAMS ((dw_die_ref)); static int is_comdat_die PARAMS ((dw_die_ref)); static int is_symbol_die PARAMS ((dw_die_ref)); static void assign_symbol_names PARAMS ((dw_die_ref)); static void break_out_includes PARAMS ((dw_die_ref)); +static hashval_t htab_cu_hash PARAMS ((const void *)); +static int htab_cu_eq PARAMS ((const void *, const void *)); +static void htab_cu_del PARAMS ((void *)); +static int check_duplicate_cu PARAMS ((dw_die_ref, htab_t, unsigned *)); +static void record_comdat_symbol_number PARAMS ((dw_die_ref, htab_t, unsigned)); static void add_sibling_attributes PARAMS ((dw_die_ref)); static void build_abbrev_table PARAMS ((dw_die_ref)); static void output_location_lists PARAMS ((dw_die_ref)); @@ -3586,6 +3605,7 @@ static unsigned long size_of_die PARAMS ((dw_die_ref)); static void calc_die_sizes PARAMS ((dw_die_ref)); static void mark_dies PARAMS ((dw_die_ref)); static void unmark_dies PARAMS ((dw_die_ref)); +static void unmark_all_dies PARAMS ((dw_die_ref)); static unsigned long size_of_pubnames PARAMS ((void)); static unsigned long size_of_aranges PARAMS ((void)); static enum dwarf_form value_format PARAMS ((dw_attr_ref)); @@ -3594,7 +3614,7 @@ static void output_abbrev_section PARAMS ((void)); static void output_die_symbol PARAMS ((dw_die_ref)); static void output_die PARAMS ((dw_die_ref)); static void output_compilation_unit_header PARAMS ((void)); -static void output_comp_unit PARAMS ((dw_die_ref)); +static void output_comp_unit PARAMS ((dw_die_ref, int)); static const char *dwarf2_name PARAMS ((tree, int)); static void add_pubname PARAMS ((tree, dw_die_ref)); static void output_pubnames PARAMS ((void)); @@ -5420,9 +5440,10 @@ loc_checksum (loc, ctx) /* Calculate the checksum of an attribute. */ static void -attr_checksum (at, ctx) +attr_checksum (at, ctx, mark) dw_attr_ref at; struct md5_ctx *ctx; + int *mark; { dw_loc_descr_ref loc; rtx r; @@ -5480,9 +5501,8 @@ attr_checksum (at, ctx) break; case dw_val_class_die_ref: - if (AT_ref (at)->die_offset) - CHECKSUM (AT_ref (at)->die_offset); - /* FIXME else use target die name or something. */ + die_checksum (AT_ref (at), ctx, mark); + break; case dw_val_class_fde_ref: case dw_val_class_lbl_id: @@ -5497,25 +5517,195 @@ attr_checksum (at, ctx) /* Calculate the checksum of a DIE. */ static void -die_checksum (die, ctx) +die_checksum (die, ctx, mark) dw_die_ref die; struct md5_ctx *ctx; + int *mark; { dw_die_ref c; dw_attr_ref a; + /* To avoid infinite recursion. */ + if (die->die_mark) + { + CHECKSUM (die->die_mark); + return; + } + die->die_mark = ++(*mark); + CHECKSUM (die->die_tag); for (a = die->die_attr; a; a = a->dw_attr_next) - attr_checksum (a, ctx); + attr_checksum (a, ctx, mark); for (c = die->die_child; c; c = c->die_sib) - die_checksum (c, ctx); + die_checksum (c, ctx, mark); } #undef CHECKSUM #undef CHECKSUM_STRING +/* Do the location expressions look same? */ +static inline int +same_loc_p (loc1, loc2, mark) + dw_loc_descr_ref loc1; + dw_loc_descr_ref loc2; + int *mark; +{ + return loc1->dw_loc_opc == loc2->dw_loc_opc + && same_dw_val_p (&loc1->dw_loc_oprnd1, &loc2->dw_loc_oprnd1, mark) + && same_dw_val_p (&loc1->dw_loc_oprnd2, &loc2->dw_loc_oprnd2, mark); +} + +/* Do the values look the same? */ +static int +same_dw_val_p (v1, v2, mark) + dw_val_node *v1; + dw_val_node *v2; + int *mark; +{ + dw_loc_descr_ref loc1, loc2; + rtx r1, r2; + unsigned i; + + if (v1->val_class != v2->val_class) + return 0; + + switch (v1->val_class) + { + case dw_val_class_const: + return v1->v.val_int == v2->v.val_int; + case dw_val_class_unsigned_const: + return v1->v.val_unsigned == v2->v.val_unsigned; + case dw_val_class_long_long: + return v1->v.val_long_long.hi == v2->v.val_long_long.hi + && v1->v.val_long_long.low == v2->v.val_long_long.low; + case dw_val_class_float: + if (v1->v.val_float.length != v2->v.val_float.length) + return 0; + for (i = 0; i < v1->v.val_float.length; i++) + if (v1->v.val_float.array[i] != v2->v.val_float.array[i]) + return 0; + return 1; + case dw_val_class_flag: + return v1->v.val_flag == v2->v.val_flag; + case dw_val_class_str: + return !strcmp((const char *) HT_STR (&v1->v.val_str->id), + (const char *) HT_STR (&v2->v.val_str->id)); + + case dw_val_class_addr: + r1 = v1->v.val_addr; + r2 = v2->v.val_addr; + if (GET_CODE (r1) != GET_CODE (r2)) + return 0; + switch (GET_CODE (r1)) + { + case SYMBOL_REF: + return !strcmp (XSTR (r1, 0), XSTR (r2, 0)); + + default: + abort (); + } + + case dw_val_class_offset: + return v1->v.val_offset == v2->v.val_offset; + + case dw_val_class_loc: + for (loc1 = v1->v.val_loc, loc2 = v2->v.val_loc; + loc1 && loc2; + loc1 = loc1->dw_loc_next, loc2 = loc2->dw_loc_next) + if (!same_loc_p (loc1, loc2, mark)) + return 0; + return !loc1 && !loc2; + + case dw_val_class_die_ref: + return same_die_p (v1->v.val_die_ref.die, v2->v.val_die_ref.die, mark); + + case dw_val_class_fde_ref: + case dw_val_class_lbl_id: + case dw_val_class_lbl_offset: + return 1; + + default: + return 1; + } +} + +/* Do the attributes look the same? */ + +static int +same_attr_p (at1, at2, mark) + dw_attr_ref at1; + dw_attr_ref at2; + int *mark; +{ + if (at1->dw_attr != at2->dw_attr) + return 0; + + /* We don't care about differences in file numbering. */ + if (at1->dw_attr == DW_AT_decl_file + /* Or that this was compiled with a different compiler snapshot; if + the output is the same, that's what matters. */ + || at1->dw_attr == DW_AT_producer) + return 1; + + return same_dw_val_p (&at1->dw_attr_val, &at2->dw_attr_val, mark); +} + +/* Do the dies look the same? */ + +static int +same_die_p (die1, die2, mark) + dw_die_ref die1; + dw_die_ref die2; + int *mark; +{ + dw_die_ref c1, c2; + dw_attr_ref a1, a2; + + /* To avoid infinite recursion. */ + if (die1->die_mark) + return die1->die_mark == die2->die_mark; + die1->die_mark = die2->die_mark = ++(*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) + 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)) + return 0; + if (c1 || c2) + return 0; + + return 1; +} + +/* Do the dies look the same? Wrapper around same_die_p. */ + +static int +same_die_p_wrap (die1, die2) + dw_die_ref die1; + dw_die_ref die2; +{ + int mark = 0; + int ret = same_die_p (die1, die2, &mark); + + unmark_all_dies (die1); + unmark_all_dies (die2); + + return ret; +} + /* The prefix to attach to symbols on DIEs in the current comdat debug info section. */ static char *comdat_symbol_id; @@ -5530,10 +5720,11 @@ static void compute_section_prefix (unit_die) dw_die_ref unit_die; { - const char *base = lbasename (get_AT_string (unit_die, DW_AT_name)); + const char *die_name = get_AT_string (unit_die, DW_AT_name); + const char *base = die_name ? lbasename (die_name) : "anonymous"; char *name = (char *) alloca (strlen (base) + 64); char *p; - int i; + int i, mark; unsigned char checksum[16]; struct md5_ctx ctx; @@ -5541,7 +5732,9 @@ compute_section_prefix (unit_die) the name filename of the unit. */ md5_init_ctx (&ctx); - die_checksum (unit_die, &ctx); + mark = 0; + die_checksum (unit_die, &ctx, &mark); + unmark_all_dies (unit_die); md5_finish_ctx (&ctx, checksum); sprintf (name, "%s.", base); @@ -5583,6 +5776,7 @@ is_type_die (die) case DW_TAG_file_type: case DW_TAG_packed_type: case DW_TAG_volatile_type: + case DW_TAG_typedef: return 1; default: return 0; @@ -5668,6 +5862,104 @@ assign_symbol_names (die) assign_symbol_names (c); } +struct cu_hash_table_entry +{ + dw_die_ref cu; + unsigned min_comdat_num, max_comdat_num; + struct cu_hash_table_entry *next; +}; + +/* Routines to manipulate hash table of CUs. */ +static hashval_t +htab_cu_hash (of) + const void *of; +{ + const struct cu_hash_table_entry *entry = of; + + return htab_hash_string (entry->cu->die_symbol); +} + +static int +htab_cu_eq (of1, of2) + const void *of1; + const void *of2; +{ + const struct cu_hash_table_entry *entry1 = of1; + const struct die_struct *entry2 = of2; + + return !strcmp (entry1->cu->die_symbol, entry2->die_symbol); +} + +static void +htab_cu_del (what) + void *what; +{ + struct cu_hash_table_entry *next, *entry = what; + + while (entry) + { + next = entry->next; + free (entry); + entry = next; + } +} + +/* Check whether we have already seen this CU and set up SYM_NUM + accordingly. */ +static int +check_duplicate_cu (cu, htable, sym_num) + dw_die_ref cu; + htab_t htable; + unsigned *sym_num; +{ + struct cu_hash_table_entry dummy; + struct cu_hash_table_entry **slot, *entry, *last = &dummy; + + dummy.max_comdat_num = 0; + + slot = (struct cu_hash_table_entry **) + htab_find_slot_with_hash (htable, cu, htab_hash_string (cu->die_symbol), + INSERT); + entry = *slot; + + for (; entry; last = entry, entry = entry->next) + { + if (same_die_p_wrap (cu, entry->cu)) + break; + } + + if (entry) + { + *sym_num = entry->min_comdat_num; + return 1; + } + + entry = xcalloc (1, sizeof (struct cu_hash_table_entry)); + entry->cu = cu; + entry->min_comdat_num = *sym_num = last->max_comdat_num; + entry->next = *slot; + *slot = entry; + + return 0; +} + +/* Record SYM_NUM to record of CU in HTABLE. */ +static void +record_comdat_symbol_number (cu, htable, sym_num) + dw_die_ref cu; + htab_t htable; + unsigned sym_num; +{ + struct cu_hash_table_entry **slot, *entry; + + slot = (struct cu_hash_table_entry **) + htab_find_slot_with_hash (htable, cu, htab_hash_string (cu->die_symbol), + NO_INSERT); + entry = *slot; + + entry->max_comdat_num = sym_num; +} + /* Traverse the DIE (which is always comp_unit_die), and set up additional compilation units for each of the include files we see bracketed by BINCL/EINCL. */ @@ -5678,7 +5970,8 @@ break_out_includes (die) { dw_die_ref *ptr; dw_die_ref unit = NULL; - limbo_die_node *node; + limbo_die_node *node, **pnode; + htab_t cu_hash_table; for (ptr = &(die->die_child); *ptr;) { @@ -5719,11 +6012,27 @@ break_out_includes (die) #endif assign_symbol_names (die); - for (node = limbo_die_list; node; node = node->next) + cu_hash_table = htab_create (10, htab_cu_hash, htab_cu_eq, htab_cu_del); + for (node = limbo_die_list, pnode = &limbo_die_list; + node; + node = node->next) { + int is_dupl; + compute_section_prefix (node->die); + is_dupl = check_duplicate_cu (node->die, cu_hash_table, + &comdat_symbol_number); assign_symbol_names (node->die); + if (is_dupl) + *pnode = node->next; + else + { + pnode = &node->next; + record_comdat_symbol_number (node->die, cu_hash_table, + comdat_symbol_number); + } } + htab_delete (cu_hash_table); } /* Traverse the DIE and add a sibling attribute if it may have the @@ -5968,6 +6277,9 @@ mark_dies (die) { dw_die_ref c; + if (die->die_mark) + abort (); + die->die_mark = 1; for (c = die->die_child; c; c = c->die_sib) mark_dies (c); @@ -5981,11 +6293,35 @@ unmark_dies (die) { dw_die_ref c; + if (!die->die_mark) + abort (); + die->die_mark = 0; for (c = die->die_child; c; c = c->die_sib) unmark_dies (c); } +/* Clear the marks for a die, its children and referred dies. */ + +static void +unmark_all_dies (die) + dw_die_ref die; +{ + dw_die_ref c; + dw_attr_ref a; + + if (!die->die_mark) + return; + die->die_mark = 0; + + for (c = die->die_child; c; c = c->die_sib) + unmark_all_dies (c); + + for (a = die->die_attr; a; a = a->dw_attr_next) + if (AT_class (a) == dw_val_class_die_ref) + unmark_all_dies (AT_ref (a)); +} + /* Return the size of the .debug_pubnames table generated for the compilation unit. */ @@ -6455,10 +6791,16 @@ output_compilation_unit_header () /* Output the compilation unit DIE and its children. */ static void -output_comp_unit (die) +output_comp_unit (die, output_if_empty) dw_die_ref die; + int output_if_empty; { const char *secname; + char *oldsym, *tmp; + + /* Unless we are outputting main CU, we may throw away empty ones. */ + if (!output_if_empty && die->die_child == NULL) + return; /* Even if there are no children of this DIE, we must output the information about the compilation unit. Otherwise, on an empty translation unit, we @@ -6473,11 +6815,12 @@ output_comp_unit (die) next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE; calc_die_sizes (die); - if (die->die_symbol) + oldsym = die->die_symbol; + if (oldsym) { - char *tmp = (char *) alloca (strlen (die->die_symbol) + 24); + tmp = (char *) alloca (strlen (oldsym) + 24); - sprintf (tmp, ".gnu.linkonce.wi.%s", die->die_symbol); + sprintf (tmp, ".gnu.linkonce.wi.%s", oldsym); secname = tmp; die->die_symbol = NULL; } @@ -6491,8 +6834,11 @@ output_comp_unit (die) /* Leave the marks on the main CU, so we can check them in output_pubnames. */ - if (die->die_symbol) - unmark_dies (die); + if (oldsym) + { + unmark_dies (die); + die->die_symbol = oldsym; + } } /* The DWARF2 pubname for a nested thingy looks like "A::f". The @@ -11981,13 +12327,17 @@ dwarf2out_start_source_file (lineno, filename) unsigned int lineno; const char *filename; { - if (flag_eliminate_dwarf2_dups) + if (flag_eliminate_dwarf2_dups && !is_main_source) { /* Record the beginning of the file for break_out_includes. */ - dw_die_ref bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL); + dw_die_ref bincl_die; + + bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL); add_AT_string (bincl_die, DW_AT_name, filename); } + is_main_source = 0; + if (debug_info_level >= DINFO_LEVEL_VERBOSE) { named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); @@ -12100,6 +12450,7 @@ dwarf2out_init (main_input_filename) taken as being relative to the directory from which the compiler was invoked when the given (base) source file was compiled. */ comp_unit_die = gen_compile_unit_die (main_input_filename); + is_main_source = 1; VARRAY_TREE_INIT (incomplete_types, 64, "incomplete_types"); @@ -12317,9 +12668,9 @@ dwarf2out_finish (input_filename) /* Output all of the compilation units. We put the main one last so that the offsets are available to output_pubnames. */ for (node = limbo_die_list; node; node = node->next) - output_comp_unit (node->die); + output_comp_unit (node->die, 0); - output_comp_unit (comp_unit_die); + output_comp_unit (comp_unit_die, 0); /* Output the abbreviation table. */ named_section_flags (DEBUG_ABBREV_SECTION, SECTION_DEBUG); diff --git a/gcc/toplev.c b/gcc/toplev.c index 8e94326..a811c4b 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -2316,6 +2316,17 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end) timevar_pop (TV_SYMOUT); } #endif +#ifdef DWARF2_DEBUGGING_INFO + else if ((write_symbols == DWARF2_DEBUG + || write_symbols == VMS_AND_DWARF2_DEBUG) + && top_level + && TREE_CODE (decl) == TYPE_DECL) + { + timevar_push (TV_SYMOUT); + dwarf2out_decl (decl); + timevar_pop (TV_SYMOUT); + } +#endif } /* Called after finishing a record, union or enumeral type. */ -- 2.7.4