This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Bug in dwarf2out.c:output_file_names()
With a bit of thinking I came up with the appended patch. It should
catch the cases rth mentioned without much increase in compile time.
We have at most twice at many entries.
I'll do a bit more testing today but you might want to review it now.
--
---------------. ,-. 1325 Chesapeake Terrace
Ulrich Drepper \ ,-------------------' \ Sunnyvale, CA 94089 USA
Red Hat `--' drepper at redhat.com `------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dwarf2out.c,v
retrieving revision 1.233
diff -u -d -u -p -r1.233 dwarf2out.c
--- dwarf2out.c 2001/01/19 17:11:15 1.233
+++ dwarf2out.c 2001/01/23 08:45:49
@@ -6499,6 +6499,36 @@ file_info_cmp (p1, p2)
}
}
+/* Compute the maximum prefix of P2 appearing also in P1. Entire
+ directory names must match. */
+static int prefix_of PARAMS ((struct dir_info *, struct dir_info *));
+static int
+prefix_of (p1, p2)
+ struct dir_info *p1;
+ struct dir_info *p2;
+{
+ char *s1 = p1->path;
+ char *s2 = p2->path;
+
+ /* The algorithm in `output_file_names' must ensure that the already
+ added entries have no longer directory names. */
+ if (p1->length > p2->length)
+ abort ();
+
+ while (*s1 == *s2 && s1 < p1->path + p1->length)
+ ++s1, ++s2;
+
+ if (*s1 == '/' && *s2 == '/')
+ /* The whole of P1 is the prefix. */
+ return p1->length;
+
+ /* Go back to the last directory component. */
+ while (s1 > p1->path && *--s1 != '/')
+ /* go */;
+
+ return s1 - p1->path + 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. */
@@ -6518,7 +6548,7 @@ output_file_names ()
/* Allocate the various arrays we need. */
files = (struct file_info *) alloca (line_file_table.in_use
* sizeof (struct file_info));
- dirs = (struct dir_info *) alloca (line_file_table.in_use
+ dirs = (struct dir_info *) alloca (line_file_table.in_use * 2
* sizeof (struct dir_info));
/* Sort the file names. */
@@ -6567,6 +6597,8 @@ output_file_names ()
else
{
int j;
+ int max_idx;
+ int max_len;
/* This is a new directory. */
dirs[ndirs].path = files[i].path;
@@ -6578,12 +6610,44 @@ output_file_names ()
files[i].dir_idx = ndirs;
/* Search for a prefix. */
- dirs[ndirs].prefix = -1;
+ max_len = 0;
+ max_idx = 0;
for (j = 0; j < ndirs; ++j)
- if (dirs[j].length < dirs[ndirs].length
- && dirs[j].length != 0
- && memcmp (dirs[j].path, dirs[ndirs].path, dirs[j].length) == 0)
- dirs[ndirs].prefix = j;
+ if (dirs[j].length > max_len)
+ {
+ int this_len = prefix_of (&dirs[j], &dirs[ndirs]);
+
+ if (this_len > max_len)
+ {
+ max_len = this_len;
+ max_idx = j;
+ }
+ }
+
+ /* Remember the prefix. If this is a known prefix simply
+ remember the index. Otherwise we will have to create an
+ artificial entry. */
+ if (max_len == dirs[max_idx].length)
+ /* This is our prefix. */
+ dirs[ndirs].prefix = max_idx;
+ else
+ {
+ /* Create an entry without associated file. Since we have
+ to keep the dirs array sorted (means, entries with paths
+ which come first) we have to move the new entry in the
+ place of the old one. */
+ dirs[++ndirs] = dirs[max_idx];
+
+ /* We don't have to set .path. */
+ dirs[max_idx].length = max_len;
+ dirs[max_idx].nbytes = 0;
+ dirs[max_idx].count = 0;
+ dirs[max_idx].dir_idx = ndirs;
+ dirs[max_idx].used = 0;
+ dirs[max_idx].prefix = dirs[ndirs].prefix;
+
+ dirs[ndirs - 1].prefix = dirs[ndirs].prefix = max_idx;
+ }
++ndirs;
}
@@ -6671,7 +6735,7 @@ output_file_names ()
confuse these indices with the one for the constructed table
(even though most of the time they are identical). */
idx = 1;
- idx_offset = dirs[0].path[0] == '/' ? 1 : 0;
+ idx_offset = dirs[0].length > 0 ? 1 : 0;
for (i = 1 - idx_offset; i < ndirs; ++i)
if (dirs[i].used != 0)
{