Skip to content

Commit 28f1752

Browse files
author
dmalcolm
committed
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@223163 138bc75d-0d04-0410-961f-82ee72b054a4
1 parent 8cb30e1 commit 28f1752

File tree

8 files changed

+471
-1
lines changed

8 files changed

+471
-1
lines changed

gcc/ChangeLog

+13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
2015-05-13 David Malcolm <[email protected]>
2+
3+
* common.opt (fdump-internal-locations): New option.
4+
* input.c: Include diagnostic-core.h.
5+
(get_end_location): New function.
6+
(write_digit): New function.
7+
(write_digit_row): New function.
8+
(dump_location_range): New function.
9+
(dump_labelled_location_range): New function.
10+
(dump_location_info): New function.
11+
* input.h (dump_location_info): New prototype.
12+
* toplev.c (compile_file): Handle flag_dump_locations.
13+
114
2015-05-13 Eric Botcazou <[email protected]>
215

316
* gimple-expr.h (is_gimple_constant): Reorder.

gcc/common.opt

+4
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,10 @@ Common Driver Var(flag_report_bug)
11661166
Collect and dump debug information into temporary file if ICE in C/C++
11671167
compiler occured.
11681168

1169+
fdump-internal-locations
1170+
Common Var(flag_dump_locations) Init(0)
1171+
Dump detailed information on GCC's internal representation of source code locations
1172+
11691173
fdump-passes
11701174
Common Var(flag_dump_passes) Init(0)
11711175
Dump optimization passes

gcc/input.c

+224
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
2323
#include "intl.h"
2424
#include "input.h"
2525
#include "vec.h"
26+
#include "diagnostic-core.h"
2627

2728
/* This is a cache used by get_next_line to store the content of a
2829
file to be searched for file lines. */
@@ -869,3 +870,226 @@ dump_line_table_statistics (void)
869870
STAT_LABEL (total_used_map_size));
870871
fprintf (stderr, "\n");
871872
}
873+
874+
/* Get location one beyond the final location in ordinary map IDX. */
875+
876+
static source_location
877+
get_end_location (struct line_maps *set, unsigned int idx)
878+
{
879+
if (idx == LINEMAPS_ORDINARY_USED (set) - 1)
880+
return set->highest_location;
881+
882+
struct line_map *next_map = LINEMAPS_ORDINARY_MAP_AT (set, idx + 1);
883+
return MAP_START_LOCATION (next_map);
884+
}
885+
886+
/* Helper function for write_digit_row. */
887+
888+
static void
889+
write_digit (FILE *stream, int digit)
890+
{
891+
fputc ('0' + (digit % 10), stream);
892+
}
893+
894+
/* Helper function for dump_location_info.
895+
Write a row of numbers to STREAM, numbering a source line,
896+
giving the units, tens, hundreds etc of the column number. */
897+
898+
static void
899+
write_digit_row (FILE *stream, int indent,
900+
source_location loc, int max_col, int divisor)
901+
{
902+
fprintf (stream, "%*c", indent, ' ');
903+
fprintf (stream, "|");
904+
for (int column = 1; column < max_col; column++)
905+
{
906+
source_location column_loc = loc + column;
907+
write_digit (stream, column_loc / divisor);
908+
}
909+
fprintf (stream, "\n");
910+
}
911+
912+
/* Write a half-closed (START) / half-open (END) interval of
913+
source_location to STREAM. */
914+
915+
static void
916+
dump_location_range (FILE *stream,
917+
source_location start, source_location end)
918+
{
919+
fprintf (stream,
920+
" source_location interval: %u <= loc < %u\n",
921+
start, end);
922+
}
923+
924+
/* Write a labelled description of a half-closed (START) / half-open (END)
925+
interval of source_location to STREAM. */
926+
927+
static void
928+
dump_labelled_location_range (FILE *stream,
929+
const char *name,
930+
source_location start, source_location end)
931+
{
932+
fprintf (stream, "%s\n", name);
933+
dump_location_range (stream, start, end);
934+
fprintf (stream, "\n");
935+
}
936+
937+
/* Write a visualization of the locations in the line_table to STREAM. */
938+
939+
void
940+
dump_location_info (FILE *stream)
941+
{
942+
/* Visualize the reserved locations. */
943+
dump_labelled_location_range (stream, "RESERVED LOCATIONS",
944+
0, RESERVED_LOCATION_COUNT);
945+
946+
/* Visualize the ordinary line_map instances, rendering the sources. */
947+
for (unsigned int idx = 0; idx < LINEMAPS_ORDINARY_USED (line_table); idx++)
948+
{
949+
source_location end_location = get_end_location (line_table, idx);
950+
/* half-closed: doesn't include this one. */
951+
952+
struct line_map *map = LINEMAPS_ORDINARY_MAP_AT (line_table, idx);
953+
fprintf (stream, "ORDINARY MAP: %i\n", idx);
954+
dump_location_range (stream,
955+
MAP_START_LOCATION (map), end_location);
956+
fprintf (stream, " file: %s\n", ORDINARY_MAP_FILE_NAME (map));
957+
fprintf (stream, " starting at line: %i\n",
958+
ORDINARY_MAP_STARTING_LINE_NUMBER (map));
959+
fprintf (stream, " column bits: %i\n",
960+
ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map));
961+
962+
/* Render the span of source lines that this "map" covers. */
963+
for (source_location loc = MAP_START_LOCATION (map);
964+
loc < end_location;
965+
loc++)
966+
{
967+
expanded_location exploc
968+
= linemap_expand_location (line_table, map, loc);
969+
970+
if (0 == exploc.column)
971+
{
972+
/* Beginning of a new source line: draw the line. */
973+
974+
int line_size;
975+
const char *line_text = location_get_source_line (exploc, &line_size);
976+
if (!line_text)
977+
break;
978+
fprintf (stream,
979+
"%s:%3i|loc:%5i|%.*s\n",
980+
exploc.file, exploc.line,
981+
loc,
982+
line_size, line_text);
983+
984+
/* "loc" is at column 0, which means "the whole line".
985+
Render the locations *within* the line, by underlining
986+
it, showing the source_location numeric values
987+
at each column. */
988+
int max_col
989+
= (1 << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map)) - 1;
990+
if (max_col > line_size)
991+
max_col = line_size + 1;
992+
993+
int indent = 14 + strlen (exploc.file);
994+
995+
/* Thousands. */
996+
if (end_location > 999)
997+
write_digit_row (stream, indent, loc, max_col, 1000);
998+
999+
/* Hundreds. */
1000+
if (end_location > 99)
1001+
write_digit_row (stream, indent, loc, max_col, 100);
1002+
1003+
/* Tens. */
1004+
write_digit_row (stream, indent, loc, max_col, 10);
1005+
1006+
/* Units. */
1007+
write_digit_row (stream, indent, loc, max_col, 1);
1008+
}
1009+
}
1010+
fprintf (stream, "\n");
1011+
}
1012+
1013+
/* Visualize unallocated values. */
1014+
dump_labelled_location_range (stream, "UNALLOCATED LOCATIONS",
1015+
line_table->highest_location,
1016+
LINEMAPS_MACRO_LOWEST_LOCATION (line_table));
1017+
1018+
/* Visualize the macro line_map instances, rendering the sources. */
1019+
for (unsigned int i = 0; i < LINEMAPS_MACRO_USED (line_table); i++)
1020+
{
1021+
/* Each macro map that is allocated owns source_location values
1022+
that are *lower* that the one before them.
1023+
Hence it's meaningful to view them either in order of ascending
1024+
source locations, or in order of ascending macro map index. */
1025+
const bool ascending_source_locations = true;
1026+
unsigned int idx = (ascending_source_locations
1027+
? (LINEMAPS_MACRO_USED (line_table) - (i + 1))
1028+
: i);
1029+
struct line_map *map = LINEMAPS_MACRO_MAP_AT (line_table, idx);
1030+
fprintf (stream, "MACRO %i: %s (%u tokens)\n",
1031+
idx,
1032+
linemap_map_get_macro_name (map),
1033+
MACRO_MAP_NUM_MACRO_TOKENS (map));
1034+
dump_location_range (stream,
1035+
map->start_location,
1036+
(map->start_location
1037+
+ MACRO_MAP_NUM_MACRO_TOKENS (map)));
1038+
inform (MACRO_MAP_EXPANSION_POINT_LOCATION (map),
1039+
"expansion point is location %i",
1040+
MACRO_MAP_EXPANSION_POINT_LOCATION (map));
1041+
fprintf (stream, " map->start_location: %u\n",
1042+
map->start_location);
1043+
1044+
fprintf (stream, " macro_locations:\n");
1045+
for (unsigned int i = 0; i < MACRO_MAP_NUM_MACRO_TOKENS (map); i++)
1046+
{
1047+
source_location x = MACRO_MAP_LOCATIONS (map)[2 * i];
1048+
source_location y = MACRO_MAP_LOCATIONS (map)[(2 * i) + 1];
1049+
1050+
/* linemap_add_macro_token encodes token numbers in an expansion
1051+
by putting them after MAP_START_LOCATION. */
1052+
1053+
/* I'm typically seeing 4 uninitialized entries at the end of
1054+
0xafafafaf.
1055+
This appears to be due to macro.c:replace_args
1056+
adding 2 extra args for padding tokens; presumably there may
1057+
be a leading and/or trailing padding token injected,
1058+
each for 2 more location slots.
1059+
This would explain there being up to 4 source_locations slots
1060+
that may be uninitialized. */
1061+
1062+
fprintf (stream, " %u: %u, %u\n",
1063+
i,
1064+
x,
1065+
y);
1066+
if (x == y)
1067+
{
1068+
if (x < MAP_START_LOCATION (map))
1069+
inform (x, "token %u has x-location == y-location == %u", i, x);
1070+
else
1071+
fprintf (stream,
1072+
"x-location == y-location == %u encodes token # %u\n",
1073+
x, x - MAP_START_LOCATION (map));
1074+
}
1075+
else
1076+
{
1077+
inform (x, "token %u has x-location == %u", i, x);
1078+
inform (x, "token %u has y-location == %u", i, y);
1079+
}
1080+
}
1081+
fprintf (stream, "\n");
1082+
}
1083+
1084+
/* It appears that MAX_SOURCE_LOCATION itself is never assigned to a
1085+
macro map, presumably due to an off-by-one error somewhere
1086+
between the logic in linemap_enter_macro and
1087+
LINEMAPS_MACRO_LOWEST_LOCATION. */
1088+
dump_labelled_location_range (stream, "MAX_SOURCE_LOCATION",
1089+
MAX_SOURCE_LOCATION,
1090+
MAX_SOURCE_LOCATION + 1);
1091+
1092+
/* Visualize ad-hoc values. */
1093+
dump_labelled_location_range (stream, "AD-HOC LOCATIONS",
1094+
MAX_SOURCE_LOCATION + 1, UINT_MAX);
1095+
}

gcc/input.h

+2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ extern location_t input_location;
7777

7878
void dump_line_table_statistics (void);
7979

80+
void dump_location_info (FILE *stream);
81+
8082
void diagnostics_file_cache_fini (void);
8183

8284
#endif

gcc/toplev.c

+3
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,9 @@ compile_file (void)
593593
timevar_pop (TV_PARSE_GLOBAL);
594594
timevar_stop (TV_PHASE_PARSING);
595595

596+
if (flag_dump_locations)
597+
dump_location_info (stderr);
598+
596599
/* Compilation is now finished except for writing
597600
what's left of the symbol table output. */
598601

libcpp/ChangeLog

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
2015-05-13 David Malcolm <[email protected]>
2+
3+
* include/line-map.h (source_location): Add a reference to
4+
location-example.txt to the descriptive comment.
5+
* location-example.txt: New file.
6+
17
2015-05-13 David Malcolm <[email protected]>
28

39
* include/line-map.h (MAX_SOURCE_LOCATION): Convert from a macro

libcpp/include/line-map.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ typedef unsigned int linenum_type;
113113
... | |
114114
0xffffffff | UINT_MAX |
115115
-----------+-------------------------------+-------------------------------
116-
. */
116+
117+
To see how this works in practice, see the worked example in
118+
libcpp/location-example.txt. */
117119
typedef unsigned int source_location;
118120

119121
/* Memory allocation function typedef. Works like xrealloc. */

0 commit comments

Comments
 (0)