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
This commit is contained in:
David Malcolm 2015-05-13 13:58:18 +00:00 committed by David Malcolm
parent 49d50b6b8f
commit ba4ad400f1
8 changed files with 471 additions and 1 deletions

View 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.

View 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

View 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);
}

View 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

View 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. */

View 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

View 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. */

216
libcpp/location-example.txt Normal file
View File

@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^