#include "except.h"
#include "vec.h"
#include "timevar.h"
-#include "output.h"
#include "pointer-set.h"
#include "lto-streamer.h"
+#include "data-streamer.h"
+#include "tree-streamer.h"
#include "gcov-io.h"
-static void output_varpool (cgraph_node_set, varpool_node_set);
-static void output_cgraph_opt_summary (cgraph_node_set set);
-static void input_cgraph_opt_summary (VEC (cgraph_node_ptr, heap) * nodes);
+static void output_cgraph_opt_summary (void);
+static void input_cgraph_opt_summary (VEC (symtab_node, heap) * nodes);
+/* Number of LDPR values known to GCC. */
+#define LDPR_NUM_KNOWN (LDPR_PREVAILING_DEF_IRONLY_EXP + 1)
+
+/* All node orders are ofsetted by ORDER_BASE. */
+static int order_base;
/* Cgraph streaming is organized as set of record whose type
is indicated by a tag. */
-enum LTO_cgraph_tags
+enum LTO_symtab_tags
{
/* Must leave 0 for the stopper. */
/* Cgraph node without body available. */
- LTO_cgraph_unavail_node = 1,
+ LTO_symtab_unavail_node = 1,
/* Cgraph node with function body. */
- LTO_cgraph_analyzed_node,
+ LTO_symtab_analyzed_node,
/* Cgraph edges. */
- LTO_cgraph_edge,
- LTO_cgraph_indirect_edge
+ LTO_symtab_edge,
+ LTO_symtab_indirect_edge,
+ LTO_symtab_variable,
+ LTO_symtab_last_tag
};
-/* Create a new cgraph encoder. */
+/* Create a new symtab encoder. */
-lto_cgraph_encoder_t
-lto_cgraph_encoder_new (void)
+lto_symtab_encoder_t
+lto_symtab_encoder_new (void)
{
- lto_cgraph_encoder_t encoder = XCNEW (struct lto_cgraph_encoder_d);
+ lto_symtab_encoder_t encoder = XCNEW (struct lto_symtab_encoder_d);
encoder->map = pointer_map_create ();
encoder->nodes = NULL;
- encoder->body = pointer_set_create ();
return encoder;
}
/* Delete ENCODER and its components. */
void
-lto_cgraph_encoder_delete (lto_cgraph_encoder_t encoder)
+lto_symtab_encoder_delete (lto_symtab_encoder_t encoder)
{
- VEC_free (cgraph_node_ptr, heap, encoder->nodes);
+ VEC_free (lto_encoder_entry, heap, encoder->nodes);
pointer_map_destroy (encoder->map);
- pointer_set_destroy (encoder->body);
free (encoder);
}
-/* Return the existing reference number of NODE in the cgraph encoder in
+/* Return the existing reference number of NODE in the symtab encoder in
output block OB. Assign a new reference if this is the first time
NODE is encoded. */
int
-lto_cgraph_encoder_encode (lto_cgraph_encoder_t encoder,
- struct cgraph_node *node)
+lto_symtab_encoder_encode (lto_symtab_encoder_t encoder,
+ symtab_node node)
{
int ref;
void **slot;
slot = pointer_map_contains (encoder->map, node);
- if (!slot)
+ if (!slot || !*slot)
{
- ref = VEC_length (cgraph_node_ptr, encoder->nodes);
- slot = pointer_map_insert (encoder->map, node);
- *slot = (void *) (intptr_t) ref;
- VEC_safe_push (cgraph_node_ptr, heap, encoder->nodes, node);
+ lto_encoder_entry entry = {node, false, false, false};
+ ref = VEC_length (lto_encoder_entry, encoder->nodes);
+ if (!slot)
+ slot = pointer_map_insert (encoder->map, node);
+ *slot = (void *) (intptr_t) (ref + 1);
+ VEC_safe_push (lto_encoder_entry, heap, encoder->nodes, entry);
}
else
- ref = (int) (intptr_t) *slot;
+ ref = (size_t) *slot - 1;
return ref;
}
-#define LCC_NOT_FOUND (-1)
-
-/* Look up NODE in encoder. Return NODE's reference if it has been encoded
- or LCC_NOT_FOUND if it is not there. */
+/* Remove NODE from encoder. */
-int
-lto_cgraph_encoder_lookup (lto_cgraph_encoder_t encoder,
- struct cgraph_node *node)
+bool
+lto_symtab_encoder_delete_node (lto_symtab_encoder_t encoder,
+ symtab_node node)
{
- void **slot = pointer_map_contains (encoder->map, node);
- return (slot ? (int) (intptr_t) *slot : LCC_NOT_FOUND);
-}
+ void **slot, **last_slot;
+ int index;
+ lto_encoder_entry last_node;
+ slot = pointer_map_contains (encoder->map, node);
+ if (slot == NULL || !*slot)
+ return false;
-/* Return the cgraph node corresponding to REF using ENCODER. */
+ index = (size_t) *slot - 1;
+ gcc_checking_assert (VEC_index (lto_encoder_entry,
+ encoder->nodes, index).node
+ == node);
-struct cgraph_node *
-lto_cgraph_encoder_deref (lto_cgraph_encoder_t encoder, int ref)
-{
- if (ref == LCC_NOT_FOUND)
- return NULL;
+ /* Remove from vector. We do this by swapping node with the last element
+ of the vector. */
+ last_node = VEC_pop (lto_encoder_entry, encoder->nodes);
+ if (last_node.node != node)
+ {
+ last_slot = pointer_map_contains (encoder->map, last_node.node);
+ gcc_checking_assert (last_slot && *last_slot);
+ *last_slot = (void *)(size_t) (index + 1);
+
+ /* Move the last element to the original spot of NODE. */
+ VEC_replace (lto_encoder_entry, encoder->nodes, index,
+ last_node);
+ }
- return VEC_index (cgraph_node_ptr, encoder->nodes, ref);
+ /* Remove element from hash table. */
+ *slot = NULL;
+ return true;
}
/* Return TRUE if we should encode initializer of NODE (if any). */
bool
-lto_cgraph_encoder_encode_body_p (lto_cgraph_encoder_t encoder,
+lto_symtab_encoder_encode_body_p (lto_symtab_encoder_t encoder,
struct cgraph_node *node)
{
- return pointer_set_contains (encoder->body, node);
+ int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+ return VEC_index (lto_encoder_entry, encoder->nodes, index).body;
}
/* Return TRUE if we should encode body of NODE (if any). */
static void
-lto_set_cgraph_encoder_encode_body (lto_cgraph_encoder_t encoder,
+lto_set_symtab_encoder_encode_body (lto_symtab_encoder_t encoder,
struct cgraph_node *node)
{
- pointer_set_insert (encoder->body, node);
-}
-
-/* Create a new varpool encoder. */
-
-lto_varpool_encoder_t
-lto_varpool_encoder_new (void)
-{
- lto_varpool_encoder_t encoder = XCNEW (struct lto_varpool_encoder_d);
- encoder->map = pointer_map_create ();
- encoder->initializer = pointer_set_create ();
- encoder->nodes = NULL;
- return encoder;
-}
-
-
-/* Delete ENCODER and its components. */
-
-void
-lto_varpool_encoder_delete (lto_varpool_encoder_t encoder)
-{
- VEC_free (varpool_node_ptr, heap, encoder->nodes);
- pointer_map_destroy (encoder->map);
- pointer_set_destroy (encoder->initializer);
- free (encoder);
-}
-
-
-/* Return the existing reference number of NODE in the varpool encoder in
- output block OB. Assign a new reference if this is the first time
- NODE is encoded. */
-
-int
-lto_varpool_encoder_encode (lto_varpool_encoder_t encoder,
- struct varpool_node *node)
-{
- int ref;
- void **slot;
-
- slot = pointer_map_contains (encoder->map, node);
- if (!slot)
- {
- ref = VEC_length (varpool_node_ptr, encoder->nodes);
- slot = pointer_map_insert (encoder->map, node);
- *slot = (void *) (intptr_t) ref;
- VEC_safe_push (varpool_node_ptr, heap, encoder->nodes, node);
- }
- else
- ref = (int) (intptr_t) *slot;
-
- return ref;
+ int index = lto_symtab_encoder_encode (encoder, (symtab_node)node);
+ gcc_checking_assert (VEC_index (lto_encoder_entry, encoder->nodes,
+ index).node == (symtab_node)node);
+ VEC_index (lto_encoder_entry, encoder->nodes, index).body = true;
}
-/* Look up NODE in encoder. Return NODE's reference if it has been encoded
- or LCC_NOT_FOUND if it is not there. */
+/* Return TRUE if we should encode initializer of NODE (if any). */
-int
-lto_varpool_encoder_lookup (lto_varpool_encoder_t encoder,
- struct varpool_node *node)
+bool
+lto_symtab_encoder_encode_initializer_p (lto_symtab_encoder_t encoder,
+ struct varpool_node *node)
{
- void **slot = pointer_map_contains (encoder->map, node);
- return (slot ? (int) (intptr_t) *slot : LCC_NOT_FOUND);
+ int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+ if (index == LCC_NOT_FOUND)
+ return false;
+ return VEC_index (lto_encoder_entry, encoder->nodes, index).initializer;
}
+/* Return TRUE if we should encode initializer of NODE (if any). */
-/* Return the varpool node corresponding to REF using ENCODER. */
-
-struct varpool_node *
-lto_varpool_encoder_deref (lto_varpool_encoder_t encoder, int ref)
+static void
+lto_set_symtab_encoder_encode_initializer (lto_symtab_encoder_t encoder,
+ struct varpool_node *node)
{
- if (ref == LCC_NOT_FOUND)
- return NULL;
-
- return VEC_index (varpool_node_ptr, encoder->nodes, ref);
+ int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+ VEC_index (lto_encoder_entry, encoder->nodes, index).initializer = true;
}
-
/* Return TRUE if we should encode initializer of NODE (if any). */
bool
-lto_varpool_encoder_encode_initializer_p (lto_varpool_encoder_t encoder,
- struct varpool_node *node)
+lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t encoder,
+ symtab_node node)
{
- return pointer_set_contains (encoder->initializer, node);
+ int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+ if (index == LCC_NOT_FOUND)
+ return false;
+ return VEC_index (lto_encoder_entry, encoder->nodes, index).in_partition;
}
-/* Return TRUE if we should encode initializer of NODE (if any). */
+/* Return TRUE if we should encode body of NODE (if any). */
-static void
-lto_set_varpool_encoder_encode_initializer (lto_varpool_encoder_t encoder,
- struct varpool_node *node)
+void
+lto_set_symtab_encoder_in_partition (lto_symtab_encoder_t encoder,
+ symtab_node node)
{
- pointer_set_insert (encoder->initializer, node);
+ int index = lto_symtab_encoder_encode (encoder, (symtab_node)node);
+ VEC_index (lto_encoder_entry, encoder->nodes, index).in_partition = true;
}
/* Output the cgraph EDGE to OB using ENCODER. */
static void
lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge,
- lto_cgraph_encoder_t encoder)
+ lto_symtab_encoder_t encoder)
{
unsigned int uid;
intptr_t ref;
struct bitpack_d bp;
if (edge->indirect_unknown_callee)
- lto_output_uleb128_stream (ob->main_stream, LTO_cgraph_indirect_edge);
+ streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
+ LTO_symtab_indirect_edge);
else
- lto_output_uleb128_stream (ob->main_stream, LTO_cgraph_edge);
+ streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
+ LTO_symtab_edge);
- ref = lto_cgraph_encoder_lookup (encoder, edge->caller);
+ ref = lto_symtab_encoder_lookup (encoder, (symtab_node)edge->caller);
gcc_assert (ref != LCC_NOT_FOUND);
- lto_output_sleb128_stream (ob->main_stream, ref);
+ streamer_write_hwi_stream (ob->main_stream, ref);
if (!edge->indirect_unknown_callee)
{
- ref = lto_cgraph_encoder_lookup (encoder, edge->callee);
+ ref = lto_symtab_encoder_lookup (encoder, (symtab_node)edge->callee);
gcc_assert (ref != LCC_NOT_FOUND);
- lto_output_sleb128_stream (ob->main_stream, ref);
+ streamer_write_hwi_stream (ob->main_stream, ref);
}
- lto_output_sleb128_stream (ob->main_stream, edge->count);
+ streamer_write_hwi_stream (ob->main_stream, edge->count);
bp = bitpack_create (ob->main_stream);
- uid = (!gimple_has_body_p (edge->caller->decl)
+ uid = (!gimple_has_body_p (edge->caller->symbol.decl)
? edge->lto_stmt_uid : gimple_uid (edge->call_stmt));
- bp_pack_value (&bp, uid, HOST_BITS_PER_INT);
- bp_pack_value (&bp, edge->inline_failed, HOST_BITS_PER_INT);
- bp_pack_value (&bp, edge->frequency, HOST_BITS_PER_INT);
- bp_pack_value (&bp, edge->call_stmt_size, HOST_BITS_PER_INT);
- bp_pack_value (&bp, edge->call_stmt_time, HOST_BITS_PER_INT);
- bp_pack_value (&bp, edge->loop_nest, 30);
+ bp_pack_enum (&bp, cgraph_inline_failed_enum,
+ CIF_N_REASONS, edge->inline_failed);
+ bp_pack_var_len_unsigned (&bp, uid);
+ bp_pack_var_len_unsigned (&bp, edge->frequency);
bp_pack_value (&bp, edge->indirect_inlining_edge, 1);
bp_pack_value (&bp, edge->call_stmt_cannot_inline_p, 1);
bp_pack_value (&bp, edge->can_throw_external, 1);
| ECF_LEAF
| ECF_NOVOPS)));
}
- lto_output_bitpack (&bp);
+ streamer_write_bitpack (&bp);
}
/* Return if LIST contain references from other partitions. */
bool
-referenced_from_other_partition_p (struct ipa_ref_list *list, cgraph_node_set set,
- varpool_node_set vset)
+referenced_from_other_partition_p (struct ipa_ref_list *list, lto_symtab_encoder_t encoder)
{
int i;
struct ipa_ref *ref;
- for (i = 0; ipa_ref_list_refering_iterate (list, i, ref); i++)
+ for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++)
{
- if (ref->refering_type == IPA_REF_CGRAPH)
- {
- if (ipa_ref_refering_node (ref)->in_other_partition
- || !cgraph_node_in_set_p (ipa_ref_refering_node (ref), set))
- return true;
- }
- else
- {
- if (ipa_ref_refering_varpool_node (ref)->in_other_partition
- || !varpool_node_in_set_p (ipa_ref_refering_varpool_node (ref),
- vset))
- return true;
- }
+ if (ref->referring->symbol.in_other_partition
+ || !lto_symtab_encoder_in_partition_p (encoder, ref->referring))
+ return true;
}
return false;
}
/* Return true when node is reachable from other partition. */
bool
-reachable_from_other_partition_p (struct cgraph_node *node, cgraph_node_set set)
+reachable_from_other_partition_p (struct cgraph_node *node, lto_symtab_encoder_t encoder)
{
struct cgraph_edge *e;
if (!node->analyzed)
if (node->global.inlined_to)
return false;
for (e = node->callers; e; e = e->next_caller)
- if (e->caller->in_other_partition
- || !cgraph_node_in_set_p (e->caller, set))
+ if (e->caller->symbol.in_other_partition
+ || !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)e->caller))
return true;
return false;
}
/* Return if LIST contain references from other partitions. */
bool
-referenced_from_this_partition_p (struct ipa_ref_list *list, cgraph_node_set set,
- varpool_node_set vset)
+referenced_from_this_partition_p (struct ipa_ref_list *list,
+ lto_symtab_encoder_t encoder)
{
int i;
struct ipa_ref *ref;
- for (i = 0; ipa_ref_list_refering_iterate (list, i, ref); i++)
- {
- if (ref->refering_type == IPA_REF_CGRAPH)
- {
- if (cgraph_node_in_set_p (ipa_ref_refering_node (ref), set))
- return true;
- }
- else
- {
- if (varpool_node_in_set_p (ipa_ref_refering_varpool_node (ref),
- vset))
- return true;
- }
- }
+ for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++)
+ if (lto_symtab_encoder_in_partition_p (encoder, ref->referring))
+ return true;
return false;
}
/* Return true when node is reachable from other partition. */
bool
-reachable_from_this_partition_p (struct cgraph_node *node, cgraph_node_set set)
+reachable_from_this_partition_p (struct cgraph_node *node, lto_symtab_encoder_t encoder)
{
struct cgraph_edge *e;
for (e = node->callers; e; e = e->next_caller)
- if (cgraph_node_in_set_p (e->caller, set))
+ if (lto_symtab_encoder_in_partition_p (encoder, (symtab_node)e->caller))
return true;
return false;
}
static void
lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
- lto_cgraph_encoder_t encoder, cgraph_node_set set,
- varpool_node_set vset)
+ lto_symtab_encoder_t encoder)
{
unsigned int tag;
struct bitpack_d bp;
bool in_other_partition = false;
struct cgraph_node *clone_of;
- boundary_p = !cgraph_node_in_set_p (node, set);
+ boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node);
if (node->analyzed && !boundary_p)
- tag = LTO_cgraph_analyzed_node;
+ tag = LTO_symtab_analyzed_node;
else
- tag = LTO_cgraph_unavail_node;
+ tag = LTO_symtab_unavail_node;
- lto_output_uleb128_stream (ob->main_stream, tag);
+ streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
+ tag);
+ streamer_write_hwi_stream (ob->main_stream, node->symbol.order);
/* In WPA mode, we only output part of the call-graph. Also, we
fake cgraph node attributes. There are two cases that we care.
Cherry-picked nodes: These are nodes we pulled from other
translation units into SET during IPA-inlining. We make them as
local static nodes to prevent clashes with other local statics. */
- if (boundary_p && node->analyzed)
+ if (boundary_p && node->analyzed && !DECL_EXTERNAL (node->symbol.decl))
{
/* Inline clones can not be part of boundary.
gcc_assert (!node->global.inlined_to);
clone_of = node->clone_of;
while (clone_of
- && (ref = lto_cgraph_encoder_lookup (encoder, clone_of)) == LCC_NOT_FOUND)
+ && (ref = lto_symtab_encoder_lookup (encoder, (symtab_node)clone_of)) == LCC_NOT_FOUND)
if (clone_of->prev_sibling_clone)
clone_of = clone_of->prev_sibling_clone;
else
clone_of = clone_of->clone_of;
- if (LTO_cgraph_analyzed_node)
+ if (LTO_symtab_analyzed_node)
gcc_assert (clone_of || !node->clone_of);
if (!clone_of)
- lto_output_sleb128_stream (ob->main_stream, LCC_NOT_FOUND);
+ streamer_write_hwi_stream (ob->main_stream, LCC_NOT_FOUND);
else
- lto_output_sleb128_stream (ob->main_stream, ref);
+ streamer_write_hwi_stream (ob->main_stream, ref);
- lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->decl);
- lto_output_sleb128_stream (ob->main_stream, node->count);
- lto_output_sleb128_stream (ob->main_stream, node->count_materialization_scale);
+ lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->symbol.decl);
+ streamer_write_hwi_stream (ob->main_stream, node->count);
+ streamer_write_hwi_stream (ob->main_stream, node->count_materialization_scale);
- if (tag == LTO_cgraph_analyzed_node)
+ if (tag == LTO_symtab_analyzed_node)
{
if (node->global.inlined_to)
{
- ref = lto_cgraph_encoder_lookup (encoder, node->global.inlined_to);
+ ref = lto_symtab_encoder_lookup (encoder, (symtab_node)node->global.inlined_to);
gcc_assert (ref != LCC_NOT_FOUND);
}
else
ref = LCC_NOT_FOUND;
- lto_output_sleb128_stream (ob->main_stream, ref);
+ streamer_write_hwi_stream (ob->main_stream, ref);
}
- if (node->same_comdat_group && !boundary_p)
+ if (node->symbol.same_comdat_group && !boundary_p)
{
- ref = lto_cgraph_encoder_lookup (encoder, node->same_comdat_group);
+ ref = lto_symtab_encoder_lookup (encoder,
+ node->symbol.same_comdat_group);
gcc_assert (ref != LCC_NOT_FOUND);
}
else
ref = LCC_NOT_FOUND;
- lto_output_sleb128_stream (ob->main_stream, ref);
+ streamer_write_hwi_stream (ob->main_stream, ref);
bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, node->local.local, 1);
- bp_pack_value (&bp, node->local.externally_visible, 1);
+ bp_pack_value (&bp, node->symbol.externally_visible, 1);
bp_pack_value (&bp, node->local.finalized, 1);
+ bp_pack_value (&bp, node->local.versionable, 1);
bp_pack_value (&bp, node->local.can_change_signature, 1);
bp_pack_value (&bp, node->local.redefined_extern_inline, 1);
- bp_pack_value (&bp, node->local.vtable_method, 1);
- bp_pack_value (&bp, node->needed, 1);
- bp_pack_value (&bp, node->address_taken, 1);
+ bp_pack_value (&bp, node->symbol.force_output, 1);
+ bp_pack_value (&bp, node->symbol.address_taken, 1);
bp_pack_value (&bp, node->abstract_and_needed, 1);
- bp_pack_value (&bp, tag == LTO_cgraph_analyzed_node
- && !DECL_EXTERNAL (node->decl)
- && !DECL_COMDAT (node->decl)
- && (reachable_from_other_partition_p (node, set)
- || referenced_from_other_partition_p (&node->ref_list, set, vset)), 1);
+ bp_pack_value (&bp, tag == LTO_symtab_analyzed_node
+ && !DECL_EXTERNAL (node->symbol.decl)
+ && !DECL_COMDAT (node->symbol.decl)
+ && (reachable_from_other_partition_p (node, encoder)
+ || referenced_from_other_partition_p (&node->symbol.ref_list,
+ encoder)), 1);
bp_pack_value (&bp, node->lowered, 1);
bp_pack_value (&bp, in_other_partition, 1);
- bp_pack_value (&bp, node->alias, 1);
- bp_pack_value (&bp, node->finalized_by_frontend, 1);
+ /* Real aliases in a boundary become non-aliases. However we still stream
+ alias info on weakrefs.
+ TODO: We lose a bit of information here - when we know that variable is
+ defined in other unit, we may use the info on aliases to resolve
+ symbol1 != symbol2 type tests that we can do only for locally defined objects
+ otherwise. */
+ bp_pack_value (&bp, node->alias && (!boundary_p || DECL_EXTERNAL (node->symbol.decl)), 1);
bp_pack_value (&bp, node->frequency, 2);
bp_pack_value (&bp, node->only_called_at_startup, 1);
bp_pack_value (&bp, node->only_called_at_exit, 1);
- lto_output_bitpack (&bp);
- lto_output_uleb128_stream (ob->main_stream, node->resolution);
+ bp_pack_value (&bp, node->tm_clone, 1);
+ bp_pack_value (&bp, node->thunk.thunk_p && !boundary_p, 1);
+ bp_pack_enum (&bp, ld_plugin_symbol_resolution,
+ LDPR_NUM_KNOWN, node->symbol.resolution);
+ streamer_write_bitpack (&bp);
- if (node->same_body)
+ if (node->thunk.thunk_p && !boundary_p)
{
- struct cgraph_node *alias;
- unsigned long alias_count = 1;
- for (alias = node->same_body; alias->next; alias = alias->next)
- alias_count++;
- lto_output_uleb128_stream (ob->main_stream, alias_count);
- do
- {
- lto_output_fn_decl_index (ob->decl_state, ob->main_stream,
- alias->decl);
- if (alias->thunk.thunk_p)
- {
- lto_output_uleb128_stream
- (ob->main_stream,
- 1 + (alias->thunk.this_adjusting != 0) * 2
- + (alias->thunk.virtual_offset_p != 0) * 4);
- lto_output_uleb128_stream (ob->main_stream,
- alias->thunk.fixed_offset);
- lto_output_uleb128_stream (ob->main_stream,
- alias->thunk.virtual_value);
- lto_output_fn_decl_index (ob->decl_state, ob->main_stream,
- alias->thunk.alias);
- }
- else
- {
- lto_output_uleb128_stream (ob->main_stream, 0);
- lto_output_fn_decl_index (ob->decl_state, ob->main_stream,
- alias->thunk.alias);
- }
- gcc_assert (cgraph_get_node (alias->thunk.alias) == node);
- lto_output_uleb128_stream (ob->main_stream, alias->resolution);
- alias = alias->previous;
- }
- while (alias);
+ streamer_write_uhwi_stream
+ (ob->main_stream,
+ 1 + (node->thunk.this_adjusting != 0) * 2
+ + (node->thunk.virtual_offset_p != 0) * 4);
+ streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset);
+ streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value);
+ }
+ if ((node->alias || node->thunk.thunk_p)
+ && (!boundary_p || (node->alias && DECL_EXTERNAL (node->symbol.decl))))
+ {
+ streamer_write_hwi_in_range (ob->main_stream, 0, 1,
+ node->thunk.alias != NULL);
+ if (node->thunk.alias != NULL)
+ lto_output_fn_decl_index (ob->decl_state, ob->main_stream,
+ node->thunk.alias);
}
- else
- lto_output_uleb128_stream (ob->main_stream, 0);
}
/* Output the varpool NODE to OB.
static void
lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node,
- lto_varpool_encoder_t varpool_encoder,
- cgraph_node_set set, varpool_node_set vset)
+ lto_symtab_encoder_t encoder)
{
- bool boundary_p = !varpool_node_in_set_p (node, vset) && node->analyzed;
+ bool boundary_p = (node->analyzed
+ && !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node));
struct bitpack_d bp;
- struct varpool_node *alias;
- int count = 0;
int ref;
- lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl);
+ streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
+ LTO_symtab_variable);
+ streamer_write_hwi_stream (ob->main_stream, node->symbol.order);
+ lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->symbol.decl);
bp = bitpack_create (ob->main_stream);
- bp_pack_value (&bp, node->externally_visible, 1);
- bp_pack_value (&bp, node->force_output, 1);
+ bp_pack_value (&bp, node->symbol.externally_visible, 1);
+ bp_pack_value (&bp, node->symbol.force_output, 1);
bp_pack_value (&bp, node->finalized, 1);
bp_pack_value (&bp, node->alias, 1);
- gcc_assert (!node->alias || !node->extra_name);
+ bp_pack_value (&bp, node->alias_of != NULL, 1);
gcc_assert (node->finalized || !node->analyzed);
- gcc_assert (node->needed);
/* Constant pool initializers can be de-unified into individual ltrans units.
FIXME: Alternatively at -Os we may want to avoid generating for them the local
labels and share them across LTRANS partitions. */
- if (DECL_IN_CONSTANT_POOL (node->decl)
- && !DECL_COMDAT (node->decl))
+ if (DECL_IN_CONSTANT_POOL (node->symbol.decl)
+ && !DECL_EXTERNAL (node->symbol.decl)
+ && !DECL_COMDAT (node->symbol.decl))
{
bp_pack_value (&bp, 0, 1); /* used_from_other_parition. */
bp_pack_value (&bp, 0, 1); /* in_other_partition. */
else
{
bp_pack_value (&bp, node->analyzed
- && referenced_from_other_partition_p (&node->ref_list,
- set, vset), 1);
- bp_pack_value (&bp, boundary_p, 1); /* in_other_partition. */
+ && referenced_from_other_partition_p (&node->symbol.ref_list,
+ encoder), 1);
+ bp_pack_value (&bp, boundary_p && !DECL_EXTERNAL (node->symbol.decl), 1);
+ /* in_other_partition. */
}
- /* Also emit any extra name aliases. */
- for (alias = node->extra_name; alias; alias = alias->next)
- count++;
- bp_pack_value (&bp, count != 0, 1);
- lto_output_bitpack (&bp);
- if (node->same_comdat_group && !boundary_p)
+ streamer_write_bitpack (&bp);
+ if (node->alias_of)
+ lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->alias_of);
+ if (node->symbol.same_comdat_group && !boundary_p)
{
- ref = lto_varpool_encoder_lookup (varpool_encoder, node->same_comdat_group);
+ ref = lto_symtab_encoder_lookup (encoder,
+ node->symbol.same_comdat_group);
gcc_assert (ref != LCC_NOT_FOUND);
}
else
ref = LCC_NOT_FOUND;
- lto_output_sleb128_stream (ob->main_stream, ref);
- lto_output_uleb128_stream (ob->main_stream, node->resolution);
-
- if (count)
- {
- lto_output_uleb128_stream (ob->main_stream, count);
- for (alias = node->extra_name; alias; alias = alias->next)
- {
- lto_output_var_decl_index (ob->decl_state, ob->main_stream, alias->decl);
- lto_output_uleb128_stream (ob->main_stream, alias->resolution);
- }
- }
+ streamer_write_hwi_stream (ob->main_stream, ref);
+ streamer_write_enum (ob->main_stream, ld_plugin_symbol_resolution,
+ LDPR_NUM_KNOWN, node->symbol.resolution);
}
/* Output the varpool NODE to OB.
static void
lto_output_ref (struct lto_simple_output_block *ob, struct ipa_ref *ref,
- lto_cgraph_encoder_t encoder,
- lto_varpool_encoder_t varpool_encoder)
+ lto_symtab_encoder_t encoder)
{
struct bitpack_d bp;
+ int nref;
+
bp = bitpack_create (ob->main_stream);
- bp_pack_value (&bp, ref->refered_type, 1);
bp_pack_value (&bp, ref->use, 2);
- lto_output_bitpack (&bp);
- if (ref->refered_type == IPA_REF_CGRAPH)
- {
- int nref = lto_cgraph_encoder_lookup (encoder, ipa_ref_node (ref));
- gcc_assert (nref != LCC_NOT_FOUND);
- lto_output_sleb128_stream (ob->main_stream, nref);
- }
- else
- {
- int nref = lto_varpool_encoder_lookup (varpool_encoder,
- ipa_ref_varpool_node (ref));
- gcc_assert (nref != LCC_NOT_FOUND);
- lto_output_sleb128_stream (ob->main_stream, nref);
- }
+ streamer_write_bitpack (&bp);
+ nref = lto_symtab_encoder_lookup (encoder, ref->referred);
+ gcc_assert (nref != LCC_NOT_FOUND);
+ streamer_write_hwi_stream (ob->main_stream, nref);
}
/* Stream out profile_summary to OB. */
GCC profile feedback and they are difficult to merge from multiple
units. */
gcc_assert (profile_info->runs);
- lto_output_uleb128_stream (ob->main_stream, profile_info->runs);
- lto_output_uleb128_stream (ob->main_stream, profile_info->sum_max);
+ streamer_write_uhwi_stream (ob->main_stream, profile_info->runs);
+ streamer_write_uhwi_stream (ob->main_stream, profile_info->sum_max);
}
else
- lto_output_uleb128_stream (ob->main_stream, 0);
-}
-
-/* Add NODE into encoder as well as nodes it is cloned from.
- Do it in a way so clones appear first. */
-
-static void
-add_node_to (lto_cgraph_encoder_t encoder, struct cgraph_node *node,
- bool include_body)
-{
- if (node->clone_of)
- add_node_to (encoder, node->clone_of, include_body);
- else if (include_body)
- lto_set_cgraph_encoder_encode_body (encoder, node);
- lto_cgraph_encoder_encode (encoder, node);
-}
-
-/* Add all references in LIST to encoders. */
-
-static void
-add_references (lto_cgraph_encoder_t encoder,
- lto_varpool_encoder_t varpool_encoder,
- struct ipa_ref_list *list)
-{
- int i;
- struct ipa_ref *ref;
- for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
- if (ref->refered_type == IPA_REF_CGRAPH)
- add_node_to (encoder, ipa_ref_node (ref), false);
- else
- {
- struct varpool_node *vnode = ipa_ref_varpool_node (ref);
- lto_varpool_encoder_encode (varpool_encoder, vnode);
- }
+ streamer_write_uhwi_stream (ob->main_stream, 0);
}
/* Output all callees or indirect outgoing edges. EDGE must be the first such
static void
output_outgoing_cgraph_edges (struct cgraph_edge *edge,
struct lto_simple_output_block *ob,
- lto_cgraph_encoder_t encoder)
+ lto_symtab_encoder_t encoder)
{
if (!edge)
return;
/* Output the part of the cgraph in SET. */
static void
-output_refs (cgraph_node_set set, varpool_node_set vset,
- lto_cgraph_encoder_t encoder,
- lto_varpool_encoder_t varpool_encoder)
+output_refs (lto_symtab_encoder_t encoder)
{
- cgraph_node_set_iterator csi;
- varpool_node_set_iterator vsi;
+ lto_symtab_encoder_iterator lsei;
struct lto_simple_output_block *ob;
int count;
struct ipa_ref *ref;
ob = lto_create_simple_output_block (LTO_section_refs);
- for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+ for (lsei = lsei_start_in_partition (encoder); !lsei_end_p (lsei);
+ lsei_next_in_partition (&lsei))
{
- struct cgraph_node *node = csi_node (csi);
+ symtab_node node = lsei_node (lsei);
- count = ipa_ref_list_nreferences (&node->ref_list);
+ count = ipa_ref_list_nreferences (&node->symbol.ref_list);
if (count)
{
- lto_output_uleb128_stream (ob->main_stream, count);
- lto_output_uleb128_stream (ob->main_stream,
- lto_cgraph_encoder_lookup (encoder, node));
- for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
- lto_output_ref (ob, ref, encoder, varpool_encoder);
+ streamer_write_uhwi_stream (ob->main_stream, count);
+ streamer_write_uhwi_stream (ob->main_stream,
+ lto_symtab_encoder_lookup (encoder, node));
+ for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list,
+ i, ref); i++)
+ lto_output_ref (ob, ref, encoder);
}
}
- lto_output_uleb128_stream (ob->main_stream, 0);
+ streamer_write_uhwi_stream (ob->main_stream, 0);
- for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi))
- {
- struct varpool_node *node = vsi_node (vsi);
+ lto_destroy_simple_output_block (ob);
+}
- count = ipa_ref_list_nreferences (&node->ref_list);
- if (count)
- {
- lto_output_uleb128_stream (ob->main_stream, count);
- lto_output_uleb128_stream (ob->main_stream,
- lto_varpool_encoder_lookup (varpool_encoder,
- node));
- for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
- lto_output_ref (ob, ref, encoder, varpool_encoder);
- }
- }
+/* Add NODE into encoder as well as nodes it is cloned from.
+ Do it in a way so clones appear first. */
+
+static void
+add_node_to (lto_symtab_encoder_t encoder, struct cgraph_node *node,
+ bool include_body)
+{
+ if (node->clone_of)
+ add_node_to (encoder, node->clone_of, include_body);
+ else if (include_body)
+ lto_set_symtab_encoder_encode_body (encoder, node);
+ lto_symtab_encoder_encode (encoder, (symtab_node)node);
+}
- lto_output_uleb128_stream (ob->main_stream, 0);
+/* Add all references in LIST to encoders. */
- lto_destroy_simple_output_block (ob);
+static void
+add_references (lto_symtab_encoder_t encoder,
+ struct ipa_ref_list *list)
+{
+ int i;
+ struct ipa_ref *ref;
+ for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
+ if (symtab_function_p (ref->referred))
+ add_node_to (encoder, ipa_ref_node (ref), false);
+ else
+ {
+ struct varpool_node *vnode = ipa_ref_varpool_node (ref);
+ lto_symtab_encoder_encode (encoder, (symtab_node)vnode);
+ }
}
-/* Find out all cgraph and varpool nodes we want to encode in current unit
- and insert them to encoders. */
-void
-compute_ltrans_boundary (struct lto_out_decl_state *state,
- cgraph_node_set set, varpool_node_set vset)
+/* Find all symbols we want to stream into given partition and insert them
+ to encoders.
+
+ The function actually replaces IN_ENCODER by new one. The reason is that
+ streaming code needs clone's origin to be streamed before clone. This
+ means that we need to insert the nodes in specific order. This order is
+ ignored by the partitioning logic earlier. */
+
+lto_symtab_encoder_t
+compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
{
struct cgraph_node *node;
- cgraph_node_set_iterator csi;
- varpool_node_set_iterator vsi;
struct cgraph_edge *edge;
int i;
- lto_cgraph_encoder_t encoder;
- lto_varpool_encoder_t varpool_encoder;
+ lto_symtab_encoder_t encoder;
+ lto_symtab_encoder_iterator lsei;
- encoder = state->cgraph_node_encoder = lto_cgraph_encoder_new ();
- varpool_encoder = state->varpool_node_encoder = lto_varpool_encoder_new ();
+ encoder = lto_symtab_encoder_new ();
- /* Go over all the nodes in SET and assign references. */
- for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+ /* Go over all entries in the IN_ENCODER and duplicate them to
+ ENCODER. At the same time insert masters of clones so
+ every master appears before clone. */
+ for (lsei = lsei_start_function_in_partition (in_encoder);
+ !lsei_end_p (lsei); lsei_next_function_in_partition (&lsei))
{
- node = csi_node (csi);
+ node = lsei_cgraph_node (lsei);
add_node_to (encoder, node, true);
- add_references (encoder, varpool_encoder, &node->ref_list);
+ lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node);
+ add_references (encoder, &node->symbol.ref_list);
}
- for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi))
+ for (lsei = lsei_start_variable_in_partition (in_encoder);
+ !lsei_end_p (lsei); lsei_next_variable_in_partition (&lsei))
{
- struct varpool_node *vnode = vsi_node (vsi);
- gcc_assert (!vnode->alias);
- lto_varpool_encoder_encode (varpool_encoder, vnode);
- lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode);
- add_references (encoder, varpool_encoder, &vnode->ref_list);
+ struct varpool_node *vnode = lsei_varpool_node (lsei);
+ gcc_assert (!vnode->alias || vnode->alias_of);
+ lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
+ lto_set_symtab_encoder_encode_initializer (encoder, vnode);
+ add_references (encoder, &vnode->symbol.ref_list);
}
/* Pickle in also the initializer of all referenced readonly variables
to help folding. Constant pool variables are not shared, so we must
pickle those too. */
- for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++)
+ for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
{
- struct varpool_node *vnode = lto_varpool_encoder_deref (varpool_encoder, i);
- if (DECL_INITIAL (vnode->decl)
- && !lto_varpool_encoder_encode_initializer_p (varpool_encoder,
- vnode)
- && const_value_known_p (vnode->decl))
+ symtab_node node = lto_symtab_encoder_deref (encoder, i);
+ if (symtab_variable_p (node))
{
- lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode);
- add_references (encoder, varpool_encoder, &vnode->ref_list);
- }
+ struct varpool_node *vnode = varpool (node);
+ if (DECL_INITIAL (vnode->symbol.decl)
+ && !lto_symtab_encoder_encode_initializer_p (encoder,
+ vnode)
+ && const_value_known_p (vnode->symbol.decl))
+ {
+ lto_set_symtab_encoder_encode_initializer (encoder, vnode);
+ add_references (encoder, &vnode->symbol.ref_list);
+ }
+ }
}
/* Go over all the nodes again to include callees that are not in
SET. */
- for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+ for (lsei = lsei_start_function_in_partition (encoder);
+ !lsei_end_p (lsei); lsei_next_function_in_partition (&lsei))
{
- node = csi_node (csi);
+ node = lsei_cgraph_node (lsei);
for (edge = node->callees; edge; edge = edge->next_callee)
{
struct cgraph_node *callee = edge->callee;
- if (!cgraph_node_in_set_p (callee, set))
+ if (!lto_symtab_encoder_in_partition_p (encoder, (symtab_node)callee))
{
/* We should have moved all the inlines. */
gcc_assert (!callee->global.inlined_to);
}
}
}
+ lto_symtab_encoder_delete (in_encoder);
+ return encoder;
}
-/* Output the part of the cgraph in SET. */
+/* Output the part of the symtab in SET and VSET. */
void
-output_cgraph (cgraph_node_set set, varpool_node_set vset)
+output_symtab (void)
{
struct cgraph_node *node;
struct lto_simple_output_block *ob;
- cgraph_node_set_iterator csi;
+ lto_symtab_encoder_iterator lsei;
int i, n_nodes;
- lto_cgraph_encoder_t encoder;
- lto_varpool_encoder_t varpool_encoder;
- struct cgraph_asm_node *can;
+ lto_symtab_encoder_t encoder;
static bool asm_nodes_output = false;
if (flag_wpa)
- output_cgraph_opt_summary (set);
+ output_cgraph_opt_summary ();
- ob = lto_create_simple_output_block (LTO_section_cgraph);
+ ob = lto_create_simple_output_block (LTO_section_symtab_nodes);
output_profile_summary (ob);
/* An encoder for cgraph nodes should have been created by
ipa_write_summaries_1. */
- gcc_assert (ob->decl_state->cgraph_node_encoder);
- gcc_assert (ob->decl_state->varpool_node_encoder);
- encoder = ob->decl_state->cgraph_node_encoder;
- varpool_encoder = ob->decl_state->varpool_node_encoder;
+ gcc_assert (ob->decl_state->symtab_node_encoder);
+ encoder = ob->decl_state->symtab_node_encoder;
/* Write out the nodes. We must first output a node and then its clones,
otherwise at a time reading back the node there would be nothing to clone
from. */
- n_nodes = lto_cgraph_encoder_size (encoder);
+ n_nodes = lto_symtab_encoder_size (encoder);
for (i = 0; i < n_nodes; i++)
{
- node = lto_cgraph_encoder_deref (encoder, i);
- lto_output_node (ob, node, encoder, set, vset);
+ symtab_node node = lto_symtab_encoder_deref (encoder, i);
+ if (symtab_function_p (node))
+ lto_output_node (ob, cgraph (node), encoder);
+ else
+ lto_output_varpool_node (ob, varpool (node), encoder);
+
}
/* Go over the nodes in SET again to write edges. */
- for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+ for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
+ lsei_next_function_in_partition (&lsei))
{
- node = csi_node (csi);
+ node = lsei_cgraph_node (lsei);
output_outgoing_cgraph_edges (node->callees, ob, encoder);
output_outgoing_cgraph_edges (node->indirect_calls, ob, encoder);
}
- lto_output_uleb128_stream (ob->main_stream, 0);
+ streamer_write_uhwi_stream (ob->main_stream, 0);
+
+ lto_destroy_simple_output_block (ob);
/* Emit toplevel asms.
When doing WPA we must output every asm just once. Since we do not partition asm
if (!asm_nodes_output)
{
asm_nodes_output = true;
- for (can = cgraph_asm_nodes; can; can = can->next)
- {
- int len = TREE_STRING_LENGTH (can->asm_str);
- lto_output_uleb128_stream (ob->main_stream, len);
- for (i = 0; i < len; ++i)
- lto_output_1_stream (ob->main_stream,
- TREE_STRING_POINTER (can->asm_str)[i]);
- }
+ lto_output_toplevel_asms ();
}
- lto_output_uleb128_stream (ob->main_stream, 0);
-
- lto_destroy_simple_output_block (ob);
- output_varpool (set, vset);
- output_refs (set, vset, encoder, varpool_encoder);
+ output_refs (encoder);
}
/* Overwrite the information in NODE based on FILE_DATA, TAG, FLAGS,
static void
input_overwrite_node (struct lto_file_decl_data *file_data,
struct cgraph_node *node,
- enum LTO_cgraph_tags tag,
- struct bitpack_d *bp,
- enum ld_plugin_symbol_resolution resolution)
+ enum LTO_symtab_tags tag,
+ struct bitpack_d *bp)
{
- node->aux = (void *) tag;
- node->local.lto_file_data = file_data;
+ node->symbol.aux = (void *) tag;
+ node->symbol.lto_file_data = file_data;
node->local.local = bp_unpack_value (bp, 1);
- node->local.externally_visible = bp_unpack_value (bp, 1);
+ node->symbol.externally_visible = bp_unpack_value (bp, 1);
node->local.finalized = bp_unpack_value (bp, 1);
+ node->local.versionable = bp_unpack_value (bp, 1);
node->local.can_change_signature = bp_unpack_value (bp, 1);
node->local.redefined_extern_inline = bp_unpack_value (bp, 1);
- node->local.vtable_method = bp_unpack_value (bp, 1);
- node->needed = bp_unpack_value (bp, 1);
- node->address_taken = bp_unpack_value (bp, 1);
+ node->symbol.force_output = bp_unpack_value (bp, 1);
+ node->symbol.address_taken = bp_unpack_value (bp, 1);
node->abstract_and_needed = bp_unpack_value (bp, 1);
- node->reachable_from_other_partition = bp_unpack_value (bp, 1);
+ node->symbol.used_from_other_partition = bp_unpack_value (bp, 1);
node->lowered = bp_unpack_value (bp, 1);
- node->analyzed = tag == LTO_cgraph_analyzed_node;
- node->in_other_partition = bp_unpack_value (bp, 1);
- if (node->in_other_partition
+ node->analyzed = tag == LTO_symtab_analyzed_node;
+ node->symbol.in_other_partition = bp_unpack_value (bp, 1);
+ if (node->symbol.in_other_partition
/* Avoid updating decl when we are seeing just inline clone.
When inlining function that has functions already inlined into it,
we produce clones of inline clones.
we might end up streaming inline clone from other partition
to support clone we are interested in. */
&& (!node->clone_of
- || node->clone_of->decl != node->decl))
+ || node->clone_of->symbol.decl != node->symbol.decl))
{
- DECL_EXTERNAL (node->decl) = 1;
- TREE_STATIC (node->decl) = 0;
+ DECL_EXTERNAL (node->symbol.decl) = 1;
+ TREE_STATIC (node->symbol.decl) = 0;
}
node->alias = bp_unpack_value (bp, 1);
- node->finalized_by_frontend = bp_unpack_value (bp, 1);
node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
node->only_called_at_startup = bp_unpack_value (bp, 1);
node->only_called_at_exit = bp_unpack_value (bp, 1);
- node->resolution = resolution;
-}
-
-/* Output the part of the cgraph in SET. */
-
-static void
-output_varpool (cgraph_node_set set, varpool_node_set vset)
-{
- struct lto_simple_output_block *ob = lto_create_simple_output_block (LTO_section_varpool);
- lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
- int len = lto_varpool_encoder_size (varpool_encoder), i;
-
- lto_output_uleb128_stream (ob->main_stream, len);
-
- /* Write out the nodes. We must first output a node and then its clones,
- otherwise at a time reading back the node there would be nothing to clone
- from. */
- for (i = 0; i < len; i++)
- {
- lto_output_varpool_node (ob, lto_varpool_encoder_deref (varpool_encoder, i),
- varpool_encoder,
- set, vset);
- }
-
- lto_destroy_simple_output_block (ob);
+ node->tm_clone = bp_unpack_value (bp, 1);
+ node->thunk.thunk_p = bp_unpack_value (bp, 1);
+ node->symbol.resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution,
+ LDPR_NUM_KNOWN);
}
/* Read a node from input_block IB. TAG is the node's tag just read.
static struct cgraph_node *
input_node (struct lto_file_decl_data *file_data,
struct lto_input_block *ib,
- enum LTO_cgraph_tags tag,
- VEC(cgraph_node_ptr, heap) *nodes)
+ enum LTO_symtab_tags tag,
+ VEC(symtab_node, heap) *nodes)
{
tree fn_decl;
struct cgraph_node *node;
struct bitpack_d bp;
unsigned decl_index;
int ref = LCC_NOT_FOUND, ref2 = LCC_NOT_FOUND;
- unsigned long same_body_count = 0;
int clone_ref;
- enum ld_plugin_symbol_resolution resolution;
+ int order;
- clone_ref = lto_input_sleb128 (ib);
+ order = streamer_read_hwi (ib) + order_base;
+ clone_ref = streamer_read_hwi (ib);
- decl_index = lto_input_uleb128 (ib);
+ decl_index = streamer_read_uhwi (ib);
fn_decl = lto_file_decl_data_get_fn_decl (file_data, decl_index);
if (clone_ref != LCC_NOT_FOUND)
{
- node = cgraph_clone_node (VEC_index (cgraph_node_ptr, nodes, clone_ref), fn_decl,
- 0, CGRAPH_FREQ_BASE, 0, false, NULL);
+ node = cgraph_clone_node (cgraph (VEC_index (symtab_node, nodes, clone_ref)), fn_decl,
+ 0, CGRAPH_FREQ_BASE, false, NULL, false);
}
else
node = cgraph_get_create_node (fn_decl);
- node->count = lto_input_sleb128 (ib);
- node->count_materialization_scale = lto_input_sleb128 (ib);
+ node->symbol.order = order;
+ if (order >= symtab_order)
+ symtab_order = order + 1;
- if (tag == LTO_cgraph_analyzed_node)
- ref = lto_input_sleb128 (ib);
+ node->count = streamer_read_hwi (ib);
+ node->count_materialization_scale = streamer_read_hwi (ib);
- ref2 = lto_input_sleb128 (ib);
+ if (tag == LTO_symtab_analyzed_node)
+ ref = streamer_read_hwi (ib);
+
+ ref2 = streamer_read_hwi (ib);
/* Make sure that we have not read this node before. Nodes that
have already been read will have their tag stored in the 'aux'
field. Since built-in functions can be referenced in multiple
functions, they are expected to be read more than once. */
- if (node->aux && !DECL_IS_BUILTIN (node->decl))
+ if (node->symbol.aux && !DECL_BUILT_IN (node->symbol.decl))
internal_error ("bytecode stream: found multiple instances of cgraph "
"node %d", node->uid);
- bp = lto_input_bitpack (ib);
- resolution = (enum ld_plugin_symbol_resolution)lto_input_uleb128 (ib);
- input_overwrite_node (file_data, node, tag, &bp, resolution);
+ bp = streamer_read_bitpack (ib);
+ input_overwrite_node (file_data, node, tag, &bp);
/* Store a reference for now, and fix up later to be a pointer. */
node->global.inlined_to = (cgraph_node_ptr) (intptr_t) ref;
/* Store a reference for now, and fix up later to be a pointer. */
- node->same_comdat_group = (cgraph_node_ptr) (intptr_t) ref2;
+ node->symbol.same_comdat_group = (symtab_node) (intptr_t) ref2;
- same_body_count = lto_input_uleb128 (ib);
- while (same_body_count-- > 0)
+ if (node->thunk.thunk_p)
+ {
+ int type = streamer_read_uhwi (ib);
+ HOST_WIDE_INT fixed_offset = streamer_read_uhwi (ib);
+ HOST_WIDE_INT virtual_value = streamer_read_uhwi (ib);
+
+ node->thunk.fixed_offset = fixed_offset;
+ node->thunk.this_adjusting = (type & 2);
+ node->thunk.virtual_value = virtual_value;
+ node->thunk.virtual_offset_p = (type & 4);
+ }
+ if (node->thunk.thunk_p || node->alias)
{
- tree alias_decl;
- int type;
- struct cgraph_node *alias;
- decl_index = lto_input_uleb128 (ib);
- alias_decl = lto_file_decl_data_get_fn_decl (file_data, decl_index);
- type = lto_input_uleb128 (ib);
- if (!type)
+ if (streamer_read_hwi_in_range (ib, "alias nonzero flag", 0, 1))
{
- tree real_alias;
- decl_index = lto_input_uleb128 (ib);
- real_alias = lto_file_decl_data_get_fn_decl (file_data, decl_index);
- alias = cgraph_same_body_alias (node, alias_decl, real_alias);
+ decl_index = streamer_read_uhwi (ib);
+ node->thunk.alias = lto_file_decl_data_get_fn_decl (file_data,
+ decl_index);
}
- else
- {
- HOST_WIDE_INT fixed_offset = lto_input_uleb128 (ib);
- HOST_WIDE_INT virtual_value = lto_input_uleb128 (ib);
- tree real_alias;
- decl_index = lto_input_uleb128 (ib);
- real_alias = lto_file_decl_data_get_fn_decl (file_data, decl_index);
- alias = cgraph_add_thunk (node, alias_decl, fn_decl, type & 2, fixed_offset,
- virtual_value,
- (type & 4) ? size_int (virtual_value) : NULL_TREE,
- real_alias);
- }
- gcc_assert (alias);
- alias->resolution = (enum ld_plugin_symbol_resolution)lto_input_uleb128 (ib);
}
return node;
}
tree var_decl;
struct varpool_node *node;
struct bitpack_d bp;
- bool aliases_p;
- int count;
int ref = LCC_NOT_FOUND;
+ bool non_null_aliasof;
+ int order;
- decl_index = lto_input_uleb128 (ib);
+ order = streamer_read_hwi (ib) + order_base;
+ decl_index = streamer_read_uhwi (ib);
var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
node = varpool_node (var_decl);
- node->lto_file_data = file_data;
-
- bp = lto_input_bitpack (ib);
- node->externally_visible = bp_unpack_value (&bp, 1);
- node->force_output = bp_unpack_value (&bp, 1);
+ node->symbol.order = order;
+ if (order >= symtab_order)
+ symtab_order = order + 1;
+ node->symbol.lto_file_data = file_data;
+
+ bp = streamer_read_bitpack (ib);
+ node->symbol.externally_visible = bp_unpack_value (&bp, 1);
+ node->symbol.force_output = bp_unpack_value (&bp, 1);
node->finalized = bp_unpack_value (&bp, 1);
node->alias = bp_unpack_value (&bp, 1);
- node->analyzed = node->finalized;
- node->used_from_other_partition = bp_unpack_value (&bp, 1);
- node->in_other_partition = bp_unpack_value (&bp, 1);
- if (node->in_other_partition)
+ non_null_aliasof = bp_unpack_value (&bp, 1);
+ node->symbol.used_from_other_partition = bp_unpack_value (&bp, 1);
+ node->symbol.in_other_partition = bp_unpack_value (&bp, 1);
+ node->analyzed = (node->finalized && (!node->alias || !node->symbol.in_other_partition));
+ if (node->symbol.in_other_partition)
{
- DECL_EXTERNAL (node->decl) = 1;
- TREE_STATIC (node->decl) = 0;
+ DECL_EXTERNAL (node->symbol.decl) = 1;
+ TREE_STATIC (node->symbol.decl) = 0;
}
- aliases_p = bp_unpack_value (&bp, 1);
- if (node->finalized)
- varpool_mark_needed_node (node);
- ref = lto_input_sleb128 (ib);
- /* Store a reference for now, and fix up later to be a pointer. */
- node->same_comdat_group = (struct varpool_node *) (intptr_t) ref;
- node->resolution = (enum ld_plugin_symbol_resolution)lto_input_uleb128 (ib);
- if (aliases_p)
+ if (non_null_aliasof)
{
- count = lto_input_uleb128 (ib);
- for (; count > 0; count --)
- {
- tree decl = lto_file_decl_data_get_var_decl (file_data,
- lto_input_uleb128 (ib));
- struct varpool_node *alias;
- alias = varpool_extra_name_alias (decl, var_decl);
- alias->resolution = (enum ld_plugin_symbol_resolution)lto_input_uleb128 (ib);
- }
+ decl_index = streamer_read_uhwi (ib);
+ node->alias_of = lto_file_decl_data_get_var_decl (file_data, decl_index);
}
+ ref = streamer_read_hwi (ib);
+ /* Store a reference for now, and fix up later to be a pointer. */
+ node->symbol.same_comdat_group = (symtab_node) (intptr_t) ref;
+ node->symbol.resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution,
+ LDPR_NUM_KNOWN);
+
return node;
}
static void
input_ref (struct lto_input_block *ib,
- struct cgraph_node *refering_node,
- struct varpool_node *refering_varpool_node,
- VEC(cgraph_node_ptr, heap) *nodes,
- VEC(varpool_node_ptr, heap) *varpool_nodes)
+ symtab_node referring_node,
+ VEC(symtab_node, heap) *nodes)
{
- struct cgraph_node *node = NULL;
- struct varpool_node *varpool_node = NULL;
+ symtab_node node = NULL;
struct bitpack_d bp;
- enum ipa_ref_type type;
enum ipa_ref_use use;
- bp = lto_input_bitpack (ib);
- type = (enum ipa_ref_type) bp_unpack_value (&bp, 1);
+ bp = streamer_read_bitpack (ib);
use = (enum ipa_ref_use) bp_unpack_value (&bp, 2);
- if (type == IPA_REF_CGRAPH)
- node = VEC_index (cgraph_node_ptr, nodes, lto_input_sleb128 (ib));
- else
- varpool_node = VEC_index (varpool_node_ptr, varpool_nodes, lto_input_sleb128 (ib));
- ipa_record_reference (refering_node, refering_varpool_node,
- node, varpool_node, use, NULL);
+ node = VEC_index (symtab_node, nodes, streamer_read_hwi (ib));
+ ipa_record_reference (referring_node, node, use, NULL);
}
/* Read an edge from IB. NODES points to a vector of previously read nodes for
indirect_unknown_callee set). */
static void
-input_edge (struct lto_input_block *ib, VEC(cgraph_node_ptr, heap) *nodes,
+input_edge (struct lto_input_block *ib, VEC(symtab_node, heap) *nodes,
bool indirect)
{
struct cgraph_node *caller, *callee;
unsigned int stmt_id;
gcov_type count;
int freq;
- unsigned int nest;
cgraph_inline_failed_t inline_failed;
struct bitpack_d bp;
int ecf_flags = 0;
- int call_stmt_time, call_stmt_size;
- caller = VEC_index (cgraph_node_ptr, nodes, lto_input_sleb128 (ib));
- if (caller == NULL || caller->decl == NULL_TREE)
+ caller = cgraph (VEC_index (symtab_node, nodes, streamer_read_hwi (ib)));
+ if (caller == NULL || caller->symbol.decl == NULL_TREE)
internal_error ("bytecode stream: no caller found while reading edge");
if (!indirect)
{
- callee = VEC_index (cgraph_node_ptr, nodes, lto_input_sleb128 (ib));
- if (callee == NULL || callee->decl == NULL_TREE)
+ callee = cgraph (VEC_index (symtab_node, nodes, streamer_read_hwi (ib)));
+ if (callee == NULL || callee->symbol.decl == NULL_TREE)
internal_error ("bytecode stream: no callee found while reading edge");
}
else
callee = NULL;
- count = (gcov_type) lto_input_sleb128 (ib);
+ count = (gcov_type) streamer_read_hwi (ib);
- bp = lto_input_bitpack (ib);
- stmt_id = (unsigned int) bp_unpack_value (&bp, HOST_BITS_PER_INT);
- inline_failed = (cgraph_inline_failed_t) bp_unpack_value (&bp,
- HOST_BITS_PER_INT);
- freq = (int) bp_unpack_value (&bp, HOST_BITS_PER_INT);
- call_stmt_size = (int) bp_unpack_value (&bp, HOST_BITS_PER_INT);
- call_stmt_time = (int) bp_unpack_value (&bp, HOST_BITS_PER_INT);
- nest = (unsigned) bp_unpack_value (&bp, 30);
+ bp = streamer_read_bitpack (ib);
+ inline_failed = bp_unpack_enum (&bp, cgraph_inline_failed_enum, CIF_N_REASONS);
+ stmt_id = bp_unpack_var_len_unsigned (&bp);
+ freq = (int) bp_unpack_var_len_unsigned (&bp);
if (indirect)
- edge = cgraph_create_indirect_edge (caller, NULL, 0, count, freq, nest);
+ edge = cgraph_create_indirect_edge (caller, NULL, 0, count, freq);
else
- edge = cgraph_create_edge (caller, callee, NULL, count, freq, nest);
+ edge = cgraph_create_edge (caller, callee, NULL, count, freq);
edge->indirect_inlining_edge = bp_unpack_value (&bp, 1);
edge->lto_stmt_uid = stmt_id;
edge->inline_failed = inline_failed;
edge->call_stmt_cannot_inline_p = bp_unpack_value (&bp, 1);
edge->can_throw_external = bp_unpack_value (&bp, 1);
- edge->call_stmt_size = call_stmt_size;
- edge->call_stmt_time = call_stmt_time;
if (indirect)
{
if (bp_unpack_value (&bp, 1))
/* Read a cgraph from IB using the info in FILE_DATA. */
-static VEC(cgraph_node_ptr, heap) *
+static VEC(symtab_node, heap) *
input_cgraph_1 (struct lto_file_decl_data *file_data,
struct lto_input_block *ib)
{
- enum LTO_cgraph_tags tag;
- VEC(cgraph_node_ptr, heap) *nodes = NULL;
- struct cgraph_node *node;
+ enum LTO_symtab_tags tag;
+ VEC(symtab_node, heap) *nodes = NULL;
+ symtab_node node;
unsigned i;
- unsigned HOST_WIDE_INT len;
- tag = (enum LTO_cgraph_tags) lto_input_uleb128 (ib);
+ tag = streamer_read_enum (ib, LTO_symtab_tags, LTO_symtab_last_tag);
+ order_base = symtab_order;
while (tag)
{
- if (tag == LTO_cgraph_edge)
+ if (tag == LTO_symtab_edge)
input_edge (ib, nodes, false);
- else if (tag == LTO_cgraph_indirect_edge)
+ else if (tag == LTO_symtab_indirect_edge)
input_edge (ib, nodes, true);
+ else if (tag == LTO_symtab_variable)
+ {
+ node = (symtab_node)input_varpool_node (file_data, ib);
+ VEC_safe_push (symtab_node, heap, nodes, node);
+ lto_symtab_encoder_encode (file_data->symtab_node_encoder, node);
+ }
else
{
- node = input_node (file_data, ib, tag,nodes);
- if (node == NULL || node->decl == NULL_TREE)
+ node = (symtab_node)input_node (file_data, ib, tag, nodes);
+ if (node == NULL || node->symbol.decl == NULL_TREE)
internal_error ("bytecode stream: found empty cgraph node");
- VEC_safe_push (cgraph_node_ptr, heap, nodes, node);
- lto_cgraph_encoder_encode (file_data->cgraph_node_encoder, node);
+ VEC_safe_push (symtab_node, heap, nodes, node);
+ lto_symtab_encoder_encode (file_data->symtab_node_encoder, node);
}
- tag = (enum LTO_cgraph_tags) lto_input_uleb128 (ib);
+ tag = streamer_read_enum (ib, LTO_symtab_tags, LTO_symtab_last_tag);
}
- /* Input toplevel asms. */
- len = lto_input_uleb128 (ib);
- while (len)
- {
- char *str = (char *)xmalloc (len + 1);
- for (i = 0; i < len; ++i)
- str[i] = lto_input_1_unsigned (ib);
- cgraph_add_asm_node (build_string (len, str));
- free (str);
+ lto_input_toplevel_asms (file_data, order_base);
- len = lto_input_uleb128 (ib);
- }
- /* AUX pointers should be all non-zero for nodes read from the stream. */
+ /* AUX pointers should be all non-zero for function nodes read from the stream. */
#ifdef ENABLE_CHECKING
- FOR_EACH_VEC_ELT (cgraph_node_ptr, nodes, i, node)
- gcc_assert (node->aux);
+ FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
+ gcc_assert (node->symbol.aux || !symtab_function_p (node));
#endif
- FOR_EACH_VEC_ELT (cgraph_node_ptr, nodes, i, node)
+ FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
{
- int ref = (int) (intptr_t) node->global.inlined_to;
+ int ref;
+ if (symtab_function_p (node))
+ {
+ ref = (int) (intptr_t) cgraph (node)->global.inlined_to;
- /* We share declaration of builtins, so we may read same node twice. */
- if (!node->aux)
- continue;
- node->aux = NULL;
+ /* We share declaration of builtins, so we may read same node twice. */
+ if (!node->symbol.aux)
+ continue;
+ node->symbol.aux = NULL;
- /* Fixup inlined_to from reference to pointer. */
- if (ref != LCC_NOT_FOUND)
- node->global.inlined_to = VEC_index (cgraph_node_ptr, nodes, ref);
- else
- node->global.inlined_to = NULL;
+ /* Fixup inlined_to from reference to pointer. */
+ if (ref != LCC_NOT_FOUND)
+ cgraph (node)->global.inlined_to = cgraph (VEC_index (symtab_node, nodes, ref));
+ else
+ cgraph (node)->global.inlined_to = NULL;
+ }
- ref = (int) (intptr_t) node->same_comdat_group;
+ ref = (int) (intptr_t) node->symbol.same_comdat_group;
/* Fixup same_comdat_group from reference to pointer. */
if (ref != LCC_NOT_FOUND)
- node->same_comdat_group = VEC_index (cgraph_node_ptr, nodes, ref);
+ node->symbol.same_comdat_group = VEC_index (symtab_node, nodes, ref);
else
- node->same_comdat_group = NULL;
+ node->symbol.same_comdat_group = NULL;
}
- FOR_EACH_VEC_ELT (cgraph_node_ptr, nodes, i, node)
- node->aux = (void *)1;
+ FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
+ node->symbol.aux = symtab_function_p (node) ? (void *)1 : NULL;
return nodes;
}
-/* Read a varpool from IB using the info in FILE_DATA. */
-
-static VEC(varpool_node_ptr, heap) *
-input_varpool_1 (struct lto_file_decl_data *file_data,
- struct lto_input_block *ib)
-{
- unsigned HOST_WIDE_INT len;
- VEC(varpool_node_ptr, heap) *varpool = NULL;
- int i;
- struct varpool_node *node;
-
- len = lto_input_uleb128 (ib);
- while (len)
- {
- VEC_safe_push (varpool_node_ptr, heap, varpool,
- input_varpool_node (file_data, ib));
- len--;
- }
-#ifdef ENABLE_CHECKING
- FOR_EACH_VEC_ELT (varpool_node_ptr, varpool, i, node)
- gcc_assert (!node->aux);
-#endif
- FOR_EACH_VEC_ELT (varpool_node_ptr, varpool, i, node)
- {
- int ref = (int) (intptr_t) node->same_comdat_group;
- /* We share declaration of builtins, so we may read same node twice. */
- if (node->aux)
- continue;
- node->aux = (void *)1;
-
- /* Fixup same_comdat_group from reference to pointer. */
- if (ref != LCC_NOT_FOUND)
- node->same_comdat_group = VEC_index (varpool_node_ptr, varpool, ref);
- else
- node->same_comdat_group = NULL;
- }
- FOR_EACH_VEC_ELT (varpool_node_ptr, varpool, i, node)
- node->aux = NULL;
- return varpool;
-}
-
/* Input ipa_refs. */
static void
input_refs (struct lto_input_block *ib,
- VEC(cgraph_node_ptr, heap) *nodes,
- VEC(varpool_node_ptr, heap) *varpool)
+ VEC(symtab_node, heap) *nodes)
{
int count;
int idx;
while (true)
{
- struct cgraph_node *node;
- count = lto_input_uleb128 (ib);
+ symtab_node node;
+ count = streamer_read_uhwi (ib);
if (!count)
break;
- idx = lto_input_uleb128 (ib);
- node = VEC_index (cgraph_node_ptr, nodes, idx);
+ idx = streamer_read_uhwi (ib);
+ node = VEC_index (symtab_node, nodes, idx);
while (count)
{
- input_ref (ib, node, NULL, nodes, varpool);
- count--;
- }
- }
- while (true)
- {
- struct varpool_node *node;
- count = lto_input_uleb128 (ib);
- if (!count)
- break;
- node = VEC_index (varpool_node_ptr, varpool, lto_input_uleb128 (ib));
- while (count)
- {
- input_ref (ib, NULL, node, nodes, varpool);
+ input_ref (ib, node, nodes);
count--;
}
}
input_profile_summary (struct lto_input_block *ib,
struct lto_file_decl_data *file_data)
{
- unsigned int runs = lto_input_uleb128 (ib);
+ unsigned int runs = streamer_read_uhwi (ib);
if (runs)
{
file_data->profile_info.runs = runs;
- file_data->profile_info.sum_max = lto_input_uleb128 (ib);
+ file_data->profile_info.sum_max = streamer_read_uhwi (ib);
}
}
/* Now compute count_materialization_scale of each node.
During LTRANS we already have values of count_materialization_scale
computed, so just update them. */
- for (node = cgraph_nodes; node; node = node->next)
- if (node->local.lto_file_data->profile_info.runs)
+ FOR_EACH_FUNCTION (node)
+ if (node->symbol.lto_file_data
+ && node->symbol.lto_file_data->profile_info.runs)
{
int scale;
scale =
((node->count_materialization_scale * max_runs
- + node->local.lto_file_data->profile_info.runs / 2)
- / node->local.lto_file_data->profile_info.runs);
+ + node->symbol.lto_file_data->profile_info.runs / 2)
+ / node->symbol.lto_file_data->profile_info.runs);
node->count_materialization_scale = scale;
if (scale < 0)
fatal_error ("Profile information in %s corrupted",
}
}
-/* Input and merge the cgraph from each of the .o files passed to
+/* Input and merge the symtab from each of the .o files passed to
lto1. */
void
-input_cgraph (void)
+input_symtab (void)
{
struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
struct lto_file_decl_data *file_data;
unsigned int j = 0;
struct cgraph_node *node;
+ cgraph_state = CGRAPH_STATE_IPA_SSA;
+
while ((file_data = file_data_vec[j++]))
{
const char *data;
size_t len;
struct lto_input_block *ib;
- VEC(cgraph_node_ptr, heap) *nodes;
- VEC(varpool_node_ptr, heap) *varpool;
+ VEC(symtab_node, heap) *nodes;
- ib = lto_create_simple_input_block (file_data, LTO_section_cgraph,
+ ib = lto_create_simple_input_block (file_data, LTO_section_symtab_nodes,
&data, &len);
if (!ib)
fatal_error ("cannot find LTO cgraph in %s", file_data->file_name);
input_profile_summary (ib, file_data);
- file_data->cgraph_node_encoder = lto_cgraph_encoder_new ();
+ file_data->symtab_node_encoder = lto_symtab_encoder_new ();
nodes = input_cgraph_1 (file_data, ib);
- lto_destroy_simple_input_block (file_data, LTO_section_cgraph,
- ib, data, len);
-
- ib = lto_create_simple_input_block (file_data, LTO_section_varpool,
- &data, &len);
- if (!ib)
- fatal_error ("cannot find LTO varpool in %s", file_data->file_name);
- varpool = input_varpool_1 (file_data, ib);
- lto_destroy_simple_input_block (file_data, LTO_section_varpool,
+ lto_destroy_simple_input_block (file_data, LTO_section_symtab_nodes,
ib, data, len);
ib = lto_create_simple_input_block (file_data, LTO_section_refs,
&data, &len);
if (!ib)
fatal_error("cannot find LTO section refs in %s", file_data->file_name);
- input_refs (ib, nodes, varpool);
+ input_refs (ib, nodes);
lto_destroy_simple_input_block (file_data, LTO_section_refs,
ib, data, len);
if (flag_ltrans)
input_cgraph_opt_summary (nodes);
- VEC_free (cgraph_node_ptr, heap, nodes);
- VEC_free (varpool_node_ptr, heap, varpool);
+ VEC_free (symtab_node, heap, nodes);
}
+
merge_profile_summaries (file_data_vec);
-
/* Clear out the aux field that was used to store enough state to
tell which nodes should be overwritten. */
- for (node = cgraph_nodes; node; node = node->next)
+ FOR_EACH_FUNCTION (node)
{
/* Some nodes may have been created by cgraph_node. This
happens when the callgraph contains nested functions. If the
node for the parent function was never emitted to the gimple
file, cgraph_node will create a node for it when setting the
context of the nested function. */
- if (node->local.lto_file_data)
- node->aux = NULL;
+ if (node->symbol.lto_file_data)
+ node->symbol.aux = NULL;
}
}
/* True when we need optimization summary for NODE. */
static int
-output_cgraph_opt_summary_p (struct cgraph_node *node, cgraph_node_set set)
+output_cgraph_opt_summary_p (struct cgraph_node *node)
{
- struct cgraph_edge *e;
-
- if (cgraph_node_in_set_p (node, set))
- {
- for (e = node->callees; e; e = e->next_callee)
- if (e->indirect_info
- && e->indirect_info->thunk_delta != 0)
- return true;
-
- for (e = node->indirect_calls; e; e = e->next_callee)
- if (e->indirect_info->thunk_delta != 0)
- return true;
- }
-
return (node->clone_of
&& (node->clone.tree_map
|| node->clone.args_to_skip
/* Output optimization summary for EDGE to OB. */
static void
-output_edge_opt_summary (struct output_block *ob,
- struct cgraph_edge *edge)
+output_edge_opt_summary (struct output_block *ob ATTRIBUTE_UNUSED,
+ struct cgraph_edge *edge ATTRIBUTE_UNUSED)
{
- if (edge->indirect_info)
- lto_output_sleb128_stream (ob->main_stream,
- edge->indirect_info->thunk_delta);
- else
- lto_output_sleb128_stream (ob->main_stream, 0);
}
/* Output optimization summary for NODE to OB. */
static void
output_node_opt_summary (struct output_block *ob,
struct cgraph_node *node,
- cgraph_node_set set)
+ lto_symtab_encoder_t encoder)
{
unsigned int index;
bitmap_iterator bi;
int i;
struct cgraph_edge *e;
- lto_output_uleb128_stream (ob->main_stream,
- bitmap_count_bits (node->clone.args_to_skip));
- EXECUTE_IF_SET_IN_BITMAP (node->clone.args_to_skip, 0, index, bi)
- lto_output_uleb128_stream (ob->main_stream, index);
- lto_output_uleb128_stream (ob->main_stream,
- bitmap_count_bits (node->clone.combined_args_to_skip));
- EXECUTE_IF_SET_IN_BITMAP (node->clone.combined_args_to_skip, 0, index, bi)
- lto_output_uleb128_stream (ob->main_stream, index);
- lto_output_uleb128_stream (ob->main_stream,
- VEC_length (ipa_replace_map_p, node->clone.tree_map));
+ if (node->clone.args_to_skip)
+ {
+ streamer_write_uhwi (ob, bitmap_count_bits (node->clone.args_to_skip));
+ EXECUTE_IF_SET_IN_BITMAP (node->clone.args_to_skip, 0, index, bi)
+ streamer_write_uhwi (ob, index);
+ }
+ else
+ streamer_write_uhwi (ob, 0);
+ if (node->clone.combined_args_to_skip)
+ {
+ streamer_write_uhwi (ob, bitmap_count_bits (node->clone.combined_args_to_skip));
+ EXECUTE_IF_SET_IN_BITMAP (node->clone.combined_args_to_skip, 0, index, bi)
+ streamer_write_uhwi (ob, index);
+ }
+ else
+ streamer_write_uhwi (ob, 0);
+ streamer_write_uhwi (ob, VEC_length (ipa_replace_map_p,
+ node->clone.tree_map));
FOR_EACH_VEC_ELT (ipa_replace_map_p, node->clone.tree_map, i, map)
{
int parm_num;
tree parm;
- for (parm_num = 0, parm = DECL_ARGUMENTS (node->decl); parm;
+ for (parm_num = 0, parm = DECL_ARGUMENTS (node->symbol.decl); parm;
parm = DECL_CHAIN (parm), parm_num++)
if (map->old_tree == parm)
break;
/* At the moment we assume all old trees to be PARM_DECLs, because we have no
mechanism to store function local declarations into summaries. */
gcc_assert (parm);
- lto_output_uleb128_stream (ob->main_stream, parm_num);
- lto_output_tree (ob, map->new_tree, true);
+ streamer_write_uhwi (ob, parm_num);
+ stream_write_tree (ob, map->new_tree, true);
bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, map->replace_p, 1);
bp_pack_value (&bp, map->ref_p, 1);
- lto_output_bitpack (&bp);
+ streamer_write_bitpack (&bp);
}
- if (cgraph_node_in_set_p (node, set))
+ if (lto_symtab_encoder_in_partition_p (encoder, (symtab_node) node))
{
for (e = node->callees; e; e = e->next_callee)
output_edge_opt_summary (ob, e);
At the moment it is the clone info structure. */
static void
-output_cgraph_opt_summary (cgraph_node_set set)
+output_cgraph_opt_summary (void)
{
- struct cgraph_node *node;
+ symtab_node node;
int i, n_nodes;
- lto_cgraph_encoder_t encoder;
+ lto_symtab_encoder_t encoder;
struct output_block *ob = create_output_block (LTO_section_cgraph_opt_sum);
unsigned count = 0;
ob->cgraph_node = NULL;
- encoder = ob->decl_state->cgraph_node_encoder;
- n_nodes = lto_cgraph_encoder_size (encoder);
+ encoder = ob->decl_state->symtab_node_encoder;
+ n_nodes = lto_symtab_encoder_size (encoder);
for (i = 0; i < n_nodes; i++)
- if (output_cgraph_opt_summary_p (lto_cgraph_encoder_deref (encoder, i),
- set))
+ if (symtab_function_p (node = lto_symtab_encoder_deref (encoder, i))
+ && output_cgraph_opt_summary_p (cgraph (node)))
count++;
- lto_output_uleb128_stream (ob->main_stream, count);
+ streamer_write_uhwi (ob, count);
for (i = 0; i < n_nodes; i++)
{
- node = lto_cgraph_encoder_deref (encoder, i);
- if (output_cgraph_opt_summary_p (node, set))
+ node = lto_symtab_encoder_deref (encoder, i);
+ if (symtab_function_p (node)
+ && output_cgraph_opt_summary_p (cgraph (node)))
{
- lto_output_uleb128_stream (ob->main_stream, i);
- output_node_opt_summary (ob, node, set);
+ streamer_write_uhwi (ob, i);
+ output_node_opt_summary (ob, cgraph (node), encoder);
}
}
produce_asm (ob, NULL);
/* Input optimisation summary of EDGE. */
static void
-input_edge_opt_summary (struct cgraph_edge *edge,
- struct lto_input_block *ib_main)
+input_edge_opt_summary (struct cgraph_edge *edge ATTRIBUTE_UNUSED,
+ struct lto_input_block *ib_main ATTRIBUTE_UNUSED)
{
- HOST_WIDE_INT thunk_delta;
- thunk_delta = lto_input_sleb128 (ib_main);
- if (thunk_delta != 0)
- {
- gcc_assert (!edge->indirect_info);
- edge->indirect_info = cgraph_allocate_init_indirect_info ();
- edge->indirect_info->thunk_delta = thunk_delta;
- }
}
/* Input optimisation summary of NODE. */
struct bitpack_d bp;
struct cgraph_edge *e;
- count = lto_input_uleb128 (ib_main);
+ count = streamer_read_uhwi (ib_main);
if (count)
node->clone.args_to_skip = BITMAP_GGC_ALLOC ();
for (i = 0; i < count; i++)
{
- bit = lto_input_uleb128 (ib_main);
+ bit = streamer_read_uhwi (ib_main);
bitmap_set_bit (node->clone.args_to_skip, bit);
}
- count = lto_input_uleb128 (ib_main);
+ count = streamer_read_uhwi (ib_main);
if (count)
node->clone.combined_args_to_skip = BITMAP_GGC_ALLOC ();
for (i = 0; i < count; i++)
{
- bit = lto_input_uleb128 (ib_main);
+ bit = streamer_read_uhwi (ib_main);
bitmap_set_bit (node->clone.combined_args_to_skip, bit);
}
- count = lto_input_uleb128 (ib_main);
+ count = streamer_read_uhwi (ib_main);
for (i = 0; i < count; i++)
{
int parm_num;
struct ipa_replace_map *map = ggc_alloc_ipa_replace_map ();
VEC_safe_push (ipa_replace_map_p, gc, node->clone.tree_map, map);
- for (parm_num = 0, parm = DECL_ARGUMENTS (node->decl); parm_num;
+ for (parm_num = 0, parm = DECL_ARGUMENTS (node->symbol.decl); parm_num;
parm = DECL_CHAIN (parm))
parm_num --;
- map->parm_num = lto_input_uleb128 (ib_main);
+ map->parm_num = streamer_read_uhwi (ib_main);
map->old_tree = NULL;
- map->new_tree = lto_input_tree (ib_main, data_in);
- bp = lto_input_bitpack (ib_main);
+ map->new_tree = stream_read_tree (ib_main, data_in);
+ bp = streamer_read_bitpack (ib_main);
map->replace_p = bp_unpack_value (&bp, 1);
map->ref_p = bp_unpack_value (&bp, 1);
}
static void
input_cgraph_opt_section (struct lto_file_decl_data *file_data,
- const char *data, size_t len, VEC (cgraph_node_ptr,
+ const char *data, size_t len, VEC (symtab_node,
heap) * nodes)
{
const struct lto_function_header *header =
(const struct lto_function_header *) data;
- const int32_t cfg_offset = sizeof (struct lto_function_header);
- const int32_t main_offset = cfg_offset + header->cfg_size;
- const int32_t string_offset = main_offset + header->main_size;
+ const int cfg_offset = sizeof (struct lto_function_header);
+ const int main_offset = cfg_offset + header->cfg_size;
+ const int string_offset = main_offset + header->main_size;
struct data_in *data_in;
struct lto_input_block ib_main;
unsigned int i;
data_in =
lto_data_in_create (file_data, (const char *) data + string_offset,
header->string_size, NULL);
- count = lto_input_uleb128 (&ib_main);
+ count = streamer_read_uhwi (&ib_main);
for (i = 0; i < count; i++)
{
- int ref = lto_input_uleb128 (&ib_main);
- input_node_opt_summary (VEC_index (cgraph_node_ptr, nodes, ref),
+ int ref = streamer_read_uhwi (&ib_main);
+ input_node_opt_summary (cgraph (VEC_index (symtab_node, nodes, ref)),
&ib_main, data_in);
}
lto_free_section_data (file_data, LTO_section_cgraph_opt_sum, NULL, data,
/* Input optimization summary of cgraph. */
static void
-input_cgraph_opt_summary (VEC (cgraph_node_ptr, heap) * nodes)
+input_cgraph_opt_summary (VEC (symtab_node, heap) * nodes)
{
struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
struct lto_file_decl_data *file_data;