From 1f8ac759918729e9402c3154c8e5110bfd4c6459 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 17 Nov 2020 08:01:50 -0800 Subject: [PATCH] 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. --- libcpp/include/line-map.h | 51 +++++++++++++++++++- libcpp/internal.h | 24 +--------- libcpp/line-map.c | 116 +++++++++++++++++++++++++++++++++++++++------- 3 files changed, 150 insertions(+), 41 deletions(-) diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index 44008be..50b2e4f 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -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 *); diff --git a/libcpp/internal.h b/libcpp/internal.h index d7780e4..3f5bafb 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -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 diff --git a/libcpp/line-map.c b/libcpp/line-map.c index 5a74174..bbb6963 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -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 (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 (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 (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; -- 2.7.4