static eh_region input_eh_region (struct lto_input_block *ib, struct data_in *data_in, int ix) { enum LTO_tags tag; eh_region r; tag = streamer_read_record_start (ib); if (tag == LTO_null) return __null; r = ((struct eh_region_d *)(ggc_internal_cleared_alloc_stat (sizeof (struct eh_region_d) ))); r->index = streamer_read_hwi (ib); r->outer = (eh_region) (intptr_t) streamer_read_hwi (ib); r->inner = (eh_region) (intptr_t) streamer_read_hwi (ib); switch (tag) { case LTO_ert_cleanup: { struct eh_catch_d *last_catch; r->u.eh_try.first_catch = lto_input_eh_catch_list (ib, data_in, &last_catch); } { tree l; add_type_for_runtime (((tree_check ((l), "../../../gcc-4.8~svn195526/gcc/lto-streamer-in.c", 346, __FUNCTION__, (TREE_LIST)))->list.value)); } } }
void 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; gimple_stmt_iterator bsi; /* This routine assumes that CFUN is set to FN, as it needs to call basic GIMPLE routines that use CFUN. */ gcc_assert (cfun == fn); index = streamer_read_uhwi (ib); bb = BASIC_BLOCK_FOR_FUNCTION (fn, index); bb->count = (streamer_read_hwi (ib) * count_materialization_scale + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; bb->loop_depth = streamer_read_hwi (ib); bb->frequency = streamer_read_hwi (ib); bb->flags = streamer_read_hwi (ib); /* LTO_bb1 has statements. LTO_bb0 does not. */ if (tag == LTO_bb0) return; bsi = gsi_start_bb (bb); tag = streamer_read_record_start (ib); while (tag) { gimple stmt = input_gimple_stmt (ib, data_in, fn, tag); if (!is_gimple_debug (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. */ tag = streamer_read_record_start (ib); lto_tag_check_set (tag, 2, LTO_eh_region, LTO_null); if (tag == LTO_eh_region) { HOST_WIDE_INT region = streamer_read_hwi (ib); gcc_assert (region == (int) region); add_stmt_to_eh_lp (stmt, region); } tag = streamer_read_record_start (ib); } tag = streamer_read_record_start (ib); while (tag) { gimple phi = input_phi (ib, bb, data_in, fn); find_referenced_vars_in (phi); tag = streamer_read_record_start (ib); } }
gcov_type streamer_read_gcov_count (struct lto_input_block *ib) { gcov_type ret = streamer_read_hwi (ib); gcc_assert (ret >= 0); return ret; }
tree streamer_read_integer_cst (struct lto_input_block *ib, struct data_in *data_in) { tree type = stream_read_tree (ib, data_in); unsigned HOST_WIDE_INT low = streamer_read_uhwi (ib); HOST_WIDE_INT high = streamer_read_hwi (ib); return build_int_cst_wide (type, low, high); }
static void lto_input_ts_exp_tree_pointers (struct lto_input_block *ib, struct data_in *data_in, tree expr) { int i, length; location_t loc; length = streamer_read_hwi (ib); gcc_assert (length == TREE_OPERAND_LENGTH (expr)); for (i = 0; i < length; i++) TREE_OPERAND (expr, i) = stream_read_tree (ib, data_in); loc = lto_input_location (ib, data_in); SET_EXPR_LOCATION (expr, loc); TREE_BLOCK (expr) = stream_read_tree (ib, data_in); }
static void input_eh_regions (struct lto_input_block *ib, struct data_in *data_in, struct function *fn) { long long i, root_region, len; enum LTO_tags tag; tag = streamer_read_record_start (ib); if (tag == LTO_null) return; len = streamer_read_hwi (ib); if (len > 0) { for (i = 0; i < len; i++) { eh_region r = input_eh_region (ib, data_in, i); } } }
tree streamer_read_chain (struct lto_input_block *ib, struct data_in *data_in) { int i, count; tree first, prev, curr; first = prev = NULL_TREE; count = streamer_read_hwi (ib); for (i = 0; i < count; i++) { curr = stream_read_tree (ib, data_in); if (prev) TREE_CHAIN (prev) = curr; else first = curr; TREE_CHAIN (curr) = NULL_TREE; prev = curr; } return first; }
tree streamer_alloc_tree (struct lto_input_block *ib, struct data_in *data_in, enum LTO_tags tag) { enum tree_code code; tree result; #ifdef LTO_STREAMER_DEBUG HOST_WIDE_INT orig_address_in_writer; #endif result = NULL_TREE; #ifdef LTO_STREAMER_DEBUG /* Read the word representing the memory address for the tree as it was written by the writer. This is useful when debugging differences between the writer and reader. */ orig_address_in_writer = streamer_read_hwi (ib); gcc_assert ((intptr_t) orig_address_in_writer == orig_address_in_writer); #endif code = lto_tag_to_tree_code (tag); /* We should never see an SSA_NAME tree. Only the version numbers of SSA names are ever written out. See input_ssa_names. */ gcc_assert (code != SSA_NAME); /* Instantiate a new tree using the header data. */ if (CODE_CONTAINS_STRUCT (code, TS_STRING)) result = streamer_read_string_cst (data_in, ib); else if (CODE_CONTAINS_STRUCT (code, TS_IDENTIFIER)) result = input_identifier (data_in, ib); else if (CODE_CONTAINS_STRUCT (code, TS_VEC)) { HOST_WIDE_INT len = streamer_read_hwi (ib); result = make_tree_vec (len); } else if (CODE_CONTAINS_STRUCT (code, TS_VECTOR)) { HOST_WIDE_INT len = streamer_read_hwi (ib); result = make_vector (len); } else if (CODE_CONTAINS_STRUCT (code, TS_BINFO)) { unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib); result = make_tree_binfo (len); } else if (CODE_CONTAINS_STRUCT (code, TS_INT_CST)) { unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib); unsigned HOST_WIDE_INT ext_len = streamer_read_uhwi (ib); result = make_int_cst (len, ext_len); } else if (code == CALL_EXPR) { unsigned HOST_WIDE_INT nargs = streamer_read_uhwi (ib); return build_vl_exp (CALL_EXPR, nargs + 3); } else if (code == OMP_CLAUSE) { enum omp_clause_code subcode = (enum omp_clause_code) streamer_read_uhwi (ib); return build_omp_clause (UNKNOWN_LOCATION, subcode); } else { /* For all other nodes, materialize the tree with a raw make_node call. */ result = make_node (code); } #ifdef LTO_STREAMER_DEBUG /* Store the original address of the tree as seen by the writer in RESULT's aux field. This is useful when debugging streaming problems. This way, a debugging session can be started on both writer and reader with a breakpoint using this address value in both. */ lto_orig_address_map (result, (intptr_t) orig_address_in_writer); #endif return result; }
static gimple input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in, struct function *fn, enum LTO_tags tag) { gimple stmt; enum gimple_code code; unsigned HOST_WIDE_INT num_ops; size_t i; struct bitpack_d bp; code = lto_tag_to_gimple_code (tag); /* Read the tuple header. */ bp = streamer_read_bitpack (ib); num_ops = bp_unpack_var_len_unsigned (&bp); stmt = gimple_alloc (code, num_ops); 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_var_len_unsigned (&bp); /* Read location information. */ gimple_set_location (stmt, lto_input_location (ib, data_in)); /* Read lexical block reference. */ gimple_set_block (stmt, stream_read_tree (ib, data_in)); /* Read in all the operands. */ switch (code) { case GIMPLE_RESX: gimple_resx_set_region (stmt, streamer_read_hwi (ib)); break; case GIMPLE_EH_MUST_NOT_THROW: gimple_eh_must_not_throw_set_fndecl (stmt, stream_read_tree (ib, data_in)); break; case GIMPLE_EH_DISPATCH: gimple_eh_dispatch_set_region (stmt, streamer_read_hwi (ib)); break; case GIMPLE_ASM: { /* FIXME lto. Move most of this into a new gimple_asm_set_string(). */ tree str; stmt->gimple_asm.ni = streamer_read_uhwi (ib); stmt->gimple_asm.no = streamer_read_uhwi (ib); stmt->gimple_asm.nc = streamer_read_uhwi (ib); stmt->gimple_asm.nl = streamer_read_uhwi (ib); str = streamer_read_string_cst (data_in, ib); stmt->gimple_asm.string = TREE_STRING_POINTER (str); } /* Fallthru */ case GIMPLE_ASSIGN: case GIMPLE_CALL: case GIMPLE_RETURN: case GIMPLE_SWITCH: case GIMPLE_LABEL: case GIMPLE_COND: case GIMPLE_GOTO: case GIMPLE_DEBUG: for (i = 0; i < num_ops; i++) { tree op = stream_read_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 (TREE_CODE (tem) != FIELD_DECL) continue; 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); } } if (is_gimple_call (stmt)) { if (gimple_call_internal_p (stmt)) gimple_call_set_internal_fn (stmt, streamer_read_enum (ib, internal_fn, IFN_LAST)); else gimple_call_set_fntype (stmt, stream_read_tree (ib, data_in)); } break; case GIMPLE_NOP: case GIMPLE_PREDICT: break; case GIMPLE_TRANSACTION: gimple_transaction_set_label (stmt, stream_read_tree (ib, data_in)); break; default: internal_error ("bytecode stream: unknown GIMPLE statement tag %s", lto_tag_name (tag)); } /* Update the properties of symbols, SSA names and labels associated with STMT. */ if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL) { tree lhs = gimple_get_lhs (stmt); if (lhs && TREE_CODE (lhs) == SSA_NAME) SSA_NAME_DEF_STMT (lhs) = stmt; } else if (code == GIMPLE_LABEL) gcc_assert (emit_label_in_global_context_p (gimple_label_label (stmt)) || DECL_CONTEXT (gimple_label_label (stmt)) == fn->decl); else if (code == GIMPLE_ASM) { unsigned i; for (i = 0; i < gimple_asm_noutputs (stmt); i++) { tree op = TREE_VALUE (gimple_asm_output_op (stmt, i)); if (TREE_CODE (op) == SSA_NAME) SSA_NAME_DEF_STMT (op) = stmt; } } /* 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; }
static gimple * input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in, enum LTO_tags tag) { gimple *stmt; enum gimple_code code; unsigned HOST_WIDE_INT num_ops; size_t i; struct bitpack_d bp; bool has_hist; code = lto_tag_to_gimple_code (tag); /* Read the tuple header. */ bp = streamer_read_bitpack (ib); num_ops = bp_unpack_var_len_unsigned (&bp); stmt = gimple_alloc (code, num_ops); stmt->no_warning = bp_unpack_value (&bp, 1); if (is_gimple_assign (stmt)) stmt->nontemporal_move = bp_unpack_value (&bp, 1); stmt->has_volatile_ops = bp_unpack_value (&bp, 1); 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 in all the operands. */ switch (code) { case GIMPLE_RESX: gimple_resx_set_region (as_a <gresx *> (stmt), streamer_read_hwi (ib)); break; case GIMPLE_EH_MUST_NOT_THROW: gimple_eh_must_not_throw_set_fndecl ( as_a <geh_mnt *> (stmt), stream_read_tree (ib, data_in)); break; case GIMPLE_EH_DISPATCH: gimple_eh_dispatch_set_region (as_a <geh_dispatch *> (stmt), streamer_read_hwi (ib)); break; case GIMPLE_ASM: { /* FIXME lto. Move most of this into a new gimple_asm_set_string(). */ gasm *asm_stmt = as_a <gasm *> (stmt); tree str; asm_stmt->ni = streamer_read_uhwi (ib); asm_stmt->no = streamer_read_uhwi (ib); asm_stmt->nc = streamer_read_uhwi (ib); asm_stmt->nl = streamer_read_uhwi (ib); str = streamer_read_string_cst (data_in, ib); asm_stmt->string = TREE_STRING_POINTER (str); } /* Fallthru */ case GIMPLE_ASSIGN: case GIMPLE_CALL: case GIMPLE_RETURN: case GIMPLE_SWITCH: case GIMPLE_LABEL: case GIMPLE_COND: case GIMPLE_GOTO: case GIMPLE_DEBUG: for (i = 0; i < num_ops; i++) { tree *opp, op = stream_read_tree (ib, data_in); gimple_set_op (stmt, i, op); if (!op) continue; opp = gimple_op_ptr (stmt, i); if (TREE_CODE (*opp) == ADDR_EXPR) opp = &TREE_OPERAND (*opp, 0); while (handled_component_p (*opp)) opp = &TREE_OPERAND (*opp, 0); /* At LTO output time we wrap all global decls in MEM_REFs to allow seamless replacement with prevailing decls. Undo this here if the prevailing decl allows for this. ??? Maybe we should simply fold all stmts. */ if (TREE_CODE (*opp) == MEM_REF && TREE_CODE (TREE_OPERAND (*opp, 0)) == ADDR_EXPR && integer_zerop (TREE_OPERAND (*opp, 1)) && (TREE_THIS_VOLATILE (*opp) == TREE_THIS_VOLATILE (TREE_OPERAND (TREE_OPERAND (*opp, 0), 0))) && !TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (*opp, 1))) && (TREE_TYPE (*opp) == TREE_TYPE (TREE_TYPE (TREE_OPERAND (*opp, 1)))) && (TREE_TYPE (*opp) == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*opp, 0), 0)))) *opp = TREE_OPERAND (TREE_OPERAND (*opp, 0), 0); } if (gcall *call_stmt = dyn_cast <gcall *> (stmt)) { if (gimple_call_internal_p (call_stmt)) gimple_call_set_internal_fn (call_stmt, streamer_read_enum (ib, internal_fn, IFN_LAST)); else gimple_call_set_fntype (call_stmt, stream_read_tree (ib, data_in)); } break; case GIMPLE_NOP: case GIMPLE_PREDICT: break; case GIMPLE_TRANSACTION: gimple_transaction_set_label (as_a <gtransaction *> (stmt), stream_read_tree (ib, data_in)); break; default: internal_error ("bytecode stream: unknown GIMPLE statement tag %s", lto_tag_name (tag)); } /* Update the properties of symbols, SSA names and labels associated with STMT. */ if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL) { tree lhs = gimple_get_lhs (stmt); if (lhs && TREE_CODE (lhs) == SSA_NAME) SSA_NAME_DEF_STMT (lhs) = stmt; } else if (code == GIMPLE_ASM) { gasm *asm_stmt = as_a <gasm *> (stmt); unsigned i; for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++) { tree op = TREE_VALUE (gimple_asm_output_op (asm_stmt, i)); if (TREE_CODE (op) == SSA_NAME) SSA_NAME_DEF_STMT (op) = stmt; } } /* Reset alias information. */ if (code == GIMPLE_CALL) gimple_call_reset_alias_info (as_a <gcall *> (stmt)); /* Mark the statement modified so its operand vectors can be filled in. */ gimple_set_modified (stmt, true); if (has_hist) stream_in_histogram_value (ib, stmt); return stmt; }