bp_pack_value (bp, 0, 1);
/* We write debug info two times, do not confuse the second one. */
bp_pack_value (bp, TYPE_P (expr) ? 0 : TREE_ASM_WRITTEN (expr), 1);
- bp_pack_value (bp, TREE_NO_WARNING (expr), 1);
+ if (TYPE_P (expr))
+ bp_pack_value (bp, TYPE_ARTIFICIAL (expr), 1);
+ else
+ bp_pack_value (bp, TREE_NO_WARNING (expr), 1);
bp_pack_value (bp, TREE_USED (expr), 1);
bp_pack_value (bp, TREE_NOTHROW (expr), 1);
bp_pack_value (bp, TREE_STATIC (expr), 1);
if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
pack_ts_block_value_fields (bp, expr);
- if (CODE_CONTAINS_STRUCT (code, TS_SSA_NAME))
- {
- /* We only stream the version number of SSA names. */
- gcc_unreachable ();
- }
-
- if (CODE_CONTAINS_STRUCT (code, TS_STATEMENT_LIST))
- {
- /* This is only used by GENERIC. */
- gcc_unreachable ();
- }
-
- if (CODE_CONTAINS_STRUCT (code, TS_OMP_CLAUSE))
- {
- /* This is only used by High GIMPLE. */
- gcc_unreachable ();
- }
-
if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
pack_ts_translation_unit_decl_value_fields (bp, expr);
+
+ if (streamer_hooks.pack_value_fields)
+ streamer_hooks.pack_value_fields (bp, expr);
}
break;
default:
- /* No other node is indexable, so it should have been handled
- by lto_output_tree. */
- gcc_unreachable ();
+ {
+ /* See if the streamer allows this node to be indexable
+ like other global declarations. */
+ if (streamer_hooks.indexable_with_decls_p
+ && streamer_hooks.indexable_with_decls_p (expr))
+ {
+ output_record_start (ob, LTO_global_decl_ref);
+ lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
+ }
+ else
+ {
+ /* No other node is indexable, so it should have been
+ handled by lto_output_tree. */
+ gcc_unreachable ();
+ }
+ }
}
}
lto_output_tree_or_ref (ob, DECL_SIZE (expr), ref_p);
lto_output_tree_or_ref (ob, DECL_SIZE_UNIT (expr), ref_p);
- if (TREE_CODE (expr) != FUNCTION_DECL
- && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
- {
- tree initial = DECL_INITIAL (expr);
- if (TREE_CODE (expr) == VAR_DECL
- && (TREE_STATIC (expr) || DECL_EXTERNAL (expr))
- && initial)
- {
- lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
- struct varpool_node *vnode = varpool_get_node (expr);
- if (!vnode)
- initial = error_mark_node;
- else if (!lto_varpool_encoder_encode_initializer_p (varpool_encoder,
- vnode))
- initial = NULL;
- }
-
- lto_output_tree_or_ref (ob, initial, ref_p);
- }
+ /* Note, DECL_INITIAL is not handled here. Since DECL_INITIAL needs
+ special handling in LTO, it must be handled by streamer hooks. */
lto_output_tree_or_ref (ob, DECL_ATTRIBUTES (expr), ref_p);
+
/* Do not stream DECL_ABSTRACT_ORIGIN. We cannot handle debug information
for early inlining so drop it on the floor instead of ICEing in
dwarf2out.c. */
lto_output_tree_or_ref (ob, BINFO_OFFSET (expr), ref_p);
lto_output_tree_or_ref (ob, BINFO_VTABLE (expr), ref_p);
- lto_output_tree_or_ref (ob, BINFO_VIRTUALS (expr), ref_p);
+ /* BINFO_VIRTUALS is used to drive type based devirtualizatoin. It often links
+ together large portions of programs making it harder to partition. Becuase
+ devirtualization is interesting before inlining, only, there is no real
+ need to ship it into ltrans partition. */
+ lto_output_tree_or_ref (ob, flag_wpa ? NULL : BINFO_VIRTUALS (expr), ref_p);
lto_output_tree_or_ref (ob, BINFO_VPTR_FIELD (expr), ref_p);
output_uleb128 (ob, VEC_length (tree, BINFO_BASE_ACCESSES (expr)));
if (CODE_CONTAINS_STRUCT (code, TS_EXP))
lto_output_ts_exp_tree_pointers (ob, expr, ref_p);
- if (CODE_CONTAINS_STRUCT (code, TS_SSA_NAME))
- {
- /* We only stream the version number of SSA names. */
- gcc_unreachable ();
- }
-
if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
lto_output_ts_block_tree_pointers (ob, expr, ref_p);
if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
lto_output_ts_constructor_tree_pointers (ob, expr, ref_p);
- if (CODE_CONTAINS_STRUCT (code, TS_STATEMENT_LIST))
- {
- /* This should only appear in GENERIC. */
- gcc_unreachable ();
- }
-
- if (CODE_CONTAINS_STRUCT (code, TS_OMP_CLAUSE))
- {
- /* This should only appear in High GIMPLE. */
- gcc_unreachable ();
- }
-
- if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION))
- sorry ("gimple bytecode streams do not support the optimization attribute");
-
if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION))
lto_output_ts_target_option (ob, expr);
enum LTO_tags tag;
enum tree_code code;
- /* We should not see any non-GIMPLE tree nodes here. */
+ /* We should not see any tree nodes not handled by the streamer. */
code = TREE_CODE (expr);
- if (!lto_is_streamable (expr))
- internal_error ("tree code %qs is not supported in gimple streams",
- tree_code_name[code]);
+ if (!streamer_hooks.is_streamable (expr))
+ internal_error ("tree code %qs is not supported in %s streams",
+ tree_code_name[code], streamer_hooks.name);
/* The header of a tree node consists of its tag, the size of
the node, and any other information needed to instantiate
output_sleb128 (ob, TREE_VEC_LENGTH (expr));
else if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
output_uleb128 (ob, BINFO_N_BASE_BINFOS (expr));
+
+ /* Allow the streamer to write any streamer-specific information
+ needed to instantiate the node when reading. */
+ if (streamer_hooks.output_tree_header)
+ streamer_hooks.output_tree_header (ob, expr);
}
/* Write all the pointer fields in EXPR. */
lto_output_tree_pointers (ob, expr, ref_p);
+ /* Call back into the streaming module to see if it needs to write
+ anything that was not written by the common streamer. */
+ if (streamer_hooks.write_tree)
+ streamer_hooks.write_tree (ob, expr, ref_p);
+
/* Mark the end of EXPR. */
output_zero (ob);
}
+/* GIMPLE hook for writing GIMPLE-specific parts of trees. OB, EXPR
+ and REF_P are as in lto_write_tree. */
+
+void
+lto_streamer_write_tree (struct output_block *ob, tree expr, bool ref_p)
+{
+ if (DECL_P (expr)
+ && TREE_CODE (expr) != FUNCTION_DECL
+ && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
+ {
+ /* Handle DECL_INITIAL for symbols. */
+ tree initial = DECL_INITIAL (expr);
+ if (TREE_CODE (expr) == VAR_DECL
+ && (TREE_STATIC (expr) || DECL_EXTERNAL (expr))
+ && initial)
+ {
+ lto_varpool_encoder_t varpool_encoder;
+ struct varpool_node *vnode;
+
+ varpool_encoder = ob->decl_state->varpool_node_encoder;
+ vnode = varpool_get_node (expr);
+ if (!vnode)
+ initial = error_mark_node;
+ else if (!lto_varpool_encoder_encode_initializer_p (varpool_encoder,
+ vnode))
+ initial = NULL;
+ }
+
+ lto_output_tree_or_ref (ob, initial, ref_p);
+ }
+}
+
+
/* Emit the integer constant CST to output block OB. If REF_P is true,
CST's type will be emitted as a reference. */
}
-/* Initialize the LTO writer. */
-
-static void
-lto_writer_init (void)
-{
- lto_streamer_init ();
-}
-
-
/* Main entry point from the pass manager. */
static void
int i, n_nodes;
lto_cgraph_encoder_t encoder = lto_get_out_decl_state ()->cgraph_node_encoder;
- lto_writer_init ();
+ /* Initialize the streamer. */
+ lto_streamer_init ();
n_nodes = lto_cgraph_encoder_size (encoder);
/* Process only the functions with bodies. */
{
node = lto_cgraph_encoder_deref (encoder, i);
if (lto_cgraph_encoder_encode_body_p (encoder, node)
+ && !node->alias
&& !node->thunk.thunk_p)
{
#ifdef ENABLE_CHECKING
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func /* todo_flags_finish */
+ 0 /* todo_flags_finish */
},
NULL, /* generate_summary */
lto_output, /* write_summary */
struct lto_streamer_cache_d *cache = ob->writer_cache;
char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
struct pointer_set_t *seen;
- struct cgraph_node *node, *alias;
- struct varpool_node *vnode, *valias;
+ struct cgraph_node *node;
+ struct varpool_node *vnode;
struct lto_output_stream stream;
lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder;
if (DECL_COMDAT (node->decl)
&& cgraph_comdat_can_be_unshared_p (node))
continue;
- if (node->alias || node->global.inlined_to)
+ if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
continue;
write_symbol (cache, &stream, node->decl, seen, false);
- for (alias = node->same_body; alias; alias = alias->next)
- write_symbol (cache, &stream, alias->decl, seen, true);
}
for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
{
if (DECL_COMDAT (node->decl)
&& cgraph_comdat_can_be_unshared_p (node))
continue;
- if (node->alias || node->global.inlined_to)
+ if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
continue;
write_symbol (cache, &stream, node->decl, seen, false);
- for (alias = node->same_body; alias; alias = alias->next)
- write_symbol (cache, &stream, alias->decl, seen, true);
}
/* Write all variables. */
&& vnode->finalized
&& DECL_VIRTUAL_P (vnode->decl))
continue;
- if (vnode->alias)
+ if (vnode->alias && !vnode->alias_of)
continue;
write_symbol (cache, &stream, vnode->decl, seen, false);
- for (valias = vnode->extra_name; valias; valias = valias->next)
- write_symbol (cache, &stream, valias->decl, seen, true);
}
for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++)
{
&& vnode->finalized
&& DECL_VIRTUAL_P (vnode->decl))
continue;
- if (vnode->alias)
+ if (vnode->alias && !vnode->alias_of)
continue;
write_symbol (cache, &stream, vnode->decl, seen, false);
- for (valias = vnode->extra_name; valias; valias = valias->next)
- write_symbol (cache, &stream, valias->decl, seen, true);
}
/* Write all aliases. */