diff options
author | David Malcolm <dmalcolm@redhat.com> | 2015-05-13 13:58:18 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2015-05-13 13:58:18 +0000 |
commit | ba4ad400f1e4f726adb431aedea3c0ddf1e3315a (patch) | |
tree | 263b351fcddaa726d296fc21e6f1f001c2221d5e /gcc | |
parent | 49d50b6b8f727b681410a1865aadd915a14df2a5 (diff) | |
download | gcc-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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/common.opt | 4 | ||||
-rw-r--r-- | gcc/input.c | 224 | ||||
-rw-r--r-- | gcc/input.h | 2 | ||||
-rw-r--r-- | gcc/toplev.c | 3 |
5 files changed, 246 insertions, 0 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. */ |