/* Read the GIMPLE representation from a file stream.
- Copyright 2009 Free Software Foundation, Inc.
+ Copyright 2009, 2010 Free Software Foundation, Inc.
Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
Re-implemented by Diego Novillo <dnovillo@google.com>
#include "flags.h"
#include "params.h"
#include "input.h"
-#include "varray.h"
#include "hashtab.h"
#include "basic-block.h"
#include "tree-flow.h"
#include "output.h"
#include "ipa-utils.h"
#include "lto-streamer.h"
+#include "tree-pass.h"
/* Data structure used to hash file names in the source_location field. */
struct string_slot
unsigned int len;
unsigned int loc;
const char *result;
-
+
loc = lto_input_uleb128 (ib);
LTO_INIT_INPUT_BLOCK (str_tab, data_in->strings, loc, data_in->strings_len);
len = lto_input_uleb128 (&str_tab);
if (str_tab.p + len > data_in->strings_len)
internal_error ("bytecode stream: string too long for the string table");
-
+
result = (const char *)(data_in->strings + str_tab.p);
return result;
{
enum LTO_tags tag = (enum LTO_tags) lto_input_uleb128 (ib);
return tag;
-}
+}
/* Lookup STRING in file_name_hash_table. If found, return the existing
lto_input_location (struct lto_input_block *ib, struct data_in *data_in)
{
expanded_location xloc;
- location_t loc;
xloc.file = input_string (data_in, ib);
if (xloc.file == NULL)
return UNKNOWN_LOCATION;
+ xloc.file = canon_file_name (xloc.file);
xloc.line = lto_input_sleb128 (ib);
xloc.column = lto_input_sleb128 (ib);
+ xloc.sysp = lto_input_sleb128 (ib);
- if (data_in->current_file)
- linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+ if (data_in->current_file != xloc.file)
+ {
+ if (data_in->current_file)
+ linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+
+ linemap_add (line_table, LC_ENTER, xloc.sysp, xloc.file, xloc.line);
+ }
+ else if (data_in->current_line != xloc.line)
+ linemap_line_start (line_table, xloc.line, xloc.column);
- data_in->current_file = canon_file_name (xloc.file);
+ data_in->current_file = xloc.file;
data_in->current_line = xloc.line;
data_in->current_col = xloc.column;
- linemap_add (line_table, LC_ENTER, false, data_in->current_file, xloc.line);
- LINEMAP_POSITION_FOR_COLUMN (loc, line_table, xloc.column);
-
- return loc;
+ return linemap_position_for_column (line_table, xloc.column);
}
function scope for the read tree. */
static tree
-lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in,
+lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in,
struct function *fn, enum LTO_tags tag)
{
unsigned HOST_WIDE_INT ix_u;
case LTO_const_decl_ref:
case LTO_imported_decl_ref:
case LTO_label_decl_ref:
+ case LTO_translation_unit_decl_ref:
ix_u = lto_input_uleb128 (ib);
result = lto_file_decl_data_get_var_decl (data_in->file_data, ix_u);
- if (tag == LTO_global_decl_ref)
- varpool_mark_needed_node (varpool_node (result));
break;
default:
lto_tag_check_range (tag, LTO_eh_catch, LTO_eh_catch);
/* Read the catch node. */
- n = GGC_CNEW (struct eh_catch_d);
+ n = ggc_alloc_cleared_eh_catch_d ();
n->type_list = lto_input_tree (ib, data_in);
n->filter_list = lto_input_tree (ib, data_in);
n->label = lto_input_tree (ib, data_in);
if (tag == LTO_null)
return NULL;
- r = GGC_CNEW (struct eh_region_d);
+ r = ggc_alloc_cleared_eh_region_d ();
r->index = lto_input_sleb128 (ib);
gcc_assert (r->index == ix);
lto_tag_check_range (tag, LTO_eh_landing_pad, LTO_eh_landing_pad);
- lp = GGC_CNEW (struct eh_landing_pad_d);
+ lp = ggc_alloc_cleared_eh_landing_pad_d ();
lp->index = lto_input_sleb128 (ib);
gcc_assert (lp->index == ix);
lp->next_lp = (eh_landing_pad) (intptr_t) lto_input_sleb128 (ib);
/* Convert all the index numbers stored in pointer fields into
pointers to the corresponding slots in the EH region array. */
- for (i = 0; VEC_iterate (eh_region, eh_array, i, r); i++)
+ FOR_EACH_VEC_ELT (eh_region, eh_array, i, r)
{
/* The array may contain NULL regions. */
if (r == NULL)
/* Convert all the index numbers stored in pointer fields into
pointers to the corresponding slots in the EH landing pad array. */
- for (i = 0; VEC_iterate (eh_landing_pad, lp_array, i, lp); i++)
+ FOR_EACH_VEC_ELT (eh_landing_pad, lp_array, i, lp)
{
/* The array may contain NULL landing pads. */
if (lp == NULL)
static void
lto_init_eh (void)
{
+ static bool eh_initialized_p = false;
+
+ if (eh_initialized_p)
+ return;
+
/* Contrary to most other FEs, we only initialize EH support when at
least one of the files in the set contains exception regions in
it. Since this happens much later than the call to init_eh in
if (dwarf2out_do_frame ())
dwarf2out_frame_init ();
#endif
+
+ eh_initialized_p = true;
}
{
HOST_WIDE_INT i, root_region, len;
enum LTO_tags tag;
- static bool eh_initialized_p = false;
-
+
tag = input_record_start (ib);
if (tag == LTO_null)
return;
/* If the file contains EH regions, then it was compiled with
-fexceptions. In that case, initialize the backend EH
machinery. */
- if (!eh_initialized_p)
- {
- lto_init_eh ();
- eh_initialized_p = true;
- }
+ lto_init_eh ();
gcc_assert (fn->eh);
basic_block bb = alloc_block ();
bb->index = index;
SET_BASIC_BLOCK_FOR_FUNCTION (fn, index, bb);
- bb->il.gimple = GGC_CNEW (struct gimple_bb_info);
+ bb->il.gimple = ggc_alloc_cleared_gimple_bb_info ();
n_basic_blocks_for_function (fn)++;
bb->flags = 0;
set_bb_seq (bb, gimple_seq_alloc ());
/* Read the CFG for function FN from input block IB. */
-static void
-input_cfg (struct lto_input_block *ib, struct function *fn)
+static void
+input_cfg (struct lto_input_block *ib, struct function *fn,
+ int count_materialization_scale)
{
unsigned int bb_count;
basic_block p_bb;
init_empty_tree_cfg_for_function (fn);
init_ssa_operands ();
- profile_status_for_function (fn) =
+ profile_status_for_function (fn) =
(enum profile_status_d) lto_input_uleb128 (ib);
bb_count = lto_input_uleb128 (ib);
basic_block_info_for_function (fn), bb_count);
if (bb_count > VEC_length (basic_block, label_to_block_map_for_function (fn)))
- VEC_safe_grow_cleared (basic_block, gc,
+ VEC_safe_grow_cleared (basic_block, gc,
label_to_block_map_for_function (fn), bb_count);
index = lto_input_sleb128 (ib);
dest_index = lto_input_uleb128 (ib);
probability = (int) lto_input_sleb128 (ib);
- count = (gcov_type) lto_input_sleb128 (ib);
+ count = ((gcov_type) lto_input_sleb128 (ib) * count_materialization_scale
+ + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
edge_flags = lto_input_uleb128 (ib);
dest = BASIC_BLOCK_FOR_FUNCTION (fn, dest_index);
- if (dest == NULL)
+ if (dest == NULL)
dest = make_new_block (fn, dest_index);
e = make_edge (bb, dest, edge_flags);
int src_index = lto_input_uleb128 (ib);
location_t arg_loc = lto_input_location (ib, data_in);
basic_block sbb = BASIC_BLOCK_FOR_FUNCTION (fn, src_index);
-
+
edge e = NULL;
int j;
-
+
for (j = 0; j < len; j++)
if (EDGE_PRED (bb, j)->src == sbb)
{
break;
}
- add_phi_arg (result, def, e, arg_loc);
+ add_phi_arg (result, def, e, arg_loc);
}
return result;
set_default_def (SSA_NAME_VAR (ssa_name), ssa_name);
i = lto_input_uleb128 (ib);
- }
+ }
}
-
/* Read a statement with tag TAG in function FN from block IB using
descriptors in DATA_IN. */
enum gimple_code code;
unsigned HOST_WIDE_INT num_ops;
size_t i;
- struct bitpack_d *bp;
+ struct bitpack_d bp;
code = lto_tag_to_gimple_code (tag);
/* Read the tuple header. */
bp = lto_input_bitpack (ib);
- num_ops = bp_unpack_value (bp, sizeof (unsigned) * 8);
+ num_ops = bp_unpack_value (&bp, sizeof (unsigned) * 8);
stmt = gimple_alloc (code, num_ops);
- stmt->gsbase.no_warning = bp_unpack_value (bp, 1);
+ stmt->gsbase.no_warning = bp_unpack_value (&bp, 1);
if (is_gimple_assign (stmt))
- stmt->gsbase.nontemporal_move = bp_unpack_value (bp, 1);
- stmt->gsbase.has_volatile_ops = bp_unpack_value (bp, 1);
- stmt->gsbase.subcode = bp_unpack_value (bp, 16);
- bitpack_delete (bp);
+ stmt->gsbase.nontemporal_move = bp_unpack_value (&bp, 1);
+ stmt->gsbase.has_volatile_ops = bp_unpack_value (&bp, 1);
+ stmt->gsbase.subcode = bp_unpack_value (&bp, 16);
/* Read location information. */
gimple_set_location (stmt, lto_input_location (ib, data_in));
stmt->gimple_asm.ni = lto_input_uleb128 (ib);
stmt->gimple_asm.no = lto_input_uleb128 (ib);
stmt->gimple_asm.nc = lto_input_uleb128 (ib);
+ stmt->gimple_asm.nl = lto_input_uleb128 (ib);
str = input_string_cst (data_in, ib);
stmt->gimple_asm.string = TREE_STRING_POINTER (str);
}
{
tree op = lto_input_tree (ib, data_in);
gimple_set_op (stmt, i, op);
+ if (!op)
+ continue;
+
+ /* Fixup FIELD_DECLs in COMPONENT_REFs, they are not handled
+ by decl merging. */
+ if (TREE_CODE (op) == ADDR_EXPR)
+ op = TREE_OPERAND (op, 0);
+ while (handled_component_p (op))
+ {
+ if (TREE_CODE (op) == COMPONENT_REF)
+ {
+ tree field, type, tem;
+ tree closest_match = NULL_TREE;
+ field = TREE_OPERAND (op, 1);
+ type = DECL_CONTEXT (field);
+ for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
+ {
+ if (tem == field)
+ break;
+ if (DECL_NONADDRESSABLE_P (tem)
+ == DECL_NONADDRESSABLE_P (field)
+ && gimple_compare_field_offset (tem, field))
+ {
+ if (types_compatible_p (TREE_TYPE (tem),
+ TREE_TYPE (field)))
+ break;
+ else
+ closest_match = tem;
+ }
+ }
+ /* In case of type mismatches across units we can fail
+ to unify some types and thus not find a proper
+ field-decl here. */
+ if (tem == NULL_TREE)
+ {
+ /* Thus, emit a ODR violation warning. */
+ if (warning_at (gimple_location (stmt), 0,
+ "use of type %<%E%> with two mismatching "
+ "declarations at field %<%E%>",
+ type, TREE_OPERAND (op, 1)))
+ {
+ if (TYPE_FIELDS (type))
+ inform (DECL_SOURCE_LOCATION (TYPE_FIELDS (type)),
+ "original type declared here");
+ inform (DECL_SOURCE_LOCATION (TREE_OPERAND (op, 1)),
+ "field in mismatching type declared here");
+ if (TYPE_NAME (TREE_TYPE (field))
+ && (TREE_CODE (TYPE_NAME (TREE_TYPE (field)))
+ == TYPE_DECL))
+ inform (DECL_SOURCE_LOCATION
+ (TYPE_NAME (TREE_TYPE (field))),
+ "type of field declared here");
+ if (closest_match
+ && TYPE_NAME (TREE_TYPE (closest_match))
+ && (TREE_CODE (TYPE_NAME
+ (TREE_TYPE (closest_match))) == TYPE_DECL))
+ inform (DECL_SOURCE_LOCATION
+ (TYPE_NAME (TREE_TYPE (closest_match))),
+ "type of mismatching field declared here");
+ }
+ /* And finally fixup the types. */
+ TREE_OPERAND (op, 0)
+ = build1 (VIEW_CONVERT_EXPR, type,
+ TREE_OPERAND (op, 0));
+ }
+ else
+ TREE_OPERAND (op, 1) = tem;
+ }
+
+ op = TREE_OPERAND (op, 0);
+ }
}
break;
+ case GIMPLE_NOP:
case GIMPLE_PREDICT:
break;
}
}
+ /* Reset alias information. */
+ if (code == GIMPLE_CALL)
+ gimple_call_reset_alias_info (stmt);
+
/* Mark the statement modified so its operand vectors can be filled in. */
gimple_set_modified (stmt, true);
return stmt;
}
-
+
/* Read a basic block with tag TAG from DATA_IN using input block IB.
FN is the function being processed. */
static void
-input_bb (struct lto_input_block *ib, enum LTO_tags tag,
- struct data_in *data_in, struct function *fn)
+input_bb (struct lto_input_block *ib, enum LTO_tags tag,
+ struct data_in *data_in, struct function *fn,
+ int count_materialization_scale)
{
unsigned int index;
basic_block bb;
index = lto_input_uleb128 (ib);
bb = BASIC_BLOCK_FOR_FUNCTION (fn, index);
- bb->count = lto_input_sleb128 (ib);
+ bb->count = (lto_input_sleb128 (ib) * count_materialization_scale
+ + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
bb->loop_depth = lto_input_sleb128 (ib);
bb->frequency = lto_input_sleb128 (ib);
bb->flags = lto_input_sleb128 (ib);
{
gimple stmt = input_gimple_stmt (ib, data_in, fn, tag);
- /* Drop debug stmts on-the-fly if we do not have VTA enabled.
- This allows us to build for example static libs with debugging
- enabled and do the final link without. */
- if (MAY_HAVE_DEBUG_STMTS
- || !is_gimple_debug (stmt))
- {
- find_referenced_vars_in (stmt);
- gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
- }
+ find_referenced_vars_in (stmt);
+ gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
/* After the statement, expect a 0 delimiter or the EH region
that the previous statement belongs to. */
{
HOST_WIDE_INT region = lto_input_sleb128 (ib);
gcc_assert (region == (int) region);
- if (MAY_HAVE_DEBUG_STMTS || !is_gimple_debug (stmt))
- add_stmt_to_eh_lp (stmt, region);
+ add_stmt_to_eh_lp (stmt, region);
}
tag = input_record_start (ib);
struct cgraph_edge *cedge;
for (cedge = node->callees; cedge; cedge = cedge->next_callee)
cedge->call_stmt = stmts[cedge->lto_stmt_uid];
+ for (cedge = node->indirect_calls; cedge; cedge = cedge->next_callee)
+ cedge->call_stmt = stmts[cedge->lto_stmt_uid];
}
/* Fixup call_stmt pointers in NODE and all clones. */
/* Read the body of function FN_DECL from DATA_IN using input block IB. */
static void
-input_function (tree fn_decl, struct data_in *data_in,
+input_function (tree fn_decl, struct data_in *data_in,
struct lto_input_block *ib)
{
struct function *fn;
enum LTO_tags tag;
gimple *stmts;
basic_block bb;
- struct bitpack_d *bp;
+ struct bitpack_d bp;
+ struct cgraph_node *node;
+ tree args, narg, oarg;
+ int len;
fn = DECL_STRUCT_FUNCTION (fn_decl);
tag = input_record_start (ib);
/* Read all the attributes for FN. */
bp = lto_input_bitpack (ib);
- fn->is_thunk = bp_unpack_value (bp, 1);
- fn->has_local_explicit_reg_vars = bp_unpack_value (bp, 1);
- fn->after_tree_profile = bp_unpack_value (bp, 1);
- fn->returns_pcc_struct = bp_unpack_value (bp, 1);
- fn->returns_struct = bp_unpack_value (bp, 1);
- fn->always_inline_functions_inlined = bp_unpack_value (bp, 1);
- fn->after_inlining = bp_unpack_value (bp, 1);
- fn->dont_save_pending_sizes_p = bp_unpack_value (bp, 1);
- fn->stdarg = bp_unpack_value (bp, 1);
- fn->has_nonlocal_label = bp_unpack_value (bp, 1);
- fn->calls_alloca = bp_unpack_value (bp, 1);
- fn->calls_setjmp = bp_unpack_value (bp, 1);
- fn->function_frequency = (enum function_frequency) bp_unpack_value (bp, 2);
- fn->va_list_fpr_size = bp_unpack_value (bp, 8);
- fn->va_list_gpr_size = bp_unpack_value (bp, 8);
- bitpack_delete (bp);
+ fn->is_thunk = bp_unpack_value (&bp, 1);
+ fn->has_local_explicit_reg_vars = bp_unpack_value (&bp, 1);
+ fn->after_tree_profile = bp_unpack_value (&bp, 1);
+ fn->returns_pcc_struct = bp_unpack_value (&bp, 1);
+ fn->returns_struct = bp_unpack_value (&bp, 1);
+ fn->can_throw_non_call_exceptions = bp_unpack_value (&bp, 1);
+ fn->always_inline_functions_inlined = bp_unpack_value (&bp, 1);
+ fn->after_inlining = bp_unpack_value (&bp, 1);
+ fn->dont_save_pending_sizes_p = bp_unpack_value (&bp, 1);
+ fn->stdarg = bp_unpack_value (&bp, 1);
+ fn->has_nonlocal_label = bp_unpack_value (&bp, 1);
+ fn->calls_alloca = bp_unpack_value (&bp, 1);
+ fn->calls_setjmp = bp_unpack_value (&bp, 1);
+ fn->va_list_fpr_size = bp_unpack_value (&bp, 8);
+ fn->va_list_gpr_size = bp_unpack_value (&bp, 8);
+
+ /* Input the function start and end loci. */
+ fn->function_start_locus = lto_input_location (ib, data_in);
+ fn->function_end_locus = lto_input_location (ib, data_in);
+
+ /* Input the current IL state of the function. */
+ fn->curr_properties = lto_input_uleb128 (ib);
/* Read the static chain and non-local goto save area. */
fn->static_chain_decl = lto_input_tree (ib, data_in);
fn->nonlocal_goto_save_area = lto_input_tree (ib, data_in);
/* Read all the local symbols. */
- fn->local_decls = lto_input_tree (ib, data_in);
+ len = lto_input_sleb128 (ib);
+ if (len > 0)
+ {
+ int i;
+ VEC_safe_grow (tree, gc, fn->local_decls, len);
+ for (i = 0; i < len; i++)
+ {
+ tree t = lto_input_tree (ib, data_in);
+ VEC_replace (tree, fn->local_decls, i, t);
+ }
+ }
+
+ /* Read all function arguments. We need to re-map them here to the
+ arguments of the merged function declaration. */
+ args = lto_input_tree (ib, data_in);
+ for (oarg = args, narg = DECL_ARGUMENTS (fn_decl);
+ oarg && narg;
+ oarg = TREE_CHAIN (oarg), narg = TREE_CHAIN (narg))
+ {
+ int ix;
+ bool res;
+ res = lto_streamer_cache_lookup (data_in->reader_cache, oarg, &ix);
+ gcc_assert (res);
+ /* Replace the argument in the streamer cache. */
+ lto_streamer_cache_insert_at (data_in->reader_cache, narg, ix);
+ }
+ gcc_assert (!oarg && !narg);
/* Read all the SSA names. */
input_ssa_names (ib, data_in, fn);
DECL_INITIAL (fn_decl) = lto_input_tree (ib, data_in);
gcc_assert (DECL_INITIAL (fn_decl));
DECL_SAVED_TREE (fn_decl) = NULL_TREE;
-
- /* Read all function arguments. */
- DECL_ARGUMENTS (fn_decl) = lto_input_tree (ib, data_in);
+ node = cgraph_node (fn_decl);
/* Read all the basic blocks. */
tag = input_record_start (ib);
while (tag)
{
- input_bb (ib, tag, data_in, fn);
+ input_bb (ib, tag, data_in, fn,
+ node->count_materialization_scale);
tag = input_record_start (ib);
}
stmts = (gimple *) xcalloc (gimple_stmt_max_uid (fn), sizeof (gimple));
FOR_ALL_BB (bb)
{
- gimple_stmt_iterator bsi;
- for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
+ gimple_stmt_iterator bsi = gsi_start_bb (bb);
+ while (!gsi_end_p (bsi))
{
gimple stmt = gsi_stmt (bsi);
- stmts[gimple_uid (stmt)] = stmt;
+ /* If we're recompiling LTO objects with debug stmts but
+ we're not supposed to have debug stmts, remove them now.
+ We can't remove them earlier because this would cause uid
+ mismatches in fixups, but we can do it at this point, as
+ long as debug stmts don't require fixups. */
+ if (!MAY_HAVE_DEBUG_STMTS && is_gimple_debug (stmt))
+ {
+ gimple_stmt_iterator gsi = bsi;
+ gsi_next (&bsi);
+ gsi_remove (&gsi, true);
+ }
+ else
+ {
+ gsi_next (&bsi);
+ stmts[gimple_uid (stmt)] = stmt;
+ }
}
}
gimple_set_body (fn_decl, bb_seq (ei_edge (ei)->dest));
}
- fixup_call_stmt_edges (cgraph_node (fn_decl), stmts);
+ fixup_call_stmt_edges (node, stmts);
+ execute_all_ipa_stmt_fixups (node, stmts);
- update_ssa (TODO_update_ssa_only_virtuals);
+ update_ssa (TODO_update_ssa_only_virtuals);
+ free_dominance_info (CDI_DOMINATORS);
+ free_dominance_info (CDI_POST_DOMINATORS);
free (stmts);
}
{
const char *orig_name, *new_name;
alias_pair *p;
-
+
p = VEC_safe_push (alias_pair, gc, alias_pairs, NULL);
p->decl = var;
p->target = lto_input_tree (ib, data_in);
section type is LTO_section_function_body, FN must be the decl for
that function. */
-static void
+static void
lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
const char *data, enum lto_section_type section_type)
{
struct lto_input_block ib_main;
header = (const struct lto_function_header *) data;
- cfg_offset = sizeof (struct lto_function_header);
+ cfg_offset = sizeof (struct lto_function_header);
main_offset = cfg_offset + header->cfg_size;
string_offset = main_offset + header->main_size;
data + main_offset,
0,
header->main_size);
-
+
data_in = lto_data_in_create (file_data, data + string_offset,
header->string_size, NULL);
{
struct function *fn = DECL_STRUCT_FUNCTION (fn_decl);
struct lto_in_decl_state *decl_state;
+ struct cgraph_node *node = cgraph_node (fn_decl);
push_cfun (fn);
init_tree_ssa (fn);
gcc_assert (decl_state);
file_data->current_decl_state = decl_state;
- input_cfg (&ib_cfg, fn);
+ input_cfg (&ib_cfg, fn, node->count_materialization_scale);
/* Set up the struct function. */
input_function (fn_decl, data_in, &ib_main);
/* We should now be in SSA. */
cfun->gimple_df->in_ssa_p = true;
- /* Fill in properties we know hold for the rebuilt CFG. */
- cfun->curr_properties = PROP_ssa
- | PROP_cfg
- | PROP_gimple_any
- | PROP_gimple_lcf
- | PROP_gimple_leh
- | PROP_referenced_vars;
-
/* Restore decl state */
file_data->current_decl_state = file_data->global_decl_state;
pop_cfun ();
}
- else
+ else
{
input_alias_pairs (&ib_main, data_in);
}
/* Read the body of FN_DECL using DATA. FILE_DATA holds the global
decls and types. */
-void
+void
lto_input_function_body (struct lto_file_decl_data *file_data,
tree fn_decl, const char *data)
{
/* Read in VAR_DECL using DATA. FILE_DATA holds the global decls and
types. */
-void
+void
lto_input_constructors_and_inits (struct lto_file_decl_data *file_data,
const char *data)
{
if (data_in->globals_resolution)
{
ld_plugin_symbol_resolution_t ret;
- gcc_assert (index < VEC_length (ld_plugin_symbol_resolution_t,
- data_in->globals_resolution));
+ /* We can have references to not emitted functions in
+ DECL_FUNCTION_PERSONALITY at least. So we can and have
+ to indeed return LDPR_UNKNOWN in some cases. */
+ if (VEC_length (ld_plugin_symbol_resolution_t,
+ data_in->globals_resolution) <= index)
+ return LDPR_UNKNOWN;
ret = VEC_index (ld_plugin_symbol_resolution_t,
data_in->globals_resolution,
index);
- gcc_assert (ret != LDPR_UNKNOWN);
return ret;
}
else
- {
- /* Fake symbol resolution if no resolution file was provided. */
- tree t = lto_streamer_cache_get (data_in->reader_cache, index);
-
- gcc_assert (TREE_PUBLIC (t));
-
- /* There should be no DECL_ABSTRACT in the middle end. */
- gcc_assert (!DECL_ABSTRACT (t));
-
- /* If T is a weak definition, we select the first one we see to
- be the prevailing definition. */
- if (DECL_WEAK (t))
- {
- tree prevailing_decl;
- if (DECL_EXTERNAL (t))
- return LDPR_RESOLVED_IR;
-
- /* If this is the first time we see T, it won't have a
- prevailing definition yet. */
- prevailing_decl = lto_symtab_prevailing_decl (t);
- if (prevailing_decl == t
- || prevailing_decl == NULL_TREE
- || DECL_EXTERNAL (prevailing_decl))
- return LDPR_PREVAILING_DEF;
- else
- return LDPR_PREEMPTED_IR;
- }
- else
- {
- /* For non-weak definitions, extern declarations are assumed
- to be resolved elsewhere (LDPR_RESOLVED_IR), otherwise T
- is a prevailing definition. */
- if (DECL_EXTERNAL (t))
- return LDPR_RESOLVED_IR;
- else
- return LDPR_PREVAILING_DEF;
- }
- }
+ /* Delay resolution finding until decl merging. */
+ return LDPR_UNKNOWN;
}
so we skip it here. */
TREE_PUBLIC (expr) = (unsigned) bp_unpack_value (bp, 1);
}
+ else
+ bp_unpack_value (bp, 4);
TREE_ADDRESSABLE (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_THIS_VOLATILE (expr) = (unsigned) bp_unpack_value (bp, 1);
if (DECL_P (expr))
DECL_UNSIGNED (expr) = (unsigned) bp_unpack_value (bp, 1);
else if (TYPE_P (expr))
TYPE_UNSIGNED (expr) = (unsigned) bp_unpack_value (bp, 1);
+ else
+ bp_unpack_value (bp, 1);
TREE_ASM_WRITTEN (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_NO_WARNING (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_USED (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_DEPRECATED (expr) = (unsigned) bp_unpack_value (bp, 1);
if (TYPE_P (expr))
TYPE_SATURATING (expr) = (unsigned) bp_unpack_value (bp, 1);
- if (TREE_CODE (expr) == SSA_NAME)
+ else if (TREE_CODE (expr) == SSA_NAME)
SSA_NAME_IS_DEFAULT_DEF (expr) = (unsigned) bp_unpack_value (bp, 1);
+ else
+ bp_unpack_value (bp, 1);
}
unsigned i;
REAL_VALUE_TYPE r;
REAL_VALUE_TYPE *rp;
-
+
r.cl = (unsigned) bp_unpack_value (bp, 2);
r.decimal = (unsigned) bp_unpack_value (bp, 1);
r.sign = (unsigned) bp_unpack_value (bp, 1);
for (i = 0; i < SIGSZ; i++)
r.sig[i] = (unsigned long) bp_unpack_value (bp, HOST_BITS_PER_LONG);
- rp = GGC_NEW (REAL_VALUE_TYPE);
+ rp = ggc_alloc_real_value ();
memcpy (rp, &r, sizeof (REAL_VALUE_TYPE));
TREE_REAL_CST_PTR (expr) = rp;
}
unpack_ts_fixed_cst_value_fields (struct bitpack_d *bp, tree expr)
{
struct fixed_value fv;
-
+
fv.data.low = (HOST_WIDE_INT) bp_unpack_value (bp, HOST_BITS_PER_WIDE_INT);
fv.data.high = (HOST_WIDE_INT) bp_unpack_value (bp, HOST_BITS_PER_WIDE_INT);
+ fv.mode = (enum machine_mode) bp_unpack_value (bp, HOST_BITS_PER_INT);
TREE_FIXED_CST (expr) = fv;
}
if (TREE_CODE (expr) == VAR_DECL
|| TREE_CODE (expr) == PARM_DECL)
DECL_HAS_VALUE_EXPR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
+ DECL_RESTRICTED_P (expr) = (unsigned) bp_unpack_value (bp, 1);
}
}
{
DECL_HARD_REGISTER (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_IN_TEXT_SECTION (expr) = (unsigned) bp_unpack_value (bp, 1);
+ DECL_IN_CONSTANT_POOL (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_TLS_MODEL (expr) = (enum tls_model) bp_unpack_value (bp, 3);
}
{
enum machine_mode mode;
- TYPE_PRECISION (expr) = (unsigned) bp_unpack_value (bp, 9);
- mode = (enum machine_mode) bp_unpack_value (bp, 7);
+ TYPE_PRECISION (expr) = (unsigned) bp_unpack_value (bp, 10);
+ mode = (enum machine_mode) bp_unpack_value (bp, 8);
SET_TYPE_MODE (expr, mode);
TYPE_STRING_FLAG (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_NO_FORCE_BLK (expr) = (unsigned) bp_unpack_value (bp, 1);
- TYPE_NEEDS_CONSTRUCTING(expr) = (unsigned) bp_unpack_value (bp, 1);
- if (TREE_CODE (expr) == UNION_TYPE)
- TYPE_TRANSPARENT_UNION (expr) = (unsigned) bp_unpack_value (bp, 1);
+ TYPE_NEEDS_CONSTRUCTING (expr) = (unsigned) bp_unpack_value (bp, 1);
+ if (RECORD_OR_UNION_TYPE_P (expr))
+ TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_RESTRICT (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr)
BLOCK_NUMBER (expr) = (unsigned) bp_unpack_value (bp, 31);
}
+/* Unpack all the non-pointer fields of the TS_TRANSLATION_UNIT_DECL
+ structure of expression EXPR from bitpack BP. */
+
+static void
+unpack_ts_translation_unit_decl_value_fields (struct bitpack_d *bp ATTRIBUTE_UNUSED, tree expr ATTRIBUTE_UNUSED)
+{
+}
/* Unpack all the non-pointer fields in EXPR into a bit pack. */
/* This is only used by High GIMPLE. */
gcc_unreachable ();
}
-}
-
-
-/* Read a bitpack from input block IB. */
-
-struct bitpack_d *
-lto_input_bitpack (struct lto_input_block *ib)
-{
- unsigned i, num_words;
- struct bitpack_d *bp;
-
- bp = bitpack_create ();
-
- /* If we are about to read more than a handful of words, something
- is wrong. This check is overly strict, but it acts as an early
- warning. No streamed object has hundreds of bits in its fields. */
- num_words = lto_input_uleb128 (ib);
- gcc_assert (num_words < 20);
-
- for (i = 0; i < num_words; i++)
- {
- bitpack_word_t w = lto_input_uleb128 (ib);
- VEC_safe_push (bitpack_word_t, heap, bp->values, w);
- }
- return bp;
+ if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
+ unpack_ts_translation_unit_decl_value_fields (bp, expr);
}
lto_materialize_tree (struct lto_input_block *ib, struct data_in *data_in,
enum LTO_tags tag, int *ix_p)
{
- struct bitpack_d *bp;
+ struct bitpack_d bp;
enum tree_code code;
tree result;
#ifdef LTO_STREAMER_DEBUG
/* The first word in BP contains the code of the tree that we
are about to read. */
- code = (enum tree_code) bp_unpack_value (bp, 16);
+ code = (enum tree_code) bp_unpack_value (&bp, 16);
lto_tag_check (lto_tree_code_to_tag (code), tag);
/* Unpack all the value fields from BP. */
- unpack_value_fields (bp, result);
- bitpack_delete (bp);
+ unpack_value_fields (&bp, result);
/* Enter RESULT in the reader cache. This will make RESULT
available so that circular references in the rest of the tree
{
int i, count;
tree first, prev, curr;
-
+
first = prev = NULL_TREE;
count = lto_input_sleb128 (ib);
for (i = 0; i < count; i++)
return first;
}
-
+
/* Read all pointer fields in the TS_COMMON structure of EXPR from input
block IB. DATA_IN contains tables and descriptors for the
file being read. */
lto_input_ts_common_tree_pointers (struct lto_input_block *ib,
struct data_in *data_in, tree expr)
{
- TREE_TYPE (expr) = lto_input_tree (ib, data_in);
+ if (TREE_CODE (expr) != IDENTIFIER_NODE)
+ TREE_TYPE (expr) = lto_input_tree (ib, data_in);
}
{
DECL_NAME (expr) = lto_input_tree (ib, data_in);
DECL_CONTEXT (expr) = lto_input_tree (ib, data_in);
+ /* We do not stream BLOCK_VARS but lazily construct it here. */
+ if (DECL_CONTEXT (expr)
+ && TREE_CODE (DECL_CONTEXT (expr)) == BLOCK)
+ {
+ TREE_CHAIN (expr) = BLOCK_VARS (DECL_CONTEXT (expr));
+ BLOCK_VARS (DECL_CONTEXT (expr)) = expr;
+ }
DECL_SOURCE_LOCATION (expr) = lto_input_location (ib, data_in);
}
if (TREE_CODE (expr) == PARM_DECL)
TREE_CHAIN (expr) = lto_input_chain (ib, data_in);
+
+ if ((TREE_CODE (expr) == VAR_DECL
+ || TREE_CODE (expr) == PARM_DECL)
+ && DECL_HAS_VALUE_EXPR_P (expr))
+ SET_DECL_VALUE_EXPR (expr, lto_input_tree (ib, data_in));
+
+ if (TREE_CODE (expr) == VAR_DECL)
+ {
+ tree dexpr = lto_input_tree (ib, data_in);
+ if (dexpr)
+ SET_DECL_DEBUG_EXPR (expr, dexpr);
+ }
}
struct data_in *data_in, tree expr)
{
tree id;
-
+
id = lto_input_tree (ib, data_in);
if (id)
{
DECL_FUNCTION_PERSONALITY (expr) = lto_input_tree (ib, data_in);
DECL_FUNCTION_SPECIFIC_TARGET (expr) = lto_input_tree (ib, data_in);
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr) = lto_input_tree (ib, data_in);
+
+ /* If the file contains a function with an EH personality set,
+ then it was compiled with -fexceptions. In that case, initialize
+ the backend EH machinery. */
+ if (DECL_FUNCTION_PERSONALITY (expr))
+ lto_init_eh ();
}
TYPE_VALUES (expr) = lto_input_tree (ib, data_in);
else if (TREE_CODE (expr) == ARRAY_TYPE)
TYPE_DOMAIN (expr) = lto_input_tree (ib, data_in);
- else if (TREE_CODE (expr) == RECORD_TYPE || TREE_CODE (expr) == UNION_TYPE)
+ else if (RECORD_OR_UNION_TYPE_P (expr))
TYPE_FIELDS (expr) = lto_input_tree (ib, data_in);
- else if (TREE_CODE (expr) == FUNCTION_TYPE || TREE_CODE (expr) == METHOD_TYPE)
+ else if (TREE_CODE (expr) == FUNCTION_TYPE
+ || TREE_CODE (expr) == METHOD_TYPE)
TYPE_ARG_TYPES (expr) = lto_input_tree (ib, data_in);
- else if (TREE_CODE (expr) == VECTOR_TYPE)
- TYPE_DEBUG_REPRESENTATION_TYPE (expr) = lto_input_tree (ib, data_in);
TYPE_SIZE (expr) = lto_input_tree (ib, data_in);
TYPE_SIZE_UNIT (expr) = lto_input_tree (ib, data_in);
if (RECORD_OR_UNION_TYPE_P (expr))
TYPE_BINFO (expr) = lto_input_tree (ib, data_in);
TYPE_CONTEXT (expr) = lto_input_tree (ib, data_in);
- TYPE_CANONICAL (expr) = lto_input_tree (ib, data_in);
+ /* TYPE_CANONICAL gets re-computed during type merging. */
+ TYPE_CANONICAL (expr) = NULL_TREE;
+ TYPE_STUB_DECL (expr) = lto_input_tree (ib, data_in);
}
unsigned i, len;
BLOCK_SOURCE_LOCATION (expr) = lto_input_location (ib, data_in);
- BLOCK_VARS (expr) = lto_input_chain (ib, data_in);
+ /* We do not stream BLOCK_VARS but lazily construct it when reading
+ in decls. */
len = lto_input_uleb128 (ib);
- for (i = 0; i < len; i++)
+ if (len > 0)
{
- tree t = lto_input_tree (ib, data_in);
- VEC_safe_push (tree, gc, BLOCK_NONLOCALIZED_VARS (expr), t);
+ VEC_reserve_exact (tree, gc, BLOCK_NONLOCALIZED_VARS (expr), len);
+ for (i = 0; i < len; i++)
+ {
+ tree t = lto_input_tree (ib, data_in);
+ VEC_quick_push (tree, BLOCK_NONLOCALIZED_VARS (expr), t);
+ }
}
BLOCK_SUPERCONTEXT (expr) = lto_input_tree (ib, data_in);
BLOCK_ABSTRACT_ORIGIN (expr) = lto_input_tree (ib, data_in);
BLOCK_FRAGMENT_ORIGIN (expr) = lto_input_tree (ib, data_in);
BLOCK_FRAGMENT_CHAIN (expr) = lto_input_tree (ib, data_in);
- BLOCK_SUBBLOCKS (expr) = lto_input_chain (ib, data_in);
+ /* We re-compute BLOCK_SUBBLOCKS of our parent here instead
+ of streaming it. For non-BLOCK BLOCK_SUPERCONTEXTs we still
+ stream the child relationship explicitly. */
+ if (BLOCK_SUPERCONTEXT (expr)
+ && TREE_CODE (BLOCK_SUPERCONTEXT (expr)) == BLOCK)
+ {
+ BLOCK_CHAIN (expr) = BLOCK_SUBBLOCKS (BLOCK_SUPERCONTEXT (expr));
+ BLOCK_SUBBLOCKS (BLOCK_SUPERCONTEXT (expr)) = expr;
+ }
}
BINFO_VPTR_FIELD (expr) = lto_input_tree (ib, data_in);
len = lto_input_uleb128 (ib);
- for (i = 0; i < len; i++)
+ if (len > 0)
{
- tree a = lto_input_tree (ib, data_in);
- VEC_safe_push (tree, gc, BINFO_BASE_ACCESSES (expr), a);
+ VEC_reserve_exact (tree, gc, BINFO_BASE_ACCESSES (expr), len);
+ for (i = 0; i < len; i++)
+ {
+ tree a = lto_input_tree (ib, data_in);
+ VEC_quick_push (tree, BINFO_BASE_ACCESSES (expr), a);
+ }
}
BINFO_INHERITANCE_CHAIN (expr) = lto_input_tree (ib, data_in);
}
+/* Input a TS_TARGET_OPTION tree from IB into EXPR. */
+
+static void
+lto_input_ts_target_option (struct lto_input_block *ib, tree expr)
+{
+ unsigned i, len;
+ struct bitpack_d bp;
+ struct cl_target_option *t = TREE_TARGET_OPTION (expr);
+
+ bp = lto_input_bitpack (ib);
+ len = sizeof (struct cl_target_option);
+ for (i = 0; i < len; i++)
+ ((unsigned char *)t)[i] = bp_unpack_value (&bp, 8);
+ if (bp_unpack_value (&bp, 32) != 0x12345678)
+ fatal_error ("cl_target_option size mismatch in LTO reader and writer");
+}
+
+/* Input a TS_TRANSLATION_UNIT_DECL tree from IB and DATA_IN into EXPR. */
+
+static void
+lto_input_ts_translation_unit_decl_tree_pointers (struct lto_input_block *ib,
+ struct data_in *data_in,
+ tree expr)
+{
+ TRANSLATION_UNIT_LANGUAGE (expr) = xstrdup (input_string (data_in, ib));
+ VEC_safe_push (tree, gc, all_translation_units, expr);
+}
+
/* Helper for lto_input_tree. Read all pointer fields in EXPR from
input block IB. DATA_IN contains tables and descriptors for the
file being read. */
}
if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION))
- {
- sorry ("target optimization options not supported yet");
- }
-}
-
-static VEC(tree, heap) *deferred_global_decls;
-
-/* Register the queued global decls with the symtab. DATA_IN contains
- tables and descriptors for the file being read.*/
+ lto_input_ts_target_option (ib, expr);
-void
-lto_register_deferred_decls_in_symtab (struct data_in *data_in)
-{
- unsigned i;
- tree decl;
-
- for (i = 0; VEC_iterate (tree, deferred_global_decls, i, decl); ++i)
- {
- enum ld_plugin_symbol_resolution resolution;
- int ix;
-
- if (!lto_streamer_cache_lookup (data_in->reader_cache, decl, &ix))
- gcc_unreachable ();
-
- /* Register and adjust the decls type. */
- TREE_TYPE (decl) = gimple_register_type (TREE_TYPE (decl));
-
- if (TREE_CODE (decl) == VAR_DECL)
- {
- gcc_assert (TREE_PUBLIC (decl));
- resolution = get_resolution (data_in, ix);
- lto_symtab_merge_var (decl, resolution);
- }
- else if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- gcc_assert (TREE_PUBLIC (decl) && !DECL_ABSTRACT (decl));
- resolution = get_resolution (data_in, ix);
- lto_symtab_merge_fn (decl, resolution, data_in->file_data);
- }
- else
- gcc_unreachable ();
- }
-
- VEC_free (tree, heap, deferred_global_decls);
- deferred_global_decls = NULL;
+ if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
+ lto_input_ts_translation_unit_decl_tree_pointers (ib, data_in, expr);
}
different files. */
static void
-lto_register_var_decl_in_symtab (tree decl)
-{
- /* Register symbols with file or global scope to mark what input
- file has their definition. */
- if (decl_function_context (decl) == NULL_TREE)
- {
- /* Variable has file scope, not local. Need to ensure static variables
- between different files don't clash unexpectedly. */
- if (!TREE_PUBLIC (decl))
- {
- /* ??? We normally pre-mangle names before we serialize them
- out. Here, in lto1, we do not know the language, and
- thus cannot do the mangling again. Instead, we just
- append a suffix to the mangled name. The resulting name,
- however, is not a properly-formed mangled name, and will
- confuse any attempt to unmangle it. */
- const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- char *label;
-
- ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
- SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
- rest_of_decl_compilation (decl, 1, 0);
- }
+lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl)
+{
+ tree context;
+
+ /* Variable has file scope, not local. Need to ensure static variables
+ between different files don't clash unexpectedly. */
+ if (!TREE_PUBLIC (decl)
+ && !((context = decl_function_context (decl))
+ && auto_var_in_fn_p (decl, context)))
+ {
+ /* ??? We normally pre-mangle names before we serialize them
+ out. Here, in lto1, we do not know the language, and
+ thus cannot do the mangling again. Instead, we just
+ append a suffix to the mangled name. The resulting name,
+ however, is not a properly-formed mangled name, and will
+ confuse any attempt to unmangle it. */
+ const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ char *label;
+
+ ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
+ SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
+ rest_of_decl_compilation (decl, 1, 0);
}
/* If this variable has already been declared, queue the
declaration for merging. */
if (TREE_PUBLIC (decl))
- VEC_safe_push (tree, heap, deferred_global_decls, decl);
+ {
+ int ix;
+ if (!lto_streamer_cache_lookup (data_in->reader_cache, decl, &ix))
+ gcc_unreachable ();
+ lto_symtab_register_decl (decl, get_resolution (data_in, ix),
+ data_in->file_data);
+ }
}
attempt to unmangle it. */
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
char *label;
-
+
ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
/* Also register the reverse mapping so that we can find the
new name given to an existing assembler name (used when
- restoring alias pairs in input_constructors_or_inits. */
+ restoring alias pairs in input_constructors_or_inits. */
lto_record_renamed_decl (data_in->file_data,
IDENTIFIER_POINTER (new_assembler_name),
IDENTIFIER_POINTER (old_assembler_name));
- }
+ }
}
/* If this variable has already been declared, queue the
declaration for merging. */
if (TREE_PUBLIC (decl) && !DECL_ABSTRACT (decl))
- VEC_safe_push (tree, heap, deferred_global_decls, decl);
+ {
+ int ix;
+ if (!lto_streamer_cache_lookup (data_in->reader_cache, decl, &ix))
+ gcc_unreachable ();
+ lto_symtab_register_decl (decl, get_resolution (data_in, ix),
+ data_in->file_data);
+ }
}
gcc_assert (fclass == BUILT_IN_NORMAL || fclass == BUILT_IN_MD);
fcode = (enum built_in_function) lto_input_uleb128 (ib);
- gcc_assert (fcode < END_BUILTINS);
ix = lto_input_sleb128 (ib);
gcc_assert (ix == (int) ix);
- result = built_in_decls[fcode];
- gcc_assert (result);
+ if (fclass == BUILT_IN_NORMAL)
+ {
+ gcc_assert (fcode < END_BUILTINS);
+ result = built_in_decls[fcode];
+ gcc_assert (result);
+ }
+ else if (fclass == BUILT_IN_MD)
+ {
+ result = targetm.builtin_decl (fcode, true);
+ if (!result || result == error_mark_node)
+ fatal_error ("target specific builtin not available");
+ }
+ else
+ gcc_unreachable ();
asmname = input_string (data_in, ib);
if (asmname)
enum LTO_tags tag)
{
tree result;
- char end_marker;
int ix;
result = lto_materialize_tree (ib, data_in, tag, &ix);
gcc_assert (!lto_stream_as_builtin_p (result));
if (TREE_CODE (result) == VAR_DECL)
- lto_register_var_decl_in_symtab (result);
+ lto_register_var_decl_in_symtab (data_in, result);
else if (TREE_CODE (result) == FUNCTION_DECL && !DECL_BUILT_IN (result))
lto_register_function_decl_in_symtab (data_in, result);
- end_marker = lto_input_1_unsigned (ib);
+ /* end_marker = */ lto_input_1_unsigned (ib);
#ifdef LTO_STREAMER_DEBUG
/* Remove the mapping to RESULT's original address set by
{
enum LTO_tags tag;
tree result;
-
+
tag = input_record_start (ib);
gcc_assert ((unsigned) tag < (unsigned) LTO_NUM_TAGS);