This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

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)
       {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]