diff options
Diffstat (limited to 'libcpp/line-map.c')
-rw-r--r-- | libcpp/line-map.c | 274 |
1 files changed, 233 insertions, 41 deletions
diff --git a/libcpp/line-map.c b/libcpp/line-map.c index 3c19f93b7a5..c5aa4223b1b 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -27,9 +27,9 @@ along with this program; see the file COPYING3. If not see #include "hashtab.h" /* Do not track column numbers higher than this one. As a result, the - range of column_bits is [7, 18] (or 0 if column numbers are + range of column_bits is [12, 18] (or 0 if column numbers are disabled). */ -const unsigned int LINE_MAP_MAX_COLUMN_NUMBER = (1U << 17); +const unsigned int LINE_MAP_MAX_COLUMN_NUMBER = (1U << 12); /* Do not track column numbers if locations get higher than this. */ const source_location LINE_MAP_MAX_LOCATION_WITH_COLS = 0x60000000; @@ -46,7 +46,7 @@ static const line_map_macro* linemap_macro_map_lookup (struct line_maps *, static source_location linemap_macro_map_loc_to_def_point (const line_map_macro *, source_location); static source_location linemap_macro_map_loc_unwind_toward_spelling -(const line_map_macro *, source_location); +(line_maps *set, const line_map_macro *, source_location); static source_location linemap_macro_map_loc_to_exp_point (const line_map_macro *, source_location); static source_location linemap_macro_loc_to_spelling_point @@ -69,7 +69,10 @@ location_adhoc_data_hash (const void *l) { const struct location_adhoc_data *lb = (const struct location_adhoc_data *) l; - return (hashval_t) lb->locus + (size_t) lb->data; + return ((hashval_t) lb->locus + + (hashval_t) lb->src_range.m_start + + (hashval_t) lb->src_range.m_finish + + (size_t) lb->data); } /* Compare function for location_adhoc_data hashtable. */ @@ -81,7 +84,10 @@ location_adhoc_data_eq (const void *l1, const void *l2) (const struct location_adhoc_data *) l1; const struct location_adhoc_data *lb2 = (const struct location_adhoc_data *) l2; - return lb1->locus == lb2->locus && lb1->data == lb2->data; + return (lb1->locus == lb2->locus + && lb1->src_range.m_start == lb2->src_range.m_start + && lb1->src_range.m_finish == lb2->src_range.m_finish + && lb1->data == lb2->data); } /* Update the hashtable when location_adhoc_data is reallocated. */ @@ -106,23 +112,103 @@ rebuild_location_adhoc_htab (struct line_maps *set) set->location_adhoc_data_map.data + i, INSERT); } +/* Helper function for get_combined_adhoc_loc. + Can the given LOCUS + SRC_RANGE and DATA pointer be stored compactly + within a source_location, without needing to use an ad-hoc location. */ + +static bool +can_be_stored_compactly_p (struct line_maps *set, + source_location locus, + source_range src_range, + void *data) +{ + /* If there's an ad-hoc pointer, we can't store it directly in the + source_location, we need the lookaside. */ + if (data) + return false; + + /* We only store ranges that begin at the locus and that are sufficiently + "sane". */ + if (src_range.m_start != locus) + return false; + + if (src_range.m_finish < src_range.m_start) + return false; + + if (src_range.m_start < RESERVED_LOCATION_COUNT) + return false; + + if (locus >= LINE_MAP_MAX_LOCATION_WITH_COLS) + return false; + + /* All 3 locations must be within ordinary maps, typically, the same + ordinary map. */ + source_location lowest_macro_loc = LINEMAPS_MACRO_LOWEST_LOCATION (set); + if (locus >= lowest_macro_loc) + return false; + if (src_range.m_start >= lowest_macro_loc) + return false; + if (src_range.m_finish >= lowest_macro_loc) + return false; + + /* Passed all tests. */ + return true; +} + /* Combine LOCUS and DATA to a combined adhoc loc. */ source_location get_combined_adhoc_loc (struct line_maps *set, - source_location locus, void *data) + source_location locus, + source_range src_range, + void *data) { struct location_adhoc_data lb; struct location_adhoc_data **slot; - linemap_assert (data); - if (IS_ADHOC_LOC (locus)) locus = set->location_adhoc_data_map.data[locus & MAX_SOURCE_LOCATION].locus; if (locus == 0 && data == NULL) return 0; + + /* Any ordinary locations ought to be "pure" at this point: no + compressed ranges. */ + linemap_assert (locus < RESERVED_LOCATION_COUNT + || locus >= LINE_MAP_MAX_LOCATION_WITH_COLS + || locus >= LINEMAPS_MACRO_LOWEST_LOCATION (set) + || pure_location_p (set, locus)); + + /* Consider short-range optimization. */ + if (can_be_stored_compactly_p (set, locus, src_range, data)) + { + /* The low bits ought to be clear. */ + linemap_assert (pure_location_p (set, locus)); + const line_map *map = linemap_lookup (set, locus); + const line_map_ordinary *ordmap = linemap_check_ordinary (map); + unsigned int int_diff = src_range.m_finish - src_range.m_start; + unsigned int col_diff = (int_diff >> ordmap->m_range_bits); + if (col_diff < (1U << ordmap->m_range_bits)) + { + source_location packed = locus | col_diff; + set->num_optimized_ranges++; + return packed; + } + } + + /* We can also compactly store the reserved locations + when locus == start == finish (and data is NULL). */ + if (locus < RESERVED_LOCATION_COUNT + && locus == src_range.m_start + && locus == src_range.m_finish + && !data) + return locus; + + if (!data) + set->num_unoptimized_ranges++; + lb.locus = locus; + lb.src_range = src_range; lb.data = data; slot = (struct location_adhoc_data **) htab_find_slot (set->location_adhoc_data_map.htab, &lb, INSERT); @@ -177,6 +263,60 @@ get_location_from_adhoc_loc (struct line_maps *set, source_location loc) return set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus; } +/* Return the source_range for adhoc location LOC. */ + +static source_range +get_range_from_adhoc_loc (struct line_maps *set, source_location loc) +{ + linemap_assert (IS_ADHOC_LOC (loc)); + return set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].src_range; +} + +/* Get the source_range of location LOC, either from the ad-hoc + lookaside table, or embedded inside LOC itself. */ + +source_range +get_range_from_loc (struct line_maps *set, + source_location loc) +{ + if (IS_ADHOC_LOC (loc)) + return get_range_from_adhoc_loc (set, loc); + + /* For ordinary maps, extract packed range. */ + if (loc >= RESERVED_LOCATION_COUNT + && loc < LINEMAPS_MACRO_LOWEST_LOCATION (set) + && loc <= LINE_MAP_MAX_LOCATION_WITH_COLS) + { + const line_map *map = linemap_lookup (set, loc); + const line_map_ordinary *ordmap = linemap_check_ordinary (map); + source_range result; + int offset = loc & ((1 << ordmap->m_range_bits) - 1); + result.m_start = loc - offset; + result.m_finish = result.m_start + (offset << ordmap->m_range_bits); + return result; + } + + return source_range::from_location (loc); +} + +/* Get whether location LOC is a "pure" location, or + whether it is an ad-hoc location, or embeds range information. */ + +bool +pure_location_p (line_maps *set, source_location loc) +{ + if (IS_ADHOC_LOC (loc)) + return false; + + const line_map *map = linemap_lookup (set, loc); + const line_map_ordinary *ordmap = linemap_check_ordinary (map); + + if (loc & ((1U << ordmap->m_range_bits) - 1)) + return false; + + return true; +} + /* Finalize the location_adhoc_data structure. */ void location_adhoc_data_fini (struct line_maps *set) @@ -319,7 +459,19 @@ const struct line_map * linemap_add (struct line_maps *set, enum lc_reason reason, unsigned int sysp, const char *to_file, linenum_type to_line) { - source_location start_location = set->highest_location + 1; + /* Generate a start_location above the current highest_location. + If possible, make the low range bits be zero. */ + source_location start_location; + if (set->highest_location < LINE_MAP_MAX_LOCATION_WITH_COLS) + { + start_location = set->highest_location + (1 << set->default_range_bits); + if (set->default_range_bits) + start_location &= ~((1 << set->default_range_bits) - 1); + linemap_assert (0 == (start_location + & ((1 << set->default_range_bits) - 1))); + } + else + start_location = set->highest_location + 1; linemap_assert (!(LINEMAPS_ORDINARY_USED (set) && (start_location @@ -398,11 +550,18 @@ linemap_add (struct line_maps *set, enum lc_reason reason, map->to_file = to_file; map->to_line = to_line; LINEMAPS_ORDINARY_CACHE (set) = LINEMAPS_ORDINARY_USED (set) - 1; - map->column_bits = 0; + map->m_column_and_range_bits = 0; + map->m_range_bits = 0; set->highest_location = start_location; set->highest_line = start_location; set->max_column_hint = 0; + /* This assertion is placed after set->highest_location has + been updated, since the latter affects + linemap_location_from_macro_expansion_p, which ultimately affects + pure_location_p. */ + linemap_assert (pure_location_p (set, start_location)); + if (reason == LC_ENTER) { map->included_from = @@ -549,13 +708,14 @@ linemap_line_start (struct line_maps *set, linenum_type to_line, SOURCE_LINE (map, set->highest_line); int line_delta = to_line - last_line; bool add_map = false; + linemap_assert (map->m_column_and_range_bits >= map->m_range_bits); + int effective_column_bits = map->m_column_and_range_bits - map->m_range_bits; if (line_delta < 0 || (line_delta > 10 - && line_delta * ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) > 1000) - || (max_column_hint >= (1U << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map))) - || (max_column_hint <= 80 - && ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) >= 10) + && line_delta * map->m_column_and_range_bits > 1000) + || (max_column_hint >= (1U << effective_column_bits)) + || (max_column_hint <= 80 && effective_column_bits >= 10) || (highest > LINE_MAP_MAX_LOCATION_WITH_COLS && (set->max_column_hint || highest >= LINE_MAP_MAX_SOURCE_LOCATION))) add_map = true; @@ -564,22 +724,27 @@ linemap_line_start (struct line_maps *set, linenum_type to_line, if (add_map) { int column_bits; + int range_bits; if (max_column_hint > LINE_MAP_MAX_COLUMN_NUMBER || highest > LINE_MAP_MAX_LOCATION_WITH_COLS) { /* If the column number is ridiculous or we've allocated a huge - number of source_locations, give up on column numbers. */ + number of source_locations, give up on column numbers + (and on packed ranges). */ max_column_hint = 0; column_bits = 0; + range_bits = 0; if (highest > LINE_MAP_MAX_SOURCE_LOCATION) return 0; } else { column_bits = 7; + range_bits = set->default_range_bits; while (max_column_hint >= (1U << column_bits)) column_bits++; max_column_hint = 1U << column_bits; + column_bits += range_bits; } /* Allocate the new line_map. However, if the current map only has a single line we can sometimes just increase its column_bits instead. */ @@ -592,14 +757,14 @@ linemap_line_start (struct line_maps *set, linenum_type to_line, ORDINARY_MAP_IN_SYSTEM_HEADER_P (map), ORDINARY_MAP_FILE_NAME (map), to_line))); - map->column_bits = column_bits; + map->m_column_and_range_bits = column_bits; + map->m_range_bits = range_bits; r = (MAP_START_LOCATION (map) + ((to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map)) << column_bits)); } else - r = highest - SOURCE_COLUMN (map, highest) - + (line_delta << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map)); + r = set->highest_line + (line_delta << map->m_column_and_range_bits); /* Locations of ordinary tokens are always lower than locations of macro tokens. */ @@ -610,6 +775,18 @@ linemap_line_start (struct line_maps *set, linenum_type to_line, if (r > set->highest_location) set->highest_location = r; set->max_column_hint = max_column_hint; + + /* At this point, we expect one of: + (a) the normal case: a "pure" location with 0 range bits, or + (b) we've gone past LINE_MAP_MAX_LOCATION_WITH_COLS so can't track + columns anymore (or ranges), or + (c) we're in a region with a column hint exceeding + LINE_MAP_MAX_COLUMN_NUMBER, so column-tracking is off, + with column_bits == 0. */ + linemap_assert (pure_location_p (set, r) + || r >= LINE_MAP_MAX_LOCATION_WITH_COLS + || map->m_column_and_range_bits == 0); + linemap_assert (SOURCE_LINE (map, r) == to_line); return r; } @@ -640,7 +817,8 @@ linemap_position_for_column (struct line_maps *set, unsigned int to_column) r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50); } } - r = r + to_column; + line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set); + r = r + (to_column << map->m_range_bits); if (r >= set->highest_location) set->highest_location = r; return r; @@ -650,16 +828,25 @@ linemap_position_for_column (struct line_maps *set, unsigned int to_column) column. */ source_location -linemap_position_for_line_and_column (const line_map_ordinary *ord_map, +linemap_position_for_line_and_column (line_maps *set, + const line_map_ordinary *ord_map, linenum_type line, unsigned column) { linemap_assert (ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map) <= line); - return (MAP_START_LOCATION (ord_map) - + ((line - ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map)) - << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (ord_map)) - + (column & ((1 << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (ord_map)) - 1))); + source_location r = MAP_START_LOCATION (ord_map); + r += ((line - ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map)) + << ord_map->m_column_and_range_bits); + if (r <= LINE_MAP_MAX_LOCATION_WITH_COLS) + r += ((column & ((1 << ord_map->m_column_and_range_bits) - 1)) + << ord_map->m_range_bits); + source_location upper_limit = LINEMAPS_MACRO_LOWEST_LOCATION (set); + if (r >= upper_limit) + r = upper_limit - 1; + if (r > set->highest_location) + set->highest_location = r; + return r; } /* Encode and return a source_location starting from location LOC and @@ -673,6 +860,9 @@ linemap_position_for_loc_and_offset (struct line_maps *set, { const line_map_ordinary * map = NULL; + if (IS_ADHOC_LOC (loc)) + loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus; + /* This function does not support virtual locations yet. */ if (linemap_assert_fails (!linemap_location_from_macro_expansion_p (set, loc))) @@ -711,11 +901,11 @@ linemap_position_for_loc_and_offset (struct line_maps *set, } offset += column; - if (linemap_assert_fails (offset < (1u << map->column_bits))) + if (linemap_assert_fails (offset < (1u << map->m_column_and_range_bits))) return loc; source_location r = - linemap_position_for_line_and_column (map, line, offset); + linemap_position_for_line_and_column (set, map, line, offset); if (linemap_assert_fails (r <= set->highest_location) || linemap_assert_fails (map == linemap_lookup (set, r))) return loc; @@ -893,14 +1083,19 @@ linemap_macro_map_loc_to_def_point (const line_map_macro *map, In other words, this returns the xI location presented in the comments of line_map_macro above. */ source_location -linemap_macro_map_loc_unwind_toward_spelling (const line_map_macro* map, +linemap_macro_map_loc_unwind_toward_spelling (line_maps *set, + const line_map_macro* map, source_location location) { unsigned token_no; + if (IS_ADHOC_LOC (location)) + location = get_location_from_adhoc_loc (set, location); + linemap_assert (linemap_macro_expansion_map_p (map) && location >= MAP_START_LOCATION (map)); linemap_assert (location >= RESERVED_LOCATION_COUNT); + linemap_assert (!IS_ADHOC_LOC (location)); token_no = location - MAP_START_LOCATION (map); linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map)); @@ -1010,7 +1205,7 @@ linemap_location_in_system_header_p (struct line_maps *set, /* It's a token resulting from a macro expansion. */ source_location loc = - linemap_macro_map_loc_unwind_toward_spelling (macro_map, location); + linemap_macro_map_loc_unwind_toward_spelling (set, macro_map, location); if (loc < RESERVED_LOCATION_COUNT) /* This token might come from a built-in macro. Let's look at where that macro got expanded. */ @@ -1183,11 +1378,6 @@ linemap_macro_loc_to_spelling_point (struct line_maps *set, const line_map_ordinary **original_map) { struct line_map *map; - - if (IS_ADHOC_LOC (location)) - location = set->location_adhoc_data_map.data[location - & MAX_SOURCE_LOCATION].locus; - linemap_assert (set && location >= RESERVED_LOCATION_COUNT); while (true) @@ -1198,7 +1388,7 @@ linemap_macro_loc_to_spelling_point (struct line_maps *set, location = linemap_macro_map_loc_unwind_toward_spelling - (linemap_check_macro (map), + (set, linemap_check_macro (map), location); } @@ -1341,10 +1531,11 @@ linemap_resolve_location (struct line_maps *set, enum location_resolution_kind lrk, const line_map_ordinary **map) { + source_location locus = loc; if (IS_ADHOC_LOC (loc)) - loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus; + locus = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus; - if (loc < RESERVED_LOCATION_COUNT) + if (locus < RESERVED_LOCATION_COUNT) { /* A reserved location wasn't encoded in a map. Let's return a NULL map here, just like what linemap_ordinary_map_lookup @@ -1396,7 +1587,7 @@ linemap_unwind_toward_expansion (struct line_maps *set, loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus; resolved_location = - linemap_macro_map_loc_unwind_toward_spelling (macro_map, loc); + linemap_macro_map_loc_unwind_toward_spelling (set, macro_map, loc); resolved_map = linemap_lookup (set, resolved_location); if (!linemap_macro_expansion_map_p (resolved_map)) @@ -1478,9 +1669,9 @@ linemap_expand_location (struct line_maps *set, memset (&xloc, 0, sizeof (xloc)); if (IS_ADHOC_LOC (loc)) { - loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus; xloc.data = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].data; + loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus; } if (loc < RESERVED_LOCATION_COUNT) @@ -1760,13 +1951,14 @@ line_table_dump (FILE *stream, struct line_maps *set, unsigned int num_ordinary, /* Construct a rich_location with location LOC as its initial range. */ -rich_location::rich_location (source_location loc) : +rich_location::rich_location (line_maps *set, source_location loc) : m_loc (loc), m_num_ranges (0), m_have_expanded_location (false) { - /* Set up the 0th range: */ - add_range (loc, loc, true); + /* Set up the 0th range, extracting any range from LOC. */ + source_range src_range = get_range_from_loc (set, loc); + add_range (src_range, true); m_ranges[0].m_caret = lazily_expand_location (); } |