dwarf2out.c (dwarf_file_data): New.

* 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.

From-SVN: r116873
This commit is contained in:
Geoffrey Keating 2006-09-12 05:54:00 +00:00 committed by Geoffrey Keating
parent df29fa4d8b
commit d5688810fe
4 changed files with 337 additions and 218 deletions

View file

@ -1,3 +1,52 @@
2006-09-11 Geoffrey Keating <geoffk@apple.com>
* 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 <hongjiu.lu@intel.com>
PR target/13685

View file

@ -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, "<null>");
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;
}
numfiles = last_emitted_file->emitted_number;
/* 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));
files = alloca (numfiles * sizeof (struct file_info));
dirs = alloca (numfiles * sizeof (struct dir_info));
/* Sort the file names. */
for (i = 1; i < VARRAY_ACTIVE_SIZE (file_table); i++)
{
char *f;
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);
/* Skip all leading "./". */
f = VARRAY_CHAR_PTR (file_table, i);
while (f[0] == '.' && f[1] == '/')
f += 2;
/* Create a new array entry. */
files[i].path = f;
files[i].length = strlen (f);
files[i].file_idx = i;
/* Search for the file name part. */
f = strrchr (f, '/');
files[i].fname = f == NULL ? files[i].path : f + 1;
}
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 <built-in>. */
&& 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)
{

View file

@ -1,3 +1,7 @@
2006-09-11 Geoffrey Keating <geoffk@apple.com>
* gcc.dg/debug/dwarf2/dwarf-file1.c: New.
2006-09-11 Jack Howarth <howarth@bromo.med.uc.edu>
PR testsuite/28950

View file

@ -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;