/* Read the CFG for function FN from input block IB. */
static void
-input_cfg (struct lto_input_block *ib, struct function *fn)
+input_cfg (struct lto_input_block *ib, struct function *fn,
+ int count_materialization_scale)
{
unsigned int bb_count;
basic_block p_bb;
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 (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
- || (gimple_types_compatible_p (TREE_TYPE (tem),
- TREE_TYPE (field),
- GTC_DIAG)
- && DECL_NONADDRESSABLE_P (tem)
- == DECL_NONADDRESSABLE_P (field)
- && gimple_compare_field_offset (tem, field)))
+ 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. So only assert here if checking
- is enabled. */
-#ifdef ENABLE_CHECKING
- gcc_assert (tem != NULL_TREE);
-#endif
- if (tem != NULL_TREE)
+ 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;
}
static void
input_bb (struct lto_input_block *ib, enum LTO_tags tag,
- struct data_in *data_in, struct function *fn)
+ 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);
DECL_INITIAL (fn_decl) = lto_input_tree (ib, data_in);
gcc_assert (DECL_INITIAL (fn_decl));
DECL_SAVED_TREE (fn_decl) = NULL_TREE;
+ 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);
}
gimple_set_body (fn_decl, bb_seq (ei_edge (ei)->dest));
}
- node = cgraph_node (fn_decl);
fixup_call_stmt_edges (node, stmts);
execute_all_ipa_stmt_fixups (node, stmts);
{
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);
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);
}
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);
if (len > 0)
static void
lto_register_var_decl_in_symtab (struct data_in *data_in, 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);
- }
+ 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