libcpp/input.c: Add a way to visualize the linemaps (-fdump-internal-locations)
authorDavid Malcolm <dmalcolm@redhat.com>
Wed, 13 May 2015 13:58:18 +0000 (13:58 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Wed, 13 May 2015 13:58:18 +0000 (13:58 +0000)
gcc/ChangeLog:
* common.opt (fdump-internal-locations): New option.
* input.c: Include diagnostic-core.h.
(get_end_location): New function.
(write_digit): New function.
(write_digit_row): New function.
(dump_location_range): New function.
(dump_labelled_location_range): New function.
(dump_location_info): New function.
* input.h (dump_location_info): New prototype.
* toplev.c (compile_file): Handle flag_dump_locations.

libcpp/ChangeLog:
* include/line-map.h (source_location): Add a reference to
location-example.txt to the descriptive comment.
* location-example.txt: New file.

From-SVN: r223163

gcc/ChangeLog
gcc/common.opt
gcc/input.c
gcc/input.h
gcc/toplev.c
libcpp/ChangeLog
libcpp/include/line-map.h
libcpp/location-example.txt [new file with mode: 0644]

index f85bbae4fda1d14d3a38dbd029ae4c22d2db450a..ada1757d34af086ff0573b729a71e470383278c7 100644 (file)
@@ -1,3 +1,16 @@
+2015-05-13  David Malcolm  <dmalcolm@redhat.com>
+
+       * common.opt (fdump-internal-locations): New option.
+       * input.c: Include diagnostic-core.h.
+       (get_end_location): New function.
+       (write_digit): New function.
+       (write_digit_row): New function.
+       (dump_location_range): New function.
+       (dump_labelled_location_range): New function.
+       (dump_location_info): New function.
+       * input.h (dump_location_info): New prototype.
+       * toplev.c (compile_file): Handle flag_dump_locations.
+
 2015-05-13  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gimple-expr.h (is_gimple_constant): Reorder.
index 6753fd31b6225005ca4905b983e5e0a0159465d3..859488f7a1c0dcf225c8722371d3a3cc5d30a887 100644 (file)
@@ -1166,6 +1166,10 @@ Common Driver Var(flag_report_bug)
 Collect and dump debug information into temporary file if ICE in C/C++
 compiler occured.
 
+fdump-internal-locations
+Common Var(flag_dump_locations) Init(0)
+Dump detailed information on GCC's internal representation of source code locations
+
 fdump-passes
 Common Var(flag_dump_passes) Init(0)
 Dump optimization passes
index 18c1e50aa04911c5b0518ad6df477ba90cbd055f..d633b762d756cfc6ac51d8ef61c66e0a47f1e1f1 100644 (file)
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "intl.h"
 #include "input.h"
 #include "vec.h"
+#include "diagnostic-core.h"
 
 /* This is a cache used by get_next_line to store the content of a
    file to be searched for file lines.  */
@@ -869,3 +870,226 @@ dump_line_table_statistics (void)
            STAT_LABEL (total_used_map_size));
   fprintf (stderr, "\n");
 }
+
+/* Get location one beyond the final location in ordinary map IDX.  */
+
+static source_location
+get_end_location (struct line_maps *set, unsigned int idx)
+{
+  if (idx == LINEMAPS_ORDINARY_USED (set) - 1)
+    return set->highest_location;
+
+  struct line_map *next_map = LINEMAPS_ORDINARY_MAP_AT (set, idx + 1);
+  return MAP_START_LOCATION (next_map);
+}
+
+/* Helper function for write_digit_row.  */
+
+static void
+write_digit (FILE *stream, int digit)
+{
+  fputc ('0' + (digit % 10), stream);
+}
+
+/* Helper function for dump_location_info.
+   Write a row of numbers to STREAM, numbering a source line,
+   giving the units, tens, hundreds etc of the column number.  */
+
+static void
+write_digit_row (FILE *stream, int indent,
+                source_location loc, int max_col, int divisor)
+{
+  fprintf (stream, "%*c", indent, ' ');
+  fprintf (stream, "|");
+  for (int column = 1; column < max_col; column++)
+    {
+      source_location column_loc = loc + column;
+      write_digit (stream, column_loc / divisor);
+    }
+  fprintf (stream, "\n");
+}
+
+/* Write a half-closed (START) / half-open (END) interval of
+   source_location to STREAM.  */
+
+static void
+dump_location_range (FILE *stream,
+                    source_location start, source_location end)
+{
+  fprintf (stream,
+          "  source_location interval: %u <= loc < %u\n",
+          start, end);
+}
+
+/* Write a labelled description of a half-closed (START) / half-open (END)
+   interval of source_location to STREAM.  */
+
+static void
+dump_labelled_location_range (FILE *stream,
+                             const char *name,
+                             source_location start, source_location end)
+{
+  fprintf (stream, "%s\n", name);
+  dump_location_range (stream, start, end);
+  fprintf (stream, "\n");
+}
+
+/* Write a visualization of the locations in the line_table to STREAM.  */
+
+void
+dump_location_info (FILE *stream)
+{
+  /* Visualize the reserved locations.  */
+  dump_labelled_location_range (stream, "RESERVED LOCATIONS",
+                               0, RESERVED_LOCATION_COUNT);
+
+  /* Visualize the ordinary line_map instances, rendering the sources. */
+  for (unsigned int idx = 0; idx < LINEMAPS_ORDINARY_USED (line_table); idx++)
+    {
+      source_location end_location = get_end_location (line_table, idx);
+      /* half-closed: doesn't include this one. */
+
+      struct line_map *map = LINEMAPS_ORDINARY_MAP_AT (line_table, idx);
+      fprintf (stream, "ORDINARY MAP: %i\n", idx);
+      dump_location_range (stream,
+                          MAP_START_LOCATION (map), end_location);
+      fprintf (stream, "  file: %s\n", ORDINARY_MAP_FILE_NAME (map));
+      fprintf (stream, "  starting at line: %i\n",
+              ORDINARY_MAP_STARTING_LINE_NUMBER (map));
+      fprintf (stream, "  column bits: %i\n",
+              ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map));
+
+      /* Render the span of source lines that this "map" covers.  */
+      for (source_location loc = MAP_START_LOCATION (map);
+          loc < end_location;
+          loc++)
+       {
+         expanded_location exploc
+           = linemap_expand_location (line_table, map, loc);
+
+         if (0 == exploc.column)
+           {
+             /* Beginning of a new source line: draw the line.  */
+
+             int line_size;
+             const char *line_text = location_get_source_line (exploc, &line_size);
+             if (!line_text)
+               break;
+             fprintf (stream,
+                      "%s:%3i|loc:%5i|%.*s\n",
+                      exploc.file, exploc.line,
+                      loc,
+                      line_size, line_text);
+
+             /* "loc" is at column 0, which means "the whole line".
+                Render the locations *within* the line, by underlining
+                it, showing the source_location numeric values
+                at each column.  */
+             int max_col
+               = (1 << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map)) - 1;
+             if (max_col > line_size)
+               max_col = line_size + 1;
+
+             int indent = 14 + strlen (exploc.file);
+
+             /* Thousands.  */
+             if (end_location > 999)
+               write_digit_row (stream, indent, loc, max_col, 1000);
+
+             /* Hundreds.  */
+             if (end_location > 99)
+               write_digit_row (stream, indent, loc, max_col, 100);
+
+             /* Tens.  */
+             write_digit_row (stream, indent, loc, max_col, 10);
+
+             /* Units.  */
+             write_digit_row (stream, indent, loc, max_col, 1);
+           }
+       }
+      fprintf (stream, "\n");
+    }
+
+  /* Visualize unallocated values.  */
+  dump_labelled_location_range (stream, "UNALLOCATED LOCATIONS",
+                               line_table->highest_location,
+                               LINEMAPS_MACRO_LOWEST_LOCATION (line_table));
+
+  /* Visualize the macro line_map instances, rendering the sources. */
+  for (unsigned int i = 0; i < LINEMAPS_MACRO_USED (line_table); i++)
+    {
+      /* Each macro map that is allocated owns source_location values
+        that are *lower* that the one before them.
+        Hence it's meaningful to view them either in order of ascending
+        source locations, or in order of ascending macro map index.  */
+      const bool ascending_source_locations = true;
+      unsigned int idx = (ascending_source_locations
+                         ? (LINEMAPS_MACRO_USED (line_table) - (i + 1))
+                         : i);
+      struct line_map *map = LINEMAPS_MACRO_MAP_AT (line_table, idx);
+      fprintf (stream, "MACRO %i: %s (%u tokens)\n",
+              idx,
+              linemap_map_get_macro_name (map),
+              MACRO_MAP_NUM_MACRO_TOKENS (map));
+      dump_location_range (stream,
+                          map->start_location,
+                          (map->start_location
+                           + MACRO_MAP_NUM_MACRO_TOKENS (map)));
+      inform (MACRO_MAP_EXPANSION_POINT_LOCATION (map),
+             "expansion point is location %i",
+             MACRO_MAP_EXPANSION_POINT_LOCATION (map));
+      fprintf (stream, "  map->start_location: %u\n",
+              map->start_location);
+
+      fprintf (stream, "  macro_locations:\n");
+      for (unsigned int i = 0; i < MACRO_MAP_NUM_MACRO_TOKENS (map); i++)
+       {
+         source_location x = MACRO_MAP_LOCATIONS (map)[2 * i];
+         source_location y = MACRO_MAP_LOCATIONS (map)[(2 * i) + 1];
+
+         /* linemap_add_macro_token encodes token numbers in an expansion
+            by putting them after MAP_START_LOCATION. */
+
+         /* I'm typically seeing 4 uninitialized entries at the end of
+            0xafafafaf.
+            This appears to be due to macro.c:replace_args
+            adding 2 extra args for padding tokens; presumably there may
+            be a leading and/or trailing padding token injected,
+            each for 2 more location slots.
+            This would explain there being up to 4 source_locations slots
+            that may be uninitialized.  */
+
+         fprintf (stream, "    %u: %u, %u\n",
+                  i,
+                  x,
+                  y);
+         if (x == y)
+           {
+             if (x < MAP_START_LOCATION (map))
+               inform (x, "token %u has x-location == y-location == %u", i, x);
+             else
+               fprintf (stream,
+                        "x-location == y-location == %u encodes token # %u\n",
+                        x, x - MAP_START_LOCATION (map));
+               }
+         else
+           {
+             inform (x, "token %u has x-location == %u", i, x);
+             inform (x, "token %u has y-location == %u", i, y);
+           }
+       }
+      fprintf (stream, "\n");
+    }
+
+  /* It appears that MAX_SOURCE_LOCATION itself is never assigned to a
+     macro map, presumably due to an off-by-one error somewhere
+     between the logic in linemap_enter_macro and
+     LINEMAPS_MACRO_LOWEST_LOCATION.  */
+  dump_labelled_location_range (stream, "MAX_SOURCE_LOCATION",
+                               MAX_SOURCE_LOCATION,
+                               MAX_SOURCE_LOCATION + 1);
+
+  /* Visualize ad-hoc values.  */
+  dump_labelled_location_range (stream, "AD-HOC LOCATIONS",
+                               MAX_SOURCE_LOCATION + 1, UINT_MAX);
+}
index 93eb6ed4c32036c2127eaac04f9a6cf6b4b6a246..5ba4d3b46f53f6ec8ec513ceecb0606aa8bae1e9 100644 (file)
@@ -77,6 +77,8 @@ extern location_t input_location;
 
 void dump_line_table_statistics (void);
 
+void dump_location_info (FILE *stream);
+
 void diagnostics_file_cache_fini (void);
 
 #endif
index 9b1151b01869f72ebf1b6b5039bbe989cb5eeb01..3c1ba38d9c2f23574dd24202bcae7198f2274948 100644 (file)
@@ -593,6 +593,9 @@ compile_file (void)
   timevar_pop (TV_PARSE_GLOBAL);
   timevar_stop (TV_PHASE_PARSING);
 
+  if (flag_dump_locations)
+    dump_location_info (stderr);
+
   /* Compilation is now finished except for writing
      what's left of the symbol table output.  */
 
index 229ffd33f039e7492986fe088422dfb767aa1f5d..32582ddeada8346ad3c8df13df89f41b6744d94c 100644 (file)
@@ -1,3 +1,9 @@
+2015-05-13  David Malcolm  <dmalcolm@redhat.com>
+
+       * include/line-map.h (source_location): Add a reference to
+       location-example.txt to the descriptive comment.
+       * location-example.txt: New file.
+
 2015-05-13  David Malcolm  <dmalcolm@redhat.com>
 
        * include/line-map.h (MAX_SOURCE_LOCATION): Convert from a macro
index 86a33f1638bfe25e89c3e783bfd4f2867d61b671..27aa094c99776fa2a3e2be3f6bfec0360f8c06ae 100644 (file)
@@ -113,7 +113,9 @@ typedef unsigned int linenum_type;
   ...        |                               |
   0xffffffff | UINT_MAX                      |
   -----------+-------------------------------+-------------------------------
-  .  */
+
+  To see how this works in practice, see the worked example in
+  libcpp/location-example.txt.  */
 typedef unsigned int source_location;
 
 /* Memory allocation function typedef.  Works like xrealloc.  */
diff --git a/libcpp/location-example.txt b/libcpp/location-example.txt
new file mode 100644 (file)
index 0000000..a5f95b2
--- /dev/null
@@ -0,0 +1,216 @@
+Consider compiling test.c, with this content:
+VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
+#include "test.h"
+
+int
+main (int argc, char **argv)
+{
+  int a = PLUS (1,2);
+  int b = PLUS (3,4);
+  return 0;
+}
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+...where test.h has this content:
+VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
+extern int foo ();
+
+#define PLUS(A, B) A + B
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+The undocumented -fdump-internal-locations option outputs this information
+to stderr, showing what each source_location value means.  Source code
+lines are quoted, showing both per-line source_location values and
+per-line&column source_location values (written vertically under the
+corresponding character of source code).
+
+VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
+RESERVED LOCATIONS
+  source_location interval: 0 <= loc < 2
+
+ORDINARY MAP: 0
+  source_location interval: 2 <= loc < 3
+  file: test.c
+  starting at line: 1
+  column bits: 7
+test.c:  1|loc:    2|#include "test.h"
+                    |00000001111111111
+                    |34567890123456789
+
+ORDINARY MAP: 1
+  source_location interval: 3 <= loc < 4
+  file: <built-in>
+  starting at line: 0
+  column bits: 0
+
+ORDINARY MAP: 2
+  source_location interval: 4 <= loc < 5
+  file: <command-line>
+  starting at line: 0
+  column bits: 0
+
+ORDINARY MAP: 3
+  source_location interval: 5 <= loc < 5005
+  file: /usr/include/stdc-predef.h
+  starting at line: 1
+  column bits: 7
+(contents of /usr/include/stdc-predef.h snipped for brevity)
+
+ORDINARY MAP: 4
+  source_location interval: 5005 <= loc < 5006
+  file: <command-line>
+  starting at line: 1
+  column bits: 7
+
+ORDINARY MAP: 5
+  source_location interval: 5006 <= loc < 5134
+  file: test.c
+  starting at line: 1
+  column bits: 7
+test.c:  1|loc: 5006|#include "test.h"
+                    |55555555555555555
+                    |00000000000000000
+                    |00011111111112222
+                    |78901234567890123
+
+ORDINARY MAP: 6
+  source_location interval: 5134 <= loc < 5416
+  file: test.h
+  starting at line: 1
+  column bits: 7
+test.h:  1|loc: 5134|extern int foo ();
+                    |555555555555555555
+                    |111111111111111111
+                    |333334444444444555
+                    |567890123456789012
+test.h:  2|loc: 5262|
+                    |
+                    |
+                    |
+                    |
+test.h:  3|loc: 5390|#define PLUS(A, B) A + B
+                    |555555555555555555555555
+                    |333333333444444444444444
+                    |999999999000000000011111
+                    |123456789012345678901234
+
+ORDINARY MAP: 7
+  source_location interval: 5416 <= loc < 6314
+  file: test.c
+  starting at line: 2
+  column bits: 7
+test.c:  2|loc: 5416|
+                    |
+                    |
+                    |
+                    |
+test.c:  3|loc: 5544|int
+                    |555
+                    |555
+                    |444
+                    |567
+test.c:  4|loc: 5672|main (int argc, char **argv)
+                    |5555555555555555555555555555
+                    |6666666666666666666666666667
+                    |7777777888888888899999999990
+                    |3456789012345678901234567890
+test.c:  5|loc: 5800|{
+                    |5
+                    |8
+                    |0
+                    |1
+test.c:  6|loc: 5928|  int a = PLUS (1,2);
+                    |555555555555555555555
+                    |999999999999999999999
+                    |233333333334444444444
+                    |901234567890123456789
+test.c:  7|loc: 6056|  int b = PLUS (3,4);
+                    |666666666666666666666
+                    |000000000000000000000
+                    |555666666666677777777
+                    |789012345678901234567
+test.c:  8|loc: 6184|  return 0;
+                    |66666666666
+                    |11111111111
+                    |88888999999
+                    |56789012345
+test.c:  9|loc: 6312|}
+                    |6
+                    |3
+                    |1
+                    |3
+
+UNALLOCATED LOCATIONS
+  source_location interval: 6314 <= loc < 2147483633
+
+MACRO 1: PLUS (7 tokens)
+  source_location interval: 2147483633 <= loc < 2147483640
+test.c:7:11: note: expansion point is location 6067
+   int b = PLUS (3,4);
+           ^
+  map->start_location: 2147483633
+  macro_locations:
+    0: 6073, 5410
+test.c:7:17: note: token 0 has x-location == 6073
+   int b = PLUS (3,4);
+                 ^
+test.c:7:17: note: token 0 has y-location == 5410
+    1: 5412, 5412
+In file included from test.c:1:0:
+test.h:3:22: note: token 1 has x-location == y-location == 5412
+ #define PLUS(A, B) A + B
+                      ^
+    2: 6075, 5414
+test.c:7:19: note: token 2 has x-location == 6075
+   int b = PLUS (3,4);
+                   ^
+test.c:7:19: note: token 2 has y-location == 5414
+    3: 0, 2947526575
+cc1: note: token 3 has x-location == 0
+cc1: note: token 3 has y-location == 2947526575
+    4: 2947526575, 2947526575
+x-location == y-location == 2947526575 encodes token # 800042942
+    5: 2947526575, 2947526575
+x-location == y-location == 2947526575 encodes token # 800042942
+    6: 2947526575, 2947526575
+x-location == y-location == 2947526575 encodes token # 800042942
+
+MACRO 0: PLUS (7 tokens)
+  source_location interval: 2147483640 <= loc < 2147483647
+test.c:6:11: note: expansion point is location 5939
+   int a = PLUS (1,2);
+           ^
+  map->start_location: 2147483640
+  macro_locations:
+    0: 5945, 5410
+test.c:6:17: note: token 0 has x-location == 5945
+   int a = PLUS (1,2);
+                 ^
+test.c:6:17: note: token 0 has y-location == 5410
+    1: 5412, 5412
+In file included from test.c:1:0:
+test.h:3:22: note: token 1 has x-location == y-location == 5412
+ #define PLUS(A, B) A + B
+                      ^
+    2: 5947, 5414
+test.c:6:19: note: token 2 has x-location == 5947
+   int a = PLUS (1,2);
+                   ^
+test.c:6:19: note: token 2 has y-location == 5414
+    3: 0, 2947526575
+cc1: note: token 3 has x-location == 0
+cc1: note: token 3 has y-location == 2947526575
+    4: 2947526575, 2947526575
+x-location == y-location == 2947526575 encodes token # 800042935
+    5: 2947526575, 2947526575
+x-location == y-location == 2947526575 encodes token # 800042935
+    6: 2947526575, 2947526575
+x-location == y-location == 2947526575 encodes token # 800042935
+
+MAX_SOURCE_LOCATION
+  source_location interval: 2147483647 <= loc < 2147483648
+
+AD-HOC LOCATIONS
+  source_location interval: 2147483648 <= loc < 4294967295
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^