aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2015-05-13 13:58:18 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2015-05-13 13:58:18 +0000
commitba4ad400f1e4f726adb431aedea3c0ddf1e3315a (patch)
tree263b351fcddaa726d296fc21e6f1f001c2221d5e
parent49d50b6b8f727b681410a1865aadd915a14df2a5 (diff)
downloadgcc-ba4ad400f1e4f726adb431aedea3c0ddf1e3315a.zip
gcc-ba4ad400f1e4f726adb431aedea3c0ddf1e3315a.tar.gz
gcc-ba4ad400f1e4f726adb431aedea3c0ddf1e3315a.tar.bz2
libcpp/input.c: Add a way to visualize the linemaps (-fdump-internal-locations)
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
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/common.opt4
-rw-r--r--gcc/input.c224
-rw-r--r--gcc/input.h2
-rw-r--r--gcc/toplev.c3
-rw-r--r--libcpp/ChangeLog6
-rw-r--r--libcpp/include/line-map.h4
-rw-r--r--libcpp/location-example.txt216
8 files changed, 471 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f85bbae..ada1757 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/common.opt b/gcc/common.opt
index 6753fd3..859488f 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -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
diff --git a/gcc/input.c b/gcc/input.c
index 18c1e50..d633b76 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -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);
+}
diff --git a/gcc/input.h b/gcc/input.h
index 93eb6ed..5ba4d3b 100644
--- a/gcc/input.h
+++ b/gcc/input.h
@@ -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
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 9b1151b..3c1ba38 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -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. */
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 229ffd3..32582dd 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,5 +1,11 @@
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
to a const source_location.
(RESERVED_LOCATION_COUNT): Likewise.
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index 86a33f1..27aa094 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -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
index 0000000..a5f95b2
--- /dev/null
+++ b/libcpp/location-example.txt
@@ -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
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^