aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-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
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. */