diff options
author | Jan Hubicka <hubicka@ucw.cz> | 2015-03-27 07:58:59 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2015-03-27 06:58:59 +0000 |
commit | eaeec5ecfa45ef6af7642c6bf45c3d77dd4de6b9 (patch) | |
tree | cbd2e935efaa0cca2a297c9acffbbdf68e1c834d /gcc/lto-streamer-in.c | |
parent | 38147a2a4e7c553840b45ba7d099a5f93ac192a4 (diff) | |
download | gcc-eaeec5ecfa45ef6af7642c6bf45c3d77dd4de6b9.tar.gz |
re PR lto/65536 (LTO line number information garbled)
PR lto/65536
* lto-streamer.h (class lto_location_cache): New.
(struct data_in): Add location_cache.
(lto_input_location): Update prototype.
(stream_input_location_now): New.
* streamer-hooks.h (struct streamer_hooks): Make input_location to take
pointer to location.
(stream_input_location): Update.
* ipa-devirt.c: Include streamer-hooks.h and lto-streamer.h
(warn_odr): Apply location cache before warning.
(lto_input_location): Update prototype.
* gimple-streamer-in.c (input_phi, input_gimple_stmt):
Use stream_input_location_now.
* lto/lto.c (unify_scc): Revert location cache when unification
suceeded.
(lto_read_decls): Accept location cache after sucess;
apply location cache before calling debug hooks.
* lto-streamer-in.c (lto_location_cache::current_cache): New static
variable.
(lto_location_cache::cmp_loc): New function.
(lto_location_cache::apply_location_cache): New function.
(lto_location_cache::accept_location_cache): New function.
(lto_location_cache::revert_location_cache): New function.
(lto_location_cache::input_location): New function.
(lto_input_location): Do location caching.
(stream_input_location_now): New function.
(input_eh_region, input_struct_function_base): Use
stream_input_location_now.
(lto_data_in_create): use new.
(lto_data_in_delete): Use delete.
* tree-streamer-in.c (unpack_ts_block_value_fields,
unpack_ts_omp_clause_value_fields, streamer_read_tree_bitfields,
lto_input_ts_exp_tree_pointers): Update for cached location api.
From-SVN: r221720
Diffstat (limited to 'gcc/lto-streamer-in.c')
-rw-r--r-- | gcc/lto-streamer-in.c | 176 |
1 files changed, 152 insertions, 24 deletions
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index a045b9746c6..4268bdeb823 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -172,47 +172,174 @@ canon_file_name (const char *string) } } +/* Pointer to currently alive instance of lto_location_cache. */ -/* Read a location bitpack from input block IB. */ +lto_location_cache *lto_location_cache::current_cache; -location_t -lto_input_location (struct bitpack_d *bp, struct data_in *data_in) +/* Sort locations in source order. Start with file from last application. */ + +int +lto_location_cache::cmp_loc (const void *pa, const void *pb) +{ + const cached_location *a = ((const cached_location *)pa); + const cached_location *b = ((const cached_location *)pb); + const char *current_file = current_cache->current_file; + int current_line = current_cache->current_line; + + if (a->file == current_file && b->file != current_file) + return -1; + if (a->file != current_file && b->file == current_file) + return 1; + if (a->file == current_file && b->file == current_file) + { + if (a->line == current_line && b->line != current_line) + return -1; + if (a->line != current_line && b->line == current_line) + return 1; + } + if (a->file != b->file) + return strcmp (a->file, b->file); + if (a->line != b->line) + return a->line - b->line; + return a->col - b->col; +} + +/* Apply all changes in location cache. Add locations into linemap and patch + trees. */ + +bool +lto_location_cache::apply_location_cache () +{ + static const char *prev_file; + if (!loc_cache.length ()) + return false; + if (loc_cache.length () > 1) + loc_cache.qsort (cmp_loc); + + for (unsigned int i = 0; i < loc_cache.length (); i++) + { + struct cached_location loc = loc_cache[i]; + + if (current_file != loc.file) + linemap_add (line_table, prev_file ? LC_RENAME : LC_ENTER, + false, loc.file, loc.line); + else if (current_line != loc.line) + { + int max = loc.col; + + for (unsigned int j = i + 1; j < loc_cache.length (); j++) + if (loc.file != loc_cache[j].file + || loc.line != loc_cache[j].line) + break; + else if (max < loc_cache[j].col) + max = loc_cache[j].col; + linemap_line_start (line_table, loc.line, max + 1); + } + gcc_assert (*loc.loc == BUILTINS_LOCATION + 1); + if (current_file == loc.file && current_line == loc.line + && current_col == loc.col) + *loc.loc = current_loc; + else + current_loc = *loc.loc = linemap_position_for_column (line_table, + loc.col); + current_line = loc.line; + prev_file = current_file = loc.file; + current_col = loc.col; + } + loc_cache.truncate (0); + accepted_length = 0; + return true; +} + +/* Tree merging did not suceed; mark all changes in the cache as accepted. */ + +void +lto_location_cache::accept_location_cache () +{ + gcc_assert (current_cache == this); + accepted_length = loc_cache.length (); +} + +/* Tree merging did suceed; throw away recent changes. */ + +void +lto_location_cache::revert_location_cache () +{ + loc_cache.truncate (accepted_length); +} + +/* Read a location bitpack from input block IB and either update *LOC directly + or add it to the location cache. + It is neccesary to call apply_location_cache to get *LOC updated. */ + +void +lto_location_cache::input_location (location_t *loc, struct bitpack_d *bp, + struct data_in *data_in) { - static const char *current_file; - static int current_line; - static int current_col; + static const char *stream_file; + static int stream_line; + static int stream_col; bool file_change, line_change, column_change; - bool prev_file = current_file != NULL; + + gcc_assert (current_cache == this); if (bp_unpack_value (bp, 1)) - return UNKNOWN_LOCATION; + { + *loc = UNKNOWN_LOCATION; + return; + } + *loc = BUILTINS_LOCATION + 1; file_change = bp_unpack_value (bp, 1); line_change = bp_unpack_value (bp, 1); column_change = bp_unpack_value (bp, 1); if (file_change) - current_file = canon_file_name (bp_unpack_string (data_in, bp)); + stream_file = canon_file_name (bp_unpack_string (data_in, bp)); if (line_change) - current_line = bp_unpack_var_len_unsigned (bp); + stream_line = bp_unpack_var_len_unsigned (bp); if (column_change) - current_col = bp_unpack_var_len_unsigned (bp); + stream_col = bp_unpack_var_len_unsigned (bp); - if (file_change) + /* This optimization saves location cache operations druing gimple + streaming. */ + + if (current_file == stream_file && current_line == stream_line + && current_col == stream_col) { - if (prev_file) - linemap_add (line_table, LC_LEAVE, false, NULL, 0); - - linemap_add (line_table, LC_ENTER, false, current_file, current_line); + *loc = current_loc; + return; } - else if (line_change) - linemap_line_start (line_table, current_line, current_col); - return linemap_position_for_column (line_table, current_col); + struct cached_location entry = {stream_file, loc, stream_line, stream_col}; + loc_cache.safe_push (entry); +} + +/* Read a location bitpack from input block IB and either update *LOC directly + or add it to the location cache. + It is neccesary to call apply_location_cache to get *LOC updated. */ + +void +lto_input_location (location_t *loc, struct bitpack_d *bp, + struct data_in *data_in) +{ + data_in->location_cache.input_location (loc, bp, data_in); } +/* Read location and return it instead of going through location caching. + This should be used only when the resulting location is not going to be + discarded. */ + +location_t +stream_input_location_now (struct bitpack_d *bp, struct data_in *data_in) +{ + location_t loc; + stream_input_location (&loc, bp, data_in); + data_in->location_cache.apply_location_cache (); + return loc; +} /* Read a reference to a tree node from DATA_IN using input block IB. TAG is the expected node that should be found in IB, if TAG belongs @@ -390,7 +517,7 @@ input_eh_region (struct lto_input_block *ib, struct data_in *data_in, int ix) r->u.must_not_throw.failure_decl = stream_read_tree (ib, data_in); bitpack_d bp = streamer_read_bitpack (ib); r->u.must_not_throw.failure_loc - = stream_input_location (&bp, data_in); + = stream_input_location_now (&bp, data_in); } break; @@ -927,8 +1054,8 @@ input_struct_function_base (struct function *fn, struct data_in *data_in, fn->last_clique = bp_unpack_value (&bp, sizeof (short) * 8); /* Input the function start and end loci. */ - fn->function_start_locus = stream_input_location (&bp, data_in); - fn->function_end_locus = stream_input_location (&bp, data_in); + fn->function_start_locus = stream_input_location_now (&bp, data_in); + fn->function_end_locus = stream_input_location_now (&bp, data_in); } @@ -1126,6 +1253,7 @@ lto_read_body_or_constructor (struct lto_file_decl_data *file_data, struct symta } else input_constructor (fn_decl, data_in, &ib_main); + data_in->location_cache.apply_location_cache (); /* And fixup types we streamed locally. */ { struct streamer_tree_cache_d *cache = data_in->reader_cache; @@ -1543,7 +1671,7 @@ lto_data_in_create (struct lto_file_decl_data *file_data, const char *strings, unsigned len, vec<ld_plugin_symbol_resolution_t> resolutions) { - struct data_in *data_in = XCNEW (struct data_in); + struct data_in *data_in = new (struct data_in); data_in->file_data = file_data; data_in->strings = strings; data_in->strings_len = len; @@ -1560,5 +1688,5 @@ lto_data_in_delete (struct data_in *data_in) { data_in->globals_resolution.release (); streamer_tree_cache_delete (data_in->reader_cache); - free (data_in); + delete data_in; } |