From ba4ad400f1e4f726adb431aedea3c0ddf1e3315a Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 13 May 2015 13:58:18 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 13 +++ gcc/common.opt | 4 + gcc/input.c | 224 ++++++++++++++++++++++++++++++++++++ gcc/input.h | 2 + gcc/toplev.c | 3 + libcpp/ChangeLog | 6 + libcpp/include/line-map.h | 4 +- libcpp/location-example.txt | 216 ++++++++++++++++++++++++++++++++++ 8 files changed, 471 insertions(+), 1 deletion(-) create mode 100644 libcpp/location-example.txt diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f85bbae4fda..ada1757d34a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2015-05-13 David Malcolm + + * 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 * gimple-expr.h (is_gimple_constant): Reorder. diff --git a/gcc/common.opt b/gcc/common.opt index 6753fd31b62..859488f7a1c 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 18c1e50aa04..d633b762d75 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 93eb6ed4c32..5ba4d3b46f5 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 9b1151b0186..3c1ba38d9c2 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 229ffd33f03..32582ddeada 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,9 @@ +2015-05-13 David Malcolm + + * 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 * include/line-map.h (MAX_SOURCE_LOCATION): Convert from a macro diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index 86a33f1638b..27aa094c997 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 00000000000..a5f95b2baf8 --- /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: + starting at line: 0 + column bits: 0 + +ORDINARY MAP: 2 + source_location interval: 4 <= loc < 5 + file: + 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: + 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 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- 2.30.2