preprocessor: module line maps

This patch adds LC_MODULE as a map kind, used to indicate a c++
module.  Unlike a regular source file, it only contains a single
location, and the source locations in that module are represented by
ordinary locations whose 'included_from' location is the module.

It also exposes some entry points that modules will use to create
blocks of line maps.

In the original posting, I'd missed the deletion of the
linemap_enter_macro from internal.h.  That's included here.

	libcpp/
	* include/line-map.h (enum lc_reason): Add LC_MODULE.
	(MAP_MODULE_P): New.
	(line_map_new_raw): Declare.
	(linemap_enter_macro): Move declaration from internal.h
	(linemap_module_loc, linemap_module_reparent)
	(linemap_module_restore): Declare.
	(linemap_lookup_macro_indec): Declare.
	* internal.h (linemap_enter_macro): Moved to line-map.h.
	* line-map.c (linemap_new_raw): New, broken out of ...
	(new_linemap): ... here.  Call it.
	(LAST_SOURCE_LINE_LOCATION): New.
	(liemap_module_loc, linemap_module_reparent)
	(linemap_module_restore): New.
	(linemap_lookup_macro_index): New, broken out of ...
	(linemap_macro_map_lookup): ... here.  Call it.
	(linemap_dump): Add module dump.
This commit is contained in:
Nathan Sidwell 2020-11-17 08:01:50 -08:00
parent 6b91b3e9df
commit 1f8ac75991
3 changed files with 150 additions and 41 deletions

View File

@ -72,6 +72,7 @@ enum lc_reason
LC_RENAME, /* Other reason for name change. */
LC_RENAME_VERBATIM, /* Likewise, but "" != stdin. */
LC_ENTER_MACRO, /* Begin macro expansion. */
LC_MODULE, /* A (C++) Module. */
/* FIXME: add support for stringize and paste. */
LC_HWM /* High Water Mark. */
};
@ -439,7 +440,8 @@ struct GTY((tag ("1"))) line_map_ordinary : public line_map {
/* Location from whence this line map was included. For regular
#includes, this location will be the last location of a map. For
outermost file, this is 0. */
outermost file, this is 0. For modules it could be anywhere
within a map. */
location_t included_from;
/* Size is 20 or 24 bytes, no padding */
@ -662,6 +664,15 @@ ORDINARY_MAP_IN_SYSTEM_HEADER_P (const line_map_ordinary *ord_map)
return ord_map->sysp;
}
/* TRUE if this line map is for a module (not a source file). */
inline bool
MAP_MODULE_P (const line_map *map)
{
return (MAP_ORDINARY_P (map)
&& linemap_check_ordinary (map)->reason == LC_MODULE);
}
/* Get the filename of ordinary map MAP. */
inline const char *
@ -1076,6 +1087,9 @@ extern void linemap_check_files_exited (class line_maps *);
extern location_t linemap_line_start
(class line_maps *set, linenum_type to_line, unsigned int max_column_hint);
/* Allocate a raw block of line maps, zero initialized. */
extern line_map *line_map_new_raw (line_maps *, bool, unsigned);
/* Add a mapping of logical source line to physical source file and
line number. This function creates an "ordinary map", which is a
map that records locations of tokens that are not part of macro
@ -1093,6 +1107,39 @@ extern const line_map *linemap_add
(class line_maps *, enum lc_reason, unsigned int sysp,
const char *to_file, linenum_type to_line);
/* Create a macro map. A macro map encodes source locations of tokens
that are part of a macro replacement-list, at a macro expansion
point. See the extensive comments of struct line_map and struct
line_map_macro, in line-map.h.
This map shall be created when the macro is expanded. The map
encodes the source location of the expansion point of the macro as
well as the "original" source location of each token that is part
of the macro replacement-list. If a macro is defined but never
expanded, it has no macro map. SET is the set of maps the macro
map should be part of. MACRO_NODE is the macro which the new macro
map should encode source locations for. EXPANSION is the location
of the expansion point of MACRO. For function-like macros
invocations, it's best to make it point to the closing parenthesis
of the macro, rather than the the location of the first character
of the macro. NUM_TOKENS is the number of tokens that are part of
the replacement-list of MACRO. */
const line_map_macro *linemap_enter_macro (line_maps *, cpp_hashnode *,
location_t, unsigned int);
/* Create a source location for a module. The creator must either do
this after the TU is tokenized, or deal with saving and restoring
map state. */
extern location_t linemap_module_loc
(line_maps *, location_t from, const char *name);
extern void linemap_module_reparent
(line_maps *, location_t loc, location_t new_parent);
/* Restore the linemap state such that the map at LWM-1 continues. */
extern void linemap_module_restore
(line_maps *, unsigned lwm);
/* Given a logical source location, returns the map which the
corresponding (source file, line, column) triplet can be deduced
from. Since the set is built chronologically, the logical lines are
@ -1102,6 +1149,8 @@ extern const line_map *linemap_add
extern const line_map *linemap_lookup
(const line_maps *, location_t);
unsigned linemap_lookup_macro_index (const line_maps *, location_t);
/* Returns TRUE if the line table set tracks token locations across
macro expansion, FALSE otherwise. */
bool linemap_tracks_macro_expansion_locs_p (class line_maps *);

View File

@ -868,29 +868,7 @@ ufputs (const unsigned char *s, FILE *f)
return fputs ((const char *)s, f);
}
/* In line-map.c. */
/* Create a macro map. A macro map encodes source locations of tokens
that are part of a macro replacement-list, at a macro expansion
point. See the extensive comments of struct line_map and struct
line_map_macro, in line-map.h.
This map shall be created when the macro is expanded. The map
encodes the source location of the expansion point of the macro as
well as the "original" source location of each token that is part
of the macro replacement-list. If a macro is defined but never
expanded, it has no macro map. SET is the set of maps the macro
map should be part of. MACRO_NODE is the macro which the new macro
map should encode source locations for. EXPANSION is the location
of the expansion point of MACRO. For function-like macros
invocations, it's best to make it point to the closing parenthesis
of the macro, rather than the the location of the first character
of the macro. NUM_TOKENS is the number of tokens that are part of
the replacement-list of MACRO. */
const line_map_macro *linemap_enter_macro (class line_maps *,
struct cpp_hashnode*,
location_t,
unsigned int);
/* In line-map.c. */
/* Create and return a virtual location for a token that is part of a
macro expansion-list at a macro expansion point. See the comment

View File

@ -378,23 +378,21 @@ linemap_check_files_exited (line_maps *set)
ORDINARY_MAP_FILE_NAME (map));
}
/* Create a new line map in the line map set SET, and return it.
REASON is the reason of creating the map. It determines the type
of map created (ordinary or macro map). Note that ordinary maps and
macro maps are allocated in different memory location. */
/* Create NUM zero-initialized maps of type MACRO_P. */
static struct line_map *
new_linemap (line_maps *set, location_t start_location)
line_map *
line_map_new_raw (line_maps *set, bool macro_p, unsigned num)
{
bool macro_p = start_location >= LINE_MAP_MAX_LOCATION;
unsigned num_maps_allocated = LINEMAPS_ALLOCATED (set, macro_p);
unsigned num_maps_used = LINEMAPS_USED (set, macro_p);
if (num_maps_used == num_maps_allocated)
if (num > num_maps_allocated - num_maps_used)
{
/* We need more space! */
if (!num_maps_allocated)
num_maps_allocated = 128;
if (num_maps_allocated < num_maps_used + num)
num_maps_allocated = num_maps_used + num;
num_maps_allocated *= 2;
size_t size_of_a_map;
@ -436,13 +434,39 @@ new_linemap (line_maps *set, location_t start_location)
line_map *result = (macro_p ? (line_map *)&set->info_macro.maps[num_maps_used]
: (line_map *)&set->info_ordinary.maps[num_maps_used]);
LINEMAPS_USED (set, macro_p)++;
LINEMAPS_USED (set, macro_p) += num;
return result;
}
/* Create a new line map in the line map set SET, and return it.
REASON is the reason of creating the map. It determines the type
of map created (ordinary or macro map). Note that ordinary maps and
macro maps are allocated in different memory location. */
static struct line_map *
new_linemap (line_maps *set, location_t start_location)
{
line_map *result = line_map_new_raw (set,
start_location >= LINE_MAP_MAX_LOCATION,
1);
result->start_location = start_location;
return result;
}
/* Return the location of the last source line within an ordinary
map. */
inline location_t
LAST_SOURCE_LINE_LOCATION (const line_map_ordinary *map)
{
return (((map[1].start_location - 1
- map->start_location)
& ~((1 << map->m_column_and_range_bits) - 1))
+ map->start_location);
}
/* Add a mapping of logical source line to physical source file and
line number.
@ -570,6 +594,56 @@ linemap_add (line_maps *set, enum lc_reason reason,
return map;
}
/* Create a location for a module NAME imported at FROM. */
location_t
linemap_module_loc (line_maps *set, location_t from, const char *name)
{
const line_map_ordinary *map
= linemap_check_ordinary (linemap_add (set, LC_MODULE, false, name, 0));
const_cast <line_map_ordinary *> (map)->included_from = from;
location_t loc = linemap_line_start (set, 0, 0);
return loc;
}
/* The linemap containing LOC is being reparented to be
imported/included from ADOPTOR. This can happen when an
indirectly imported module is then directly imported, or when
partitions are involved. */
void
linemap_module_reparent (line_maps *set, location_t loc, location_t adoptor)
{
const line_map_ordinary *map = linemap_ordinary_map_lookup (set, loc);
const_cast<line_map_ordinary *> (map)->included_from = adoptor;
}
/* A linemap at LWM-1 was interrupted to insert module locations & imports.
Append a new map, continuing the interrupted one. */
void
linemap_module_restore (line_maps *set, unsigned lwm)
{
if (lwm && lwm != LINEMAPS_USED (set, false))
{
const line_map_ordinary *pre_map
= linemap_check_ordinary (LINEMAPS_MAP_AT (set, false, lwm - 1));
unsigned src_line = SOURCE_LINE (pre_map,
LAST_SOURCE_LINE_LOCATION (pre_map));
location_t inc_at = pre_map->included_from;
if (const line_map_ordinary *post_map
= (linemap_check_ordinary
(linemap_add (set, LC_RENAME_VERBATIM,
ORDINARY_MAP_IN_SYSTEM_HEADER_P (pre_map),
ORDINARY_MAP_FILE_NAME (pre_map), src_line))))
/* linemap_add will think we were included from the same as
the preceeding map. */
const_cast <line_map_ordinary *> (post_map)->included_from = inc_at;
}
}
/* Returns TRUE if the line table set tracks token locations across
macro expansion, FALSE otherwise. */
@ -1003,14 +1077,25 @@ linemap_macro_map_lookup (const line_maps *set, location_t line)
if (set == NULL)
return NULL;
unsigned ix = linemap_lookup_macro_index (set, line);
const struct line_map_macro *result = LINEMAPS_MACRO_MAP_AT (set, ix);
linemap_assert (MAP_START_LOCATION (result) <= line);
return result;
}
unsigned
linemap_lookup_macro_index (const line_maps *set, location_t line)
{
unsigned mn = LINEMAPS_MACRO_CACHE (set);
unsigned mx = LINEMAPS_MACRO_USED (set);
const struct line_map_macro *cached = LINEMAPS_MACRO_MAP_AT (set, mn);
if (line >= MAP_START_LOCATION (cached))
{
if (mn == 0 || line < MAP_START_LOCATION (&cached[-1]))
return cached;
if (line < (MAP_START_LOCATION (cached)
+ MACRO_MAP_NUM_MACRO_TOKENS (cached)))
return mn;
mx = mn - 1;
mn = 0;
}
@ -1025,10 +1110,7 @@ linemap_macro_map_lookup (const line_maps *set, location_t line)
}
LINEMAPS_MACRO_CACHE (set) = mx;
const struct line_map_macro *result = LINEMAPS_MACRO_MAP_AT (set, mx);
linemap_assert (MAP_START_LOCATION (result) <= line);
return result;
return mx;
}
/* Return TRUE if MAP encodes locations coming from a macro
@ -1747,7 +1829,7 @@ linemap_dump (FILE *stream, class line_maps *set, unsigned ix, bool is_macro)
{
const char *const lc_reasons_v[LC_HWM]
= { "LC_ENTER", "LC_LEAVE", "LC_RENAME", "LC_RENAME_VERBATIM",
"LC_ENTER_MACRO" };
"LC_ENTER_MACRO", "LC_MODULE" };
const line_map *map;
unsigned reason;