#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "stor-layout.h"
+#include "stringpool.h"
#include "expr.h"
#include "flags.h"
#include "params.h"
#include "input.h"
#include "hashtab.h"
#include "basic-block.h"
-#include "tree-flow.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimple-ssa.h"
+#include "tree-ssanames.h"
#include "tree-pass.h"
-#include "cgraph.h"
#include "function.h"
#include "ggc.h"
#include "diagnostic-core.h"
static bool
tree_is_indexable (tree t)
{
- if (TREE_CODE (t) == PARM_DECL)
- return true;
+ /* Parameters and return values of functions of variably modified types
+ must go to global stream, because they may be used in the type
+ definition. */
+ if (TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
+ return variably_modified_type_p (TREE_TYPE (DECL_CONTEXT (t)), NULL_TREE);
else if (TREE_CODE (t) == VAR_DECL && decl_function_context (t)
&& !TREE_STATIC (t))
return false;
{
if (!lto_is_streamable (expr))
internal_error ("tree code %qs is not supported in LTO streams",
- tree_code_name[TREE_CODE (expr)]);
+ get_tree_code_name (TREE_CODE (expr)));
/* Write the header, containing everything needed to materialize
EXPR on the reading side. */
if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
{
- if (TREE_CODE (expr) == FUNCTION_DECL)
- {
- for (tree t = DECL_ARGUMENTS (expr); t; t = TREE_CHAIN (t))
- DFS_follow_tree_edge (t);
- DFS_follow_tree_edge (DECL_RESULT (expr));
- }
- else if (TREE_CODE (expr) == TYPE_DECL)
+ if (TREE_CODE (expr) == TYPE_DECL)
DFS_follow_tree_edge (DECL_ORIGINAL_TYPE (expr));
DFS_follow_tree_edge (DECL_VINDEX (expr));
}
FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_ACCESSES (expr), i, t)
DFS_follow_tree_edge (t);
- DFS_follow_tree_edge (BINFO_INHERITANCE_CHAIN (expr));
- DFS_follow_tree_edge (BINFO_SUBVTT_INDEX (expr));
- DFS_follow_tree_edge (BINFO_VPTR_INDEX (expr));
+ /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX
+ and BINFO_VPTR_INDEX; these are used by C++ FE only. */
}
if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
{
- v = iterative_hash_host_wide_int (TREE_INT_CST_LOW (t), v);
- v = iterative_hash_host_wide_int (TREE_INT_CST_HIGH (t), v);
+ int i;
+ v = iterative_hash_host_wide_int (TREE_INT_CST_NUNITS (t), v);
+ v = iterative_hash_host_wide_int (TREE_INT_CST_EXT_NUNITS (t), v);
+ for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
+ v = iterative_hash_host_wide_int (TREE_INT_CST_ELT (t, i), v);
}
if (CODE_CONTAINS_STRUCT (code, TS_REAL_CST))
v = iterative_hash_host_wide_int (DECL_ALIGN (t), v);
if (code == LABEL_DECL)
{
- v = iterative_hash_host_wide_int (DECL_ERROR_ISSUED (t), v);
v = iterative_hash_host_wide_int (EH_LANDING_PAD_NR (t), v);
v = iterative_hash_host_wide_int (LABEL_DECL_UID (t), v);
}
if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
{
- v = iterative_hash_host_wide_int (DECL_DEFER_OUTPUT (t)
- | (DECL_COMMON (t) << 1)
- | (DECL_DLLIMPORT_P (t) << 2)
- | (DECL_WEAK (t) << 3)
- | (DECL_SEEN_IN_BIND_EXPR_P (t) << 4)
- | (DECL_COMDAT (t) << 5)
+ v = iterative_hash_host_wide_int ((DECL_COMMON (t))
+ | (DECL_DLLIMPORT_P (t) << 1)
+ | (DECL_WEAK (t) << 2)
+ | (DECL_SEEN_IN_BIND_EXPR_P (t) << 3)
+ | (DECL_COMDAT (t) << 4)
| (DECL_VISIBILITY_SPECIFIED (t) << 6),
v);
v = iterative_hash_host_wide_int (DECL_VISIBILITY (t), v);
if (code == VAR_DECL)
{
+ /* DECL_IN_TEXT_SECTION is set during final asm output only. */
v = iterative_hash_host_wide_int (DECL_HARD_REGISTER (t)
- | (DECL_IN_TEXT_SECTION (t) << 1)
- | (DECL_IN_CONSTANT_POOL (t) << 2),
+ | (DECL_IN_CONSTANT_POOL (t) << 1),
v);
v = iterative_hash_host_wide_int (DECL_TLS_MODEL (t), v);
}
+ if (TREE_CODE (t) == FUNCTION_DECL)
+ v = iterative_hash_host_wide_int (DECL_FINAL_P (t)
+ | (DECL_CXX_CONSTRUCTOR_P (t) << 1)
+ | (DECL_CXX_DESTRUCTOR_P (t) << 2),
+ v);
if (VAR_OR_FUNCTION_DECL_P (t))
v = iterative_hash_host_wide_int (DECL_INIT_PRIORITY (t), v);
}
| (TYPE_USER_ALIGN (t) << 5)
| (TYPE_READONLY (t) << 6), v);
if (RECORD_OR_UNION_TYPE_P (t))
- v = iterative_hash_host_wide_int (TYPE_TRANSPARENT_AGGR (t), v);
+ {
+ v = iterative_hash_host_wide_int (TYPE_TRANSPARENT_AGGR (t)
+ | (TYPE_FINAL_P (t) << 1), v);
+ }
else if (code == ARRAY_TYPE)
v = iterative_hash_host_wide_int (TYPE_NONALIASED_COMPONENT (t), v);
v = iterative_hash_host_wide_int (TYPE_PRECISION (t), v);
if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
{
- if (code == FUNCTION_DECL)
- {
- for (tree a = DECL_ARGUMENTS (t); a; a = DECL_CHAIN (a))
- visit (a);
- visit (DECL_RESULT (t));
- }
- else if (code == TYPE_DECL)
+ if (code == TYPE_DECL)
visit (DECL_ORIGINAL_TYPE (t));
visit (DECL_VINDEX (t));
}
visit (BINFO_VPTR_FIELD (t));
FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_ACCESSES (t), i, b)
visit (b);
- visit (BINFO_INHERITANCE_CHAIN (t));
- visit (BINFO_SUBVTT_INDEX (t));
- visit (BINFO_VPTR_INDEX (t));
+ /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX
+ and BINFO_VPTR_INDEX; these are used by C++ FE only. */
}
if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
if (!lto_is_streamable (t))
internal_error ("tree code %qs is not supported "
"in LTO streams",
- tree_code_name[TREE_CODE (t)]);
+ get_tree_code_name (TREE_CODE (t)));
gcc_checking_assert (!streamer_handle_as_builtin_p (t));
streamer_write_hwi (ob, -1);
- bb = ENTRY_BLOCK_PTR;
+ bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
while (bb->next_bb)
{
streamer_write_hwi (ob, bb->next_bb->index);
streamer_write_hwi (ob, loop->any_upper_bound);
if (loop->any_upper_bound)
{
- streamer_write_uhwi (ob, loop->nb_iterations_upper_bound.low);
- streamer_write_hwi (ob, loop->nb_iterations_upper_bound.high);
+ int len = loop->nb_iterations_upper_bound.get_len ();
+ int i;
+
+ streamer_write_uhwi (ob, loop->nb_iterations_upper_bound.get_precision ());
+ streamer_write_uhwi (ob, len);
+ for (i = 0; i < len; i++)
+ streamer_write_hwi (ob, loop->nb_iterations_upper_bound.elt (i));
}
streamer_write_hwi (ob, loop->any_estimate);
if (loop->any_estimate)
{
- streamer_write_uhwi (ob, loop->nb_iterations_estimate.low);
- streamer_write_hwi (ob, loop->nb_iterations_estimate.high);
+ int len = loop->nb_iterations_estimate.get_len ();
+ int i;
+
+ streamer_write_uhwi (ob, loop->nb_iterations_estimate.get_precision ());
+ streamer_write_uhwi (ob, len);
+ for (i = 0; i < len; i++)
+ streamer_write_hwi (ob, loop->nb_iterations_estimate.elt (i));
}
}
basic_block bb;
struct output_block *ob;
- function = node->symbol.decl;
+ function = node->decl;
fn = DECL_STRUCT_FUNCTION (function);
ob = create_output_block (LTO_section_function_body);
streamer_write_record_start (ob, LTO_function);
- output_struct_function_base (ob, fn);
-
- /* Output all the SSA names used in the function. */
- output_ssa_names (ob, fn);
-
- /* Output any exception handling regions. */
- output_eh_regions (ob, fn);
+ /* Output decls for parameters and args. */
+ stream_write_tree (ob, DECL_RESULT (function), true);
+ streamer_write_chain (ob, DECL_ARGUMENTS (function), true);
/* Output DECL_INITIAL for the function, which contains the tree of
lexical scopes. */
stream_write_tree (ob, DECL_INITIAL (function), true);
- /* We will renumber the statements. The code that does this uses
- the same ordering that we use for serializing them so we can use
- the same code on the other end and not have to write out the
- statement numbers. We do not assign UIDs to PHIs here because
- virtual PHIs get re-computed on-the-fly which would make numbers
- inconsistent. */
- set_gimple_stmt_max_uid (cfun, 0);
- FOR_ALL_BB (bb)
- {
- gimple_stmt_iterator gsi;
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ /* We also stream abstract functions where we stream only stuff needed for
+ debug info. */
+ if (gimple_has_body_p (function))
+ {
+ streamer_write_uhwi (ob, 1);
+ output_struct_function_base (ob, fn);
+
+ /* Output all the SSA names used in the function. */
+ output_ssa_names (ob, fn);
+
+ /* Output any exception handling regions. */
+ output_eh_regions (ob, fn);
+
+
+ /* We will renumber the statements. The code that does this uses
+ the same ordering that we use for serializing them so we can use
+ the same code on the other end and not have to write out the
+ statement numbers. We do not assign UIDs to PHIs here because
+ virtual PHIs get re-computed on-the-fly which would make numbers
+ inconsistent. */
+ set_gimple_stmt_max_uid (cfun, 0);
+ FOR_ALL_BB (bb)
{
- gimple stmt = gsi_stmt (gsi);
- gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
+ gimple_stmt_iterator gsi;
+ for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+
+ /* Virtual PHIs are not going to be streamed. */
+ if (!virtual_operand_p (gimple_phi_result (stmt)))
+ gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
+ }
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
+ }
+ }
+ /* To avoid keeping duplicate gimple IDs in the statements, renumber
+ virtual phis now. */
+ FOR_ALL_BB (bb)
+ {
+ gimple_stmt_iterator gsi;
+ for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ if (virtual_operand_p (gimple_phi_result (stmt)))
+ gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
+ }
}
- }
- /* Output the code for the function. */
- FOR_ALL_BB_FN (bb, fn)
- output_bb (ob, bb, fn);
+ /* Output the code for the function. */
+ FOR_ALL_BB_FN (bb, fn)
+ output_bb (ob, bb, fn);
- /* The terminator for this function. */
- streamer_write_record_start (ob, LTO_null);
+ /* The terminator for this function. */
+ streamer_write_record_start (ob, LTO_null);
+
+ output_cfg (ob, fn);
- output_cfg (ob, fn);
+ pop_cfun ();
+ }
+ else
+ streamer_write_uhwi (ob, 0);
/* Create a section to hold the pickled output of this function. */
produce_asm (ob, function);
destroy_output_block (ob);
-
- pop_cfun ();
}
static void
copy_function (struct cgraph_node *node)
{
- tree function = node->symbol.decl;
- struct lto_file_decl_data *file_data = node->symbol.lto_file_data;
+ tree function = node->decl;
+ struct lto_file_decl_data *file_data = node->lto_file_data;
struct lto_output_stream *output_stream = XCNEW (struct lto_output_stream);
const char *data;
size_t len;
/* Copy decls. */
in_state =
- lto_get_function_in_decl_state (node->symbol.lto_file_data, function);
+ lto_get_function_in_decl_state (node->lto_file_data, function);
gcc_assert (in_state);
for (i = 0; i < LTO_N_DECL_STREAMS; i++)
/* Main entry point from the pass manager. */
-static void
+void
lto_output (void)
{
struct lto_out_decl_state *decl_state;
/* Process only the functions with bodies. */
for (i = 0; i < n_nodes; i++)
{
- symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+ symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
cgraph_node *node = dyn_cast <cgraph_node> (snode);
if (node
&& lto_symtab_encoder_encode_body_p (encoder, node)
- && !node->symbol.alias
- && !node->thunk.thunk_p)
+ && !node->alias)
{
#ifdef ENABLE_CHECKING
- gcc_assert (!bitmap_bit_p (output, DECL_UID (node->symbol.decl)));
- bitmap_set_bit (output, DECL_UID (node->symbol.decl));
+ gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl)));
+ bitmap_set_bit (output, DECL_UID (node->decl));
#endif
decl_state = lto_new_out_decl_state ();
lto_push_out_decl_state (decl_state);
- if (gimple_has_body_p (node->symbol.decl))
+ if (gimple_has_body_p (node->decl) || !flag_wpa)
output_function (node);
else
copy_function (node);
gcc_assert (lto_get_out_decl_state () == decl_state);
lto_pop_out_decl_state ();
- lto_record_function_out_decl_state (node->symbol.decl, decl_state);
+ lto_record_function_out_decl_state (node->decl, decl_state);
}
}
#endif
}
-struct ipa_opt_pass_d pass_ipa_lto_gimple_out =
-{
- {
- IPA_PASS,
- "lto_gimple_out", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- gate_lto_out, /* gate */
- NULL, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_IPA_LTO_GIMPLE_OUT, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0 /* todo_flags_finish */
- },
- NULL, /* generate_summary */
- lto_output, /* write_summary */
- NULL, /* read_summary */
- lto_output, /* write_optimization_summary */
- NULL, /* read_optimization_summary */
- NULL, /* stmt_fixup */
- 0, /* TODOs */
- NULL, /* function_transform */
- NULL /* variable_transform */
-};
-
-
/* Write each node in encoded by ENCODER to OB, as well as those reachable
from it and required for correct representation of its semantics.
Each node in ENCODER must be a global declaration or a type. A node
if (!TREE_PUBLIC (t)
|| is_builtin_fn (t)
|| DECL_ABSTRACT (t)
- || TREE_CODE (t) == RESULT_DECL
|| (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t)))
return;
+ gcc_assert (TREE_CODE (t) != RESULT_DECL);
gcc_assert (TREE_CODE (t) == VAR_DECL
|| TREE_CODE (t) == FUNCTION_DECL);
/* When something is defined, it should have node attached. */
gcc_assert (alias || TREE_CODE (t) != VAR_DECL
- || varpool_get_node (t)->symbol.definition);
+ || varpool_get_node (t)->definition);
gcc_assert (alias || TREE_CODE (t) != FUNCTION_DECL
|| (cgraph_get_node (t)
- && cgraph_get_node (t)->symbol.definition));
+ && cgraph_get_node (t)->definition));
}
/* Imitate what default_elf_asm_output_external do.
&& !targetm.binds_local_p (t))
visibility = GCCPV_DEFAULT;
else
- switch (DECL_VISIBILITY(t))
+ switch (DECL_VISIBILITY (t))
{
case VISIBILITY_DEFAULT:
visibility = GCCPV_DEFAULT;
/* Return true if NODE should appear in the plugin symbol table. */
bool
-output_symbol_p (symtab_node node)
+output_symbol_p (symtab_node *node)
{
struct cgraph_node *cnode;
if (!symtab_real_symbol_p (node))
and devirtualization. We do not want to see them in symbol table as
references unless they are really used. */
cnode = dyn_cast <cgraph_node> (node);
- if (cnode && DECL_EXTERNAL (cnode->symbol.decl)
+ if (cnode && (!node->definition || DECL_EXTERNAL (cnode->decl))
&& cnode->callers)
return true;
part of the compilation unit until they are used by folding. Some symbols,
like references to external construction vtables can not be referred to at all.
We decide this at can_refer_decl_in_current_unit_p. */
- if (DECL_EXTERNAL (node->symbol.decl))
+ if (!node->definition || DECL_EXTERNAL (node->decl))
{
int i;
struct ipa_ref *ref;
- for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
+ for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
i, ref); i++)
{
if (ref->use == IPA_REF_ALIAS)
continue;
if (is_a <cgraph_node> (ref->referring))
return true;
- if (!DECL_EXTERNAL (ref->referring->symbol.decl))
+ if (!DECL_EXTERNAL (ref->referring->decl))
return true;
}
return false;
for (lsei = lsei_start (encoder);
!lsei_end_p (lsei); lsei_next (&lsei))
{
- symtab_node node = lsei_node (lsei);
+ symtab_node *node = lsei_node (lsei);
- if (!output_symbol_p (node) || DECL_EXTERNAL (node->symbol.decl))
+ if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl))
continue;
- write_symbol (cache, &stream, node->symbol.decl, seen, false);
+ write_symbol (cache, &stream, node->decl, seen, false);
}
for (lsei = lsei_start (encoder);
!lsei_end_p (lsei); lsei_next (&lsei))
{
- symtab_node node = lsei_node (lsei);
+ symtab_node *node = lsei_node (lsei);
- if (!output_symbol_p (node) || !DECL_EXTERNAL (node->symbol.decl))
+ if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl))
continue;
- write_symbol (cache, &stream, node->symbol.decl, seen, false);
+ write_symbol (cache, &stream, node->decl, seen, false);
}
lto_write_stream (&stream);
this file to be written in to a section that can then be read in to
recover these on other side. */
-static void
+void
produce_asm_for_decls (void)
{
struct lto_out_decl_state *out_state;
lto_output_decl_state_refs (ob, decl_state_stream, fn_out_state);
}
lto_write_stream (decl_state_stream);
- free(decl_state_stream);
+ free (decl_state_stream);
lto_write_stream (ob->main_stream);
lto_write_stream (ob->string_stream);
lto_function_decl_states.release ();
destroy_output_block (ob);
}
-
-
-struct ipa_opt_pass_d pass_ipa_lto_finish_out =
-{
- {
- IPA_PASS,
- "lto_decls_out", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- gate_lto_out, /* gate */
- NULL, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_IPA_LTO_DECL_OUT, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0 /* todo_flags_finish */
- },
- NULL, /* generate_summary */
- produce_asm_for_decls, /* write_summary */
- NULL, /* read_summary */
- produce_asm_for_decls, /* write_optimization_summary */
- NULL, /* read_optimization_summary */
- NULL, /* stmt_fixup */
- 0, /* TODOs */
- NULL, /* function_transform */
- NULL /* variable_transform */
-};