From 69278c24c11bbe89fcfbdc11a63f230283b84d8e Mon Sep 17 00:00:00 2001 From: geoffk Date: Tue, 12 Sep 2006 05:54:00 +0000 Subject: [PATCH] * dwarf2out.c (dwarf_file_data): New. (enum dw_val_class): Add dw_val_class_file. (struct dw_val_struct): Add val_file. (file_table): Change to a hash table. (file_table_emitted): Delete. (file_table_last_lookup_index): Delete. (emitcount): Delete. (last_emitted_file): New. (lookup_filename): Change prototype to return a struct dwarf_file_data. (init_file_table): Delete. (maybe_emit_file): Change prototype to take a struct dwarf_file_data. (AT_addr): Add comment. (add_AT_file): New. (AT_file): New. (get_AT_file): New. (print_die): Handle dw_val_class_file. (print_dwarf_line_table): Update for new file table structure. (attr_checksum): Do checksum a filename. (same_dw_val_p, same_attr_p): Do compare a filename. (size_of_die): Handle dw_val_class_file. (value_format): Likewise. (output_die): Likewise. Also, call maybe_emit_file here. (struct file_info): Constify filenames. Make file_idx a pointer to a struct dwarf_file_data. (struct dir_info): Constify directory names. Remove 'used' field. (struct file_name_acquire_data): New. (file_name_acquire): New. (output_file_names): Modify to handle new file data structures. (add_src_coords_attributes): Use add_AT_file. (add_call_src_coords_attributes): Likewise. (dwarf2out_imported_module_or_decl): Likewise. (gen_subprogram_die): Modify for new file data structures. (gen_variable_die): Likewise. (file_table_eq): New. (file_table_hash): New. (file_table_last_lookup): New. (lookup_filename): Rewrite to handle new file data structures. (maybe_emit_file): Rewrite to handle new file data structures. (dwarf2out_source_line): Always call lookup_filename and maybe_emit_file. (dwarf2out_init): Create file_table here. (prune_unused_types_walk_attribs): Don't call maybe_emit_file here. (file_table_relative_p): New. (dwarf2out_finish): Change detection of relative filenames to work with new file data structures. Move output_line_info call after debug_info output. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@116873 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 49 +++ gcc/dwarf2out.c | 497 +++++++++++++----------- gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-file1.c | 5 + 4 files changed, 337 insertions(+), 218 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-file1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d2b3658..b937ee5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,52 @@ +2006-09-11 Geoffrey Keating + + * dwarf2out.c (dwarf_file_data): New. + (enum dw_val_class): Add dw_val_class_file. + (struct dw_val_struct): Add val_file. + (file_table): Change to a hash table. + (file_table_emitted): Delete. + (file_table_last_lookup_index): Delete. + (emitcount): Delete. + (last_emitted_file): New. + (lookup_filename): Change prototype to return a struct dwarf_file_data. + (init_file_table): Delete. + (maybe_emit_file): Change prototype to take a struct dwarf_file_data. + (AT_addr): Add comment. + (add_AT_file): New. + (AT_file): New. + (get_AT_file): New. + (print_die): Handle dw_val_class_file. + (print_dwarf_line_table): Update for new file table structure. + (attr_checksum): Do checksum a filename. + (same_dw_val_p, same_attr_p): Do compare a filename. + (size_of_die): Handle dw_val_class_file. + (value_format): Likewise. + (output_die): Likewise. Also, call maybe_emit_file here. + (struct file_info): Constify filenames. Make file_idx a pointer + to a struct dwarf_file_data. + (struct dir_info): Constify directory names. Remove 'used' field. + (struct file_name_acquire_data): New. + (file_name_acquire): New. + (output_file_names): Modify to handle new file data structures. + (add_src_coords_attributes): Use add_AT_file. + (add_call_src_coords_attributes): Likewise. + (dwarf2out_imported_module_or_decl): Likewise. + (gen_subprogram_die): Modify for new file data structures. + (gen_variable_die): Likewise. + (file_table_eq): New. + (file_table_hash): New. + (file_table_last_lookup): New. + (lookup_filename): Rewrite to handle new file data structures. + (maybe_emit_file): Rewrite to handle new file data structures. + (dwarf2out_source_line): Always call lookup_filename and + maybe_emit_file. + (dwarf2out_init): Create file_table here. + (prune_unused_types_walk_attribs): Don't call maybe_emit_file here. + (file_table_relative_p): New. + (dwarf2out_finish): Change detection of relative filenames + to work with new file data structures. Move output_line_info call + after debug_info output. + 2006-09-11 H.J. Lu PR target/13685 diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 6d6080c..9bf5ffc 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -2653,6 +2653,13 @@ dwarf2out_frame_finish (void) /* And now, the subset of the debugging information support code necessary for emitting location expressions. */ +/* Data about a single source file. */ +struct dwarf_file_data GTY(()) +{ + const char * filename; + int emitted_number; +}; + /* We need some way to distinguish DW_OP_addr with a direct symbol relocation from DW_OP_addr with a dtp-relative symbol relocation. */ #define INTERNAL_DW_OP_tls_addr (0x100 + DW_OP_addr) @@ -2684,7 +2691,8 @@ enum dw_val_class dw_val_class_lbl_id, dw_val_class_lineptr, dw_val_class_str, - dw_val_class_macptr + dw_val_class_macptr, + dw_val_class_file }; /* Describe a double word constant value. */ @@ -2732,6 +2740,7 @@ typedef struct dw_val_struct GTY(()) struct indirect_string_node * GTY ((tag ("dw_val_class_str"))) val_str; char * GTY ((tag ("dw_val_class_lbl_id"))) val_lbl_id; unsigned char GTY ((tag ("dw_val_class_flag"))) val_flag; + struct dwarf_file_data * GTY ((tag ("dw_val_class_file"))) val_file; } GTY ((desc ("%1.val_class"))) v; } @@ -3851,9 +3860,7 @@ static GTY(()) dw_die_ref comp_unit_die; static GTY(()) limbo_die_node *limbo_die_list; /* Filenames referenced by this compilation unit. */ -static GTY(()) varray_type file_table; -static GTY(()) varray_type file_table_emitted; -static GTY(()) size_t file_table_last_lookup_index; +static GTY((param_is (struct dwarf_file_data))) htab_t file_table; /* A hash table of references to DIE's that describe declarations. The key is a DECL_UID() which is a unique number identifying each decl. */ @@ -3985,8 +3992,8 @@ static int current_function_has_inlines; static int comp_unit_has_inlines; #endif -/* Number of file tables emitted in maybe_emit_file(). */ -static GTY(()) int emitcount = 0; +/* The last file entry emitted by maybe_emit_file(). */ +static GTY(()) struct dwarf_file_data * last_emitted_file; /* Number of internal labels generated by gen_internal_sym(). */ static GTY(()) int label_num; @@ -4219,8 +4226,7 @@ static dw_die_ref force_decl_die (tree); static dw_die_ref force_type_die (tree); static dw_die_ref setup_namespace_context (tree, dw_die_ref); static void declare_in_namespace (tree, dw_die_ref); -static unsigned lookup_filename (const char *); -static void init_file_table (void); +static struct dwarf_file_data * lookup_filename (const char *); static void retry_incomplete_types (void); static void gen_type_die_for_member (tree, tree, dw_die_ref); static void splice_child_die (dw_die_ref, dw_die_ref); @@ -4239,7 +4245,7 @@ static void prune_unused_types_walk (dw_die_ref); static void prune_unused_types_walk_attribs (dw_die_ref); static void prune_unused_types_prune (dw_die_ref); static void prune_unused_types (void); -static int maybe_emit_file (int); +static int maybe_emit_file (struct dwarf_file_data *fd); /* Section names used to hold DWARF debugging information. */ #ifndef DEBUG_INFO_SECTION @@ -5180,6 +5186,8 @@ add_AT_addr (dw_die_ref die, enum dwarf_attribute attr_kind, rtx addr) add_dwarf_attr (die, &attr); } +/* Get the RTX from to an address DIE attribute. */ + static inline rtx AT_addr (dw_attr_ref a) { @@ -5187,6 +5195,29 @@ AT_addr (dw_attr_ref a) return a->dw_attr_val.v.val_addr; } +/* Add a file attribute value to a DIE. */ + +static inline void +add_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind, + struct dwarf_file_data *fd) +{ + dw_attr_node attr; + + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_file; + attr.dw_attr_val.v.val_file = fd; + add_dwarf_attr (die, &attr); +} + +/* Get the dwarf_file_data from a file DIE attribute. */ + +static inline struct dwarf_file_data * +AT_file (dw_attr_ref a) +{ + gcc_assert (a && AT_class (a) == dw_val_class_file); + return a->dw_attr_val.v.val_file; +} + /* Add a label identifier attribute value to a DIE. */ static inline void @@ -5357,6 +5388,14 @@ get_AT_ref (dw_die_ref die, enum dwarf_attribute attr_kind) return a ? AT_ref (a) : NULL; } +static inline struct dwarf_file_data * +get_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind) +{ + dw_attr_ref a = get_AT (die, attr_kind); + + return a ? AT_file (a) : NULL; +} + /* Return TRUE if the language is C or C++. */ static inline bool @@ -5766,6 +5805,10 @@ print_die (dw_die_ref die, FILE *outfile) else fprintf (outfile, ""); break; + case dw_val_class_file: + fprintf (outfile, "\"%s\" (%d)", AT_file (a)->filename, + AT_file (a)->emitted_number); + break; default: break; } @@ -5796,11 +5839,9 @@ print_dwarf_line_table (FILE *outfile) for (i = 1; i < line_info_table_in_use; i++) { line_info = &line_info_table[i]; - fprintf (outfile, "%5d: ", i); - fprintf (outfile, "%-20s", - VARRAY_CHAR_PTR (file_table, line_info->dw_file_num)); - fprintf (outfile, "%6ld", line_info->dw_line_num); - fprintf (outfile, "\n"); + fprintf (outfile, "%5d: %4ld %6ld\n", i, + line_info->dw_file_num, + line_info->dw_line_num); } fprintf (outfile, "\n\n"); @@ -5874,11 +5915,9 @@ attr_checksum (dw_attr_ref at, struct md5_ctx *ctx, int *mark) CHECKSUM (at->dw_attr); - /* We don't care about differences in file numbering. */ - if (at->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. */ - || at->dw_attr == DW_AT_producer) + /* We don't care that this was compiled with a different compiler + snapshot; if the output is the same, that's what matters. */ + if (at->dw_attr == DW_AT_producer) return; switch (AT_class (at)) @@ -5927,6 +5966,10 @@ attr_checksum (dw_attr_ref at, struct md5_ctx *ctx, int *mark) case dw_val_class_macptr: break; + case dw_val_class_file: + CHECKSUM_STRING (AT_file (at)->filename); + break; + default: break; } @@ -6029,6 +6072,9 @@ same_dw_val_p (dw_val_node *v1, dw_val_node *v2, int *mark) case dw_val_class_macptr: return 1; + case dw_val_class_file: + return v1->v.val_file == v2->v.val_file; + default: return 1; } @@ -6042,11 +6088,9 @@ same_attr_p (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) + /* We don't care that this was compiled with a different compiler + snapshot; if the output is the same, that's what matters. */ + if (at1->dw_attr == DW_AT_producer) return 1; return same_dw_val_p (&at1->dw_attr_val, &at2->dw_attr_val, mark); @@ -6622,6 +6666,9 @@ size_of_die (dw_die_ref die) else size += strlen (a->dw_attr_val.v.val_str->str) + 1; break; + case dw_val_class_file: + size += constant_size (maybe_emit_file (a->dw_attr_val.v.val_file)); + break; default: gcc_unreachable (); } @@ -6804,6 +6851,18 @@ value_format (dw_attr_ref a) return DW_FORM_data; case dw_val_class_str: return AT_string_form (a); + case dw_val_class_file: + switch (constant_size (maybe_emit_file (a->dw_attr_val.v.val_file))) + { + case 1: + return DW_FORM_data1; + case 2: + return DW_FORM_data2; + case 4: + return DW_FORM_data4; + default: + gcc_unreachable (); + } default: gcc_unreachable (); @@ -7163,6 +7222,15 @@ output_die (dw_die_ref die) dw2_asm_output_nstring (AT_string (a), -1, "%s", name); break; + case dw_val_class_file: + { + int f = maybe_emit_file (a->dw_attr_val.v.val_file); + + dw2_asm_output_data (constant_size (f), f, "%s (%s)", name, + a->dw_attr_val.v.val_file->filename); + break; + } + default: gcc_unreachable (); } @@ -7502,10 +7570,10 @@ output_ranges (void) /* Data structure containing information about input files. */ struct file_info { - char *path; /* Complete file name. */ - char *fname; /* File name part. */ + const char *path; /* Complete file name. */ + const char *fname; /* File name part. */ int length; /* Length of entire string. */ - int file_idx; /* Index in input file table. */ + struct dwarf_file_data * file_idx; /* Index in input file table. */ int dir_idx; /* Index in directory table. */ }; @@ -7513,12 +7581,11 @@ struct file_info files. */ struct dir_info { - char *path; /* Path including directory name. */ + const char *path; /* Path including directory name. */ int length; /* Path length. */ int prefix; /* Index of directory entry which is a prefix. */ int count; /* Number of files in this directory. */ int dir_idx; /* Index of directory used as base. */ - int used; /* Used in the end? */ }; /* Callback function for file_info comparison. We sort by looking at @@ -7559,6 +7626,48 @@ file_info_cmp (const void *p1, const void *p2) } } +struct file_name_acquire_data +{ + struct file_info *files; + int used_files; + int max_files; +}; + +/* Traversal function for the hash table. */ + +static int +file_name_acquire (void ** slot, void *data) +{ + struct file_name_acquire_data *fnad = data; + struct dwarf_file_data *d = *slot; + struct file_info *fi; + const char *f; + + gcc_assert (fnad->max_files >= d->emitted_number); + + if (! d->emitted_number) + return 1; + + gcc_assert (fnad->max_files != fnad->used_files); + + fi = fnad->files + fnad->used_files++; + + /* Skip all leading "./". */ + f = d->filename; + while (f[0] == '.' && f[1] == '/') + f += 2; + + /* Create a new array entry. */ + fi->path = f; + fi->length = strlen (f); + fi->file_idx = d; + + /* Search for the file name part. */ + f = strrchr (f, '/'); + fi->fname = f == NULL ? fi->path : f + 1; + return 1; +} + /* Output the directory table and the file name table. We try to minimize the total amount of memory needed. A heuristic is used to avoid large slowdowns with many input files. */ @@ -7566,62 +7675,49 @@ file_info_cmp (const void *p1, const void *p2) static void output_file_names (void) { + struct file_name_acquire_data fnad; + int numfiles; struct file_info *files; struct dir_info *dirs; int *saved; int *savehere; int *backmap; - size_t ndirs; + int ndirs; int idx_offset; - size_t i; + int i; int idx; - /* Handle the case where file_table is empty. */ - if (VARRAY_ACTIVE_SIZE (file_table) <= 1) + if (!last_emitted_file) { dw2_asm_output_data (1, 0, "End directory table"); dw2_asm_output_data (1, 0, "End file name table"); return; } - /* Allocate the various arrays we need. */ - files = alloca (VARRAY_ACTIVE_SIZE (file_table) * sizeof (struct file_info)); - dirs = alloca (VARRAY_ACTIVE_SIZE (file_table) * sizeof (struct dir_info)); - - /* Sort the file names. */ - for (i = 1; i < VARRAY_ACTIVE_SIZE (file_table); i++) - { - char *f; - - /* Skip all leading "./". */ - f = VARRAY_CHAR_PTR (file_table, i); - while (f[0] == '.' && f[1] == '/') - f += 2; + numfiles = last_emitted_file->emitted_number; - /* Create a new array entry. */ - files[i].path = f; - files[i].length = strlen (f); - files[i].file_idx = i; + /* Allocate the various arrays we need. */ + files = alloca (numfiles * sizeof (struct file_info)); + dirs = alloca (numfiles * sizeof (struct dir_info)); - /* Search for the file name part. */ - f = strrchr (f, '/'); - files[i].fname = f == NULL ? files[i].path : f + 1; - } + fnad.files = files; + fnad.used_files = 0; + fnad.max_files = numfiles; + htab_traverse (file_table, file_name_acquire, &fnad); + gcc_assert (fnad.used_files == fnad.max_files); - qsort (files + 1, VARRAY_ACTIVE_SIZE (file_table) - 1, - sizeof (files[0]), file_info_cmp); + qsort (files, numfiles, sizeof (files[0]), file_info_cmp); /* Find all the different directories used. */ - dirs[0].path = files[1].path; - dirs[0].length = files[1].fname - files[1].path; + dirs[0].path = files[0].path; + dirs[0].length = files[0].fname - files[0].path; dirs[0].prefix = -1; dirs[0].count = 1; dirs[0].dir_idx = 0; - dirs[0].used = 0; - files[1].dir_idx = 0; + files[0].dir_idx = 0; ndirs = 1; - for (i = 2; i < VARRAY_ACTIVE_SIZE (file_table); i++) + for (i = 1; i < numfiles; i++) if (files[i].fname - files[i].path == dirs[ndirs - 1].length && memcmp (dirs[ndirs - 1].path, files[i].path, dirs[ndirs - 1].length) == 0) @@ -7632,14 +7728,13 @@ output_file_names (void) } else { - size_t j; + int j; /* This is a new directory. */ dirs[ndirs].path = files[i].path; dirs[ndirs].length = files[i].fname - files[i].path; dirs[ndirs].count = 1; dirs[ndirs].dir_idx = ndirs; - dirs[ndirs].used = 0; files[i].dir_idx = ndirs; /* Search for a prefix. */ @@ -7667,7 +7762,7 @@ output_file_names (void) memset (saved, '\0', ndirs * sizeof (saved[0])); for (i = 0; i < ndirs; i++) { - size_t j; + int j; int total; /* We can always save some space for the current directory. But this @@ -7690,7 +7785,7 @@ output_file_names (void) if (k == (int) i) { - /* Yes it is. We can possibly safe some memory but + /* Yes it is. We can possibly save some memory by writing the filenames in dirs[j] relative to dirs[i]. */ savehere[j] = dirs[i].length; @@ -7699,7 +7794,7 @@ output_file_names (void) } } - /* Check whether we can safe enough to justify adding the dirs[i] + /* Check whether we can save enough to justify adding the dirs[i] directory. */ if (total > dirs[i].length + 1) { @@ -7716,51 +7811,33 @@ output_file_names (void) } } - /* We have to emit them in the order they appear in the file_table array - since the index is used in the debug info generation. To do this - efficiently we generate a back-mapping of the indices first. */ - backmap = alloca (VARRAY_ACTIVE_SIZE (file_table) * sizeof (int)); - for (i = 1; i < VARRAY_ACTIVE_SIZE (file_table); i++) - { - backmap[files[i].file_idx] = i; - - /* Mark this directory as used. */ - dirs[dirs[files[i].dir_idx].dir_idx].used = 1; - } - - /* That was it. We are ready to emit the information. First emit the - directory name table. We have to make sure the first actually emitted - directory name has index one; zero is reserved for the current working - directory. Make sure we do not confuse these indices with the one for the - constructed table (even though most of the time they are identical). */ + /* Emit the directory name table. */ idx = 1; idx_offset = dirs[0].length > 0 ? 1 : 0; for (i = 1 - idx_offset; i < ndirs; i++) - if (dirs[i].used != 0) - { - dirs[i].used = idx++; - dw2_asm_output_nstring (dirs[i].path, dirs[i].length - 1, - "Directory Entry: 0x%x", dirs[i].used); - } + dw2_asm_output_nstring (dirs[i].path, dirs[i].length - 1, + "Directory Entry: 0x%x", i + idx_offset); dw2_asm_output_data (1, 0, "End directory table"); - /* Correct the index for the current working directory entry if it - exists. */ - if (idx_offset == 0) - dirs[0].used = 0; + /* We have to emit them in the order of emitted_number since that's + used in the debug info generation. To do this efficiently we + generate a back-mapping of the indices first. */ + backmap = alloca (numfiles * sizeof (int)); + for (i = 0; i < numfiles; i++) + backmap[files[i].file_idx->emitted_number - 1] = i; /* Now write all the file names. */ - for (i = 1; i < VARRAY_ACTIVE_SIZE (file_table); i++) + for (i = 0; i < numfiles; i++) { int file_idx = backmap[i]; int dir_idx = dirs[files[file_idx].dir_idx].dir_idx; dw2_asm_output_nstring (files[file_idx].path + dirs[dir_idx].length, -1, - "File Entry: 0x%lx", (unsigned long) i); + "File Entry: 0x%x", (unsigned) i + 1); /* Include directory index. */ - dw2_asm_output_data_uleb128 (dirs[dir_idx].used, NULL); + dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL); /* Modification time. */ dw2_asm_output_data_uleb128 (0, NULL); @@ -7916,9 +7993,7 @@ output_line_info (void) { current_file = line_info->dw_file_num; dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file"); - dw2_asm_output_data_uleb128 (current_file, "(\"%s\")", - VARRAY_CHAR_PTR (file_table, - current_file)); + dw2_asm_output_data_uleb128 (current_file, "%lu", current_file); } /* Emit debug info for the current line number, choosing the encoding @@ -8025,9 +8100,7 @@ output_line_info (void) { current_file = line_info->dw_file_num; dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file"); - dw2_asm_output_data_uleb128 (current_file, "(\"%s\")", - VARRAY_CHAR_PTR (file_table, - current_file)); + dw2_asm_output_data_uleb128 (current_file, "%lu", current_file); } /* Emit debug info for the current line number, choosing the encoding @@ -10843,9 +10916,8 @@ static void add_src_coords_attributes (dw_die_ref die, tree decl) { expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl)); - unsigned file_index = lookup_filename (s.file); - add_AT_unsigned (die, DW_AT_decl_file, file_index); + add_AT_file (die, DW_AT_decl_file, lookup_filename (s.file)); add_AT_unsigned (die, DW_AT_decl_line, s.line); } @@ -11591,7 +11663,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) else if (old_die) { expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl)); - unsigned file_index = lookup_filename (s.file); + struct dwarf_file_data * file_index = lookup_filename (s.file); if (!get_AT_flag (old_die, DW_AT_declaration) /* We can have a normal definition following an inline one in the @@ -11613,7 +11685,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) apply; we just use the old DIE. */ if ((old_die->die_parent == comp_unit_die || context_die == NULL) && (DECL_ARTIFICIAL (decl) - || (get_AT_unsigned (old_die, DW_AT_decl_file) == file_index + || (get_AT_file (old_die, DW_AT_decl_file) == file_index && (get_AT_unsigned (old_die, DW_AT_decl_line) == (unsigned) s.line)))) { @@ -11631,12 +11703,10 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) { subr_die = new_die (DW_TAG_subprogram, context_die, decl); add_AT_specification (subr_die, old_die); - if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index) - add_AT_unsigned (subr_die, DW_AT_decl_file, file_index); - if (get_AT_unsigned (old_die, DW_AT_decl_line) - != (unsigned) s.line) - add_AT_unsigned - (subr_die, DW_AT_decl_line, s.line); + if (get_AT_file (old_die, DW_AT_decl_file) != file_index) + add_AT_file (subr_die, DW_AT_decl_file, file_index); + if (get_AT_unsigned (old_die, DW_AT_decl_line) != (unsigned) s.line) + add_AT_unsigned (subr_die, DW_AT_decl_line, s.line); } } else @@ -11925,13 +11995,12 @@ gen_variable_die (tree decl, dw_die_ref context_die) if (DECL_NAME (decl)) { expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl)); - unsigned file_index = lookup_filename (s.file); + struct dwarf_file_data * file_index = lookup_filename (s.file); - if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index) - add_AT_unsigned (var_die, DW_AT_decl_file, file_index); + if (get_AT_file (old_die, DW_AT_decl_file) != file_index) + add_AT_file (var_die, DW_AT_decl_file, file_index); - if (get_AT_unsigned (old_die, DW_AT_decl_line) - != (unsigned) s.line) + if (get_AT_unsigned (old_die, DW_AT_decl_line) != (unsigned) s.line) add_AT_unsigned (var_die, DW_AT_decl_line, s.line); } @@ -12019,9 +12088,8 @@ static inline void add_call_src_coords_attributes (tree stmt, dw_die_ref die) { expanded_location s = expand_location (BLOCK_SOURCE_LOCATION (stmt)); - unsigned file_index = lookup_filename (s.file); - add_AT_unsigned (die, DW_AT_call_file, file_index); + add_AT_file (die, DW_AT_call_file, lookup_filename (s.file)); add_AT_unsigned (die, DW_AT_call_line, s.line); } @@ -13207,7 +13275,6 @@ dwarf2out_imported_module_or_decl (tree decl, tree context) { dw_die_ref imported_die, at_import_die; dw_die_ref scope_die; - unsigned file_index; expanded_location xloc; if (debug_info_level <= DINFO_LEVEL_TERSE) @@ -13263,8 +13330,7 @@ dwarf2out_imported_module_or_decl (tree decl, tree context) imported_die = new_die (DW_TAG_imported_declaration, scope_die, context); xloc = expand_location (input_location); - file_index = lookup_filename (xloc.file); - add_AT_unsigned (imported_die, DW_AT_decl_file, file_index); + add_AT_file (imported_die, DW_AT_decl_file, lookup_filename (xloc.file)); add_AT_unsigned (imported_die, DW_AT_decl_line, xloc.line); add_AT_die_ref (imported_die, DW_AT_import, at_import_die); } @@ -13428,6 +13494,23 @@ dwarf2out_ignore_block (tree block) return 1; } +/* Hash table routines for file_hash. */ + +static int +file_table_eq (const void *p1_p, const void *p2_p) +{ + const struct dwarf_file_data * p1 = p1_p; + const char * p2 = p2_p; + return strcmp (p1->filename, p2) == 0; +} + +static hashval_t +file_table_hash (const void *p_p) +{ + const struct dwarf_file_data * p = p_p; + return htab_hash_string (p->filename); +} + /* Lookup FILE_NAME (in the list of filenames that we know about here in dwarf2out.c) and return its "index". The index of each (known) filename is just a unique number which is associated with only that one filename. We @@ -13439,46 +13522,32 @@ dwarf2out_ignore_block (tree block) the index of the filename was looked up last. This handles the majority of all searches. */ -static unsigned +static GTY(()) struct dwarf_file_data * file_table_last_lookup; + +static struct dwarf_file_data * lookup_filename (const char *file_name) { - size_t i, n; - char *save_file_name; + void ** slot; + struct dwarf_file_data * created; /* Check to see if the file name that was searched on the previous call matches this file name. If so, return the index. */ - if (file_table_last_lookup_index != 0) - { - const char *last - = VARRAY_CHAR_PTR (file_table, file_table_last_lookup_index); - if (strcmp (file_name, last) == 0) - return file_table_last_lookup_index; - } + if (file_table_last_lookup + && (file_name == file_table_last_lookup->filename + || strcmp (file_table_last_lookup->filename, file_name) == 0)) + return file_table_last_lookup; /* Didn't match the previous lookup, search the table. */ - n = VARRAY_ACTIVE_SIZE (file_table); - for (i = 1; i < n; i++) - if (strcmp (file_name, VARRAY_CHAR_PTR (file_table, i)) == 0) - { - file_table_last_lookup_index = i; - return i; - } + slot = htab_find_slot_with_hash (file_table, file_name, + htab_hash_string (file_name), INSERT); + if (*slot) + return *slot; - /* Add the new entry to the end of the filename table. */ - file_table_last_lookup_index = n; - save_file_name = (char *) ggc_strdup (file_name); - VARRAY_PUSH_CHAR_PTR (file_table, save_file_name); - VARRAY_PUSH_UINT (file_table_emitted, 0); - - /* If the assembler is emitting the file table, and we aren't eliminating - unused debug types, then we must emit .file here. If we are eliminating - unused debug types, then this will be done by the maybe_emit_file call in - prune_unused_types_walk_attribs. */ - - if (DWARF2_ASM_LINE_DEBUG_INFO && ! flag_eliminate_unused_debug_types) - return maybe_emit_file (i); - - return i; + created = ggc_alloc (sizeof (struct dwarf_file_data)); + created->filename = file_name; + created->emitted_number = 0; + *slot = created; + return created; } /* If the assembler will construct the file table, then translate the compiler @@ -13488,38 +13557,25 @@ lookup_filename (const char *file_name) types, which may include filenames. */ static int -maybe_emit_file (int fileno) +maybe_emit_file (struct dwarf_file_data * fd) { - if (DWARF2_ASM_LINE_DEBUG_INFO && fileno > 0) + if (! fd->emitted_number) { - if (!VARRAY_UINT (file_table_emitted, fileno)) + if (last_emitted_file) + fd->emitted_number = last_emitted_file->emitted_number + 1; + else + fd->emitted_number = 1; + last_emitted_file = fd; + + if (DWARF2_ASM_LINE_DEBUG_INFO) { - VARRAY_UINT (file_table_emitted, fileno) = ++emitcount; - fprintf (asm_out_file, "\t.file %u ", - VARRAY_UINT (file_table_emitted, fileno)); - output_quoted_string (asm_out_file, - VARRAY_CHAR_PTR (file_table, fileno)); + fprintf (asm_out_file, "\t.file %u ", fd->emitted_number); + output_quoted_string (asm_out_file, fd->filename); fputc ('\n', asm_out_file); } - return VARRAY_UINT (file_table_emitted, fileno); } - else - return fileno; -} - -/* Initialize the compiler internal file table. */ - -static void -init_file_table (void) -{ - /* Allocate the initial hunk of the file_table. */ - VARRAY_CHAR_PTR_INIT (file_table, 64, "file_table"); - VARRAY_UINT_INIT (file_table_emitted, 64, "file_table_emitted"); - - /* Skip the first entry - file numbers begin at 1. */ - VARRAY_PUSH_CHAR_PTR (file_table, NULL); - VARRAY_PUSH_UINT (file_table_emitted, 0); - file_table_last_lookup_index = 0; + + return fd->emitted_number; } /* Called by the final INSN scan whenever we see a var location. We @@ -13596,6 +13652,8 @@ dwarf2out_source_line (unsigned int line, const char *filename) if (debug_info_level >= DINFO_LEVEL_NORMAL && line != 0) { + int file_num = maybe_emit_file (lookup_filename (filename)); + switch_to_section (current_function_section ()); /* If requested, emit something human-readable. */ @@ -13605,10 +13663,6 @@ dwarf2out_source_line (unsigned int line, const char *filename) if (DWARF2_ASM_LINE_DEBUG_INFO) { - unsigned file_num = lookup_filename (filename); - - file_num = maybe_emit_file (file_num); - /* Emit the .loc directive understood by GNU as. */ fprintf (asm_out_file, "\t.loc %d %d 0\n", file_num, line); @@ -13618,8 +13672,9 @@ dwarf2out_source_line (unsigned int line, const char *filename) else if (function_section (current_function_decl) != text_section) { dw_separate_line_info_ref line_info; - targetm.asm_out.internal_label (asm_out_file, SEPARATE_LINE_CODE_LABEL, - separate_line_info_table_in_use); + targetm.asm_out.internal_label (asm_out_file, + SEPARATE_LINE_CODE_LABEL, + separate_line_info_table_in_use); /* Expand the line info table if necessary. */ if (separate_line_info_table_in_use @@ -13640,7 +13695,7 @@ dwarf2out_source_line (unsigned int line, const char *filename) /* Add the new entry at the end of the line_info_table. */ line_info = &separate_line_info_table[separate_line_info_table_in_use++]; - line_info->dw_file_num = lookup_filename (filename); + line_info->dw_file_num = file_num; line_info->dw_line_num = line; line_info->function = current_function_funcdef_no; } @@ -13665,7 +13720,7 @@ dwarf2out_source_line (unsigned int line, const char *filename) /* Add the new entry at the end of the line_info_table. */ line_info = &line_info_table[line_info_table_in_use++]; - line_info->dw_file_num = lookup_filename (filename); + line_info->dw_file_num = file_num; line_info->dw_line_num = line; } } @@ -13687,15 +13742,14 @@ dwarf2out_start_source_file (unsigned int lineno, const char *filename) if (debug_info_level >= DINFO_LEVEL_VERBOSE) { - int fileno; + int file_num = maybe_emit_file (lookup_filename (filename)); switch_to_section (debug_macinfo_section); dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file"); dw2_asm_output_data_uleb128 (lineno, "Included from line number %d", lineno); - fileno = maybe_emit_file (lookup_filename (filename)); - dw2_asm_output_data_uleb128 (fileno, "Filename we just started"); + dw2_asm_output_data_uleb128 (file_num, "file %s", filename); } } @@ -13754,7 +13808,9 @@ dwarf2out_undef (unsigned int lineno ATTRIBUTE_UNUSED, static void dwarf2out_init (const char *filename ATTRIBUTE_UNUSED) { - init_file_table (); + /* Allocate the file_table. */ + file_table = htab_create_ggc (50, file_table_hash, + file_table_eq, NULL); /* Allocate the decl_die_table. */ decl_die_table = htab_create_ggc (10, decl_die_table_hash, @@ -13914,12 +13970,6 @@ prune_unused_types_walk_attribs (dw_die_ref die) Make sure that it will get emitted. */ prune_unused_types_mark (a->dw_attr_val.v.val_die_ref.die, 1); } - else if (a->dw_attr == DW_AT_decl_file || a->dw_attr == DW_AT_call_file) - { - /* A reference to a file. Make sure the file name is emitted. */ - 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) @@ -14129,6 +14179,21 @@ prune_unused_types (void) prune_unmark_dies (node->die); } +/* Set the parameter to true if there are any relative pathnames in + the file table. */ +static int +file_table_relative_p (void ** slot, void *param) +{ + bool *p = param; + struct dwarf_file_data *d = *slot; + if (d->emitted_number && d->filename[0] != DIR_SEPARATOR) + { + *p = true; + return 0; + } + return 1; +} + /* Output stuff that dwarf requires at the end of every file, and generate the DWARF-2 debugging info. */ @@ -14145,15 +14210,10 @@ dwarf2out_finish (const char *filename) add_comp_dir_attribute (comp_unit_die); else if (get_AT (comp_unit_die, DW_AT_comp_dir) == NULL) { - size_t i; - for (i = 1; i < VARRAY_ACTIVE_SIZE (file_table); i++) - if (VARRAY_CHAR_PTR (file_table, i)[0] != DIR_SEPARATOR - /* Don't add cwd for . */ - && VARRAY_CHAR_PTR (file_table, i)[0] != '<') - { - add_comp_dir_attribute (comp_unit_die); - break; - } + bool p = false; + htab_traverse (file_table, file_table_relative_p, &p); + if (p) + add_comp_dir_attribute (comp_unit_die); } /* Traverse the limbo die list, and add parent/child links. The only @@ -14238,17 +14298,6 @@ dwarf2out_finish (const char *filename) targetm.asm_out.internal_label (asm_out_file, COLD_END_LABEL, 0); } - /* Output the source line correspondence table. We must do this - even if there is no line information. Otherwise, on an empty - translation unit, we will generate a present, but empty, - .debug_info section. IRIX 6.5 `nm' will then complain when - examining the file. */ - if (! DWARF2_ASM_LINE_DEBUG_INFO) - { - switch_to_section (debug_line_section); - output_line_info (); - } - /* We can only use the low/high_pc attributes if all of the code was in .text. */ if (!have_multiple_function_sections) @@ -14314,6 +14363,18 @@ dwarf2out_finish (const char *filename) output_ranges (); } + /* Output the source line correspondence table. We must do this + even if there is no line information. Otherwise, on an empty + translation unit, we will generate a present, but empty, + .debug_info section. IRIX 6.5 `nm' will then complain when + examining the file. This is done late so that any filenames + used by the debug_info section are marked as 'used'. */ + if (! DWARF2_ASM_LINE_DEBUG_INFO) + { + switch_to_section (debug_line_section); + output_line_info (); + } + /* Have to end the macro section. */ if (debug_info_level >= DINFO_LEVEL_VERBOSE) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3235b2d..d67ebb7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2006-09-11 Geoffrey Keating + + * gcc.dg/debug/dwarf2/dwarf-file1.c: New. + 2006-09-11 Jack Howarth PR testsuite/28950 diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-file1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-file1.c new file mode 100644 index 0000000..96a2b5a --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-file1.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -gdwarf-2 -dA" } */ +/* { dg-final { scan-assembler "File Entry:" } } */ +/* Verify that a file entry is output for this file. */ +int bar = 3; -- 2.7.4