aboutsummaryrefslogtreecommitdiff
path: root/gcc/lto-streamer-in.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/lto-streamer-in.c')
-rw-r--r--gcc/lto-streamer-in.c206
1 files changed, 189 insertions, 17 deletions
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index d9c207d0b7f..000be331a94 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
#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
@@ -274,26 +275,31 @@ static location_t
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);
}
@@ -868,6 +874,128 @@ input_ssa_names (struct lto_input_block *ib, struct data_in *data_in,
}
+/* Fixup the reference tree OP for replaced VAR_DECLs with mismatched
+ types. */
+
+static void
+maybe_fixup_handled_component (tree op)
+{
+ tree decl_type;
+ tree wanted_type;
+
+ while (handled_component_p (TREE_OPERAND (op, 0)))
+ op = TREE_OPERAND (op, 0);
+ if (TREE_CODE (TREE_OPERAND (op, 0)) != VAR_DECL)
+ return;
+
+ decl_type = TREE_TYPE (TREE_OPERAND (op, 0));
+
+ switch (TREE_CODE (op))
+ {
+ case COMPONENT_REF:
+ /* The DECL_CONTEXT of the field-decl is the record type we look for. */
+ wanted_type = DECL_CONTEXT (TREE_OPERAND (op, 1));
+ break;
+
+ case ARRAY_REF:
+ if (TREE_CODE (decl_type) == ARRAY_TYPE
+ && (TREE_TYPE (decl_type) == TREE_TYPE (op)
+ || useless_type_conversion_p (TREE_TYPE (op),
+ TREE_TYPE (decl_type))))
+ return;
+ /* An unknown size array type should be ok. But we do not
+ lower the lower bound in all cases - ugh. */
+ wanted_type = build_array_type (TREE_TYPE (op), NULL_TREE);
+ break;
+
+ case ARRAY_RANGE_REF:
+ if (TREE_CODE (decl_type) == ARRAY_TYPE
+ && (TREE_TYPE (decl_type) == TREE_TYPE (TREE_TYPE (op))
+ || useless_type_conversion_p (TREE_TYPE (TREE_TYPE (op)),
+ TREE_TYPE (decl_type))))
+ return;
+ /* An unknown size array type should be ok. But we do not
+ lower the lower bound in all cases - ugh. */
+ wanted_type = build_array_type (TREE_TYPE (TREE_TYPE (op)), NULL_TREE);
+ break;
+
+ case BIT_FIELD_REF:
+ case VIEW_CONVERT_EXPR:
+ /* Very nice - nothing to do. */
+ return;
+
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ if (TREE_CODE (decl_type) == COMPLEX_TYPE
+ && (TREE_TYPE (decl_type) == TREE_TYPE (op)
+ || useless_type_conversion_p (TREE_TYPE (op),
+ TREE_TYPE (decl_type))))
+ return;
+ wanted_type = build_complex_type (TREE_TYPE (op));
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ if (!useless_type_conversion_p (wanted_type, decl_type))
+ TREE_OPERAND (op, 0) = build1 (VIEW_CONVERT_EXPR, wanted_type,
+ TREE_OPERAND (op, 0));
+}
+
+/* Fixup reference tree operands for substituted prevailing decls
+ with mismatched types in STMT. */
+
+static void
+maybe_fixup_decls (gimple stmt)
+{
+ /* We have to fixup replaced decls here in case there were
+ inter-TU type mismatches. Catch the most common cases
+ for now - this way we'll get testcases for the rest as
+ the type verifier will complain. */
+ if (gimple_assign_single_p (stmt))
+ {
+ tree lhs = gimple_assign_lhs (stmt);
+ tree rhs = gimple_assign_rhs1 (stmt);
+
+ /* First catch loads and aggregate copies by adjusting the rhs. */
+ if (TREE_CODE (rhs) == VAR_DECL)
+ {
+ if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
+ gimple_assign_set_rhs1 (stmt, build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (lhs), rhs));
+ }
+ else if (handled_component_p (rhs))
+ maybe_fixup_handled_component (rhs);
+ /* Then catch scalar stores. */
+ else if (TREE_CODE (lhs) == VAR_DECL)
+ {
+ if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
+ gimple_assign_set_lhs (stmt, build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (rhs), lhs));
+ }
+ else if (handled_component_p (lhs))
+ maybe_fixup_handled_component (lhs);
+ }
+ else if (is_gimple_call (stmt))
+ {
+ tree lhs = gimple_call_lhs (stmt);
+
+ if (lhs && TREE_CODE (lhs) == VAR_DECL)
+ {
+ if (!useless_type_conversion_p (TREE_TYPE (lhs),
+ gimple_call_return_type (stmt)))
+ gimple_call_set_lhs (stmt, build1 (VIEW_CONVERT_EXPR,
+ gimple_call_return_type (stmt),
+ lhs));
+ }
+ else if (lhs && handled_component_p (lhs))
+ maybe_fixup_handled_component (lhs);
+
+ /* Arguments, especially for varargs functions will be funny... */
+ }
+}
+
/* Read a statement with tag TAG in function FN from block IB using
descriptors in DATA_IN. */
@@ -939,6 +1067,36 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
{
tree op = lto_input_tree (ib, data_in);
gimple_set_op (stmt, i, op);
+
+ /* Fixup FIELD_DECLs. */
+ while (op && handled_component_p (op))
+ {
+ if (TREE_CODE (op) == COMPONENT_REF)
+ {
+ tree field, type, tem;
+ field = TREE_OPERAND (op, 1);
+ type = DECL_CONTEXT (field);
+ for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
+ {
+ if (tem == field
+ || (TREE_TYPE (tem) == TREE_TYPE (field)
+ && (DECL_FIELD_OFFSET (tem)
+ == DECL_FIELD_OFFSET (field))
+ && (DECL_FIELD_BIT_OFFSET (tem)
+ == DECL_FIELD_BIT_OFFSET (field))
+ && (DECL_OFFSET_ALIGN (tem)
+ == DECL_OFFSET_ALIGN (field))))
+ break;
+ }
+ /* In case of type mismatches across units we can fail
+ to unify some types and thus not find a proper
+ field-decl here. Just do nothing in this case. */
+ if (tem != NULL_TREE)
+ TREE_OPERAND (op, 1) = tem;
+ }
+
+ op = TREE_OPERAND (op, 0);
+ }
}
break;
@@ -974,6 +1132,10 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
}
}
+ /* Fixup reference tree operands for substituted prevailing decls
+ with mismatched types. */
+ maybe_fixup_decls (stmt);
+
/* Mark the statement modified so its operand vectors can be filled in. */
gimple_set_modified (stmt, true);
@@ -1014,15 +1176,15 @@ input_bb (struct lto_input_block *ib, enum LTO_tags tag,
{
gimple stmt = input_gimple_stmt (ib, data_in, fn, tag);
- /* Drop debug stmts on-the-fly if we do not have VTA enabled.
+ /* Change debug stmts to nops 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);
- }
+ if (!MAY_HAVE_DEBUG_STMTS
+ && is_gimple_debug (stmt))
+ stmt = gimple_build_nop ();
+
+ 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. */
@@ -1033,8 +1195,7 @@ input_bb (struct lto_input_block *ib, enum LTO_tags tag,
{
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);
@@ -1182,6 +1343,8 @@ input_function (tree fn_decl, struct data_in *data_in,
fixup_call_stmt_edges (cgraph_node (fn_decl), stmts);
update_ssa (TODO_update_ssa_only_virtuals);
+ free_dominance_info (CDI_DOMINATORS);
+ free_dominance_info (CDI_POST_DOMINATORS);
free (stmts);
}
@@ -1296,6 +1459,15 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
/* Restore decl state */
file_data->current_decl_state = file_data->global_decl_state;
+ /* FIXME: ipa_transforms_to_apply holds list of passes that have optimization
+ summaries computed and needs to apply changes. At the moment WHOPR only
+ supports inlining, so we can push it here by hand. In future we need to stream
+ this field into ltrans compilation. This will also need to move the field
+ from struct function into cgraph node where it belongs. */
+ if (flag_ltrans && !cgraph_node (fn_decl)->global.inlined_to)
+ VEC_safe_push (ipa_opt_pass, heap,
+ cfun->ipa_transforms_to_apply,
+ (ipa_opt_pass)&pass_ipa_inline);
pop_cfun ();
}
else