@@ -332,7 +332,7 @@ cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h $(DIAGNOSTIC_CORE_H) \
cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) toplev.h \
$(FLAGS_H) output.h $(RTL_H) $(TIMEVAR_H) \
$(TREE_INLINE_H) $(CGRAPH_H) $(TARGET_H) $(C_COMMON_H) $(GIMPLE_H) \
- bitmap.h gt-cp-semantics.h c-family/c-objc.h
+ bitmap.h gt-cp-semantics.h c-family/c-objc.h $(CXX_PPH_STREAMER_H)
cp/dump.o: cp/dump.c $(CXX_TREE_H) $(TM_H) $(TREE_DUMP_H)
cp/optimize.o: cp/optimize.c $(CXX_TREE_H) $(TM_H) \
input.h $(PARAMS_H) debug.h $(TREE_INLINE_H) $(GIMPLE_H) \
@@ -5900,7 +5900,7 @@ cp_rest_of_decl_compilation (tree decl, int top_level, int at_end)
/* If we are generating a PPH image, add DECL to its symbol table. */
if (pph_out_file)
- pph_add_decl_to_symtab (decl);
+ pph_add_decl_to_symtab (decl, PPH_SYMTAB_DECLARE, top_level, at_end);
}
@@ -12834,10 +12834,6 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
start_fname_decls ();
store_parm_decls (current_function_parms);
-
- /* If we are generating a PPH image, add DECL1 to its symbol table. */
- if (pph_out_file)
- pph_add_decl_to_symtab (decl1);
}
@@ -355,10 +355,10 @@ pph_in_ld_min (pph_stream *stream, struct lang_decl_min *ldm)
static VEC(tree,gc) *
pph_in_tree_vec (pph_stream *stream)
{
- unsigned i, num;
+ HOST_WIDE_INT i, num;
VEC(tree,gc) *v;
- num = pph_in_uint (stream);
+ num = pph_in_hwi (stream);
v = NULL;
for (i = 0; i < num; i++)
{
@@ -708,29 +708,37 @@ pph_in_ld_fn (pph_stream *stream, struct lang_decl_fn *ldf)
/* Read applicable fields of struct function from STREAM. Associate
- the read structure to its corresponding FUNCTION_DECL and return
- it. */
+ the read structure to DECL. */
-static struct function *
-pph_in_struct_function (pph_stream *stream)
+static void
+pph_in_struct_function (pph_stream *stream, tree decl)
{
size_t count, i;
unsigned image_ix, ix;
enum pph_record_marker marker;
struct function *fn;
- tree decl;
+ tree t;
marker = pph_in_start_record (stream, &image_ix, &ix);
if (marker == PPH_RECORD_END)
- return NULL;
-
- /* Since struct function is embedded in every decl, fn cannot be shared. */
- gcc_assert (!pph_is_reference_marker (marker));
+ return;
+ else if (pph_is_reference_marker (marker))
+ {
+ fn = (struct function *) pph_cache_get (&stream->cache, image_ix, ix);
+ gcc_assert (DECL_STRUCT_FUNCTION (decl) == fn);
+ return;
+ }
- decl = pph_in_tree (stream);
+ /* Allocate a new DECL_STRUCT_FUNCTION for DECL. */
+ t = pph_in_tree (stream);
+ gcc_assert (t == decl);
allocate_struct_function (decl, false);
fn = DECL_STRUCT_FUNCTION (decl);
+ /* Now register it. We would normally use ALLOC_AND_REGISTER,
+ but allocate_struct_function does not return a pointer. */
+ pph_cache_insert_at (&stream->cache, fn, ix);
+
input_struct_function_base (fn, stream->encoder.r.data_in,
stream->encoder.r.ib);
@@ -788,8 +796,6 @@ pph_in_struct_function (pph_stream *stream)
/* unsigned int after_tree_profile : 1; -- in base */
/* unsigned int has_local_explicit_reg_vars : 1; -- in base */
/* unsigned int is_thunk : 1; -- in base */
-
- return fn;
}
@@ -1233,17 +1239,97 @@ pph_in_identifiers (pph_stream *stream, cpp_idents_used *identifiers)
/* Read a symbol table marker from STREAM. */
-static inline enum pph_symtab_marker
-pph_in_symtab_marker (pph_stream *stream)
+static inline enum pph_symtab_action
+pph_in_symtab_action (pph_stream *stream)
{
- enum pph_symtab_marker m = (enum pph_symtab_marker) pph_in_uchar (stream);
- gcc_assert (m == PPH_SYMTAB_FUNCTION
- || m == PPH_SYMTAB_FUNCTION_BODY
- || m == PPH_SYMTAB_DECL);
+ enum pph_symtab_action m = (enum pph_symtab_action) pph_in_uchar (stream);
+ gcc_assert (m == PPH_SYMTAB_DECLARE || m == PPH_SYMTAB_EXPAND);
return m;
}
+/* Read and return a callgraph node from STREAM. If this is the first
+ time we read this node, add it to the callgraph. */
+
+static struct cgraph_node *
+pph_in_cgraph_node (pph_stream *stream)
+{
+ enum pph_record_marker marker;
+ unsigned image_ix, ix;
+ struct cgraph_node *node;
+ tree fndecl;
+ struct bitpack_d bp;
+
+ marker = pph_in_start_record (stream, &image_ix, &ix);
+ if (marker == PPH_RECORD_END)
+ return NULL;
+ else if (pph_is_reference_marker (marker))
+ return (struct cgraph_node *) pph_cache_get (&stream->cache, image_ix, ix);
+
+ fndecl = pph_in_tree (stream);
+ ALLOC_AND_REGISTER (&stream->cache, ix, node, cgraph_create_node (fndecl));
+
+ node->origin = pph_in_cgraph_node (stream);
+ node->nested = pph_in_cgraph_node (stream);
+ node->next_nested = pph_in_cgraph_node (stream);
+ node->next_needed = pph_in_cgraph_node (stream);
+ node->next_sibling_clone = pph_in_cgraph_node (stream);
+ node->prev_sibling_clone = pph_in_cgraph_node (stream);
+ node->clones = pph_in_cgraph_node (stream);
+ node->clone_of = pph_in_cgraph_node (stream);
+ node->same_comdat_group = pph_in_cgraph_node (stream);
+ gcc_assert (node->call_site_hash == NULL);
+ node->former_clone_of = pph_in_tree (stream);
+ gcc_assert (node->aux == NULL);
+ gcc_assert (VEC_empty (ipa_opt_pass, node->ipa_transforms_to_apply));
+
+ gcc_assert (VEC_empty (ipa_ref_t, node->ref_list.references));
+ gcc_assert (VEC_empty (ipa_ref_ptr, node->ref_list.refering));
+
+ gcc_assert (node->local.lto_file_data == NULL);
+ bp = pph_in_bitpack (stream);
+ node->local.local = bp_unpack_value (&bp, 1);
+ node->local.externally_visible = bp_unpack_value (&bp, 1);
+ node->local.finalized = 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->global.inlined_to = pph_in_cgraph_node (stream);
+
+ node->rtl.preferred_incoming_stack_boundary = pph_in_uint (stream);
+
+ gcc_assert (VEC_empty (ipa_replace_map_p, node->clone.tree_map));
+ node->thunk.fixed_offset = pph_in_uhwi (stream);
+ node->thunk.virtual_value = pph_in_uhwi (stream);
+ node->thunk.alias = pph_in_tree (stream);
+ bp = pph_in_bitpack (stream);
+ node->thunk.this_adjusting = bp_unpack_value (&bp, 1);
+ node->thunk.virtual_offset_p = bp_unpack_value (&bp, 1);
+ node->thunk.thunk_p = bp_unpack_value (&bp, 1);
+
+ node->count = pph_in_uhwi (stream);
+ node->count_materialization_scale = pph_in_uint (stream);
+
+ bp = pph_in_bitpack (stream);
+ node->needed = bp_unpack_value (&bp, 1);
+ node->address_taken = bp_unpack_value (&bp, 1);
+ node->abstract_and_needed = bp_unpack_value (&bp, 1);
+ node->reachable = bp_unpack_value (&bp, 1);
+ node->reachable_from_other_partition = bp_unpack_value (&bp, 1);
+ node->lowered = bp_unpack_value (&bp, 1);
+ node->analyzed = bp_unpack_value (&bp, 1);
+ node->in_other_partition = bp_unpack_value (&bp, 1);
+ node->process = bp_unpack_value (&bp, 1);
+ node->alias = bp_unpack_value (&bp, 1);
+ node->same_body_alias = 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);
+
+ return node;
+}
+
+
/* Read the symbol table from STREAM. When this image is read into
another translation unit, we want to guarantee that the IL
instances taken from this image are instantiated in the same order
@@ -1262,32 +1348,38 @@ pph_in_symtab (pph_stream *stream)
num = pph_in_uint (stream);
for (i = 0; i < num; i++)
{
- enum pph_symtab_marker kind = pph_in_symtab_marker (stream);
- if (kind == PPH_SYMTAB_FUNCTION || kind == PPH_SYMTAB_FUNCTION_BODY)
+ enum pph_symtab_action action;
+ tree decl;
+ bool top_level, at_end;
+
+ action = pph_in_symtab_action (stream);
+ decl = pph_in_tree (stream);
+ if (action == PPH_SYMTAB_DECLARE)
+ {
+ struct bitpack_d bp;
+ bp = pph_in_bitpack (stream);
+ top_level = bp_unpack_value (&bp, 1);
+ at_end = bp_unpack_value (&bp, 1);
+ cp_rest_of_decl_compilation (decl, top_level, at_end);
+ }
+ else if (action == PPH_SYMTAB_EXPAND)
{
- struct function *fn = pph_in_struct_function (stream);
+ struct cgraph_node *node;
- if (kind == PPH_SYMTAB_FUNCTION_BODY)
+ pph_in_struct_function (stream, decl);
+ node = pph_in_cgraph_node (stream);
+ if (node && node->local.finalized)
{
- /* FIXME pph - This is somewhat gross. When we
- generated the PPH image, the parser called
- expand_or_defer_fn on FN->DECL, which marked it
- DECL_EXTERNAL (see expand_or_defer_fn_1 for details).
-
- However, this is not really an extern definition, so
- it was also marked not-really-extern (yes, I
- know...). If this happens, we need to unmark it,
- otherwise the code generator will toss it out. */
- if (DECL_NOT_REALLY_EXTERN (fn->decl))
- DECL_EXTERNAL (fn->decl) = 0;
- expand_or_defer_fn (fn->decl);
+ /* Since the writer had finalized this cgraph node,
+ we have to re-play its actions. To do that, we need
+ to clear the finalized and reachable bits in the
+ node, otherwise cgraph_finalize_function will toss
+ out this node. */
+ node->local.finalized = false;
+ node->reachable = false;
+ cgraph_finalize_function (node->decl, true);
}
}
- else if (kind == PPH_SYMTAB_DECL)
- {
- tree t = pph_in_tree (stream);
- cp_rest_of_decl_compilation (t, decl_function_context (t) == NULL, 1);
- }
else
gcc_unreachable ();
}
@@ -1598,6 +1690,20 @@ pph_in_tcc_declaration (pph_stream *stream, tree decl)
default:
break;
}
+
+ /* When the declaration was compiled originally, the parser marks
+ it DECL_EXTERNAL, to avoid emitting it more than once. It also
+ remembers the true external state in DECL_NOT_REALLY_EXTERN. So,
+ if both bits are set, the declaration should not be considered
+ external. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_NOT_REALLY_EXTERN (decl)
+ && DECL_EXTERNAL (decl))
+ {
+ DECL_EXTERNAL (decl) = 0;
+ DECL_NOT_REALLY_EXTERN (decl) = 0;
+ }
}
@@ -1612,6 +1718,7 @@ pph_in_tcc_type (pph_stream *stream, tree type)
TYPE_NEXT_VARIANT (type) = pph_in_tree (stream);
/* FIXME pph - Streaming TYPE_CANONICAL generates many type comparison
failures. Why? */
+ TREE_CHAIN (type) = pph_in_tree (stream);
/* The type values cache is built as constants are instantiated,
so we only stream it on the nodes that use it for
@@ -71,7 +71,10 @@ static void
pph_out (const void *data, size_t len, void *block ATTRIBUTE_UNUSED)
{
if (data)
- fwrite (data, len, 1, pph_out_stream->file);
+ {
+ size_t written = fwrite (data, 1, len, pph_out_stream->file);
+ gcc_assert (written == len);
+ }
}
@@ -374,7 +377,12 @@ pph_out_tree_vec (pph_stream *stream, VEC(tree,gc) *v)
unsigned i;
tree t;
- pph_out_uint (stream, VEC_length (tree, v));
+ /* Note that we use the same format used by streamer_write_chain.
+ This is to support pph_out_chain_filtered, which writes the
+ filtered chain as a VEC. Since the reader always reads chains
+ using streamer_read_chain, we have to write VECs in exactly the
+ same way as tree chains. */
+ pph_out_hwi (stream, VEC_length (tree, v));
FOR_EACH_VEC_ELT (tree, v, i, t)
pph_out_tree (stream, t);
}
@@ -497,23 +505,6 @@ pph_out_label_binding (pph_stream *stream, cp_label_binding *lb)
}
-/* Outputs chained tree T to STREAM by nulling out its chain first and
- restoring it after the streaming is done. */
-
-static inline void
-pph_out_chained_tree (pph_stream *stream, tree t)
-{
- tree saved_chain;
-
- saved_chain = TREE_CHAIN (t);
- TREE_CHAIN (t) = NULL_TREE;
-
- pph_out_tree_1 (stream, t, 2);
-
- TREE_CHAIN (t) = saved_chain;
-}
-
-
/* Output a chain of nodes to STREAM starting with FIRST. Skip any
nodes that do not match FILTER. */
@@ -1100,13 +1091,85 @@ pph_out_identifiers (pph_stream *stream, cpp_idents_used *identifiers)
}
-/* Emit symbol table MARKER to STREAM. */
+/* Emit symbol table ACTION to STREAM. */
static inline void
-pph_out_symtab_marker (pph_stream *stream, enum pph_symtab_marker marker)
+pph_out_symtab_action (pph_stream *stream, enum pph_symtab_action action)
{
- gcc_assert (marker == (enum pph_symtab_marker)(unsigned char) marker);
- pph_out_uchar (stream, marker);
+ gcc_assert (action == (enum pph_symtab_action)(unsigned char) action);
+ pph_out_uchar (stream, action);
+}
+
+/* Emit callgraph NODE to STREAM. */
+
+static void
+pph_out_cgraph_node (pph_stream *stream, struct cgraph_node *node)
+{
+ struct bitpack_d bp;
+
+ if (!pph_out_start_record (stream, node))
+ return;
+
+ pph_out_tree (stream, node->decl);
+ pph_out_cgraph_node (stream, node->origin);
+ pph_out_cgraph_node (stream, node->nested);
+ pph_out_cgraph_node (stream, node->next_nested);
+ pph_out_cgraph_node (stream, node->next_needed);
+ pph_out_cgraph_node (stream, node->next_sibling_clone);
+ pph_out_cgraph_node (stream, node->prev_sibling_clone);
+ pph_out_cgraph_node (stream, node->clones);
+ pph_out_cgraph_node (stream, node->clone_of);
+ pph_out_cgraph_node (stream, node->same_comdat_group);
+ gcc_assert (node->call_site_hash == NULL);
+ pph_out_tree (stream, node->former_clone_of);
+ gcc_assert (node->aux == NULL);
+ gcc_assert (VEC_empty (ipa_opt_pass, node->ipa_transforms_to_apply));
+
+ gcc_assert (VEC_empty (ipa_ref_t, node->ref_list.references));
+ gcc_assert (VEC_empty (ipa_ref_ptr, node->ref_list.refering));
+
+ gcc_assert (node->local.lto_file_data == NULL);
+ bp = bitpack_create (stream->encoder.w.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->local.finalized, 1);
+ bp_pack_value (&bp, node->local.can_change_signature, 1);
+ bp_pack_value (&bp, node->local.redefined_extern_inline, 1);
+ pph_out_bitpack (stream, &bp);
+
+ pph_out_cgraph_node (stream, node->global.inlined_to);
+
+ pph_out_uint (stream, node->rtl.preferred_incoming_stack_boundary);
+
+ gcc_assert (VEC_empty (ipa_replace_map_p, node->clone.tree_map));
+ pph_out_uhwi (stream, node->thunk.fixed_offset);
+ pph_out_uhwi (stream, node->thunk.virtual_value);
+ pph_out_tree (stream, node->thunk.alias);
+ bp = bitpack_create (stream->encoder.w.ob->main_stream);
+ bp_pack_value (&bp, node->thunk.this_adjusting, 1);
+ bp_pack_value (&bp, node->thunk.virtual_offset_p, 1);
+ bp_pack_value (&bp, node->thunk.thunk_p, 1);
+ pph_out_bitpack (stream, &bp);
+
+ pph_out_uhwi (stream, node->count);
+ pph_out_uint (stream, node->count_materialization_scale);
+
+ bp = bitpack_create (stream->encoder.w.ob->main_stream);
+ bp_pack_value (&bp, node->needed, 1);
+ bp_pack_value (&bp, node->address_taken, 1);
+ bp_pack_value (&bp, node->abstract_and_needed, 1);
+ bp_pack_value (&bp, node->reachable, 1);
+ bp_pack_value (&bp, node->reachable_from_other_partition, 1);
+ bp_pack_value (&bp, node->lowered, 1);
+ bp_pack_value (&bp, node->analyzed, 1);
+ bp_pack_value (&bp, node->in_other_partition, 1);
+ bp_pack_value (&bp, node->process, 1);
+ bp_pack_value (&bp, node->alias, 1);
+ bp_pack_value (&bp, node->same_body_alias, 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);
+ pph_out_bitpack (stream, &bp);
}
@@ -1121,26 +1184,30 @@ pph_out_symtab_marker (pph_stream *stream, enum pph_symtab_marker marker)
static void
pph_out_symtab (pph_stream *stream)
{
- tree decl;
+ pph_symtab_entry *entry;
unsigned i;
- pph_out_uint (stream, VEC_length (tree, stream->symtab.v));
- FOR_EACH_VEC_ELT (tree, stream->symtab.v, i, decl)
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_STRUCT_FUNCTION (decl))
- {
- /* If this is a regular (non-template) function with a body,
- mark it for expansion during reading. */
- if (DECL_SAVED_TREE (decl) && cgraph_get_node (decl))
- pph_out_symtab_marker (stream, PPH_SYMTAB_FUNCTION_BODY);
- else
- pph_out_symtab_marker (stream, PPH_SYMTAB_FUNCTION);
- pph_out_struct_function (stream, DECL_STRUCT_FUNCTION (decl));
- }
- else
- {
- pph_out_symtab_marker (stream, PPH_SYMTAB_DECL);
- pph_out_tree (stream, decl);
- }
+ pph_out_uint (stream, VEC_length (pph_symtab_entry, stream->symtab.v));
+ FOR_EACH_VEC_ELT (pph_symtab_entry, stream->symtab.v, i, entry)
+ {
+ pph_out_symtab_action (stream, entry->action);
+ pph_out_tree (stream, entry->decl);
+ if (entry->action == PPH_SYMTAB_DECLARE)
+ {
+ struct bitpack_d bp;
+ bp = bitpack_create (stream->encoder.w.ob->main_stream);
+ bp_pack_value (&bp, entry->top_level, 1);
+ bp_pack_value (&bp, entry->at_end, 1);
+ pph_out_bitpack (stream, &bp);
+ }
+ else if (entry->action == PPH_SYMTAB_EXPAND)
+ {
+ pph_out_struct_function (stream, DECL_STRUCT_FUNCTION (entry->decl));
+ pph_out_cgraph_node (stream, cgraph_get_node (entry->decl));
+ }
+ else
+ gcc_unreachable ();
+ }
}
@@ -1437,6 +1504,7 @@ pph_out_tcc_type (pph_stream *stream, tree type)
pph_out_tree (stream, TYPE_NEXT_VARIANT (type));
/* FIXME pph - Streaming TYPE_CANONICAL generates many type comparison
failures. Why? */
+ pph_out_tree (stream, TREE_CHAIN (type));
/* The type values cache is built as constants are instantiated,
so we only stream it on the nodes that use it for
@@ -1751,18 +1819,26 @@ pph_write_tree (struct output_block *ob, tree expr, bool ref_p ATTRIBUTE_UNUSED)
}
-/* Add DECL to the symbol table for pph_out_stream. */
+/* Add DECL to the symbol table for pph_out_stream. ACTION determines
+ how DECL should be presented to the middle-end when reading this
+ image. TOP_LEVEL and AT_END are as in rest_of_decl_compilation. */
void
-pph_add_decl_to_symtab (tree decl)
+pph_add_decl_to_symtab (tree decl, enum pph_symtab_action action,
+ bool top_level, bool at_end)
{
- pph_stream *stream = pph_out_stream;
+ pph_symtab_entry entry;
- if (decl == NULL || stream == NULL)
+ if (decl == NULL || pph_out_stream == NULL)
return;
- if (!pointer_set_insert (stream->symtab.m, decl))
- VEC_safe_push (tree, heap, stream->symtab.v, decl);
+ gcc_assert (DECL_P (decl));
+
+ entry.action = action;
+ entry.decl = decl;
+ entry.top_level = top_level;
+ entry.at_end = at_end;
+ VEC_safe_push (pph_symtab_entry, heap, pph_out_stream->symtab.v, &entry);
}
@@ -121,7 +121,6 @@ pph_stream_open (const char *name, const char *mode)
stream->name = xstrdup (name);
stream->write_p = (strchr (mode, 'w') != NULL);
stream->cache.m = pointer_map_create ();
- stream->symtab.m = pointer_set_create ();
if (stream->write_p)
pph_init_write (stream);
else
@@ -153,8 +152,7 @@ pph_stream_close (pph_stream *stream)
stream->file = NULL;
VEC_free (void_p, heap, stream->cache.v);
pointer_map_destroy (stream->cache.m);
- VEC_free (tree, heap, stream->symtab.v);
- pointer_set_destroy (stream->symtab.m);
+ VEC_free (pph_symtab_entry, heap, stream->symtab.v);
if (stream->write_p)
{
@@ -50,19 +50,6 @@ enum pph_record_marker {
PPH_RECORD_XREF
};
-/* Symbol table markers. These are all the symbols that need to be
- registered with the middle end. */
-enum pph_symtab_marker {
- /* A FUNCTION_DECL with DECL_STRUCT_FUNCTION but no body. */
- PPH_SYMTAB_FUNCTION = 0x01,
-
- /* A FUNCTION_DECL with DECL_STRUCT_FUNCTION and a body. */
- PPH_SYMTAB_FUNCTION_BODY,
-
- /* All other symbols. */
- PPH_SYMTAB_DECL
-};
-
/* Line table markers. We only stream line table entries from the parent header
file, other entries are referred to by the name of the file which is then
loaded as an include at the correct point in time. */
@@ -134,15 +121,41 @@ typedef struct pph_pickle_cache {
struct pointer_map_t *m;
} pph_pickle_cache;
+
+/* Actions associated with each symbol table entry. These indicate
+ what the reader should do when registering each entry with the
+ middle-end. */
+enum pph_symtab_action {
+ /* Declare this symbol with rest_of_decl_compilation. */
+ PPH_SYMTAB_DECLARE = 0x23,
+
+ /* Expand this function with expand_or_defer_fn. */
+ PPH_SYMTAB_EXPAND
+};
+
+
+/* Symbol table entry. */
+typedef struct pph_symtab_entry
+{
+ /* Registration action to perform by the reader. */
+ enum pph_symtab_action action;
+
+ /* VAR_DECL or FUNCTION_DECL to declare. */
+ tree decl;
+
+ /* Values to be passed to rest_of_decl_compilation. */
+ unsigned int top_level : 1;
+ unsigned int at_end : 1;
+} pph_symtab_entry;
+
+DEF_VEC_O(pph_symtab_entry);
+DEF_VEC_ALLOC_O(pph_symtab_entry,heap);
+
/* Symbol table for a PPH stream. */
typedef struct pph_symtab
{
/* Table of all the declarations to register in declaration order. */
- VEC(tree,heap) *v;
-
- /* Set of declarations to register used to avoid adding duplicate
- entries to the table. */
- struct pointer_set_t *m;
+ VEC(pph_symtab_entry,heap) *v;
} pph_symtab;
/* Vector of pph_stream pointers. */
@@ -233,7 +246,7 @@ void *pph_cache_get (pph_pickle_cache *, unsigned, unsigned);
void pph_flush_buffers (pph_stream *);
void pph_init_write (pph_stream *);
void pph_write_tree (struct output_block *, tree, bool);
-void pph_add_decl_to_symtab (tree);
+void pph_add_decl_to_symtab (tree, enum pph_symtab_action, bool, bool);
void pph_add_include (pph_stream *, bool);
void pph_writer_init (void);
void pph_writer_finish (void);
@@ -299,6 +312,20 @@ pph_out_uint (pph_stream *stream, unsigned int value)
{
if (flag_pph_tracer >= 4)
pph_trace_uint (stream, value);
+ streamer_write_uhwi (stream->encoder.w.ob, value);
+}
+
+/* Write an unsigned HOST_WIDE_INT VALUE to STREAM. */
+static inline void
+pph_out_uhwi (pph_stream *stream, unsigned HOST_WIDE_INT value)
+{
+ streamer_write_uhwi (stream->encoder.w.ob, value);
+}
+
+/* Write a HOST_WIDE_INT VALUE to stream. */
+static inline void
+pph_out_hwi (pph_stream *stream, HOST_WIDE_INT value)
+{
streamer_write_hwi (stream->encoder.w.ob, value);
}
@@ -389,7 +416,7 @@ pph_out_bitpack (pph_stream *stream, struct bitpack_d *bp)
streamer_write_bitpack (bp);
}
-/* Read an unsigned HOST_WIDE_INT integer from STREAM. */
+/* Read an unsigned integer from STREAM. */
static inline unsigned int
pph_in_uint (pph_stream *stream)
{
@@ -400,6 +427,20 @@ pph_in_uint (pph_stream *stream)
return (unsigned) n;
}
+/* Read an unsigned HOST_WIDE_INT from STREAM. */
+static inline unsigned HOST_WIDE_INT
+pph_in_uhwi (pph_stream *stream)
+{
+ return streamer_read_uhwi (stream->encoder.r.ib);
+}
+
+/* Read a HOST_WIDE_INT from STREAM. */
+static inline HOST_WIDE_INT
+pph_in_hwi (pph_stream *stream)
+{
+ return streamer_read_hwi (stream->encoder.r.ib);
+}
+
/* Read an unsigned char VALUE to STREAM. */
static inline unsigned char
pph_in_uchar (pph_stream *stream)
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "gimple.h"
#include "bitmap.h"
+#include "pph-streamer.h"
/* There routines provide a modular interface to perform many parsing
operations. They may therefore be used during actual parsing, or
@@ -3566,6 +3567,10 @@ is_instantiation_of_constexpr (tree fun)
bool
expand_or_defer_fn_1 (tree fn)
{
+ /* If we are generating a PPH image, add FN to its symbol table. */
+ if (pph_out_file)
+ pph_add_decl_to_symtab (fn, PPH_SYMTAB_EXPAND, false, at_eof);
+
/* When the parser calls us after finishing the body of a template
function, we don't really want to expand the body. */
if (processing_template_decl)
@@ -1,6 +1,3 @@
-// pph asm xdiff 63070
-// Looks like destructors botched.
-
#include "x0keyed1.h"
int keyed::key( int arg ) { return mix( field & arg ); }
@@ -1,6 +1,3 @@
-// pph asm xdiff 46318
-// Looks like destructors botched.
-
#include "x0keyno1.h"
int main()
@@ -1,5 +1,19 @@
-// pph asm xdiff 17472
-// Looks like destructors botched.
+// pph asm xdiff 32642
+//
+// This test case fails to compare because LFB/LFE labels are different.
+//
+// 1- Both x0keyno1.h and x0keyno2.h declare exactly the same, as
+// they both textually include a0keyed.h.
+// 2- When we read x0keyno1.pph, we instantiate all the decls and cgraph
+// nodes for struct keyed.
+// 3- When we read x0keyno2.pph, we re-instantiate the same decls and
+// cgraph nodes, which are used instead of the ones in x0keyno1.pph.
+// 4- Since the new decls and nodes have been created later, the functions
+// have different function numbers (function::funcdef_no field), which
+// is used to emit the LFB/LFE labels.
+//
+// The future merging process will fix this by choosing the decls and nodes
+// created first by x0keyno1.pph.
#include "x0keyno1.h"
#include "x0keyno2.h"