DWARF sort longer dirs before shorter ones in directory table.

Message ID 1523864057-7701-1-git-send-email-mark@klomp.org
State New
Headers show
Series
  • DWARF sort longer dirs before shorter ones in directory table.
Related show

Commit Message

Mark Wielaard April 16, 2018, 7:34 a.m.
When gcc dwarf2out generates the .debug_line table itself (for example
when generating one for a split DWARF .dwo) it uses natural sorting for
the directory table. Longer directory paths come before shorter directory
paths with the same prefix. This causes the files in the line table to
pick the shorter dir. Creating slightly ineffecient line tables because
the longer directory paths will never be used.

Fix this by changing file_info_cmp () to pick longer directory prefixes
before shorter ones. We still sort files (the compilation unit) without
any directory path before all entries with a directory path, so they
will still use dir entry 0 (the working directory).

A hello.c program would get the following dir and line table before:

Directory table:
 /opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/8.0.1/include
 /usr/include
 /usr/include/bits

File name table:
 Entry Dir   Time      Size      Name
 1     0     0         0         hello.c
 2     1     0         0         stddef.h
 3     2     0         0         bits/types.h
 4     2     0         0         libio.h
 5     2     0         0         stdio.h
 6     2     0         0         bits/sys_errlist.h

Note that the last directory table entry is never used.
After this patch it looks as follows:

Directory table:
 /opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/8.0.1/include
 /usr/include/bits
 /usr/include

File name table:
 Entry Dir   Time      Size      Name
 1     0     0         0         hello.c
 2     1     0         0         stddef.h
 3     2     0         0         types.h
 4     3     0         0         libio.h
 5     3     0         0         stdio.h
 6     2     0         0         sys_errlist.h

Which is similar to what gas would output.

gcc/ChangeLog:

	* dwarf2out.c (file_info_cmp): Sort longer dir prefixes before
	shorter ones.
---

Comments

Jakub Jelinek April 16, 2018, 7:41 a.m. | #1
On Mon, Apr 16, 2018 at 09:34:17AM +0200, Mark Wielaard wrote:
> gcc/ChangeLog:
> 
> 	* dwarf2out.c (file_info_cmp): Sort longer dir prefixes before
> 	shorter ones.

Ok, thanks.

	Jakub
Mark Wielaard April 25, 2018, 5:34 p.m. | #2
On Mon, 2018-04-16 at 09:41 +0200, Jakub Jelinek wrote:
> On Mon, Apr 16, 2018 at 09:34:17AM +0200, Mark Wielaard wrote:
> > gcc/ChangeLog:
> > 
> > 	* dwarf2out.c (file_info_cmp): Sort longer dir prefixes before
> > 	shorter ones.
> 
> Ok, thanks.

Pushed now that trunk is in stage 1 again.

Cheers,

Mark

Patch

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 620e669..d3d925d 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -11955,7 +11955,9 @@  file_info_cmp (const void *p1, const void *p2)
      we return consistent values to qsort since some will get confused if
      we return the same value when identical operands are passed in opposite
      orders.  So if neither has a directory, return 0 and otherwise return
-     1 or -1 depending on which one has the directory.  */
+     1 or -1 depending on which one has the directory.  We want the one with
+     the directory to sort after the one without, so all no directory files
+     are at the start (normally only the compilation unit file).  */
   if ((s1->path == s1->fname || s2->path == s2->fname))
     return (s2->path == s2->fname) - (s1->path == s1->fname);
 
@@ -11966,11 +11968,12 @@  file_info_cmp (const void *p1, const void *p2)
     {
       ++cp1;
       ++cp2;
-      /* Reached the end of the first path?  If so, handle like above.  */
+      /* Reached the end of the first path?  If so, handle like above,
+	 but now we want longer directory prefixes before shorter ones.  */
       if ((cp1 == (const unsigned char *) s1->fname)
 	  || (cp2 == (const unsigned char *) s2->fname))
-	return ((cp2 == (const unsigned char *) s2->fname)
-		- (cp1 == (const unsigned char *) s1->fname));
+	return ((cp1 == (const unsigned char *) s1->fname)
+		- (cp2 == (const unsigned char *) s2->fname));
 
       /* Character of current path component the same?  */
       else if (*cp1 != *cp2)