tree def = stream_read_tree (ib, data_in);
int src_index = streamer_read_uhwi (ib);
bitpack_d bp = streamer_read_bitpack (ib);
- /* Do not cache a location - we do not have API to get pointer to the
- location in PHI statement and we may trigger reallocation. */
- location_t arg_loc = stream_input_location_now (&bp, data_in);
basic_block sbb = BASIC_BLOCK_FOR_FN (fn, src_index);
-
edge e = NULL;
int j;
break;
}
- add_phi_arg (result, def, e, arg_loc);
+ add_phi_arg (result, def, e, UNKNOWN_LOCATION);
+ /* Read location and lexical block information. */
+ location_t *arg_locp = gimple_phi_arg_location_ptr (result, e->dest_idx);
+ data_in->location_cache.input_location_and_block (arg_locp, &bp, ib,
+ data_in);
}
return result;
has_hist = bp_unpack_value (&bp, 1);
stmt->subcode = bp_unpack_var_len_unsigned (&bp);
- /* Read location information. Caching here makes no sense until streamer
- cache can handle the following gimple_set_block. */
- gimple_set_location (stmt, stream_input_location_now (&bp, data_in));
-
- /* Read lexical block reference. */
- gimple_set_block (stmt, stream_read_tree (ib, data_in));
+ /* Read location and lexical block information. */
+ data_in->location_cache.input_location_and_block (gimple_location_ptr (stmt),
+ &bp, ib, data_in);
/* Read in all the operands. */
switch (code)
stream_write_tree (ob, gimple_phi_arg_def (phi, i), true);
streamer_write_uhwi (ob, gimple_phi_arg_edge (phi, i)->src->index);
bitpack_d bp = bitpack_create (ob->main_stream);
- stream_output_location (ob, &bp, gimple_phi_arg_location (phi, i));
- streamer_write_bitpack (&bp);
+ location_t loc = gimple_phi_arg_location (phi, i);
+ stream_output_location_and_block (ob, &bp, loc);
}
}
bp_pack_value (&bp, hist != NULL, 1);
bp_pack_var_len_unsigned (&bp, stmt->subcode);
- /* Emit location information for the statement. */
- stream_output_location (ob, &bp, LOCATION_LOCUS (gimple_location (stmt)));
- streamer_write_bitpack (&bp);
-
- /* Emit the lexical block holding STMT. */
- stream_write_tree (ob, gimple_block (stmt), true);
+ /* Emit location information for the statement, including gimple_block. */
+ stream_output_location_and_block (ob, &bp, gimple_location (stmt));
/* Emit the operands. */
switch (gimple_code (stmt))
g->location = location;
}
+/* Return address of the location information for statement G. */
+
+static inline location_t *
+gimple_location_ptr (gimple *g)
+{
+ return &g->location;
+}
+
/* Return true if G contains location information. */
gimple_phi_arg (phi, i)->locus = loc;
}
+/* Return address of source location of gimple argument I of phi node PHI. */
+
+static inline location_t *
+gimple_phi_arg_location_ptr (gphi *phi, size_t i)
+{
+ return &gimple_phi_arg (phi, i)->locus;
+}
+
/* Return TRUE if argument I of phi node PHI has a location record. */
static inline bool
return a->sysp ? 1 : -1;
if (a->line != b->line)
return a->line - b->line;
- return a->col - b->col;
+ if (a->col != b->col)
+ return a->col - b->col;
+ if ((a->block == NULL_TREE) != (b->block == NULL_TREE))
+ return a->block ? 1 : -1;
+ if (a->block)
+ {
+ if (BLOCK_NUMBER (a->block) < BLOCK_NUMBER (b->block))
+ return -1;
+ if (BLOCK_NUMBER (a->block) > BLOCK_NUMBER (b->block))
+ return 1;
+ }
+ return 0;
}
/* Apply all changes in location cache. Add locations into linemap and patch
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);
+ if (current_file != loc.file
+ || current_line != loc.line
+ || current_col != loc.col)
+ {
+ current_loc = linemap_position_for_column (line_table, loc.col);
+ if (loc.block)
+ current_loc = set_block (current_loc, loc.block);
+ }
+ else if (current_block != loc.block)
+ {
+ if (loc.block)
+ current_loc = set_block (current_loc, loc.block);
+ else
+ current_loc = LOCATION_LOCUS (current_loc);
+ }
+ *loc.loc = current_loc;
current_line = loc.line;
prev_file = current_file = loc.file;
current_col = loc.col;
+ current_block = loc.block;
}
loc_cache.truncate (0);
accepted_length = 0;
return true;
}
-/* Tree merging did not suceed; mark all changes in the cache as accepted. */
+/* Tree merging did not succeed; mark all changes in the cache as accepted. */
void
lto_location_cache::accept_location_cache ()
accepted_length = loc_cache.length ();
}
-/* Tree merging did suceed; throw away recent changes. */
+/* Tree merging did succeed; 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.
+/* Read a location bitpack from bit pack BP and either update *LOC directly
+ or add it to the location cache. If IB is non-NULL, stream in a block
+ afterwards.
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,
- class data_in *data_in)
+lto_location_cache::input_location_and_block (location_t *loc,
+ struct bitpack_d *bp,
+ class lto_input_block *ib,
+ class data_in *data_in)
{
static const char *stream_file;
static int stream_line;
static int stream_col;
static bool stream_sysp;
- bool file_change, line_change, column_change;
+ static tree stream_block;
gcc_assert (current_cache == this);
*loc = bp_unpack_int_in_range (bp, "location", 0, RESERVED_LOCATION_COUNT);
if (*loc < RESERVED_LOCATION_COUNT)
- return;
+ {
+ if (ib)
+ {
+ bool block_change = bp_unpack_value (bp, 1);
+ if (block_change)
+ stream_block = stream_read_tree (ib, data_in);
+ if (stream_block)
+ *loc = set_block (*loc, stream_block);
+ }
+ return;
+ }
/* Keep value RESERVED_LOCATION_COUNT in *loc as linemap lookups will
ICE on it. */
- file_change = bp_unpack_value (bp, 1);
- line_change = bp_unpack_value (bp, 1);
- column_change = bp_unpack_value (bp, 1);
+ bool file_change = bp_unpack_value (bp, 1);
+ bool line_change = bp_unpack_value (bp, 1);
+ bool column_change = bp_unpack_value (bp, 1);
if (file_change)
{
if (column_change)
stream_col = bp_unpack_var_len_unsigned (bp);
- /* This optimization saves location cache operations druing gimple
+ tree block = NULL_TREE;
+ if (ib)
+ {
+ bool block_change = bp_unpack_value (bp, 1);
+ if (block_change)
+ stream_block = stream_read_tree (ib, data_in);
+ block = stream_block;
+ }
+
+ /* This optimization saves location cache operations during gimple
streaming. */
- if (current_file == stream_file && current_line == stream_line
- && current_col == stream_col && current_sysp == stream_sysp)
+ if (current_file == stream_file
+ && current_line == stream_line
+ && current_col == stream_col
+ && current_sysp == stream_sysp)
{
- *loc = current_loc;
+ if (current_block == block)
+ *loc = current_loc;
+ else if (block)
+ *loc = set_block (current_loc, block);
+ else
+ *loc = LOCATION_LOCUS (current_loc);
return;
}
struct cached_location entry
- = {stream_file, loc, stream_line, stream_col, stream_sysp};
+ = {stream_file, loc, stream_line, stream_col, stream_sysp, block};
loc_cache.safe_push (entry);
}
+/* Read a location bitpack from bit pack BP 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,
+ class data_in *data_in)
+{
+ return input_location_and_block (loc, bp, NULL, data_in);
+}
+
/* 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. */
tag = streamer_read_record_start (ib);
}
+ /* Finalize gimple_location/gimple_block of stmts and phis. */
+ data_in->location_cache.apply_location_cache ();
+
/* Fix up the call statements that are mentioned in the callgraph
edges. */
set_gimple_stmt_max_uid (cfun, 0);
ob->current_line = 0;
ob->current_col = 0;
ob->current_sysp = false;
+ /* Initialize to something that will never appear as block,
+ so that the first location with block in a function etc.
+ always streams a change_block bit and the first block. */
+ ob->current_block = void_node;
}
After outputting bitpack, lto_output_location_data has
to be done to output actual data. */
-void
-lto_output_location (struct output_block *ob, struct bitpack_d *bp,
- location_t loc)
+static void
+lto_output_location_1 (struct output_block *ob, struct bitpack_d *bp,
+ location_t orig_loc, bool block_p)
{
- expanded_location xloc;
+ location_t loc = LOCATION_LOCUS (orig_loc);
- loc = LOCATION_LOCUS (loc);
bp_pack_int_in_range (bp, 0, RESERVED_LOCATION_COUNT,
loc < RESERVED_LOCATION_COUNT
? loc : RESERVED_LOCATION_COUNT);
- if (loc < RESERVED_LOCATION_COUNT)
- return;
+ if (loc >= RESERVED_LOCATION_COUNT)
+ {
+ expanded_location xloc = expand_location (loc);
- xloc = expand_location (loc);
+ bp_pack_value (bp, ob->current_file != xloc.file, 1);
+ bp_pack_value (bp, ob->current_line != xloc.line, 1);
+ bp_pack_value (bp, ob->current_col != xloc.column, 1);
- bp_pack_value (bp, ob->current_file != xloc.file, 1);
- bp_pack_value (bp, ob->current_line != xloc.line, 1);
- bp_pack_value (bp, ob->current_col != xloc.column, 1);
+ if (ob->current_file != xloc.file)
+ {
+ bp_pack_string (ob, bp, remap_debug_filename (xloc.file), true);
+ bp_pack_value (bp, xloc.sysp, 1);
+ }
+ ob->current_file = xloc.file;
+ ob->current_sysp = xloc.sysp;
+
+ if (ob->current_line != xloc.line)
+ bp_pack_var_len_unsigned (bp, xloc.line);
+ ob->current_line = xloc.line;
+
+ if (ob->current_col != xloc.column)
+ bp_pack_var_len_unsigned (bp, xloc.column);
+ ob->current_col = xloc.column;
+ }
- if (ob->current_file != xloc.file)
+ if (block_p)
{
- bp_pack_string (ob, bp, remap_debug_filename (xloc.file), true);
- bp_pack_value (bp, xloc.sysp, 1);
+ tree block = LOCATION_BLOCK (orig_loc);
+ bp_pack_value (bp, ob->current_block != block, 1);
+ streamer_write_bitpack (bp);
+ if (ob->current_block != block)
+ lto_output_tree (ob, block, true, true);
+ ob->current_block = block;
}
- ob->current_file = xloc.file;
- ob->current_sysp = xloc.sysp;
+}
+
+/* Output info about new location into bitpack BP.
+ After outputting bitpack, lto_output_location_data has
+ to be done to output actual data. */
- if (ob->current_line != xloc.line)
- bp_pack_var_len_unsigned (bp, xloc.line);
- ob->current_line = xloc.line;
+void
+lto_output_location (struct output_block *ob, struct bitpack_d *bp,
+ location_t loc)
+{
+ lto_output_location_1 (ob, bp, loc, false);
+}
+
+/* Output info about new location into bitpack BP.
+ After outputting bitpack, lto_output_location_data has
+ to be done to output actual data. Like lto_output_location, but
+ additionally output LOCATION_BLOCK info too and write the BP bitpack. */
- if (ob->current_col != xloc.column)
- bp_pack_var_len_unsigned (bp, xloc.column);
- ob->current_col = xloc.column;
+void
+lto_output_location_and_block (struct output_block *ob, struct bitpack_d *bp,
+ location_t loc)
+{
+ lto_output_location_1 (ob, bp, loc, true);
}
streamer_hooks.read_tree = lto_input_tree;
streamer_hooks.input_location = lto_input_location;
streamer_hooks.output_location = lto_output_location;
+ streamer_hooks.output_location_and_block = lto_output_location_and_block;
}
/* The location cache holds expanded locations for streamed in trees.
This is done to reduce memory usage of libcpp linemap that strongly prefers
- locations to be inserted in the soruce order. */
+ locations to be inserted in the source order. */
class lto_location_cache
{
void revert_location_cache ();
void input_location (location_t *loc, struct bitpack_d *bp,
class data_in *data_in);
+ void input_location_and_block (location_t *loc, struct bitpack_d *bp,
+ class lto_input_block *ib,
+ class data_in *data_in);
lto_location_cache ()
: loc_cache (), accepted_length (0), current_file (NULL), current_line (0),
- current_col (0), current_sysp (false), current_loc (UNKNOWN_LOCATION)
+ current_col (0), current_sysp (false), current_loc (UNKNOWN_LOCATION),
+ current_block (NULL_TREE)
{
gcc_assert (!current_cache);
current_cache = this;
location_t *loc;
int line, col;
bool sysp;
+ tree block;
};
/* The location cache. */
int current_col;
bool current_sysp;
location_t current_loc;
+ tree current_block;
};
/* Structure used as buffer for reading an LTO file. */
int current_line;
int current_col;
bool current_sysp;
+ tree current_block;
/* Cache of nodes written in this section. */
struct streamer_tree_cache_d *writer_cache;
void lto_output_decl_state_refs (struct output_block *,
struct lto_output_stream *,
struct lto_out_decl_state *);
-void lto_output_location (struct output_block *, struct bitpack_d *, location_t);
+void lto_output_location (struct output_block *, struct bitpack_d *,
+ location_t);
+void lto_output_location_and_block (struct output_block *, struct bitpack_d *,
+ location_t);
void lto_output_init_mode_table (void);
void lto_prepare_function_for_streaming (cgraph_node *);
/* [REQ] Called by every streaming routine that needs to read a location. */
void (*input_location) (location_t *, struct bitpack_d *, class data_in *);
- /* [REQ] Called by every streaming routine that needs to write a location. */
- void (*output_location) (struct output_block *, struct bitpack_d *, location_t);
+ /* [REQ] Called by every streaming routine that needs to write a
+ location. */
+ void (*output_location) (struct output_block *, struct bitpack_d *,
+ location_t);
+
+ /* [REQ] Called by every streaming routine that needs to write a
+ location, both LOCATION_LOCUS and LOCATION_BLOCK. */
+ void (*output_location_and_block) (struct output_block *, struct bitpack_d *,
+ location_t);
};
#define stream_write_tree(OB, EXPR, REF_P) \
#define stream_output_location(OB, BP, LOC) \
streamer_hooks.output_location (OB, BP, LOC)
+#define stream_output_location_and_block(OB, BP, LOC) \
+ streamer_hooks.output_location_and_block (OB, BP, LOC)
+
/* Streamer hooks. */
extern struct streamer_hooks streamer_hooks;