This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[pph] Merge and rename pph sources. (issue5440063)


Merge pph.c and pph-streamer.c into pph-core.c.
Shorten pph-streamer-in.c to pph-in.c.
Shorten pph-streamer-out.c to pph-out.c.
Reduce redundancies in make dependences.


Index: gcc/cp/ChangeLog.pph

2011-11-29   Lawrence Crowl  <crowl@google.com>

	* pph-streamer.c: Renamed pph-core.c.
	* pph.c: Contents moved into pph-core.c.
	(pph_dump_min_decl): Removed unused.
	(flatten_name): Rename pph_flatten_name.
	* pph-streamer-in.c: Renamed pph-in.c.
	* pph-streamer-out.c: Renamed pph-out.c.
	* pph-streamer.h: Adjust to reflect above.  Remove unneeded decls.
	* pph.h: Adjust to reflect above.
	* config-lang.in: Adjust to reflect above.
	* Make-lang.in: Adjust to reflect above.
	(CXX_PPH_STREAMER_H): Remove redundancies.
	(CXX_PPH_COMMON_H): New.
	(CXX_PPH_COMMON_H): New.
	(cp/pph-core.o): Remove redundancies.
	(cp/pph-in.o): Remove redundancies.
	(cp/pph-out.o): Remove redundancies.
	(cp/pt.o): Add depndence on CXX_PPH_H.
	* pt.c: Remove redundant #include "pph-streamer.h".


Index: gcc/cp/pph-core.c
===================================================================
--- gcc/cp/pph-core.c	(revision 181815)
+++ gcc/cp/pph-core.c	(working copy)
@@ -1,6 +1,8 @@
-/* Routines for streaming PPH data.
-   Copyright (C) 2011 Free Software Foundation, Inc.
-   Contributed by Diego Novillo <dnovillo@google.com>.
+/* Factored pre-parsed header (PPH) support for C++.
+   Common routines for streaming PPH data.
+   Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+   Contributed by Lawrence Crowl <crowl@google.com> and
+   Diego Novillo <dnovillo@google.com>.
 
    This file is part of GCC.
 
@@ -18,320 +20,131 @@ You should have received a copy of the G
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
 #include "pph.h"
+#include "cpplib.h"
+#include "toplev.h"
 #include "tree.h"
+#include "cp-tree.h"
 #include "langhooks.h"
+#include "timevar.h"
 #include "tree-iterator.h"
 #include "tree-pretty-print.h"
 #include "lto-streamer.h"
 #include "pph-streamer.h"
+#include "pointer-set.h"
+#include "fixed-value.h"
+#include "md5.h"
 #include "tree-pass.h"
+#include "tree-dump.h"
+#include "tree-inline.h"
+#include "tree-pretty-print.h"
+#include "cxx-pretty-print.h"
+#include "parser.h"
 #include "version.h"
 #include "cppbuiltin.h"
 #include "streamer-hooks.h"
 
-/* List of PPH images opened for reading.  Images opened during #include
-   processing and opened from pph_in_includes cannot be closed
-   immediately after reading, because the pickle cache contained in
-   them may be referenced from other images.  We delay closing all of
-   them until the end of parsing (when pph_streamer_finish is called).  */
-static VEC(pph_stream_ptr, heap) *pph_read_images = NULL;
-
-/* A cache of pre-loaded common tree nodes.  */
-static pph_cache *pph_preloaded_cache;
-
-/* Pre-load common tree nodes into CACHE.  These nodes are always built by the
-   front end, so there is no need to pickle them.  */
-
-static void
-pph_cache_preload (pph_cache *cache)
-{
-  unsigned i;
-
-  for (i = itk_char; i < itk_none; i++)
-    pph_cache_add (cache, integer_types[i], NULL,
-                   pph_tree_code_to_tag (integer_types[i]));
-
-  for (i = 0; i < TYPE_KIND_LAST; i++)
-    pph_cache_add (cache, sizetype_tab[i], NULL,
-                   pph_tree_code_to_tag (sizetype_tab[i]));
-
-  /* global_trees[] can have NULL entries in it.  Skip them.  */
-  for (i = 0; i < TI_MAX; i++)
-    if (global_trees[i])
-      pph_cache_add (cache, global_trees[i], NULL,
-                     pph_tree_code_to_tag (global_trees[i]));
-
-  /* c_global_trees[] can have NULL entries in it.  Skip them.  */
-  for (i = 0; i < CTI_MAX; i++)
-    if (c_global_trees[i])
-      pph_cache_add (cache, c_global_trees[i], NULL,
-                     pph_tree_code_to_tag (c_global_trees[i]));
-
-  /* cp_global_trees[] can have NULL entries in it.  Skip them.  */
-  for (i = 0; i < CPTI_MAX; i++)
-    {
-      /* Also skip trees which are generated while parsing.  */
-      if (i == CPTI_KEYED_CLASSES)
-	continue;
-
-      if (cp_global_trees[i])
-	pph_cache_add (cache, cp_global_trees[i], NULL,
-                       pph_tree_code_to_tag (cp_global_trees[i]));
-    }
-
-  /* Add other well-known nodes that should always be taken from the
-     current compilation context.  */
-  pph_cache_add (cache, global_namespace, NULL,
-                 pph_tree_code_to_tag (global_namespace));
-  pph_cache_add (cache, DECL_CONTEXT (global_namespace), NULL,
-                 pph_tree_code_to_tag (DECL_CONTEXT (global_namespace)));
-}
-
-
-/* Callback for writing ASTs to a stream.  Write EXPR to the PPH stream
-   in OB.  */
-
-static void
-pph_write_tree (struct output_block *ob, tree expr, bool ref_p ATTRIBUTE_UNUSED)
-{
-  pph_out_tree ((pph_stream *) ob->sdata, expr);
-}
-
-
-/* Callback for reading ASTs from a stream.  Instantiate and return a
-   new tree from the PPH stream in DATA_IN.  */
 
-static tree
-pph_read_tree (struct lto_input_block *ib ATTRIBUTE_UNUSED,
-	       struct data_in *data_in)
-{
-  return pph_in_tree ((pph_stream *) data_in->sdata);
-}
-
-
-/* Callback for streamer_hooks.input_location.  An offset is applied to
-   the location_t read in according to the properties of the merged
-   line_table.  IB and DATA_IN are as in lto_input_location.  This function
-   should only be called after pph_in_and_merge_line_table was called as
-   we expect pph_loc_offset to be set.  */
-
-static location_t
-pph_input_location (struct lto_input_block *ib ATTRIBUTE_UNUSED,
-                    struct data_in *data_in)
-{
-  return pph_in_location ((pph_stream *) data_in->sdata);
-}
-
-
-/* Callback for streamer_hooks.output_location.  Output the LOC directly,
-   an offset will be applied on input after rebuilding the line_table.
-   OB and LOC are as in lto_output_location.  */
-
-static void
-pph_output_location (struct output_block *ob, location_t loc)
-{
-  pph_out_location ((pph_stream *) ob->sdata, loc);
-}
-
-
-/* Initialize all the streamer hooks used for streaming ASTs.  */
-
-static void
-pph_hooks_init (void)
-{
-  streamer_hooks_init ();
-  streamer_hooks.write_tree = pph_write_tree;
-  streamer_hooks.read_tree = pph_read_tree;
-  streamer_hooks.input_location = pph_input_location;
-  streamer_hooks.output_location = pph_output_location;
-}
+/*************************************************************** pph logging */
 
 
-/* Initialize an empty pickle CACHE.  */
-
-static void
-pph_cache_init (pph_cache *cache)
-{
-  cache->v = NULL;
-  cache->m = pointer_map_create ();
-}
+/* Log file where PPH analysis is written to.  Controlled by
+   -fpph_logfile.  If this flag is not given, stdout is used.  */
+FILE *pph_logfile = NULL;
 
 
-/* Initialize the pre-loaded cache.  This contains all the common
-   tree nodes built by the compiler on startup.  */
+/* Convert a checked tree_code CODE to a string.  */
 
-static void
-pph_init_preloaded_cache (void)
+const char *
+pph_tree_code_text (enum tree_code code)
 {
-  pph_preloaded_cache = XCNEW (pph_cache);
-  pph_cache_init (pph_preloaded_cache);
-  pph_cache_preload (pph_preloaded_cache);
+  gcc_assert (code < MAX_TREE_CODES);
+  return tree_code_name[code];
 }
 
 
-/* Initialize the streamer.  */
+/* Dump a location LOC to FILE.  */
 
 void
-pph_streamer_init (void)
+pph_dump_location (FILE *file, location_t loc)
 {
-  pph_hooks_init ();
-  pph_init_preloaded_cache ();
+  expanded_location xloc = expand_location (loc);
+  fprintf (file, "%s:%d", xloc.file, xloc.line);
 }
 
 
-/* Finalize the streamer.  */
+/* Dump a complicated name for tree T to FILE using FLAGS.
+   See TDF_* in tree-pass.h for flags.  */
 
 void
-pph_streamer_finish (void)
+pph_dump_tree_name (FILE *file, tree t, int flags)
 {
-  unsigned i;
-  pph_stream *image;
-
-  /* Finalize the writer.  */
-  pph_writer_finish ();
-
-  /* Finalize the reader.  */
-  pph_reader_finish ();
-
-  /* Close any images read during parsing.  */
-  FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, i, image)
-    pph_stream_close (image);
-
-  VEC_free (pph_stream_ptr, heap, pph_read_images);
+  enum tree_code code = TREE_CODE (t);
+  const char *text = pph_tree_code_text (code);
+  if (DECL_P (t))
+    fprintf (file, "%s %s\n", text, decl_as_string (t, flags));
+  else if (TYPE_P (t))
+    fprintf (file, "%s %s\n", text, type_as_string (t, flags));
+  else if (EXPR_P (t))
+    fprintf (file, "%s %s\n", text, expr_as_string (t, flags));
+  else
+    {
+      fprintf (file, "%s ", text );
+      print_generic_expr (file, t, flags);
+      fprintf (file, "\n");
+    }
 }
 
 
-/* If FILENAME has already been read, return the stream associated with it.  */
-
-static pph_stream *
-pph_find_stream_for (const char *filename)
-{
-  pph_stream *include;
-  unsigned i;
-
-  /* FIXME pph, implement a hash map to avoid this linear search.  */
-  FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, i, include)
-    if (strcmp (include->name, filename) == 0)
-      return include;
-
-  return NULL;
-}
+static void
+pph_dump_binding (FILE *file, cp_binding_level *level);
 
 
-/* Add STREAM to the list of read images.  */
+/* Dump namespace NS for PPH.  */
 
 void
-pph_mark_stream_read (pph_stream *stream)
+pph_dump_namespace (FILE *file, tree ns)
 {
-  stream->in_memory_p = true;
-  VEC_safe_push (pph_stream_ptr, heap, pph_read_images, stream);
+  fprintf (file, "namespace ");
+  pph_dump_tree_name (file, ns, 0);
+  fprintf (file, "{\n");
+  pph_dump_binding (file, NAMESPACE_LEVEL (ns));
+  fprintf (file, "}\n");
 }
 
 
-/* Create a new PPH stream to be stored on the file called NAME.
-   MODE is passed to fopen directly.  */
+/* Dump a CHAIN for PPH.  */
 
-pph_stream *
-pph_stream_open (const char *name, const char *mode)
+static void
+pph_dump_chain (FILE *file, tree chain)
 {
-  pph_stream *stream;
-  FILE *f;
-
-  /* If we have already opened a PPH stream named NAME, just return
-     its associated stream.  */
-  stream = pph_find_stream_for (name);
-  if (stream)
+  tree t, next;
+  for (t = chain; t; t = next)
     {
-      gcc_assert (stream->in_memory_p);
-      return stream;
+      next = DECL_CHAIN (t);
+      if (!DECL_IS_BUILTIN (t))
+        pph_dump_tree_name (file, t, 0);
     }
-
-  f = fopen (name, mode);
-  if (!f)
-    return NULL;
-
-  stream = XCNEW (pph_stream);
-  stream->file = f;
-  stream->name = xstrdup (name);
-  stream->write_p = (strchr (mode, 'w') != NULL);
-  pph_cache_init (&stream->cache);
-  stream->preloaded_cache = pph_preloaded_cache;
-  if (stream->write_p)
-    pph_init_write (stream);
-  else
-    pph_init_read (stream);
-
-  return stream;
 }
 
 
-
-/* Close PPH stream STREAM.  */
+/* Dump cp_binding_level LEVEL for PPH.  */
 
 void
-pph_stream_close (pph_stream *stream)
+pph_dump_binding (FILE *file, cp_binding_level *level)
 {
-  /* STREAM can be NULL if it could not be properly opened.  An error
-     has already been emitted, so avoid crashing here.  */
-  if (stream == NULL)
-    return;
-
-  if (flag_pph_tracer >= 1)
-    fprintf (pph_logfile, "PPH: Closing %s\n", stream->name);
-
-  /* If we were writing to STREAM, flush all the memory buffers.  This
-     does the actual writing of all the pickled data structures.  */
-  if (stream->write_p)
-    pph_flush_buffers (stream);
-
-  fclose (stream->file);
-
-  /* Deallocate all memory used.  */
-  stream->file = NULL;
-  VEC_free (pph_cache_entry, heap, stream->cache.v);
-  pointer_map_destroy (stream->cache.m);
-  VEC_free (pph_symtab_entry, heap, stream->symtab.v);
-  VEC_free (pph_stream_ptr, heap, stream->includes);
-
-  if (stream->write_p)
-    {
-      destroy_output_block (stream->encoder.w.ob);
-      free (stream->encoder.w.decl_state_stream);
-      lto_delete_out_decl_state (stream->encoder.w.out_state);
-    }
-  else
+  tree t, next;
+  pph_dump_chain (file, level->names);
+  for (t = level->namespaces; t; t = next)
     {
-      unsigned i;
-
-      free (stream->encoder.r.ib);
-      lto_data_in_delete (stream->encoder.r.data_in);
-      for (i = 0; i < PPH_NUM_SECTIONS; i++)
-	free (stream->encoder.r.pph_sections[i]);
-      free (stream->encoder.r.pph_sections);
-      free (stream->encoder.r.file_data);
+      next = DECL_CHAIN (t);
+      if (!DECL_IS_BUILTIN (t))
+        pph_dump_namespace (file, t);
     }
-
-  free (stream);
-}
-
-
-/* Add INCLUDE, and the images included by it, to the list of files
-   included by STREAM.  */
-
-void
-pph_add_include (pph_stream *stream, pph_stream *include)
-{
-  pph_stream *include_child;
-  unsigned i;
-
-  include->parent = stream;
-  VEC_safe_push (pph_stream_ptr, heap, stream->includes, include);
-  FOR_EACH_VEC_ELT (pph_stream_ptr, include->includes, i, include_child)
-    VEC_safe_push (pph_stream_ptr, heap, stream->includes, include_child);
 }
 
 
@@ -367,6 +180,10 @@ static const char *tag_strings[] =
   "PPH_sorted_fields_type"
 };
 
+
+/* Trace print a MARKER and TAG.  */
+
+
 void
 pph_trace_marker (enum pph_record_marker marker, enum pph_tag tag)
 {
@@ -456,6 +273,84 @@ pph_trace_tree (tree t, enum pph_trace_e
 }
 
 
+/************************************************* pph pointer mapping cache */
+
+
+/* Initialize an empty pickle CACHE.  */
+
+static void
+pph_cache_init (pph_cache *cache)
+{
+  cache->v = NULL;
+  cache->m = pointer_map_create ();
+}
+
+
+/* A cache of pre-loaded common tree nodes.  */
+static pph_cache *pph_preloaded_cache;
+
+
+/* Pre-load common tree nodes into CACHE.  These nodes are always built by the
+   front end, so there is no need to pickle them.  */
+
+static void
+pph_cache_preload (pph_cache *cache)
+{
+  unsigned i;
+
+  for (i = itk_char; i < itk_none; i++)
+    pph_cache_add (cache, integer_types[i], NULL,
+                   pph_tree_code_to_tag (integer_types[i]));
+
+  for (i = 0; i < TYPE_KIND_LAST; i++)
+    pph_cache_add (cache, sizetype_tab[i], NULL,
+                   pph_tree_code_to_tag (sizetype_tab[i]));
+
+  /* global_trees[] can have NULL entries in it.  Skip them.  */
+  for (i = 0; i < TI_MAX; i++)
+    if (global_trees[i])
+      pph_cache_add (cache, global_trees[i], NULL,
+                     pph_tree_code_to_tag (global_trees[i]));
+
+  /* c_global_trees[] can have NULL entries in it.  Skip them.  */
+  for (i = 0; i < CTI_MAX; i++)
+    if (c_global_trees[i])
+      pph_cache_add (cache, c_global_trees[i], NULL,
+                     pph_tree_code_to_tag (c_global_trees[i]));
+
+  /* cp_global_trees[] can have NULL entries in it.  Skip them.  */
+  for (i = 0; i < CPTI_MAX; i++)
+    {
+      /* Also skip trees which are generated while parsing.  */
+      if (i == CPTI_KEYED_CLASSES)
+	continue;
+
+      if (cp_global_trees[i])
+	pph_cache_add (cache, cp_global_trees[i], NULL,
+                       pph_tree_code_to_tag (cp_global_trees[i]));
+    }
+
+  /* Add other well-known nodes that should always be taken from the
+     current compilation context.  */
+  pph_cache_add (cache, global_namespace, NULL,
+                 pph_tree_code_to_tag (global_namespace));
+  pph_cache_add (cache, DECL_CONTEXT (global_namespace), NULL,
+                 pph_tree_code_to_tag (DECL_CONTEXT (global_namespace)));
+}
+
+
+/* Initialize the pre-loaded cache.  This contains all the common
+   tree nodes built by the compiler on startup.  */
+
+static void
+pph_init_preloaded_cache (void)
+{
+  pph_preloaded_cache = XCNEW (pph_cache);
+  pph_cache_init (pph_preloaded_cache);
+  pph_cache_preload (pph_preloaded_cache);
+}
+
+
 /* Insert DATA in CACHE at slot IX.  TAG represents the data structure
    pointed-to by DATA.  As a restriction to prevent stomping on cache
    entries, this will not allow inserting into the same slot more than
@@ -485,6 +380,30 @@ pph_cache_insert_at (pph_cache *cache, v
 }
 
 
+/* Add pointer DATA with data type TAG to CACHE.  If IX_P is not NULL,
+   on exit *IX_P will contain the slot number where DATA is stored.
+   Return the newly added entry.  */
+
+pph_cache_entry *
+pph_cache_add (pph_cache *cache, void *data, unsigned *ix_p, enum pph_tag tag)
+{
+  unsigned ix;
+  pph_cache_entry *e;
+
+  e = pph_cache_lookup (cache, data, &ix, tag);
+  if (e == NULL)
+    {
+      ix = VEC_length (pph_cache_entry, cache->v);
+      e = pph_cache_insert_at (cache, data, ix, tag);
+    }
+
+  if (ix_p)
+    *ix_p = ix;
+
+  return e;
+}
+
+
 /* If DATA exists in CACHE, return the cache entry holding it.  If
    IX_P is not NULL, store the cache slot where DATA resides in *IX_P
    (or (unsigned)-1 if DATA is not found). If CACHE is NULL use
@@ -591,28 +510,7 @@ pph_cache_lookup_in_includes (pph_stream
 }
 
 
-/* Add pointer DATA with data type TAG to CACHE.  If IX_P is not NULL,
-   on exit *IX_P will contain the slot number where DATA is stored.
-   Return the newly added entry.  */
-
-pph_cache_entry *
-pph_cache_add (pph_cache *cache, void *data, unsigned *ix_p, enum pph_tag tag)
-{
-  unsigned ix;
-  pph_cache_entry *e;
-
-  e = pph_cache_lookup (cache, data, &ix, tag);
-  if (e == NULL)
-    {
-      ix = VEC_length (pph_cache_entry, cache->v);
-      e = pph_cache_insert_at (cache, data, ix, tag);
-    }
-
-  if (ix_p)
-    *ix_p = ix;
-
-  return e;
-}
+/*************************************************** tree contents signature */
 
 
 /* Associate signature CRC with the first NBYTES of the area memory
@@ -672,3 +570,511 @@ pph_get_signature (tree t, size_t *nbyte
 
   return crc;
 }
+
+
+/****************************************************** pph include handling */
+
+
+/* Return true if PPH image NAME can be used at the point of inclusion
+   (given by LOC).  */
+
+static bool
+pph_is_valid_here (const char *name, location_t loc)
+{
+  /* If we are inside a scope, reject the image.  We could be inside a
+     namespace or a structure which changes the parsing context for
+     the original text file.  */
+  if (scope_chain->x_brace_nesting > 0)
+    {
+      error_at (loc, "PPH file %s not included at global scope", name);
+      return false;
+    }
+
+  return true;
+}
+
+
+/* Record a #include or #include_next for PPH.
+   READER is the main pre-processor object, LOC is the location where
+   the #include is being emitted from, DNAME is the name of the
+   #include directive used, NAME is the canonical name of the file being
+   included, ANGLE_BRACKETS is non-zero if this #include uses <> and
+   TOK_P is a pointer to the current token being pre-processed.  */
+
+static bool
+pph_include_handler (cpp_reader *reader,
+                     location_t loc,
+                     const unsigned char *dname,
+                     const char *name,
+                     int angle_brackets,
+                     const cpp_token **tok_p ATTRIBUTE_UNUSED)
+{
+  const char *pph_file;
+  bool read_text_file_p;
+
+  if (flag_pph_tracer >= 1)
+    {
+      fprintf (pph_logfile, "PPH: #%s", dname);
+      fprintf (pph_logfile, " %c", angle_brackets ? '<' : '"');
+      fprintf (pph_logfile, "%s", name);
+      fprintf (pph_logfile, "%c\n", angle_brackets ? '>' : '"');
+    }
+
+  read_text_file_p = true;
+  pph_file = query_pph_include_map (name);
+  if (pph_file != NULL
+      && pph_is_valid_here (name, loc)
+      && !cpp_included_before (reader, name, input_location))
+    {
+      pph_stream *include;
+
+      /* Hack. We do this to mimic what the non-pph compiler does in
+	_cpp_stack_include as our goal is to have identical line_tables.  */
+      line_table->highest_location--;
+
+      include = pph_read_file (pph_file);
+
+      /* If we are generating a new PPH image, add the stream we just
+	 read to the list of includes.   This way, the parser will be
+	 able to resolve references to symbols in INCLUDE and its
+	 children.  */
+      if (pph_writer_enabled_p ())
+	pph_writer_add_include (include);
+
+      read_text_file_p = false;
+    }
+
+  return read_text_file_p;
+}
+
+
+/* PPH include tree dumper.  Each entry in this file has the format:
+
+	DEPTH|SYSP|DNAME|CANONICAL-NAME|FULL-NAME|PPH-NAME
+
+  Where:
+	DEPTH		is the include depth of the file.
+	SYSP		1 for a system header
+			2 for a C system header that needs 'extern "C"'
+			0 otherwise.
+	DNAME		name of the #include directive used.
+	CANONICAL-NAME	is the name of the file as specified by the
+			#include directive.
+	FULL-NAME	is the full path name where the included file
+			was found by the pre-processor.
+	PPH-NAME	is the name of the associated PPH file.  */
+
+typedef struct {
+  /* Name of current #include directive.  */
+  const unsigned char *dname;
+
+  /* Canonical name of file being included.  */
+  const char *name;
+
+  /* Previous libcpp #include handler.  */
+  void (*prev_file_change) (cpp_reader *, const struct line_map *);
+
+  /* Previous libcpp file change handler.  */
+  bool (*prev_include) (cpp_reader *, source_location, const unsigned char *,
+		        const char *, int, const cpp_token **);
+} pph_include_tree_dumper;
+
+static pph_include_tree_dumper tree_dumper;
+
+
+/* #include handler for libcpp.  READER is the main pre-processor object,
+   LOC is the location where the #include is being emitted from, DNAME
+   is the name of the #include directive used, NAME is the canonical
+   name of the file being included, ANGLE_BRACKETS is non-zero if this
+   #include uses <> and TOK_P is a pointer to the current token being
+   pre-processed.  */
+
+static bool
+pph_include_handler_for_map (cpp_reader *reader,
+			     location_t loc,
+                             const unsigned char *dname,
+                             const char *name,
+                             int angle_brackets,
+                             const cpp_token **tok_p)
+{
+  bool retval = true;
+
+  if (tree_dumper.prev_include)
+    retval &= tree_dumper.prev_include (reader, loc, dname, name,
+					angle_brackets, tok_p);
+  tree_dumper.dname = dname;
+  tree_dumper.name = name;
+
+  return retval;
+}
+
+
+/* Return a copy of NAME with the characters '/' and '.' replaced with
+   '_'.  The caller is reponsible for freeing the returned string.  */
+
+static char *
+pph_flatten_name (const char *name)
+{
+  char *str = xstrdup (name);
+  size_t i;
+
+  for (i = 0; i < strlen (str); i++)
+    if (str[i] == DIR_SEPARATOR || str[i] == '.')
+      str[i] = '_';
+
+  return str;
+}
+
+
+/* File change handler for libcpp.  READER is the main pre-processor object,
+   MAP is the line map entry for the file that we are entering into.  */
+
+static void
+pph_file_change_handler (cpp_reader *reader, const struct line_map *map)
+{
+  char *flat;
+
+  if (tree_dumper.prev_file_change)
+    tree_dumper.prev_file_change (reader, map);
+
+  /* We are only interested in line maps that describe a new file being
+     entered.  */
+  if (map == NULL || map->reason != LC_ENTER)
+    return;
+
+  /* Emit a line to the map file with the format:
+
+	DEPTH|SYSP|DNAME|CANONICAL-NAME|FULL-NAME|PPH-NAME
+  */
+  flat = pph_flatten_name (map->d.ordinary.to_file);
+  fprintf (stderr, "%d|%d|%s|%s|%s|%s.pph\n", line_table->depth,
+	   map->d.ordinary.sysp, tree_dumper.dname, tree_dumper.name,
+	   map->d.ordinary.to_file, flat);
+  free (flat);
+  tree_dumper.dname = NULL;
+  tree_dumper.name = NULL;
+}
+
+
+/* Initialize the #include tree dumper.  */
+
+void
+pph_init_include_tree (void)
+{
+  cpp_callbacks *cb;
+
+  memset (&tree_dumper, 0, sizeof (tree_dumper));
+
+  if (pph_enabled_p ())
+    fatal_error ("do not use -fpph-map-gen with any other PPH flag");
+
+  /* Set up the libcpp handler for file change events.  Each event
+     will generate a new entry in the map file.  */
+  cb = cpp_get_callbacks (parse_in);
+
+  tree_dumper.prev_file_change = cb->file_change;
+  cb->file_change = pph_file_change_handler;
+
+  tree_dumper.prev_include = cb->include;
+  cb->include = pph_include_handler_for_map;
+}
+
+
+/* Add INCLUDE, and the images included by it, to the list of files
+   included by STREAM.  */
+
+void
+pph_add_include (pph_stream *stream, pph_stream *include)
+{
+  pph_stream *include_child;
+  unsigned i;
+
+  include->parent = stream;
+  VEC_safe_push (pph_stream_ptr, heap, stream->includes, include);
+  FOR_EACH_VEC_ELT (pph_stream_ptr, include->includes, i, include_child)
+    VEC_safe_push (pph_stream_ptr, heap, stream->includes, include_child);
+}
+
+
+/*********************************************************** stream handling */
+
+
+/* List of PPH images opened for reading.  Images opened during #include
+   processing and opened from pph_in_includes cannot be closed
+   immediately after reading, because the pickle cache contained in
+   them may be referenced from other images.  We delay closing all of
+   them until the end of parsing (when pph_streamer_finish is called).  */
+static VEC(pph_stream_ptr, heap) *pph_read_images = NULL;
+
+
+/* If FILENAME has already been read, return the stream associated with it.  */
+
+static pph_stream *
+pph_find_stream_for (const char *filename)
+{
+  pph_stream *include;
+  unsigned i;
+
+  /* FIXME pph, implement a hash map to avoid this linear search.  */
+  FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, i, include)
+    if (strcmp (include->name, filename) == 0)
+      return include;
+
+  return NULL;
+}
+
+
+/* Add STREAM to the list of read images.  */
+
+void
+pph_mark_stream_read (pph_stream *stream)
+{
+  stream->in_memory_p = true;
+  VEC_safe_push (pph_stream_ptr, heap, pph_read_images, stream);
+}
+
+
+/* Create a new PPH stream to be stored on the file called NAME.
+   MODE is passed to fopen directly.  */
+
+pph_stream *
+pph_stream_open (const char *name, const char *mode)
+{
+  pph_stream *stream;
+  FILE *f;
+
+  /* If we have already opened a PPH stream named NAME, just return
+     its associated stream.  */
+  stream = pph_find_stream_for (name);
+  if (stream)
+    {
+      gcc_assert (stream->in_memory_p);
+      return stream;
+    }
+
+  f = fopen (name, mode);
+  if (!f)
+    return NULL;
+
+  stream = XCNEW (pph_stream);
+  stream->file = f;
+  stream->name = xstrdup (name);
+  stream->write_p = (strchr (mode, 'w') != NULL);
+  pph_cache_init (&stream->cache);
+  stream->preloaded_cache = pph_preloaded_cache;
+  if (stream->write_p)
+    pph_init_write (stream);
+  else
+    pph_init_read (stream);
+
+  return stream;
+}
+
+
+/* Close PPH stream STREAM.  */
+
+void
+pph_stream_close (pph_stream *stream)
+{
+  /* STREAM can be NULL if it could not be properly opened.  An error
+     has already been emitted, so avoid crashing here.  */
+  if (stream == NULL)
+    return;
+
+  if (flag_pph_tracer >= 1)
+    fprintf (pph_logfile, "PPH: Closing %s\n", stream->name);
+
+  /* If we were writing to STREAM, flush all the memory buffers.  This
+     does the actual writing of all the pickled data structures.  */
+  if (stream->write_p)
+    pph_flush_buffers (stream);
+
+  fclose (stream->file);
+
+  /* Deallocate all memory used.  */
+  stream->file = NULL;
+  VEC_free (pph_cache_entry, heap, stream->cache.v);
+  pointer_map_destroy (stream->cache.m);
+  VEC_free (pph_symtab_entry, heap, stream->symtab.v);
+  VEC_free (pph_stream_ptr, heap, stream->includes);
+
+  if (stream->write_p)
+    {
+      destroy_output_block (stream->encoder.w.ob);
+      free (stream->encoder.w.decl_state_stream);
+      lto_delete_out_decl_state (stream->encoder.w.out_state);
+    }
+  else
+    {
+      unsigned i;
+
+      free (stream->encoder.r.ib);
+      lto_data_in_delete (stream->encoder.r.data_in);
+      for (i = 0; i < PPH_NUM_SECTIONS; i++)
+	free (stream->encoder.r.pph_sections[i]);
+      free (stream->encoder.r.pph_sections);
+      free (stream->encoder.r.file_data);
+    }
+
+  free (stream);
+}
+
+
+/********************************************************** stream callbacks */
+
+
+/* Callback for writing ASTs to a stream.  Write EXPR to the PPH stream
+   in OB.  */
+
+static void
+pph_write_tree (struct output_block *ob, tree expr, bool ref_p ATTRIBUTE_UNUSED)
+{
+  pph_out_tree ((pph_stream *) ob->sdata, expr);
+}
+
+
+/* Callback for reading ASTs from a stream.  Instantiate and return a
+   new tree from the PPH stream in DATA_IN.  */
+
+static tree
+pph_read_tree (struct lto_input_block *ib ATTRIBUTE_UNUSED,
+	       struct data_in *data_in)
+{
+  return pph_in_tree ((pph_stream *) data_in->sdata);
+}
+
+
+/* Callback for streamer_hooks.input_location.  An offset is applied to
+   the location_t read in according to the properties of the merged
+   line_table.  IB and DATA_IN are as in lto_input_location.  This function
+   should only be called after pph_in_and_merge_line_table was called as
+   we expect pph_loc_offset to be set.  */
+
+static location_t
+pph_input_location (struct lto_input_block *ib ATTRIBUTE_UNUSED,
+                    struct data_in *data_in)
+{
+  return pph_in_location ((pph_stream *) data_in->sdata);
+}
+
+
+/* Callback for streamer_hooks.output_location.  Output the LOC directly,
+   an offset will be applied on input after rebuilding the line_table.
+   OB and LOC are as in lto_output_location.  */
+
+static void
+pph_output_location (struct output_block *ob, location_t loc)
+{
+  pph_out_location ((pph_stream *) ob->sdata, loc);
+}
+
+
+/******************************************************** pph initialization */
+
+
+/* Initialize all the streamer hooks used for streaming ASTs.  */
+
+static void
+pph_hooks_init (void)
+{
+  streamer_hooks_init ();
+  streamer_hooks.write_tree = pph_write_tree;
+  streamer_hooks.read_tree = pph_read_tree;
+  streamer_hooks.input_location = pph_input_location;
+  streamer_hooks.output_location = pph_output_location;
+}
+
+
+/* Initialize the streamer.  */
+
+static void
+pph_streamer_init (void)
+{
+  pph_hooks_init ();
+  pph_init_preloaded_cache ();
+}
+
+
+/* The initial order of the size of the lexical lookaside table,
+   which will accomodate as many as half of its slots in use.  */
+
+static const unsigned int cpp_lt_order = /* 2 to the power of */ 9;
+
+/* Initialize PPH support.  */
+
+void
+pph_init (void)
+{
+  cpp_callbacks *cb;
+  cpp_lookaside *table;
+
+  if (flag_pph_logfile)
+    {
+      pph_logfile = fopen (flag_pph_logfile, "w");
+      if (!pph_logfile)
+	fatal_error ("Cannot create %s for writing: %m", flag_pph_logfile);
+    }
+  else
+    pph_logfile = stdout;
+
+  if (flag_pph_tracer >= 1)
+    fprintf (pph_logfile, "PPH: Initializing.\n");
+
+  /* Set up the libcpp handler for #include.  */
+  cb = cpp_get_callbacks (parse_in);
+  cb->include = pph_include_handler;
+
+  table = cpp_lt_exchange (parse_in,
+                           cpp_lt_create (cpp_lt_order, flag_pph_debug/2));
+  gcc_assert (table == NULL);
+
+  pph_streamer_init ();
+
+  /* If we are generating a PPH file, initialize the writer.  */
+  if (pph_writer_enabled_p ())
+    pph_writer_init ();
+
+  pph_reader_init ();
+}
+
+
+/********************************************************** pph finalization */
+
+
+/* Finalize the streamer.  */
+
+static void
+pph_streamer_finish (void)
+{
+  unsigned i;
+  pph_stream *image;
+
+  /* Finalize the writer.  */
+  pph_writer_finish ();
+
+  /* Finalize the reader.  */
+  pph_reader_finish ();
+
+  /* Close any images read during parsing.  */
+  FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, i, image)
+    pph_stream_close (image);
+
+  VEC_free (pph_stream_ptr, heap, pph_read_images);
+}
+
+
+/* Finalize PPH support.  */
+
+void
+pph_finish (void)
+{
+  /* Finalize the streamer.  */
+  pph_streamer_finish ();
+
+  /* Close log files.  */
+  if (flag_pph_tracer >= 1)
+    fprintf (pph_logfile, "PPH: Finishing.\n");
+
+  if (flag_pph_logfile)
+    fclose (pph_logfile);
+}
Index: gcc/cp/Make-lang.in
===================================================================
--- gcc/cp/Make-lang.in	(revision 181815)
+++ gcc/cp/Make-lang.in	(working copy)
@@ -82,8 +82,8 @@ CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.
  cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \
  cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \
  cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \
- cp/cp-gimplify.o cp/pph.o cp/pph-streamer.o cp/pph-streamer-out.o \
- cp/pph-streamer-in.o tree-mudflap.o $(CXX_C_OBJS)
+ cp/cp-gimplify.o cp/pph-core.o cp/pph-out.o cp/pph-in.o \
+ tree-mudflap.o $(CXX_C_OBJS)
 
 # Language-specific object files for C++.
 CXX_OBJS = cp/cp-lang.o c-family/stub-objc.o $(CXX_AND_OBJCXX_OBJS)
@@ -265,8 +265,10 @@ CXX_TREE_H = $(TREE_H) cp/name-lookup.h 
 CXX_PARSER_H = tree.h c-family/c-pragma.h cp/parser.h
 CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H)
 CXX_PPH_H = $(CXX_TREE_H) cp/pph.h
-CXX_PPH_STREAMER_H = $(LTO_STREAMER_H) $(DATA_STREAMER_H) $(TREE_STREAMER_H) \
-	$(TREE_H) $(CXX_PPH_H) cp/pph-streamer.h
+CXX_PPH_STREAMER_H = $(CXX_PPH_H) $(DATA_STREAMER_H) $(TREE_STREAMER_H) \
+	cp/pph-streamer.h
+CXX_PPH_COMMON_H = $(CONFIG_H) $(SYSTEM_H) coretypes.h $(CXX_PPH_STREAMER_H) \
+	$(TREE_PASS_H) tree-iterator.h version.h cppbuiltin.h $(CXX_PARSER_H)
 
 cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
   $(C_PRAGMA_H) output.h input.h cp/operators.def $(TM_P_H) \
@@ -349,19 +351,8 @@ cp/name-lookup.o: cp/name-lookup.c $(CON
 	$(CXX_PPH_H) pointer-set.h
 cp/cxx-pretty-print.o: cp/cxx-pretty-print.c $(CXX_PRETTY_PRINT_H) \
   $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h $(CXX_TREE_H) tree-pretty-print.h
-cp/pph.o: cp/pph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(CPPLIB_H) \
-	toplev.h $(TREE_H) $(CXX_TREE_H) $(TIMEVAR_H) pointer-set.h \
-	fixed-value.h $(TREE_PASS_H) $(TREE_INLINE_H) tree-pretty-print.h \
-	$(CXX_PARSER_H) $(CXX_PPH_H) $(CXX_PPH_STREAMER_H)
-cp/pph-streamer.o: cp/pph-streamer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-	$(TREE_H) tree-pretty-print.h $(LTO_STREAMER_H) $(CXX_PPH_STREAMER_H) \
-	$(CXX_PPH_H) $(TREE_PASS_H) version.h cppbuiltin.h tree-iterator.h \
-	$(STREAMER_HOOKS_H)
-cp/pph-streamer-out.o: cp/pph-streamer-out.c $(CONFIG_H) $(SYSTEM_H) \
-	coretypes.h $(TREE_H) tree-pretty-print.h $(LTO_STREAMER_H) \
-	$(CXX_PPH_STREAMER_H) $(CXX_PPH_H) $(TREE_PASS_H) version.h \
-	$(CXX_PARSER_H) cppbuiltin.h tree-iterator.h $(CGRAPH_H)
-cp/pph-streamer-in.o: cp/pph-streamer-in.c $(CONFIG_H) $(SYSTEM_H) \
-	coretypes.h $(TREE_H) tree-pretty-print.h $(LTO_STREAMER_H) \
-	$(CXX_PPH_STREAMER_H) $(CXX_PPH_H) $(TREE_PASS_H) version.h \
-	$(CXX_PARSER_H) cppbuiltin.h tree-iterator.h toplev.h
+cp/pph-core.o: cp/pph-core.c $(CXX_PPH_COMMON_H) $(CPPLIB_H) $(TIMEVAR_H) \
+	$(TREE_INLINE_H) tree-pretty-print.h fixed-value.h pointer-set.h \
+        toplev.h
+cp/pph-out.o: cp/pph-out.c $(CXX_PPH_COMMON_H) $(CGRAPH_H)
+cp/pph-in.o: cp/pph-in.c $(CXX_PPH_COMMON_H) pointer-set.h toplev.h
Index: gcc/cp/pph.c
===================================================================
--- gcc/cp/pph.c	(revision 181815)
+++ gcc/cp/pph.c	(working copy)
@@ -1,403 +0,0 @@
-/* Factored pre-parsed header (PPH) support for C++
-   Copyright (C) 2010, 2011 Free Software Foundation, Inc.
-   Contributed by Lawrence Crowl <crowl@google.com> and
-   Diego Novillo <dnovillo@google.com>.
-
-   This file is part of GCC.
-
-   GCC is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3, or (at your option)
-   any later version.
-
-   GCC is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "pph.h"
-#include "cpplib.h"
-#include "toplev.h"
-#include "tree.h"
-#include "cp-tree.h"
-#include "timevar.h"
-#include "pointer-set.h"
-#include "fixed-value.h"
-#include "md5.h"
-#include "tree-pass.h"
-#include "tree-dump.h"
-#include "tree-inline.h"
-#include "tree-pretty-print.h"
-#include "cxx-pretty-print.h"
-#include "parser.h"
-#include "pph-streamer.h"
-
-/* Log file where PPH analysis is written to.  Controlled by
-   -fpph_logfile.  If this flag is not given, stdout is used.  */
-FILE *pph_logfile = NULL;
-
-/* Convert a checked tree_code CODE to a string.  */
-
-const char *
-pph_tree_code_text (enum tree_code code)
-{
-  gcc_assert (code < MAX_TREE_CODES);
-  return tree_code_name[code];
-}
-
-
-/* Dump a location LOC to FILE.  */
-
-void
-pph_dump_location (FILE *file, location_t loc)
-{
-  expanded_location xloc = expand_location (loc);
-  fprintf (file, "%s:%d", xloc.file, xloc.line);
-}
-
-/* Dump identifying information for a minimal DECL to FILE.  */
-
-void
-pph_dump_min_decl (FILE *file, tree decl)
-{
-  print_generic_expr (file, DECL_NAME (decl), 0);
-  print_generic_expr (file, DECL_CONTEXT (decl), 0);
-  pph_dump_location (file, DECL_SOURCE_LOCATION (decl));
-}
-
-/* Dump a complicated name for tree T to FILE using FLAGS.
-   See TDF_* in tree-pass.h for flags.  */
-
-void
-pph_dump_tree_name (FILE *file, tree t, int flags)
-{
-  enum tree_code code = TREE_CODE (t);
-  const char *text = pph_tree_code_text (code);
-  if (DECL_P (t))
-    fprintf (file, "%s %s\n", text, decl_as_string (t, flags));
-  else if (TYPE_P (t))
-    fprintf (file, "%s %s\n", text, type_as_string (t, flags));
-  else if (EXPR_P (t))
-    fprintf (file, "%s %s\n", text, expr_as_string (t, flags));
-  else
-    {
-      fprintf (file, "%s ", text );
-      print_generic_expr (file, t, flags);
-      fprintf (file, "\n");
-    }
-}
-
-
-/* Dump namespace NS for PPH.  */
-
-void
-pph_dump_namespace (FILE *file, tree ns)
-{
-  fprintf (file, "namespace ");
-  pph_dump_tree_name (file, ns, 0);
-  fprintf (file, "{\n");
-  pph_dump_binding (file, NAMESPACE_LEVEL (ns));
-  fprintf (file, "}\n");
-}
-
-
-/* Dump cp_binding_level LEVEL for PPH.  */
-
-void
-pph_dump_binding (FILE *file, cp_binding_level *level)
-{
-  tree t, next;
-  pph_dump_chain (file, level->names);
-  for (t = level->namespaces; t; t = next)
-    {
-      next = DECL_CHAIN (t);
-      if (!DECL_IS_BUILTIN (t))
-        pph_dump_namespace (file, t);
-    }
-}
-
-
-/* Dump a CHAIN for PPH.  */
-
-void
-pph_dump_chain (FILE *file, tree chain)
-{
-  tree t, next;
-  for (t = chain; t; t = next)
-    {
-      next = DECL_CHAIN (t);
-      if (!DECL_IS_BUILTIN (t))
-        pph_dump_tree_name (file, t, 0);
-    }
-}
-
-
-/* Return true if PPH image NAME can be used at the point of inclusion
-   (given by LOC).  */
-
-static bool
-pph_is_valid_here (const char *name, location_t loc)
-{
-  /* If we are inside a scope, reject the image.  We could be inside a
-     namespace or a structure which changes the parsing context for
-     the original text file.  */
-  if (scope_chain->x_brace_nesting > 0)
-    {
-      error_at (loc, "PPH file %s not included at global scope", name);
-      return false;
-    }
-
-  return true;
-}
-
-
-/* Record a #include or #include_next for PPH.
-   READER is the main pre-processor object, LOC is the location where
-   the #include is being emitted from, DNAME is the name of the
-   #include directive used, NAME is the canonical name of the file being
-   included, ANGLE_BRACKETS is non-zero if this #include uses <> and
-   TOK_P is a pointer to the current token being pre-processed.  */
-
-static bool
-pph_include_handler (cpp_reader *reader,
-                     location_t loc,
-                     const unsigned char *dname,
-                     const char *name,
-                     int angle_brackets,
-                     const cpp_token **tok_p ATTRIBUTE_UNUSED)
-{
-  const char *pph_file;
-  bool read_text_file_p;
-
-  if (flag_pph_tracer >= 1)
-    {
-      fprintf (pph_logfile, "PPH: #%s", dname);
-      fprintf (pph_logfile, " %c", angle_brackets ? '<' : '"');
-      fprintf (pph_logfile, "%s", name);
-      fprintf (pph_logfile, "%c\n", angle_brackets ? '>' : '"');
-    }
-
-  read_text_file_p = true;
-  pph_file = query_pph_include_map (name);
-  if (pph_file != NULL
-      && pph_is_valid_here (name, loc)
-      && !cpp_included_before (reader, name, input_location))
-    {
-      pph_stream *include;
-
-      /* Hack. We do this to mimic what the non-pph compiler does in
-	_cpp_stack_include as our goal is to have identical line_tables.  */
-      line_table->highest_location--;
-
-      include = pph_read_file (pph_file);
-
-      /* If we are generating a new PPH image, add the stream we just
-	 read to the list of includes.   This way, the parser will be
-	 able to resolve references to symbols in INCLUDE and its
-	 children.  */
-      if (pph_writer_enabled_p ())
-	pph_writer_add_include (include);
-
-      read_text_file_p = false;
-    }
-
-  return read_text_file_p;
-}
-
-
-/* The initial order of the size of the lexical lookaside table,
-   which will accomodate as many as half of its slots in use.  */
-
-static const unsigned int cpp_lt_order = /* 2 to the power of */ 9;
-
-/* Initialize PPH support.  */
-
-void
-pph_init (void)
-{
-  cpp_callbacks *cb;
-  cpp_lookaside *table;
-
-  if (flag_pph_logfile)
-    {
-      pph_logfile = fopen (flag_pph_logfile, "w");
-      if (!pph_logfile)
-	fatal_error ("Cannot create %s for writing: %m", flag_pph_logfile);
-    }
-  else
-    pph_logfile = stdout;
-
-  if (flag_pph_tracer >= 1)
-    fprintf (pph_logfile, "PPH: Initializing.\n");
-
-  /* Set up the libcpp handler for #include.  */
-  cb = cpp_get_callbacks (parse_in);
-  cb->include = pph_include_handler;
-
-  table = cpp_lt_exchange (parse_in,
-                           cpp_lt_create (cpp_lt_order, flag_pph_debug/2));
-  gcc_assert (table == NULL);
-
-  pph_streamer_init ();
-
-  /* If we are generating a PPH file, initialize the writer.  */
-  if (pph_writer_enabled_p ())
-    pph_writer_init ();
-
-  pph_reader_init ();
-}
-
-
-/* Finalize PPH support.  */
-
-void
-pph_finish (void)
-{
-  /* Finalize the streamer.  */
-  pph_streamer_finish ();
-
-  /* Close log files.  */
-  if (flag_pph_tracer >= 1)
-    fprintf (pph_logfile, "PPH: Finishing.\n");
-
-  if (flag_pph_logfile)
-    fclose (pph_logfile);
-}
-
-
-/* PPH include tree dumper.  Each entry in this file has the format:
-
-	DEPTH|SYSP|DNAME|CANONICAL-NAME|FULL-NAME|PPH-NAME
-
-  Where:
-	DEPTH		is the include depth of the file.
-	SYSP		1 for a system header
-			2 for a C system header that needs 'extern "C"'
-			0 otherwise.
-	DNAME		name of the #include directive used.
-	CANONICAL-NAME	is the name of the file as specified by the
-			#include directive.
-	FULL-NAME	is the full path name where the included file
-			was found by the pre-processor.
-	PPH-NAME	is the name of the associated PPH file.  */
-typedef struct {
-  /* Name of current #include directive.  */
-  const unsigned char *dname;
-
-  /* Canonical name of file being included.  */
-  const char *name;
-
-  /* Previous libcpp #include handler.  */
-  void (*prev_file_change) (cpp_reader *, const struct line_map *);
-
-  /* Previous libcpp file change handler.  */
-  bool (*prev_include) (cpp_reader *, source_location, const unsigned char *,
-		        const char *, int, const cpp_token **);
-} pph_include_tree_dumper;
-
-static pph_include_tree_dumper tree_dumper;
-
-
-/* Return a copy of NAME with the characters '/' and '.' replaced with
-   '_'.  The caller is reponsible for freeing the returned string.  */
-
-static char *
-flatten_name (const char *name)
-{
-  char *str = xstrdup (name);
-  size_t i;
-
-  for (i = 0; i < strlen (str); i++)
-    if (str[i] == DIR_SEPARATOR || str[i] == '.')
-      str[i] = '_';
-
-  return str;
-}
-
-
-/* File change handler for libcpp.  READER is the main pre-processor object,
-   MAP is the line map entry for the file that we are entering into.  */
-
-static void
-pph_file_change_handler (cpp_reader *reader, const struct line_map *map)
-{
-  char *flat;
-
-  if (tree_dumper.prev_file_change)
-    tree_dumper.prev_file_change (reader, map);
-
-  /* We are only interested in line maps that describe a new file being
-     entered.  */
-  if (map == NULL || map->reason != LC_ENTER)
-    return;
-
-  /* Emit a line to the map file with the format:
-
-	DEPTH|SYSP|DNAME|CANONICAL-NAME|FULL-NAME|PPH-NAME
-  */
-  flat = flatten_name (map->d.ordinary.to_file);
-  fprintf (stderr, "%d|%d|%s|%s|%s|%s.pph\n", line_table->depth,
-	   map->d.ordinary.sysp, tree_dumper.dname, tree_dumper.name,
-	   map->d.ordinary.to_file, flat);
-  free (flat);
-  tree_dumper.dname = NULL;
-  tree_dumper.name = NULL;
-}
-
-
-/* #include handler for libcpp.  READER is the main pre-processor object,
-   LOC is the location where the #include is being emitted from, DNAME
-   is the name of the #include directive used, NAME is the canonical
-   name of the file being included, ANGLE_BRACKETS is non-zero if this
-   #include uses <> and TOK_P is a pointer to the current token being
-   pre-processed.  */
-
-static bool
-pph_include_handler_for_map (cpp_reader *reader,
-			     location_t loc,
-                             const unsigned char *dname,
-                             const char *name,
-                             int angle_brackets,
-                             const cpp_token **tok_p)
-{
-  bool retval = true;
-
-  if (tree_dumper.prev_include)
-    retval &= tree_dumper.prev_include (reader, loc, dname, name,
-					angle_brackets, tok_p);
-  tree_dumper.dname = dname;
-  tree_dumper.name = name;
-
-  return retval;
-}
-
-
-/* Initialize the #include tree dumper.  */
-
-void
-pph_init_include_tree (void)
-{
-  cpp_callbacks *cb;
-
-  memset (&tree_dumper, 0, sizeof (tree_dumper));
-
-  if (pph_enabled_p ())
-    fatal_error ("do not use -fpph-map-gen with any other PPH flag");
-
-  /* Set up the libcpp handler for file change events.  Each event
-     will generate a new entry in the map file.  */
-  cb = cpp_get_callbacks (parse_in);
-
-  tree_dumper.prev_file_change = cb->file_change;
-  cb->file_change = pph_file_change_handler;
-
-  tree_dumper.prev_include = cb->include;
-  cb->include = pph_include_handler_for_map;
-}
Index: gcc/cp/pph.h
===================================================================
--- gcc/cp/pph.h	(revision 181815)
+++ gcc/cp/pph.h	(working copy)
@@ -137,14 +137,14 @@ extern FILE *pph_logfile;
 
 /* Extern functions.  */
 
-/* In pph.c  */
+/* In pph-core.c  */
 extern void pph_init (void);
 extern void pph_finish (void);
 extern void pph_dump_location (FILE *file, location_t loc);
 extern void pph_dump_tree_name (FILE *file, tree t, int flags);
 extern void pph_init_include_tree (void);
 
-/* In pph-streamer-out.c.  */
+/* In pph-out.c.  */
 extern void pph_out_uint (pph_stream *stream, unsigned int value);
 extern void pph_out_location (pph_stream *stream, location_t loc);
 extern void pph_out_tree (pph_stream *stream, tree t);
@@ -152,7 +152,7 @@ extern void pph_out_record_marker (pph_s
 			enum pph_record_marker marker, enum pph_tag tag);
 void pph_add_decl_to_symtab (tree, enum pph_symtab_action, bool, bool);
 
-/* In pph-streamer-in.c.  */
+/* In pph-in.c.  */
 extern unsigned int pph_in_uint (pph_stream *stream);
 extern location_t pph_in_location (pph_stream *stream);
 extern tree pph_in_tree (pph_stream *stream);
Index: gcc/cp/pph-streamer-in.c
===================================================================
--- gcc/cp/pph-streamer-in.c	(revision 181815)
+++ gcc/cp/pph-streamer-in.c	(working copy)
@@ -1,2728 +0,0 @@
-/* Routines for reading PPH data.
-   Copyright (C) 2011 Free Software Foundation, Inc.
-   Contributed by Diego Novillo <dnovillo@google.com>.
-
-   This file is part of GCC.
-
-   GCC is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3, or (at your option)
-   any later version.
-
-   GCC is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "pph.h"
-#include "tree.h"
-#include "langhooks.h"
-#include "tree-iterator.h"
-#include "tree-pretty-print.h"
-#include "lto-streamer.h"
-#include "pph-streamer.h"
-#include "tree-pass.h"
-#include "version.h"
-#include "cppbuiltin.h"
-#include "toplev.h"
-#include "parser.h"
-#include "pointer-set.h"
-
-
-/********************************************************* type declarations */
-
-
-typedef char *char_p;
-DEF_VEC_P(char_p);
-DEF_VEC_ALLOC_P(char_p,heap);
-
-
-/****************************************************** forward declarations */
-
-
-/* Forward declarations to avoid circularity.  */
-static tree pph_in_merge_key_tree (pph_stream *, tree *);
-
-
-/***************************************************** stream initialization */
-
-
-/* String tables for all input streams.  These are allocated separately
-  from streams because they cannot be deallocated after the streams
-  have been read (string streaming works by pointing into these
-  tables).
-
-  Each stream will create a new entry in this table of tables.  The
-  memory will remain allocated until the end of compilation.  */
-static VEC(char_p,heap) *string_tables = NULL;
-
-
-/* Read into memory the contents of the file in STREAM.  Initialize
-   internal tables and data structures needed to re-construct the
-   ASTs in the file.  */
-
-void
-pph_init_read (pph_stream *stream)
-{
-  struct stat st;
-  size_t i, bytes_read, strtab_size, body_size;
-  int retcode;
-  pph_file_header *header;
-  const char *strtab, *body;
-  char *new_strtab;
-
-  /* Read STREAM->NAME into the memory buffer stream->encoder.r.file_data.  */
-  retcode = fstat (fileno (stream->file), &st);
-  gcc_assert (retcode == 0);
-  stream->encoder.r.file_size = (size_t) st.st_size;
-  stream->encoder.r.file_data = XCNEWVEC (char, stream->encoder.r.file_size);
-  bytes_read = fread (stream->encoder.r.file_data, 1,
-		      stream->encoder.r.file_size, stream->file);
-  gcc_assert (bytes_read == stream->encoder.r.file_size);
-
-  /* Set up the file sections, header, body and string table for the
-     low-level streaming routines.  */
-  stream->encoder.r.pph_sections = XCNEWVEC (struct lto_file_decl_data *,
-					     PPH_NUM_SECTIONS);
-  for (i = 0; i < PPH_NUM_SECTIONS; i++)
-    stream->encoder.r.pph_sections[i] = XCNEW (struct lto_file_decl_data);
-
-  header = (pph_file_header *) stream->encoder.r.file_data;
-  strtab = (const char *) header + sizeof (pph_file_header);
-  strtab_size = header->strtab_size;
-  body = strtab + strtab_size;
-  gcc_assert (stream->encoder.r.file_size
-	      >= strtab_size + sizeof (pph_file_header));
-  body_size = stream->encoder.r.file_size
-	      - strtab_size - sizeof (pph_file_header);
-
-  /* Create a new string table for STREAM.  This table is not part of
-     STREAM because it needs to remain around until the end of
-     compilation (all the string streaming routines work by pointing
-     into the string table, so we cannot deallocate it after reading
-     STREAM).  */
-  new_strtab = XNEWVEC (char, strtab_size);
-  memcpy (new_strtab, strtab, strtab_size);
-  VEC_safe_push (char_p, heap, string_tables, new_strtab);
-
-  /* Create an input block structure pointing right after the string
-     table.  */
-  stream->encoder.r.ib = XCNEW (struct lto_input_block);
-  LTO_INIT_INPUT_BLOCK_PTR (stream->encoder.r.ib, body, 0, body_size);
-  stream->encoder.r.data_in
-      = lto_data_in_create (stream->encoder.r.pph_sections[0],
-			    new_strtab, strtab_size, NULL);
-
-  /* Associate STREAM with STREAM->ENCODER.R.DATA_IN so we can recover
-     it from the streamer hooks.  */
-  stream->encoder.r.data_in->sdata = (void *) stream;
-}
-
-
-/********************************************************** primitive values */
-
-
-/* Read an unsigned char VALUE to STREAM.  */
-
-static unsigned char
-pph_in_uchar (pph_stream *stream)
-{
-  unsigned char n = streamer_read_uchar (stream->encoder.r.ib);
-  return n;
-}
-
-
-/* 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 int from STREAM.  */
-
-static inline int
-pph_in_int (pph_stream *stream)
-{
-  HOST_WIDE_INT n = streamer_read_hwi (stream->encoder.r.ib);
-  gcc_assert (n == (int) n);
-  return (int) 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 an unsigned integer from STREAM.  */
-
-unsigned int
-pph_in_uint (pph_stream *stream)
-{
-  HOST_WIDE_INT unsigned n = streamer_read_uhwi (stream->encoder.r.ib);
-  gcc_assert (n == (unsigned) n);
-  return (unsigned) n;
-}
-
-
-/* Read N bytes from STREAM into P.  The caller is responsible for
-   allocating a sufficiently large buffer.  */
-
-static void
-pph_in_bytes (pph_stream *stream, void *p, size_t n)
-{
-  lto_input_data_block (stream->encoder.r.ib, p, n);
-}
-
-
-/* Read and return a string from STREAM.  */
-
-static const char *
-pph_in_string (pph_stream *stream)
-{
-  const char *s = streamer_read_string (stream->encoder.r.data_in,
-                                        stream->encoder.r.ib);
-  return s;
-}
-
-
-/* Read a bitpack from STREAM.  */
-
-static struct bitpack_d
-pph_in_bitpack (pph_stream *stream)
-{
-  struct bitpack_d bp = streamer_read_bitpack (stream->encoder.r.ib);
-  return bp;
-}
-
-
-/******************************************************** source information */
-
-
-/* Set in pph_in_and_merge_line_table. Represents the source_location offset
-   which every streamed in token must add to it's serialized source_location.
-
-   FIXME pph: Ideally this would be in pph_stream.encoder.r, but for that we
-   first need to get rid of the dependency to the streamer_hook for locations.
-   */
-static int pph_loc_offset;
-
-
-/* Read a linenum_type from STREAM.  */
-
-static inline linenum_type
-pph_in_linenum_type (pph_stream *stream)
-{
-  return (linenum_type) pph_in_uint (stream);
-}
-
-
-/* Read a source_location from STREAM.  */
-
-static inline source_location
-pph_in_source_location (pph_stream *stream)
-{
-  return (source_location) pph_in_uint (stream);
-}
-
-
-/* Read a line table marker from STREAM.  */
-
-static inline enum pph_linetable_marker
-pph_in_linetable_marker (pph_stream *stream)
-{
-  enum pph_linetable_marker m =
-    (enum pph_linetable_marker) pph_in_uchar (stream);
-  gcc_assert (m == PPH_LINETABLE_ENTRY
-	      || m == PPH_LINETABLE_REFERENCE
-	      || m == PPH_LINETABLE_END);
-  return m;
-}
-
-
-
-/* Read all the fields of struct line_map LM from STREAM.  LM is assumed
-   to be an ordinary line map.  */
-
-static void
-pph_in_line_map_ordinary (pph_stream *stream, struct line_map *lm)
-{
-  struct bitpack_d bp;
-
-  ORDINARY_MAP_FILE_NAME (lm) = pph_in_string (stream);
-  ORDINARY_MAP_STARTING_LINE_NUMBER (lm) = pph_in_linenum_type (stream);
-
-  /* Note that this index is an offset indicating the distance from LM
-     to the line map entry for LM's includer.  It needs to be adjusted
-     while reading the line table in pph_in_line_table_and_includes.  */
-  ORDINARY_MAP_INCLUDER_FILE_INDEX (lm) = pph_in_int (stream);
-  bp = pph_in_bitpack (stream);
-  ORDINARY_MAP_IN_SYSTEM_HEADER_P (lm)
-      = (unsigned char) bp_unpack_value (&bp, CHAR_BIT);
-  ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (lm) = bp_unpack_value (&bp,
-							     COLUMN_BITS_BIT);
-}
-
-
-/* Read a line_map from STREAM into LM.  */
-
-static void
-pph_in_line_map (pph_stream *stream, struct line_map *lm)
-{
-  struct lto_input_block *ib = stream->encoder.r.ib;
-
-  lm->start_location = pph_in_source_location (stream);
-  lm->reason = streamer_read_enum (ib, lc_reason, LC_ENTER_MACRO);
-
-  /* FIXME pph.  We currently do not support location tracking for
-     macros in PPH images.  */
-  gcc_assert (lm->reason != LC_ENTER_MACRO);
-  pph_in_line_map_ordinary (stream, lm);
-}
-
-
-/* Read in from STREAM and merge a referenced include into the current parsing
-   context.  */
-
-static void
-pph_in_include (pph_stream *stream)
-{
-  int old_loc_offset;
-  const char *include_name;
-  pph_stream *include_stream;
-  source_location prev_start_loc = pph_in_source_location (stream);
-
-  /* Simulate highest_location to be as it would be at this point in a non-pph
-     compilation.  */
-  line_table->highest_location = (prev_start_loc - 1) + pph_loc_offset;
-
-  /* FIXME pph: If we move pph_loc_offset to pph_stream.encoder.r, we could
-     have an independent offset for each stream and not have to save and
-     restore the state of a global pph_loc_offset as we are doing here.  */
-  old_loc_offset = pph_loc_offset;
-
-  include_name = pph_in_string (stream);
-  include_stream = pph_read_file (include_name);
-
-  /* Add INCLUDE_STREAM, and the images included by it, to the list
-     of included images for STREAM.  */
-  pph_add_include (stream, include_stream);
-
-  pph_loc_offset = old_loc_offset;
-}
-
-
-/* Read the line_table from STREAM and merge it in the current
-   line_table.  At the same time load includes in the order they were
-   originally included by loading them at the point they were
-   referenced in the line_table.
-
-   Returns the source_location of line 1 / col 0 for this include.  */
-
-static source_location
-pph_in_line_table_and_includes (pph_stream *stream)
-{
-  unsigned int used_before, old_depth;
-  bool first;
-  enum pph_linetable_marker next_lt_marker;
-  int top_includer_ix;
-
-  used_before = LINEMAPS_ORDINARY_USED (line_table);
-  first = true;
-
-  /* All line map entries that have -1 as the includer, will now be
-     relocated to the current last line map entry in the line table.  */
-  top_includer_ix = used_before - 1;
-
-  for (next_lt_marker = pph_in_linetable_marker (stream);
-       next_lt_marker != PPH_LINETABLE_END;
-       next_lt_marker = pph_in_linetable_marker (stream))
-    {
-      if (next_lt_marker == PPH_LINETABLE_REFERENCE)
-	{
-	  gcc_assert (!first);
-	  pph_in_include (stream);
-	}
-      else
-	{
-	  struct line_map *lm;
-	  int last_entry_ix;
-
-	  lm = linemap_new_map (line_table, LC_ENTER);
-	  pph_in_line_map (stream, lm);
-
-	  /* All the entries that we read from STREAM will be appended
-	     to the end of line_table.  Calculate the index for the
-	     last entry so that we can resolve the relative indices
-	     for all the includer file index entries we read from
-	     STREAM.  Note that LAST_ENTRY_IX is the index of the line
-	     map LM that we have just read.  */
-	  last_entry_ix = LINEMAPS_ORDINARY_USED (line_table) - 1;
-
-	  if (first)
-	    {
-	      first = false;
-	      pph_loc_offset = (line_table->highest_location + 1)
-		               - lm->start_location;
-	      gcc_assert (ORDINARY_MAP_INCLUDER_FILE_INDEX (lm) == -1);
-	    }
-
-	  /* Relocate the includer file index.  For most entries, the
-	     writer wrote ORDINARY_MAP_INCLUDER_FILE_INDEX as a
-	     relative offset between this entry and the original
-	     includer file index (see pph_out_line_map_ordinary).
-	     Convert that relative index into an absolute index in the
-	     current line_table.
-
-	     A relocation value of -1 means that line map LM is
-	     included by the current top includer (i.e., STREAM), so
-	     we use the value TOP_INCLUDER_IX for it.  */
-	  if (ORDINARY_MAP_INCLUDER_FILE_INDEX (lm) == -1)
-	    ORDINARY_MAP_INCLUDER_FILE_INDEX (lm) = top_includer_ix;
-	  else
-	    ORDINARY_MAP_INCLUDER_FILE_INDEX (lm) -= last_entry_ix;
-
-	  lm->start_location += pph_loc_offset;
-	}
-    }
-
-  /* We used to expect exactly the same number of entries, but files
-     included from this PPH file may sometimes not be needed.  For
-     example,
-
-	#include "2.pph"
-	#include "foo.pph"
-	  +-->	#include "1.pph"
-		#include "2.pph"
-		#include "3.pph"
-
-     When foo.pph was originally created, the line table was built
-     with inclusions of 1.pph, 2.pph and 3.pph.  But when compiling
-     the main translation unit, we include 2.pph before foo.pph, so
-     the inclusion of 2.pph from foo.pph does nothing.  Leaving the
-     line table in a different shape than the original compilation.
-
-     Instead of insisting on getting EXPECTED_IN entries, we expect at
-     most EXPECTED_IN entries.  */
-  {
-    unsigned int expected = pph_in_uint (stream);
-    gcc_assert (LINEMAPS_ORDINARY_USED (line_table) - used_before <= expected);
-  }
-
-  line_table->highest_location = pph_loc_offset + pph_in_uint (stream);
-  line_table->highest_line = pph_loc_offset + pph_in_uint (stream);
-
-  /* The MAX_COLUMN_HINT can be directly overwritten.  */
-  line_table->max_column_hint = pph_in_uint (stream);
-
-  /* The line_table doesn't store the last LC_LEAVE in any given compilation;
-     thus we need to replay the LC_LEAVE for the header now.  For that same
-     reason, the line_table should currently be in a state representing a depth
-     one include deeper then the depth at which this pph was included.  The
-     LC_LEAVE replay will then bring the depth back to what it was before
-     calling this function.  */
-  old_depth = line_table->depth++;
-  linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
-  gcc_assert (line_table->depth == old_depth);
-
-  return MAP_START_LOCATION (LINEMAPS_ORDINARY_MAP_AT (line_table, used_before));
-}
-
-
-/*********************************************************** record handling */
-
-
-/* Wrapper for memory allocation calls that should have their results
-   registered in the PPH streamer cache.  DATA is the pointer returned
-   by the memory allocation call in ALLOC_EXPR.  IX is the cache slot 
-   in CACHE where the newly allocated DATA should be registered at.  */
-#define ALLOC_AND_REGISTER(CACHE, IX, TAG, DATA, ALLOC_EXPR)	\
-    do {							\
-      (DATA) = (ALLOC_EXPR);					\
-      pph_cache_insert_at (CACHE, DATA, IX, TAG);		\
-    } while (0)
-
-
-/* Read and return a record marker from STREAM.  On return, *TAG_P will
-   contain the tag for the data type stored in this record.  */
-enum pph_record_marker
-pph_in_record_marker (pph_stream *stream, enum pph_tag *tag_p)
-{
-  enum pph_record_marker m = (enum pph_record_marker) pph_in_uchar (stream);
-  gcc_assert (m == PPH_RECORD_START
-              || m == PPH_RECORD_START_NO_CACHE
-              || m == PPH_RECORD_START_MUTATED
-	      || m == PPH_RECORD_START_MERGE_KEY
-	      || m == PPH_RECORD_START_MERGE_BODY
-              || m == PPH_RECORD_END
-              || m == PPH_RECORD_IREF
-              || m == PPH_RECORD_XREF
-              || m == PPH_RECORD_PREF);
-
-  *tag_p = (enum pph_tag) pph_in_uint (stream);
-  gcc_assert ((unsigned) *tag_p < (unsigned) PPH_NUM_TAGS);
-
-  if (flag_pph_tracer >= 5)
-    pph_trace_marker (m, *tag_p);
-
-  return m;
-}
-
-
-/* Read and return a record header from STREAM.  EXPECTED_TAG indicates
-   the data type that should be stored in this record.  When a
-   PPH_RECORD_START marker is read, the next word read is an index
-   into the streamer cache where the rematerialized data structure
-   should be stored. When the writer stored this data structure for
-   the first time, it added it to its own streamer cache at slot
-   number *CACHE_IX_P.
-
-   This way, if the same data structure was written a second time to
-   the stream, instead of writing the whole structure again, only the
-   index *CACHE_IX_P is written as a PPH_RECORD_IREF record.
-
-   Therefore, when reading a PPH_RECORD_START marker, *CACHE_IX_P will
-   contain the slot number where the materialized data should be
-   cached at.  When reading a PPH_RECORD_IREF marker, *CACHE_IX_P will
-   contain the slot number the reader can find the previously
-   materialized structure.
-
-   If the record starts with PPH_RECORD_XREF, this means that the data
-   we are about to read is located in the pickle cache of one of
-   STREAM's included images.  In this case, the record consists of two
-   indices: the first one (*INCLUDE_IX_P) indicates which included
-   image contains the data (it is an index into STREAM->INCLUDES), the
-   second one indicates which slot in that image's pickle cache we can
-   find the data.  */
-
-static inline enum pph_record_marker
-pph_in_start_record (pph_stream *stream, unsigned *include_ix_p,
-		     unsigned *cache_ix_p, enum pph_tag expected_tag)
-{
-  enum pph_tag read_tag;
-  enum pph_record_marker marker = pph_in_record_marker (stream, &read_tag);
-
-  /* If the caller expects any tree, make sure we get a valid tree code.  */
-  if (expected_tag == PPH_any_tree)
-    gcc_assert (read_tag < PPH_any_tree);
-  else
-    gcc_assert (read_tag == expected_tag);
-
-  *include_ix_p = (unsigned) -1;
-  *cache_ix_p = (unsigned) -1;
-
-  /* For PPH_RECORD_START and PPH_RECORD_IREF markers, read the
-     streamer cache slot where we should store or find the
-     rematerialized data structure (see description above).
-     Also read the preloaded cache slot in IX for PPH_RECORD_PREF.  */
-  if (marker == PPH_RECORD_START
-      || marker == PPH_RECORD_IREF
-      || marker == PPH_RECORD_PREF
-      || marker == PPH_RECORD_START_MERGE_BODY
-      || marker == PPH_RECORD_START_MERGE_KEY)
-    *cache_ix_p = pph_in_uint (stream);
-  else if (marker == PPH_RECORD_XREF
-           || marker == PPH_RECORD_START_MUTATED)
-    {
-      *include_ix_p = pph_in_uint (stream);
-      *cache_ix_p = pph_in_uint (stream);
-    }
-  else if (marker == PPH_RECORD_END || marker == PPH_RECORD_START_NO_CACHE)
-    ; /* Nothing to do.  This record will not need cache updates.  */
-  else
-    gcc_unreachable ();
-
-  return marker;
-}
-
-
-/********************************************************** lexical elements */
-
-
-/* Read and return a location_t from STREAM.  */
-
-location_t
-pph_in_location (pph_stream *stream)
-{
-  struct bitpack_d bp;
-  bool is_builtin;
-  unsigned HOST_WIDE_INT n;
-  location_t old_loc;
-
-  bp = pph_in_bitpack (stream);
-  is_builtin = bp_unpack_value (&bp, 1);
-
-  n = pph_in_uhwi (stream);
-  old_loc = (location_t) n;
-  gcc_assert (old_loc == n);
-
-  return is_builtin ? old_loc : old_loc + pph_loc_offset;
-}
-
-
-/* Load the tree value associated with TOKEN from STREAM.  */
-
-static void
-pph_in_token_value (pph_stream *stream, cp_token *token)
-{
-  switch (token->type)
-    {
-      case CPP_TEMPLATE_ID:
-      case CPP_NESTED_NAME_SPECIFIER:
-	/* FIXME pph - Need to handle struct tree_check.  */
-	break;
-
-      case CPP_KEYWORD:
-	token->u.value = ridpointers[token->keyword];
-	break;
-
-      case CPP_NAME:
-      case CPP_CHAR:
-      case CPP_WCHAR:
-      case CPP_CHAR16:
-      case CPP_CHAR32:
-      case CPP_NUMBER:
-      case CPP_STRING:
-      case CPP_WSTRING:
-      case CPP_STRING16:
-      case CPP_STRING32:
-	token->u.value = pph_in_tree (stream);
-	break;
-
-      case CPP_PRAGMA:
-	/* Nothing to do.  Field pragma_kind has already been loaded.  */
-	break;
-
-      default:
-	pph_in_bytes (stream, &token->u.value, sizeof (token->u.value));
-	gcc_assert (token->u.value == NULL);
-    }
-}
-
-
-/* Read and return a token from STREAM.  */
-
-static cp_token *
-pph_in_token (pph_stream *stream)
-{
-  cp_token *token = ggc_alloc_cleared_cp_token ();
-
-  /* Do not read the whole structure, the token value has
-     dynamic size as it contains swizzled pointers.
-     FIXME pph, restructure to allow bulk reads of the whole
-     section.  */
-  pph_in_bytes (stream, token, sizeof (cp_token) - sizeof (void *));
-
-  /* FIXME pph.  Use an arbitrary (but valid) location to avoid
-     confusing the rest of the compiler for now.  */
-  token->location = input_location;
-
-  /* FIXME pph: verify that pph_in_token_value works with no tokens.  */
-  pph_in_token_value (stream, token);
-
-  return token;
-}
-
-
-/* Read and return a cp_token_cache instance from STREAM.  */
-
-static cp_token_cache *
-pph_in_token_cache (pph_stream *stream)
-{
-  unsigned i, num;
-  cp_token *first, *last;
-
-  num = pph_in_uint (stream);
-  for (last = first = NULL, i = 0; i < num; i++)
-    {
-      last = pph_in_token (stream);
-      if (first == NULL)
-	first = last;
-    }
-
-  return cp_token_cache_new (first, last);
-}
-
-
-/******************************************************************* vectors */
-
-
-/* Read and return a gc VEC of trees from STREAM.  */
-
-static VEC(tree,gc) *
-pph_in_tree_vec (pph_stream *stream)
-{
-  HOST_WIDE_INT i, num;
-  VEC(tree,gc) *v;
-
-  num = pph_in_hwi (stream);
-  v = NULL;
-  for (i = 0; i < num; i++)
-    {
-      tree t = pph_in_tree (stream);
-      VEC_safe_push (tree, gc, v, t);
-    }
-
-  return v;
-}
-
-
-/* Read and return a gc VEC of qualified_typedef_usage_t from STREAM.  */
-
-static VEC(qualified_typedef_usage_t,gc) *
-pph_in_qual_use_vec (pph_stream *stream)
-{
-  unsigned i, num;
-  VEC(qualified_typedef_usage_t,gc) *v;
-
-  num = pph_in_uint (stream);
-  v = NULL;
-  for (i = 0; i < num; i++)
-    {
-      qualified_typedef_usage_t q;
-      q.typedef_decl = pph_in_tree (stream);
-      q.context = pph_in_tree (stream);
-      q.locus = pph_in_location (stream);
-      VEC_safe_push (qualified_typedef_usage_t, gc, v, &q);
-    }
-
-  return v;
-}
-
-
-/* Read the vector V of tree_pair_s instances from STREAM.  */
-
-static VEC(tree_pair_s,gc) *
-pph_in_tree_pair_vec (pph_stream *stream)
-{
-  unsigned i, num;
-  VEC(tree_pair_s,gc) *v;
-
-  num = pph_in_uint (stream);
-  for (i = 0, v = NULL; i < num; i++)
-    {
-      tree_pair_s p;
-      p.purpose = pph_in_tree (stream);
-      p.value = pph_in_tree (stream);
-      VEC_safe_push (tree_pair_s, gc, v, &p);
-    }
-
-  return v;
-}
-
-
-/* Test whether tree T is an element of vector V.  */
-
-static bool
-pph_is_tree_element_of_vec (tree t, VEC(tree,gc) *v)
-{
-  unsigned i;
-  tree s;
-  FOR_EACH_VEC_ELT (tree, v, i, s)
-    if (s == t)
-      return true;
-  return false;
-}
-
-
-/* Return the union of two tree vecs.  The argument vectors are unmodified.  */
-
-static VEC(tree,gc) *
-pph_union_two_tree_vecs (VEC(tree,gc) *left, VEC(tree,gc) *right)
-{
-  /* FIXME pph: This O(left)+O(left*right) union may become a problem.
-     In the long run, we probably want to copy both into a hash table
-     and then copy the table into the result.  */
-  unsigned i;
-  tree t;
-  VEC(tree,gc) *unioned = VEC_copy (tree, gc, left);
-  FOR_EACH_VEC_ELT (tree, right, i, t)
-    {
-      if (!pph_is_tree_element_of_vec (t, left))
-	VEC_safe_push (tree, gc, unioned, t);
-    }
-  return unioned;
-}
-
-
-/* Union FROM one tree vec with and INTO a tree vec.  The INTO argument will
-   have an updated value.  The FROM argument is no longer valid.  */
-
-static void
-pph_union_into_tree_vec (VEC(tree,gc) **into, VEC(tree,gc) *from)
-{
-  if (!VEC_empty (tree, from))
-    {
-      if (*into == NULL)
-	*into = from;
-      else if (VEC_empty (tree, *into))
-	{
-	  VEC_free (tree, gc, *into);
-	  *into = from;
-	}
-      else
-	{
-	  VEC(tree,gc) *unioned = pph_union_two_tree_vecs (*into, from);
-	  VEC_free (tree, gc, *into);
-	  VEC_free (tree, gc, from);
-	  *into = unioned;
-	}
-    }
-}
-
-
-/******************************************************************** chains */
-
-
-/* Read a chain of ASTs from STREAM.  */
-
-static tree
-pph_in_chain (pph_stream *stream)
-{
-  return streamer_read_chain (stream->encoder.r.ib, stream->encoder.r.data_in);
-}
-
-
-/* Read a chain of AST merge keys from STREAM.  Merge each tree
-   into *CHAIN.  */
-
-static void
-pph_in_merge_key_chain (pph_stream *stream, tree *chain)
-{
-  unsigned i;
-  HOST_WIDE_INT count;
-
-  count = pph_in_hwi (stream);
-  for (i = 0; i < count; i++)
-    pph_in_merge_key_tree (stream, chain);
-}
-
-
-/* Read a chain of AST merge bodies from STREAM.  */
-
-static void
-pph_in_merge_body_chain (pph_stream *stream)
-{
-  unsigned i;
-  HOST_WIDE_INT count;
-
-  count = pph_in_hwi (stream);
-  for (i = 0; i < count; i++)
-    pph_in_tree (stream);
-}
-
-
-/* Merge table of contents.  This TOC is used to decide whether a
-   symbol has already been merged into a given compilation context.
-   Compilation contexts are usually tree chains (e.g.,
-   scope_chain->bindings->names), but they can be any stable memory
-   address.
-
-   This TOC is indexed by two values: the merge key read by
-   pph_in_merge_key_tree and the context in which we are doing this
-   merge.  */
-static htab_t merge_toc = NULL;
-
-/* Table of contents entry.  */
-typedef struct {
-  /* Tree being matched.  */
-  tree expr;
-
-  /* Context where this tree should be inserted into.  */
-  tree *context;
-
-  /* Name of the tree (from pph_merge_name).  */
-  const char *name;
-} merge_toc_entry;
-
-
-/* Hash and equivalence functions for the merge TOC.  */
-
-static hashval_t
-htab_merge_key_hash (const void *p)
-{
-  const merge_toc_entry *key = (const merge_toc_entry *) p;
-  hashval_t context_val = htab_hash_pointer (key->context);
-  hashval_t name_val = htab_hash_string (key->name);
-  hashval_t id_val = iterative_hash_hashval_t (name_val, TREE_CODE (key->expr));
-  return iterative_hash_hashval_t (context_val, id_val);
-}
-
-static int
-htab_merge_key_eq (const void *p1, const void *p2)
-{
-  const merge_toc_entry *key1 = (const merge_toc_entry *) p1;
-  const merge_toc_entry *key2 = (const merge_toc_entry *) p2;
-
-  if (key1->context != key2->context)
-    return false;
-
-  if (TREE_CODE (key1->expr) != TREE_CODE (key2->expr))
-    return false;
-
-  if (key1->name == NULL || key2->name == NULL)
-    return false;
-
-  return strcmp (key1->name, key2->name) == 0;
-}
-
-
-/* Look in TOC for an existing tree matching KEY.  */
-
-static tree
-pph_toc_lookup (htab_t toc, merge_toc_entry *key)
-{
-  void *slot = htab_find (toc, key);
-  tree expr = NULL;
-
-  if (slot)
-    {
-      merge_toc_entry *e = (merge_toc_entry *) slot;
-      expr = e->expr;
-    }
-
-  return expr;
-}
-
-
-/* Insert KEY into TOC.  */
-
-static void
-pph_toc_add (htab_t toc, merge_toc_entry *key)
-{
-  void **slot;
-  merge_toc_entry *entry;
-
-  slot = htab_find_slot (toc, key, INSERT);
-  gcc_assert (*slot == NULL);
-
-  entry = XCNEW (merge_toc_entry);
-  memcpy (entry, key, sizeof (*key));
-  *slot = (void *) entry;
-}
-
-
-/* Prepend a tree EXPR to a CHAIN.  */
-
-static tree
-pph_prepend_to_chain (tree expr, tree *chain)
-{
-  DECL_CHAIN (expr) = *chain;
-  *chain = expr;
-  return expr;
-}
-
-
-/* Merge the just-read header for tree EXPR with NAME onto the CHAIN.  */
-
-static tree
-pph_merge_into_chain (tree expr, const char *name, tree *chain)
-{
-  merge_toc_entry key;
-  tree found;
-
-  key.expr = expr;
-  key.context = chain;
-  key.name = name;
-  found = pph_toc_lookup (merge_toc, &key);
-  if (!found)
-    {
-      pph_toc_add (merge_toc, &key);
-
-      if (flag_pph_debug >= 3)
-        fprintf (pph_logfile, "PPH: %s NOT found on chain\n", name);
-
-      /* Types (as opposed to type decls) are not on a chain.  */
-      if (chain)
-        return pph_prepend_to_chain (expr, chain);
-      else
-        return expr;
-    }
-
-  if (flag_pph_debug >= 3)
-    fprintf (pph_logfile, "PPH: %s FOUND on chain\n", name);
-
-  gcc_assert (TREE_CODE (found) == TREE_CODE (expr));
-
-  return found;
-}
-
-
-/****************************************************************** bindings */
-
-
-/* Forward declaration to break cyclic dependencies.  */
-static cp_binding_level *pph_in_binding_level (pph_stream *);
-
-/* Helper for pph_in_cxx_binding.  Read and return a cxx_binding
-   instance from STREAM.  */
-
-static cxx_binding *
-pph_in_cxx_binding_1 (pph_stream *stream)
-{
-  struct bitpack_d bp;
-  cxx_binding *cb;
-  tree value, type;
-  enum pph_record_marker marker;
-  unsigned ix, image_ix;
-
-  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cxx_binding);
-  if (marker == PPH_RECORD_END)
-    return NULL;
-  else if (pph_is_reference_marker (marker))
-    return (cxx_binding *) pph_cache_find (stream, marker, image_ix, ix,
-					   PPH_cxx_binding);
-
-  value = pph_in_tree (stream);
-  type = pph_in_tree (stream);
-  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cxx_binding, cb,
-                      cxx_binding_make (value, type));
-  cb->scope = pph_in_binding_level (stream);
-  bp = pph_in_bitpack (stream);
-  cb->value_is_inherited = bp_unpack_value (&bp, 1);
-  cb->is_local = bp_unpack_value (&bp, 1);
-
-  return cb;
-}
-
-
-/* Read and return an instance of cxx_binding from STREAM.  */
-
-static cxx_binding *
-pph_in_cxx_binding (pph_stream *stream)
-{
-  cxx_binding *curr, *prev, *cb;
-
-  /* Read the current binding first.  */
-  cb = pph_in_cxx_binding_1 (stream);
-
-  /* Read the list of previous bindings.  */
-  for (curr = cb; curr; curr = prev)
-    {
-      prev = pph_in_cxx_binding_1 (stream);
-      curr->previous = prev;
-    }
-
-  return cb;
-}
-
-
-/* Read all the fields of cp_class_binding instance CB to STREAM.  */
-
-static cp_class_binding *
-pph_in_class_binding (pph_stream *stream)
-{
-  cp_class_binding *cb;
-  enum pph_record_marker marker;
-  unsigned image_ix, ix;
-
-  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cp_class_binding);
-  if (marker == PPH_RECORD_END)
-    return NULL;
-  else if (pph_is_reference_marker (marker))
-    return (cp_class_binding *) pph_cache_find (stream, marker, image_ix, ix,
-						PPH_cp_class_binding);
-
-  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cp_class_binding, cb,
-                      ggc_alloc_cleared_cp_class_binding ());
-  cb->base = pph_in_cxx_binding (stream);
-  cb->identifier = pph_in_tree (stream);
-
-  return cb;
-}
-
-
-/* Read and return an instance of cp_label_binding from STREAM.  */
-
-static cp_label_binding *
-pph_in_label_binding (pph_stream *stream)
-{
-  cp_label_binding *lb;
-  enum pph_record_marker marker;
-  unsigned image_ix, ix;
-
-  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cp_label_binding);
-  if (marker == PPH_RECORD_END)
-    return NULL;
-  else if (pph_is_reference_marker (marker))
-    return (cp_label_binding *) pph_cache_find (stream, marker, image_ix, ix,
-						PPH_cp_label_binding);
-
-  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cp_label_binding, lb,
-                      ggc_alloc_cleared_cp_label_binding ());
-  lb->label = pph_in_tree (stream);
-  lb->prev_value = pph_in_tree (stream);
-
-  return lb;
-}
-
-
-/* Read the contents of binding level BL from STREAM.  */
-
-static void
-pph_in_binding_level_1 (pph_stream *stream, cp_binding_level *bl)
-{
-  unsigned i, num;
-  struct bitpack_d bp;
-
-  bl->this_entity = pph_in_tree (stream);
-
-  num = pph_in_uint (stream);
-  bl->class_shadowed = NULL;
-  for (i = 0; i < num; i++)
-    {
-      cp_class_binding *cb = pph_in_class_binding (stream);
-      VEC_safe_push (cp_class_binding, gc, bl->class_shadowed, cb);
-    }
-
-  bl->type_shadowed = pph_in_tree (stream);
-
-  num = pph_in_uint (stream);
-  bl->shadowed_labels = NULL;
-  for (i = 0; i < num; i++)
-    {
-      cp_label_binding *sl = pph_in_label_binding (stream);
-      VEC_safe_push (cp_label_binding, gc, bl->shadowed_labels, sl);
-    }
-
-  bl->blocks = pph_in_tree (stream);
-  bl->level_chain = pph_in_binding_level (stream);
-  bl->dead_vars_from_for = pph_in_tree_vec (stream);
-  bl->statement_list = pph_in_chain (stream);
-  bl->binding_depth = pph_in_uint (stream);
-
-  bp = pph_in_bitpack (stream);
-  bl->kind = (enum scope_kind) bp_unpack_value (&bp, 4);
-  bl->keep = bp_unpack_value (&bp, 1);
-  bl->more_cleanups_ok = bp_unpack_value (&bp, 1);
-  bl->have_cleanups = bp_unpack_value (&bp, 1);
-}
-
-
-/* Read the start of a binding level.  Return true when processing is done.  */
-
-static bool
-pph_in_binding_level_start (pph_stream *stream, cp_binding_level **blp,
-			    unsigned *ixp)
-{
-  unsigned image_ix;
-  enum pph_record_marker marker;
-
-  marker = pph_in_start_record (stream, &image_ix, ixp, PPH_cp_binding_level);
-  if (marker == PPH_RECORD_END)
-    {
-      *blp = NULL;
-      return true;
-    }
-  else if (pph_is_reference_marker (marker))
-    {
-      *blp = (cp_binding_level *)
-          pph_cache_find (stream, marker, image_ix, *ixp, PPH_cp_binding_level);
-      return true;
-    }
-  return false;
-}
-
-
-/* Read and return an instance of cp_binding_level from STREAM.
-   This function is for use when we will not be merging the binding level.  */
-
-static cp_binding_level *
-pph_in_binding_level (pph_stream *stream)
-{
-  unsigned ix;
-  cp_binding_level *bl;
-
-  if (pph_in_binding_level_start (stream, &bl, &ix))
-    return bl;
-
-  bl = ggc_alloc_cleared_cp_binding_level ();
-  pph_cache_insert_at (&stream->cache, bl, ix, PPH_cp_binding_level);
-
-  bl->names = pph_in_chain (stream);
-  bl->namespaces = pph_in_chain (stream);
-  bl->usings = pph_in_chain (stream);
-  bl->using_directives = pph_in_chain (stream);
-  bl->static_decls = pph_in_tree_vec (stream);
-  pph_in_binding_level_1 (stream, bl);
-
-  return bl;
-}
-
-
-/* Read all the merge keys from STREAM into the cp_binding_level BL.  */
-
-static void
-pph_in_binding_merge_keys (pph_stream *stream, cp_binding_level *bl)
-{
-  /* Read all the merge keys and merge into the bindings.  */
-  pph_in_merge_key_chain (stream, &bl->names);
-  pph_in_merge_key_chain (stream, &bl->namespaces);
-  pph_in_merge_key_chain (stream, &bl->usings);
-  pph_in_merge_key_chain (stream, &bl->using_directives);
-}
-
-
-/* Read all the merge bodies from STREAM into the cp_binding_level BL.  */
-
-static void
-pph_in_binding_merge_bodies_1 (pph_stream *stream, cp_binding_level *bl)
-{
-  pph_in_merge_body_chain (stream);
-  pph_in_merge_body_chain (stream);
-  pph_in_merge_body_chain (stream);
-  pph_in_merge_body_chain (stream);
-  pph_union_into_tree_vec (&bl->static_decls, pph_in_tree_vec (stream));
-  /* FIXME pph: The following is probably too aggressive in overwriting.  */
-  pph_in_binding_level_1 (stream, bl);
-}
-
-
-/* Read all the merge bodies from STREAM into the cp_binding_level BL.  */
-
-static void
-pph_in_binding_merge_bodies (pph_stream *stream, cp_binding_level *bl)
-{
-  unsigned ix;
-  cp_binding_level *new_bl;
-
-  if (pph_in_binding_level_start (stream, &new_bl, &ix))
-    {
-      gcc_assert (new_bl == bl);
-      return;
-    }
-
-  /* The binding level is already allocated.  */
-  pph_cache_insert_at (&stream->cache, bl, ix, PPH_cp_binding_level);
-  pph_in_binding_merge_bodies_1 (stream, bl);
-}
-
-
-/********************************************************** tree aux classes */
-
-
-/* Read and return an instance of struct language_function from STREAM.  */
-
-static struct language_function *
-pph_in_language_function (pph_stream *stream)
-{
-  struct bitpack_d bp;
-  struct language_function *lf;
-  enum pph_record_marker marker;
-  unsigned image_ix, ix;
-
-  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_language_function);
-  if (marker == PPH_RECORD_END)
-    return NULL;
-  else if (pph_is_reference_marker (marker))
-    return (struct language_function *) pph_cache_find (stream, marker,
-							image_ix, ix,
-							PPH_language_function);
-
-  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_language_function, lf,
-                      ggc_alloc_cleared_language_function ());
-  lf->base.x_stmt_tree.x_cur_stmt_list = pph_in_tree_vec (stream);
-  lf->base.x_stmt_tree.stmts_are_full_exprs_p = pph_in_uint (stream);
-  lf->x_cdtor_label = pph_in_tree (stream);
-  lf->x_current_class_ptr = pph_in_tree (stream);
-  lf->x_current_class_ref = pph_in_tree (stream);
-  lf->x_eh_spec_block = pph_in_tree (stream);
-  lf->x_in_charge_parm = pph_in_tree (stream);
-  lf->x_vtt_parm = pph_in_tree (stream);
-  lf->x_return_value = pph_in_tree (stream);
-  bp = pph_in_bitpack (stream);
-  lf->returns_value = bp_unpack_value (&bp, 1);
-  lf->returns_null = bp_unpack_value (&bp, 1);
-  lf->returns_abnormally = bp_unpack_value (&bp, 1);
-  lf->x_in_function_try_handler = bp_unpack_value (&bp, 1);
-  lf->x_in_base_initializer = bp_unpack_value (&bp, 1);
-  lf->can_throw = bp_unpack_value (&bp, 1);
-
-  /* FIXME pph.  We are not reading lf->x_named_labels.  */
-
-  lf->bindings = pph_in_binding_level (stream);
-  lf->x_local_names = pph_in_tree_vec (stream);
-
-  /* FIXME pph.  We are not reading lf->extern_decl_map.  */
-
-  return lf;
-}
-
-
-/* Read applicable fields of struct function from STREAM.  Associate
-   the read structure to DECL.  */
-
-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 t;
-
-  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_function);
-  if (marker == PPH_RECORD_END)
-    return;
-  else if (pph_is_reference_marker (marker))
-    {
-      fn = (struct function *) pph_cache_find (stream, marker, image_ix, ix,
-					       PPH_function);
-      gcc_assert (DECL_STRUCT_FUNCTION (decl) == fn);
-      return;
-    }
-
-  /* Possibly allocate a new DECL_STRUCT_FUNCTION for DECL.  */
-  t = pph_in_tree (stream);
-  gcc_assert (t == decl);
-  fn = DECL_STRUCT_FUNCTION (decl);
-  if (!fn)
-    {
-      /* The DECL_STRUCT_FUNCTION does not already already exists,
-         which implies that we are reading an entirely new function
-         and not merging into an existing function.  */
-      /* We would normally use ALLOC_AND_REGISTER,
-         but allocate_struct_function does not return a pointer.  */
-      allocate_struct_function (decl, false);
-      fn = DECL_STRUCT_FUNCTION (decl);
-    }
-
-  /* Now register it.  */
-  pph_cache_insert_at (&stream->cache, fn, ix, PPH_function);
-
-  /* FIXME pph: For now, accept the new version of the fields when merging.  */
-
-  input_struct_function_base (fn, stream->encoder.r.data_in,
-			      stream->encoder.r.ib);
-
-  /* struct eh_status *eh;					-- zero init */
-  /* struct control_flow_graph *cfg;				-- zero init */
-  /* struct gimple_seq_d *gimple_body;				-- zero init */
-  /* struct gimple_df *gimple_df;				-- zero init */
-  /* struct loops *x_current_loops;				-- zero init */
-  /* struct stack_usage *su;					-- zero init */
-  /* htab_t value_histograms;					-- zero init */
-  /* tree decl;							-- zero init */
-  /* tree static_chain_decl;					-- in base */
-  /* tree nonlocal_goto_save_area;				-- in base */
-  /* tree local_decls;						-- in base */
-  /* struct machine_function * machine;				-- zero init */
-
-  fn->language = pph_in_language_function (stream);
-
-  count = pph_in_uint (stream);
-  if ( count > 0 )
-    {
-      fn->used_types_hash = htab_create_ggc (37, htab_hash_pointer,
-					     htab_eq_pointer, NULL);
-      for (i = 0; i < count;  i++)
-	{
-	  void **slot;
-	  tree type = pph_in_tree (stream);
-	  slot = htab_find_slot (fn->used_types_hash, type, INSERT);
-	  if (*slot == NULL)
-	    *slot = type;
-	}
-    }
-  /* else zero initialized */
-
-  /* int last_stmt_uid;						-- zero init */
-  /* int funcdef_no;						-- zero init */
-  /* location_t function_start_locus;				-- in base */
-  /* location_t function_end_locus;				-- in base */
-  /* unsigned int curr_properties;				-- in base */
-  /* unsigned int last_verified;				-- zero init */
-  /* const char *cannot_be_copied_reason;			-- zero init */
-
-  /* unsigned int va_list_gpr_size : 8;				-- in base */
-  /* unsigned int va_list_fpr_size : 8;				-- in base */
-  /* unsigned int calls_setjmp : 1;				-- in base */
-  /* unsigned int calls_alloca : 1;				-- in base */
-  /* unsigned int has_nonlocal_label : 1;			-- in base */
-  /* unsigned int cannot_be_copied_set : 1;			-- zero init */
-  /* unsigned int stdarg : 1;					-- in base */
-  /* unsigned int after_inlining : 1;				-- in base */
-  /* unsigned int always_inline_functions_inlined : 1;		-- in base */
-  /* unsigned int can_throw_non_call_exceptions : 1;		-- in base */
-  /* unsigned int returns_struct : 1;				-- in base */
-  /* unsigned int returns_pcc_struct : 1;			-- in base */
-  /* 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 */
-}
-
-
-/* Read all fields in lang_decl_base instance LDB from STREAM.  */
-
-static void
-pph_in_ld_base (pph_stream *stream, struct lang_decl_base *ldb)
-{
-  struct bitpack_d bp;
-
-  bp = pph_in_bitpack (stream);
-  ldb->selector = bp_unpack_value (&bp, 16);
-  ldb->language = (enum languages) bp_unpack_value (&bp, 4);
-  ldb->use_template = bp_unpack_value (&bp, 2);
-  ldb->not_really_extern = bp_unpack_value (&bp, 1);
-  ldb->initialized_in_class = bp_unpack_value (&bp, 1);
-  ldb->repo_available_p = bp_unpack_value (&bp, 1);
-  ldb->threadprivate_or_deleted_p = bp_unpack_value (&bp, 1);
-  ldb->anticipated_p = bp_unpack_value (&bp, 1);
-  ldb->friend_attr = bp_unpack_value (&bp, 1);
-  ldb->template_conv_p = bp_unpack_value (&bp, 1);
-  ldb->odr_used = bp_unpack_value (&bp, 1);
-  ldb->u2sel = bp_unpack_value (&bp, 1);
-}
-
-
-/* Read all the fields in lang_decl_min instance LDM from STREAM.  */
-
-static void
-pph_in_ld_min (pph_stream *stream, struct lang_decl_min *ldm)
-{
-  ldm->template_info = pph_in_tree (stream);
-  if (ldm->base.u2sel == 0)
-    ldm->u2.access = pph_in_tree (stream);
-  else if (ldm->base.u2sel == 1)
-    ldm->u2.discriminator = pph_in_uint (stream);
-  else
-    gcc_unreachable ();
-}
-
-
-/* Read all the fields of lang_decl_fn instance LDF from STREAM.  */
-
-static void
-pph_in_ld_fn (pph_stream *stream, struct lang_decl_fn *ldf)
-{
-  struct bitpack_d bp;
-
-  /* Read all the fields in lang_decl_min.  */
-  pph_in_ld_min (stream, &ldf->min);
-
-  bp = pph_in_bitpack (stream);
-  ldf->operator_code = (enum tree_code) bp_unpack_value (&bp, 16);
-  ldf->global_ctor_p = bp_unpack_value (&bp, 1);
-  ldf->global_dtor_p = bp_unpack_value (&bp, 1);
-  ldf->constructor_attr = bp_unpack_value (&bp, 1);
-  ldf->destructor_attr = bp_unpack_value (&bp, 1);
-  ldf->assignment_operator_p = bp_unpack_value (&bp, 1);
-  ldf->static_function = bp_unpack_value (&bp, 1);
-  ldf->pure_virtual = bp_unpack_value (&bp, 1);
-  ldf->defaulted_p = bp_unpack_value (&bp, 1);
-  ldf->has_in_charge_parm_p = bp_unpack_value (&bp, 1);
-  ldf->has_vtt_parm_p = bp_unpack_value (&bp, 1);
-  ldf->pending_inline_p = bp_unpack_value (&bp, 1);
-  ldf->nonconverting = bp_unpack_value (&bp, 1);
-  ldf->thunk_p = bp_unpack_value (&bp, 1);
-  ldf->this_thunk_p = bp_unpack_value (&bp, 1);
-  ldf->hidden_friend_p = bp_unpack_value (&bp, 1);
-
-  ldf->befriending_classes = pph_in_tree (stream);
-  ldf->context = pph_in_tree (stream);
-
-  if (ldf->thunk_p == 0)
-    ldf->u5.cloned_function = pph_in_tree (stream);
-  else if (ldf->thunk_p == 1)
-    ldf->u5.fixed_offset = pph_in_uint (stream);
-  else
-    gcc_unreachable ();
-
-  if (ldf->pending_inline_p == 1)
-    ldf->u.pending_inline_info = pph_in_token_cache (stream);
-  else if (ldf->pending_inline_p == 0)
-    ldf->u.saved_language_function = pph_in_language_function (stream);
-}
-
-
-/* Read all the fields of lang_decl_ns instance LDNS from STREAM.  */
-
-static void
-pph_in_ld_ns (pph_stream *stream, struct lang_decl_ns *ldns)
-{
-  if (ldns->level == NULL)
-    ldns->level = pph_in_binding_level (stream);
-  else
-    pph_in_binding_merge_bodies (stream, ldns->level);
-}
-
-
-/* Read all the fields of lang_decl_parm instance LDP from STREAM.  */
-
-static void
-pph_in_ld_parm (pph_stream *stream, struct lang_decl_parm *ldp)
-{
-  ldp->level = pph_in_uint (stream);
-  ldp->index = pph_in_uint (stream);
-}
-
-
-/* Read language specific data in DECL from STREAM.  */
-
-static void
-pph_in_lang_specific (pph_stream *stream, tree decl)
-{
-  struct lang_decl *ld;
-  struct lang_decl_base *ldb;
-  enum pph_record_marker marker;
-  unsigned image_ix, ix;
-
-  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_lang_decl);
-  if (marker == PPH_RECORD_END)
-    return;
-  else if (pph_is_reference_marker (marker))
-    {
-      DECL_LANG_SPECIFIC (decl) =
-	(struct lang_decl *) pph_cache_find (stream, marker, image_ix, ix,
-					     PPH_lang_decl);
-      return;
-    }
-
-  /* Allocate a lang_decl structure for DECL, if not already present.
-     Namespace merge keys preallocate it.  */
-  ld = DECL_LANG_SPECIFIC (decl);
-  if (!ld)
-    {
-      retrofit_lang_decl (decl);
-      ld = DECL_LANG_SPECIFIC (decl);
-    }
-
-  /* Now register it.  We would normally use ALLOC_AND_REGISTER,
-     but retrofit_lang_decl does not return a pointer.  */
-  pph_cache_insert_at (&stream->cache, ld, ix, PPH_lang_decl);
-
-  /* Read all the fields in lang_decl_base.  */
-  ldb = &ld->u.base;
-  pph_in_ld_base (stream, ldb);
-
-  if (ldb->selector == 0)
-    {
-      /* Read all the fields in lang_decl_min.  */
-      pph_in_ld_min (stream, &ld->u.min);
-    }
-  else if (ldb->selector == 1)
-    {
-      /* Read all the fields in lang_decl_fn.  */
-      pph_in_ld_fn (stream, &ld->u.fn);
-    }
-  else if (ldb->selector == 2)
-    {
-      /* Read all the fields in lang_decl_ns.  */
-      pph_in_ld_ns (stream, &ld->u.ns);
-    }
-  else if (ldb->selector == 3)
-    {
-      /* Read all the fields in lang_decl_parm.  */
-      pph_in_ld_parm (stream, &ld->u.parm);
-    }
-  else
-    gcc_unreachable ();
-}
-
-
-/********************************************************* tree base classes */
-
-
-/* Read in the tree_common fields.  */
-
-static void
-pph_in_tree_common (pph_stream *stream, tree t)
-{
-  /* The 'struct tree_typed typed' base class is handled in LTO.  */
-  TREE_CHAIN (t) = pph_in_tree (stream);
-}
-
-
-/* Read all the fields in lang_type_header instance LTH from STREAM.  */
-
-static void
-pph_in_lang_type_header (pph_stream *stream, struct lang_type_header *lth)
-{
-  struct bitpack_d bp;
-
-  bp = pph_in_bitpack (stream);
-  lth->is_lang_type_class = bp_unpack_value (&bp, 1);
-  lth->has_type_conversion = bp_unpack_value (&bp, 1);
-  lth->has_copy_ctor = bp_unpack_value (&bp, 1);
-  lth->has_default_ctor = bp_unpack_value (&bp, 1);
-  lth->const_needs_init = bp_unpack_value (&bp, 1);
-  lth->ref_needs_init = bp_unpack_value (&bp, 1);
-  lth->has_const_copy_assign = bp_unpack_value (&bp, 1);
-}
-
-
-/* Read a struct sorted_fields_type instance SFT to STREAM.  */
-
-static struct sorted_fields_type *
-pph_in_sorted_fields_type (pph_stream *stream)
-{
-  unsigned i, num_fields;
-  struct sorted_fields_type *v;
-  enum pph_record_marker marker;
-  unsigned image_ix, ix;
-
-  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_sorted_fields_type);
-  if (marker == PPH_RECORD_END)
-    return NULL;
-  else if (pph_is_reference_marker (marker))
-    return (struct sorted_fields_type *)
-	  pph_cache_find (stream, marker, image_ix, ix, PPH_sorted_fields_type);
-
-  num_fields = pph_in_uint (stream);
-  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_sorted_fields_type, v,
-                      sorted_fields_type_new (num_fields));
-  for (i = 0; i < num_fields; i++)
-    v->elts[i] = pph_in_tree (stream);
-
-  return v;
-}
-
-
-/* Read all the fields in lang_type_class instance LTC to STREAM.  */
-
-static void
-pph_in_lang_type_class (pph_stream *stream, struct lang_type_class *ltc)
-{
-  struct bitpack_d bp;
-  enum pph_record_marker marker;
-  unsigned image_ix, ix;
-
-  ltc->align = pph_in_uchar (stream);
-
-  bp = pph_in_bitpack (stream);
-  ltc->has_mutable = bp_unpack_value (&bp, 1);
-  ltc->com_interface = bp_unpack_value (&bp, 1);
-  ltc->non_pod_class = bp_unpack_value (&bp, 1);
-  ltc->nearly_empty_p = bp_unpack_value (&bp, 1);
-  ltc->user_align = bp_unpack_value (&bp, 1);
-  ltc->has_copy_assign = bp_unpack_value (&bp, 1);
-  ltc->has_new = bp_unpack_value (&bp, 1);
-  ltc->has_array_new = bp_unpack_value (&bp, 1);
-  ltc->gets_delete = bp_unpack_value (&bp, 2);
-  ltc->interface_only = bp_unpack_value (&bp, 1);
-  ltc->interface_unknown = bp_unpack_value (&bp, 1);
-  ltc->contains_empty_class_p = bp_unpack_value (&bp, 1);
-  ltc->anon_aggr = bp_unpack_value (&bp, 1);
-  ltc->non_zero_init = bp_unpack_value (&bp, 1);
-  ltc->empty_p = bp_unpack_value (&bp, 1);
-  ltc->vec_new_uses_cookie = bp_unpack_value (&bp, 1);
-  ltc->declared_class = bp_unpack_value (&bp, 1);
-  ltc->diamond_shaped = bp_unpack_value (&bp, 1);
-  ltc->repeated_base = bp_unpack_value (&bp, 1);
-  ltc->being_defined = bp_unpack_value (&bp, 1);
-  ltc->java_interface = bp_unpack_value (&bp, 1);
-  ltc->debug_requested = bp_unpack_value (&bp, 1);
-  ltc->fields_readonly = bp_unpack_value (&bp, 1);
-  ltc->use_template = bp_unpack_value (&bp, 2);
-  ltc->ptrmemfunc_flag = bp_unpack_value (&bp, 1);
-  ltc->was_anonymous = bp_unpack_value (&bp, 1);
-  ltc->lazy_default_ctor = bp_unpack_value (&bp, 1);
-  ltc->lazy_copy_ctor = bp_unpack_value (&bp, 1);
-  ltc->lazy_copy_assign = bp_unpack_value (&bp, 1);
-  ltc->lazy_destructor = bp_unpack_value (&bp, 1);
-  ltc->has_const_copy_ctor = bp_unpack_value (&bp, 1);
-  ltc->has_complex_copy_ctor = bp_unpack_value (&bp, 1);
-  ltc->has_complex_copy_assign = bp_unpack_value (&bp, 1);
-  ltc->non_aggregate = bp_unpack_value (&bp, 1);
-  ltc->has_complex_dflt = bp_unpack_value (&bp, 1);
-  ltc->has_list_ctor = bp_unpack_value (&bp, 1);
-  ltc->non_std_layout = bp_unpack_value (&bp, 1);
-  ltc->is_literal = bp_unpack_value (&bp, 1);
-  ltc->lazy_move_ctor = bp_unpack_value (&bp, 1);
-  ltc->lazy_move_assign = bp_unpack_value (&bp, 1);
-  ltc->has_complex_move_ctor = bp_unpack_value (&bp, 1);
-  ltc->has_complex_move_assign = bp_unpack_value (&bp, 1);
-  ltc->has_constexpr_ctor = bp_unpack_value (&bp, 1);
-
-  ltc->primary_base = pph_in_tree (stream);
-  ltc->vcall_indices = pph_in_tree_pair_vec (stream);
-  ltc->vtables = pph_in_tree (stream);
-  ltc->typeinfo_var = pph_in_tree (stream);
-  ltc->vbases = pph_in_tree_vec (stream);
-
-  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_binding_table);
-  if (marker == PPH_RECORD_START)
-    {
-      ltc->nested_udts = pph_in_binding_table (stream);
-      pph_cache_insert_at (&stream->cache, ltc->nested_udts, ix,
-                           PPH_binding_table);
-    }
-  else if (pph_is_reference_marker (marker))
-    ltc->nested_udts = (binding_table) pph_cache_find (stream, marker,
-						       image_ix, ix,
-						       PPH_binding_table);
-
-  ltc->as_base = pph_in_tree (stream);
-  ltc->pure_virtuals = pph_in_tree_vec (stream);
-  ltc->friend_classes = pph_in_tree (stream);
-  ltc->methods = pph_in_tree_vec (stream);
-  ltc->key_method = pph_in_tree (stream);
-  ltc->decl_list = pph_in_tree (stream);
-  ltc->template_info = pph_in_tree (stream);
-  ltc->befriending_classes = pph_in_tree (stream);
-  ltc->objc_info = pph_in_tree (stream);
-  ltc->sorted_fields = pph_in_sorted_fields_type (stream);
-  ltc->lambda_expr = pph_in_tree (stream);
-}
-
-
-/* Read all fields of struct lang_type_ptrmem instance LTP from STREAM.  */
-
-static void
-pph_in_lang_type_ptrmem (pph_stream *stream,
-				  struct lang_type_ptrmem *ltp)
-{
-  ltp->record = pph_in_tree (stream);
-}
-
-
-/* Read all the fields in struct lang_type from STREAM.  */
-
-static struct lang_type *
-pph_in_lang_type (pph_stream *stream)
-{
-  struct lang_type *lt;
-  enum pph_record_marker marker;
-  unsigned image_ix, ix;
-
-  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_lang_type);
-  if (marker == PPH_RECORD_END)
-    return NULL;
-  else if (pph_is_reference_marker (marker))
-    return (struct lang_type *) pph_cache_find (stream, marker, image_ix, ix,
-						PPH_lang_type);
-
-  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_lang_type, lt,
-                      ggc_alloc_cleared_lang_type (sizeof (struct lang_type)));
-
-  pph_in_lang_type_header (stream, &lt->u.h);
-  if (lt->u.h.is_lang_type_class)
-    pph_in_lang_type_class (stream, &lt->u.c);
-  else
-    pph_in_lang_type_ptrmem (stream, &lt->u.ptrmem);
-
-  return lt;
-}
-
-
-/* Read from STREAM the body of tcc_type node TYPE.  */
-
-static void
-pph_in_tcc_type (pph_stream *stream, tree type)
-{
-  TYPE_LANG_SPECIFIC (type) = pph_in_lang_type (stream);
-  TYPE_POINTER_TO (type) = pph_in_tree (stream);
-  TYPE_REFERENCE_TO (type) = pph_in_tree (stream);
-  TYPE_NEXT_VARIANT (type) = pph_in_tree (stream);
-  /* FIXME pph - Streaming TYPE_CANONICAL generates many type comparison
-     failures.  Why?  */
-  /* FIXME pph: apparently redundant.  */
-  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
-     other purposes.  */
-  switch (TREE_CODE (type))
-    {
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
-    case DECLTYPE_TYPE:
-    case TEMPLATE_TEMPLATE_PARM:
-    case TEMPLATE_TYPE_PARM:
-    case TYPENAME_TYPE:
-    case TYPEOF_TYPE:
-      TYPE_VALUES_RAW (type) = pph_in_tree (stream);
-      break;
-
-    default:
-      break;
-    }
-
-  /* If TYPE has a METHOD_VEC, we need to resort it.  Name lookup in
-     classes relies on the specific ordering of the class method
-     pointers.  Since we generally instantiate them in a different
-     order than the original compile, the pointer values will be
-     different.  This will cause name lookups to fail, unless we
-     resort the vector.  */
-  if (CLASS_TYPE_P (type) && CLASSTYPE_METHOD_VEC (type))
-    finish_struct_methods (type);
-}
-
-
-/* Read from STREAM the body of tcc_declaration tree DECL.  */
-
-static void
-pph_in_tcc_declaration (pph_stream *stream, tree decl)
-{
-  pph_in_lang_specific (stream, decl);
-  DECL_INITIAL (decl) = pph_in_tree (stream);
-
-  /* The tree streamer only writes DECL_CHAIN for PARM_DECL nodes.
-     We need to read DECL_CHAIN for variables and functions because
-     they are sometimes chained together in places other than regular
-     tree chains.  For example in BINFO_VTABLEs, the decls are chained
-     together).  */
-  if (TREE_CODE (decl) == VAR_DECL
-      || TREE_CODE (decl) == FUNCTION_DECL)
-    DECL_CHAIN (decl) = pph_in_tree (stream);
-
-  /* Handle some individual decl nodes.  */
-  switch (TREE_CODE (decl))
-    {
-    case FUNCTION_DECL:
-      DECL_SAVED_TREE (decl) = pph_in_tree (stream);
-      break;
-
-    case TYPE_DECL:
-      DECL_ORIGINAL_TYPE (decl) = pph_in_tree (stream);
-      break;
-
-    case TEMPLATE_DECL:
-      DECL_TEMPLATE_RESULT (decl) = pph_in_tree (stream);
-      DECL_TEMPLATE_PARMS (decl) = pph_in_tree (stream);
-      break;
-
-    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;
-    }
-}
-
-
-/******************************************************** tree head and body */
-
-
-/* Read the body fields of EXPR from STREAM.  */
-
-static void
-pph_in_tree_body (pph_stream *stream, tree expr)
-{
-  struct lto_input_block *ib = stream->encoder.r.ib;
-  struct data_in *data_in = stream->encoder.r.data_in;
-  bool handled_p;
-
-  /* Read the language-independent parts of EXPR's body.  */
-  streamer_read_tree_body (ib, data_in, expr);
-
-  /* Handle common tree code classes first.  */
-  handled_p = true;
-  switch (TREE_CODE_CLASS (TREE_CODE (expr)))
-    {
-      case tcc_declaration:
-	pph_in_tcc_declaration (stream, expr);
-	break;
-
-      case tcc_type:
-	pph_in_tcc_type (stream, expr);
-	break;
-
-      case tcc_constant:
-	if (TREE_CODE (expr) == PTRMEM_CST)
-	  {
-	    pph_in_tree_common (stream, expr);
-	    PTRMEM_CST_MEMBER (expr) = pph_in_tree (stream);
-	  }
-	break;
-
-      case tcc_expression:
-      case tcc_unary:
-      case tcc_binary:
-      case tcc_vl_exp:
-      case tcc_reference:
-      case tcc_comparison:
-      case tcc_statement:
-	/* These tree classes are completely handled by the tree streamer.  */
-	break;
-
-      default:
-	handled_p = false;
-	break;
-    }
-
-  /* If we've already handled the tree, we are done.  */
-  if (handled_p)
-    return;
-
-  /* Only tcc_exceptional tree codes are left to handle.  */
-  gcc_assert (TREE_CODE_CLASS (TREE_CODE (expr)) == tcc_exceptional);
-
-  switch (TREE_CODE (expr))
-    {
-    case STATEMENT_LIST:
-      {
-        HOST_WIDE_INT i, num_trees = pph_in_uint (stream);
-        for (i = 0; i < num_trees; i++)
-	  {
-	    tree stmt = pph_in_tree (stream);
-	    append_to_statement_list_force (stmt, &expr);
-	  }
-      }
-      break;
-
-    case OVERLOAD:
-      pph_in_tree_common (stream, expr);
-      OVL_FUNCTION (expr) = pph_in_tree (stream);
-      break;
-
-    case IDENTIFIER_NODE:
-      if (flag_pph_debug >= 3)
-	fprintf (pph_logfile, "in identifier %s\n", IDENTIFIER_POINTER (expr));
-      IDENTIFIER_NAMESPACE_BINDINGS (expr) = pph_in_cxx_binding (stream);
-      IDENTIFIER_BINDING (expr) = pph_in_cxx_binding (stream);
-      IDENTIFIER_TEMPLATE (expr) = pph_in_tree (stream);
-      IDENTIFIER_LABEL_VALUE (expr) = pph_in_tree (stream);
-      REAL_IDENTIFIER_TYPE_VALUE (expr) = pph_in_tree (stream);
-      break;
-
-    case BASELINK:
-      pph_in_tree_common (stream, expr);
-      BASELINK_BINFO (expr) = pph_in_tree (stream);
-      BASELINK_FUNCTIONS (expr) = pph_in_tree (stream);
-      BASELINK_ACCESS_BINFO (expr) = pph_in_tree (stream);
-      break;
-
-    case TEMPLATE_INFO:
-      pph_in_tree_common (stream, expr);
-      TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (expr)
-          = pph_in_qual_use_vec (stream);
-      break;
-
-    case DEFAULT_ARG:
-      pph_in_tree_common (stream, expr);
-      DEFARG_TOKENS (expr) = pph_in_token_cache (stream);
-      DEFARG_INSTANTIATIONS (expr) = pph_in_tree_vec (stream);
-      break;
-
-    case STATIC_ASSERT:
-      pph_in_tree_common (stream, expr);
-      STATIC_ASSERT_CONDITION (expr) = pph_in_tree (stream);
-      STATIC_ASSERT_MESSAGE (expr) = pph_in_tree (stream);
-      STATIC_ASSERT_SOURCE_LOCATION (expr) = pph_in_location (stream);
-      break;
-
-    case ARGUMENT_PACK_SELECT:
-      pph_in_tree_common (stream, expr);
-      ARGUMENT_PACK_SELECT_FROM_PACK (expr) = pph_in_tree (stream);
-      ARGUMENT_PACK_SELECT_INDEX (expr) = pph_in_uint (stream);
-      break;
-
-    case TRAIT_EXPR:
-      pph_in_tree_common (stream, expr);
-      TRAIT_EXPR_TYPE1 (expr) = pph_in_tree (stream);
-      TRAIT_EXPR_TYPE2 (expr) = pph_in_tree (stream);
-      TRAIT_EXPR_KIND (expr) = (enum cp_trait_kind) pph_in_uint (stream);
-      break;
-
-    case LAMBDA_EXPR:
-      pph_in_tree_common (stream, expr);
-      LAMBDA_EXPR_LOCATION (expr) = pph_in_location (stream);
-      LAMBDA_EXPR_CAPTURE_LIST (expr) = pph_in_tree (stream);
-      LAMBDA_EXPR_THIS_CAPTURE (expr) = pph_in_tree (stream);
-      LAMBDA_EXPR_RETURN_TYPE (expr) = pph_in_tree (stream);
-      LAMBDA_EXPR_EXTRA_SCOPE (expr) = pph_in_tree (stream);
-      LAMBDA_EXPR_DISCRIMINATOR (expr) = pph_in_uint (stream);
-      break;
-
-    case TREE_VEC:
-      /* TREE_VECs hold template argument lists.  */
-      NON_DEFAULT_TEMPLATE_ARGS_COUNT (expr) = pph_in_tree (stream);
-      break;
-
-    case PLACEHOLDER_EXPR:
-      TREE_TYPE (expr) = pph_in_tree (stream);
-      break;
-
-    case TEMPLATE_PARM_INDEX:
-      pph_in_tree_common (stream, expr);
-      TEMPLATE_PARM_IDX (expr) = pph_in_uint (stream);
-      TEMPLATE_PARM_LEVEL (expr) = pph_in_uint (stream);
-      TEMPLATE_PARM_ORIG_LEVEL (expr) = pph_in_uint (stream);
-      TEMPLATE_PARM_NUM_SIBLINGS (expr) = pph_in_uint (stream);
-      TEMPLATE_PARM_DECL (expr) = pph_in_tree (stream);
-      break;
-
-    case DEFERRED_NOEXCEPT:
-      DEFERRED_NOEXCEPT_PATTERN (expr) = pph_in_tree (stream);
-      DEFERRED_NOEXCEPT_ARGS (expr) = pph_in_tree (stream);
-      break;
-
-    /* TREES ALREADY HANDLED */
-    case ERROR_MARK:
-    case TREE_LIST:
-    case BLOCK:
-    case CONSTRUCTOR:
-    case SSA_NAME:
-    case TREE_BINFO:
-      break;
-
-    /* TREES UNIMPLEMENTED */
-    case OMP_CLAUSE:
-    case OPTIMIZATION_NODE:
-    case TARGET_OPTION_NODE:
-      fatal_error ("PPH: unimplemented tree node '%s'",
-		   pph_tree_code_text (TREE_CODE (expr)));
-      break;
-
-    /* TREES UNRECOGNIZED */
-    default:
-      fatal_error ("PPH: unrecognized tree node '%s'",
-                   pph_tree_code_text (TREE_CODE (expr)));
-    }
-}
-
-
-/* Unpack language-dependent bitfields from BP into EXPR.  */
-
-static void
-pph_unpack_value_fields (struct bitpack_d *bp, tree expr)
-{
-  if (TYPE_P (expr))
-    {
-      TYPE_LANG_FLAG_0 (expr) = bp_unpack_value (bp, 1);
-      TYPE_LANG_FLAG_1 (expr) = bp_unpack_value (bp, 1);
-      TYPE_LANG_FLAG_2 (expr) = bp_unpack_value (bp, 1);
-      TYPE_LANG_FLAG_3 (expr) = bp_unpack_value (bp, 1);
-      TYPE_LANG_FLAG_4 (expr) = bp_unpack_value (bp, 1);
-      TYPE_LANG_FLAG_5 (expr) = bp_unpack_value (bp, 1);
-      TYPE_LANG_FLAG_6 (expr) = bp_unpack_value (bp, 1);
-    }
-  else if (DECL_P (expr))
-    {
-      DECL_LANG_FLAG_0 (expr) = bp_unpack_value (bp, 1);
-      DECL_LANG_FLAG_1 (expr) = bp_unpack_value (bp, 1);
-      DECL_LANG_FLAG_2 (expr) = bp_unpack_value (bp, 1);
-      DECL_LANG_FLAG_3 (expr) = bp_unpack_value (bp, 1);
-      DECL_LANG_FLAG_4 (expr) = bp_unpack_value (bp, 1);
-      DECL_LANG_FLAG_5 (expr) = bp_unpack_value (bp, 1);
-      DECL_LANG_FLAG_6 (expr) = bp_unpack_value (bp, 1);
-      DECL_LANG_FLAG_7 (expr) = bp_unpack_value (bp, 1);
-      DECL_LANG_FLAG_8 (expr) = bp_unpack_value (bp, 1);
-    }
-
-  TREE_LANG_FLAG_0 (expr) = bp_unpack_value (bp, 1);
-  TREE_LANG_FLAG_1 (expr) = bp_unpack_value (bp, 1);
-  TREE_LANG_FLAG_2 (expr) = bp_unpack_value (bp, 1);
-  TREE_LANG_FLAG_3 (expr) = bp_unpack_value (bp, 1);
-  TREE_LANG_FLAG_4 (expr) = bp_unpack_value (bp, 1);
-  TREE_LANG_FLAG_5 (expr) = bp_unpack_value (bp, 1);
-  TREE_LANG_FLAG_6 (expr) = bp_unpack_value (bp, 1);
-}
-
-
-/* Read a tree header from STREAM and allocate a memory instance for it.
-   Return the new tree.  */
-
-static tree
-pph_in_tree_header (pph_stream *stream, enum LTO_tags tag)
-{
-  struct lto_input_block *ib = stream->encoder.r.ib;
-  struct data_in *data_in = stream->encoder.r.data_in;
-  struct bitpack_d bp;
-  tree expr;
-  enum tree_code code;
-
-  /* Allocate the tree.  Handle C++-specific codes first.  */
-  code = lto_tag_to_tree_code (tag);
-  if (code == AGGR_INIT_EXPR)
-    {
-      unsigned nargs = pph_in_uint (stream);
-      expr = build_vl_exp (AGGR_INIT_EXPR, nargs + 3);
-    }
-  else
-    expr = streamer_alloc_tree (ib, data_in, tag);
-
-  /* Read the language-independent bitfields for EXPR.  */
-  bp = streamer_read_tree_bitfields (ib, expr);
-
-  /* Unpack all language-dependent bitfields.  */
-  pph_unpack_value_fields (&bp, expr);
-
-  return expr;
-}
-
-
-/* Read a merge key from STREAM.  If the merge key read from STREAM
-   is not found in *CHAIN, the newly allocated tree is added to it.  */
-
-static tree
-pph_in_merge_key_tree (pph_stream *stream, tree *chain)
-{
-  struct lto_input_block *ib = stream->encoder.r.ib;
-  enum pph_record_marker marker;
-  unsigned image_ix, ix;
-  tree read_expr, expr;
-  enum LTO_tags tag;
-  const char *name;
-
-  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_any_tree);
-  if (marker == PPH_RECORD_END)
-    return NULL;
-  else if (pph_is_reference_marker (marker))
-    return (tree) pph_cache_find (stream, marker, image_ix, ix, PPH_any_tree);
-  gcc_assert (marker == PPH_RECORD_START_MERGE_KEY);
-
-  tag = streamer_read_record_start (ib);
-
-  /* Materialize a new node from STREAM.  This will also read all the
-     language-independent bitfields for the new tree.  */
-  read_expr = pph_in_tree_header (stream, tag);
-  gcc_assert (pph_tree_is_mergeable (read_expr));
-  name = pph_in_string (stream);
-
-  /* Look for a match in CHAIN to READ_EXPR's header.  If we found a
-     match, EXPR will be the existing tree that matches READ_EXPR.
-     Otherwise, EXPR is the newly allocated READ_EXPR.  */
-  expr = pph_merge_into_chain (read_expr, name, chain);
-
-  gcc_assert (expr != NULL);
-
-  pph_cache_insert_at (&stream->cache, expr, ix, pph_tree_code_to_tag (expr));
-
-  if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_front,
-		    expr == read_expr ? pph_trace_unmerged_key
-				      : pph_trace_merged_key);
-
-  if (DECL_P (expr))
-    {
-      if (TREE_CODE (expr) == NAMESPACE_DECL)
-        {
-	  cp_binding_level *bl;
-	  if (DECL_LANG_SPECIFIC (expr))
-	    /* Merging into an existing namespace.  */
-	    bl = NAMESPACE_LEVEL (expr);
-	  else
-	    {
-	      /* This is a new namespace.  */
-	      retrofit_lang_decl (expr);
-	      bl = ggc_alloc_cleared_cp_binding_level ();
-	      NAMESPACE_LEVEL (expr) = bl;
-	    }
-	  pph_in_binding_merge_keys (stream, bl);
-        }
-#if 0
-/* FIXME pph: Disable type merging for the moment.  */
-      else if (TREE_CODE (expr) == TYPE_DECL)
-        /* Types are not on a chain.  */
-        TREE_TYPE (expr) = pph_in_merge_key_tree (stream, NULL);
-    }
-  else if (CLASS_TYPE_P (expr))
-    {
-      pph_in_merge_key_chain (stream, &TYPE_FIELDS (expr));
-      pph_in_merge_key_chain (stream, &TYPE_METHODS (expr));
-      /*FIXME pph: Nested types are broken.
-      pph_in_binding_table (stream, &CLASSTYPE_NESTED_UTDS (expr));
-      pph_in_merge_key_chain (stream, &CLASSTYPE_DECL_LIST (expr));
-      */
-#endif
-    }
-
-  if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_back,
-		    expr == read_expr ? pph_trace_unmerged_key
-				      : pph_trace_merged_key);
-
-  return expr;
-}
-
-
-/* Read and return a tree from STREAM.  */
-
-tree
-pph_in_tree (pph_stream *stream)
-{
-  struct lto_input_block *ib = stream->encoder.r.ib;
-  struct data_in *data_in = stream->encoder.r.data_in;
-  tree expr = NULL;
-  enum pph_record_marker marker;
-  unsigned image_ix, ix;
-  enum LTO_tags tag;
-  tree saved_expr_chain = NULL;
-
-  /* Read record start and test cache.  */
-  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_any_tree);
-  if (marker == PPH_RECORD_END)
-    return NULL;
-  else if (pph_is_reference_marker (marker))
-    return (tree) pph_cache_find (stream, marker, image_ix, ix, PPH_any_tree);
-  else if (marker == PPH_RECORD_START || marker == PPH_RECORD_START_NO_CACHE)
-    {
-      /* This is a new tree that we need to allocate.  Start by
-         reading the header fields, so we know how to allocate it
-         (different tree nodes need to be allocated in different
-         ways).  */
-      tag = streamer_read_record_start (ib);
-      gcc_assert ((unsigned) tag < (unsigned) LTO_NUM_TAGS);
-      if (tag == LTO_builtin_decl)
-        {
-          /* If we are going to read a built-in function, all we need is
-             the code and class.  */
-          gcc_assert (marker == PPH_RECORD_START_NO_CACHE);
-          return streamer_get_builtin_tree (ib, data_in);
-        }
-      else if (tag == lto_tree_code_to_tag (INTEGER_CST))
-        {
-          /* For integer constants we only need the type and its hi/low
-             words.  */
-          gcc_assert (marker == PPH_RECORD_START_NO_CACHE);
-          return streamer_read_integer_cst (ib, data_in);
-        }
-
-      /* Materialize a new node from STREAM.  This will also read all the
-         language-independent bitfields for the new tree.  */
-      expr = pph_in_tree_header (stream, tag);
-    }
-
-  gcc_assert (marker == PPH_RECORD_START
-              || marker == PPH_RECORD_START_MUTATED
-	      || marker == PPH_RECORD_START_MERGE_BODY);
-
-  if (marker == PPH_RECORD_START_MUTATED)
-    {
-      /* When reading a mutated tree, we only need to re-read its
-         body, the tree itself is already in the cache for another
-         PPH image.  */
-      expr = (tree) pph_cache_find (stream, PPH_RECORD_XREF, image_ix, ix,
-				    PPH_any_tree);
-
-      /* Read the internal cache slot where EXPR should be stored at.  */
-      ix = pph_in_uint (stream);
-    }
-  else if (marker == PPH_RECORD_START_MERGE_BODY)
-    {
-      /* When reading a merge body, the tree has already been allocated
-	 and added to STREAM's cache.  All we have to do now is read
-	 its body.  FIXME pph, this read should be a merging read; we are
-	 overwriting EXPR's fields now.  */
-      expr = (tree) pph_cache_get (&stream->cache, ix);
-    }
-
-  /* Add the new tree to the cache and read its body.  The tree is
-     added to the cache before we read its body to handle circular
-     references and references from children nodes.  If we are reading
-     a merge body, then the tree is already in the cache (it was added
-     by pph_in_merge_key_tree).  */
-  if (marker != PPH_RECORD_START_MERGE_BODY)
-    pph_cache_insert_at (&stream->cache, expr, ix, pph_tree_code_to_tag (expr));
-
-  if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_front,
-	marker == PPH_RECORD_START_MERGE_BODY ? pph_trace_merge_body
-	: marker == PPH_RECORD_START_MUTATED ? pph_trace_mutate
-	: pph_trace_normal );
-
-  /* If we are reading a merge body, it means that EXPR is already in
-     some chain.  Given that EXPR may now be in a different location
-     in the chain, we need to make sure we do not lose it.  */
-  if (marker == PPH_RECORD_START_MERGE_BODY)
-    saved_expr_chain = TREE_CHAIN (expr);
-
-  pph_in_tree_body (stream, expr);
-
-  /* Restore TREE_CHAIN if necessary.  FIXME pph, we should just not
-     save TREE_CHAIN for merge bodies.  */
-  if (marker == PPH_RECORD_START_MERGE_BODY)
-    TREE_CHAIN (expr) = saved_expr_chain;
-
-  if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_back,
-	marker == PPH_RECORD_START_MERGE_BODY ? pph_trace_merge_body
-	: marker == PPH_RECORD_START_MUTATED ? pph_trace_mutate
-	: pph_trace_normal );
-
-  /* If needed, sign the recently materialized tree to detect
-     mutations.  Note that we only need to compute signatures
-     if we are generating a PPH image.  That is the only time
-     where we need to determine whether a tree read from PPH
-     was updated while parsing the header file that we are
-     currently generating.  */
-  if (pph_writer_enabled_p () && tree_needs_signature (expr))
-    {
-      unsigned crc;
-      size_t nbytes;
-      crc = pph_get_signature (expr, &nbytes);
-      pph_cache_sign (&stream->cache, ix, crc, nbytes);
-    }
-
-  return expr;
-}
-
-
-/************************************************************* file contents */
-
-
-/* Read a symbol table marker from STREAM.  */
-
-static inline enum pph_symtab_action
-pph_in_symtab_action (pph_stream *stream)
-{
-  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, PPH_cgraph_node);
-  if (marker == PPH_RECORD_END)
-    return NULL;
-  else if (pph_is_reference_marker (marker))
-    return (struct cgraph_node *) pph_cache_find (stream, marker, image_ix,
-						  ix, PPH_cgraph_node);
-
-  fndecl = pph_in_tree (stream);
-  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cgraph_node, node,
-                      cgraph_get_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;
-}
-
-
-/* Have we already emitted this DECL?  */
-
-static bool
-pph_decl_already_emitted (tree decl)
-{
-  static struct pointer_set_t *emitted_syms = NULL;
-  gcc_assert (decl != NULL);
-  if (!emitted_syms)
-    emitted_syms = pointer_set_create ();
-  return pointer_set_insert (emitted_syms, decl) != 0;
-}
-
-
-/* Have we already emitted this cgraph NODE?  */
-
-static bool
-pph_node_already_emitted (struct cgraph_node *node)
-{
-  static struct pointer_set_t *emitted_nodes = NULL;
-  gcc_assert (node != NULL);
-  if (!emitted_nodes)
-    emitted_nodes = pointer_set_create ();
-  return pointer_set_insert (emitted_nodes, node) != 0;
-}
-
-
-/* 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
-   that they were instantiated when we generated this image.
-
-   With this, we can generate code in the same order out of the
-   original header files and out of PPH images.  */
-
-static void
-pph_in_symtab (pph_stream *stream)
-{
-  unsigned i, num;
-
-  /* Register all the symbols in STREAM in the same order of the
-     original compilation for this header file.  */
-  num = pph_in_uint (stream);
-  for (i = 0; i < num; i++)
-    {
-      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);
-          if (pph_decl_already_emitted (decl))
-            continue;
-
-	  cp_rest_of_decl_compilation (decl, top_level, at_end);
-	}
-      else if (action == PPH_SYMTAB_EXPAND)
-	{
-	  struct cgraph_node *node;
-
-	  pph_in_struct_function (stream, decl);
-	  node = pph_in_cgraph_node (stream);
-	  if (node && node->local.finalized)
-	    {
-	      if (pph_node_already_emitted (node))
-		continue;
-
-	      /* 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
-	gcc_unreachable ();
-    }
-}
-
-
-/* Wrap a macro DEFINITION for printing in an error.  */
-
-static char *
-wrap_macro_def (const char *definition)
-{
-  char *string;
-  if (definition)
-    {
-      size_t length;
-      length = strlen (definition);
-      string = (char *) xmalloc (length+3);
-      string[0] = '"';
-      strcpy (string + 1, definition);
-      string[length + 1] = '"';
-      string[length + 2] = '\0';
-    }
-  else
-    string = xstrdup ("undefined");
-  return string;
-}
-
-
-/* Report a macro validation error in FILENAME for macro IDENT,
-   which should have the value EXPECTED but actually had the value FOUND. */
-
-static void
-report_validation_error (const char *filename,
-			 const char *ident, const char *found,
-			 const char *before, const char *after)
-{
-  char* quote_found = wrap_macro_def (found);
-  char* quote_before = wrap_macro_def (before);
-  char* quote_after = wrap_macro_def (after);
-  warning (0, "PPH file %s fails macro validation, "
-           "%s is %s and should be %s or %s\n",
-         filename, ident, quote_found, quote_before, quote_after);
-  free (quote_found);
-  free (quote_before);
-  free (quote_after);
-}
-
-
-/* Load the IDENTIFIERS for a hunk from a STREAM.  */
-
-static void
-pph_in_identifiers (pph_stream *stream, cpp_idents_used *identifiers)
-{
-  unsigned int j;
-  unsigned int max_ident_len, max_value_len, num_entries;
-  unsigned int ident_len, before_len, after_len;
-
-  max_ident_len = pph_in_uint (stream);
-  identifiers->max_ident_len = max_ident_len;
-  max_value_len = pph_in_uint (stream);
-  identifiers->max_value_len = max_value_len;
-  num_entries = pph_in_uint (stream);
-  identifiers->num_entries = num_entries;
-  identifiers->entries = XCNEWVEC (cpp_ident_use, num_entries);
-  identifiers->strings = XCNEW (struct obstack);
-
-  /* Strings need no alignment.  */
-  _obstack_begin (identifiers->strings, 0, 0,
-                  (void *(*) (long)) xmalloc,
-                  (void (*) (void *)) free);
-  obstack_alignment_mask (identifiers->strings) = 0;
-  /* FIXME pph: We probably need to free all these things somewhere.  */
-
-  /* Read the identifiers in HUNK. */
-  for (j = 0; j < num_entries; ++j)
-    {
-      const char *s;
-      identifiers->entries[j].used_by_directive = pph_in_uint (stream);
-      identifiers->entries[j].expanded_to_text = pph_in_uint (stream);
-      s = pph_in_string (stream);
-      gcc_assert (s);
-      ident_len = strlen (s);
-      identifiers->entries[j].ident_len = ident_len;
-      identifiers->entries[j].ident_str =
-        (const char *) obstack_copy0 (identifiers->strings, s, ident_len);
-
-      s = pph_in_string (stream);
-      if (s)
-	{
-	  before_len = strlen (s);
-	  identifiers->entries[j].before_len = before_len;
-	  identifiers->entries[j].before_str = (const char *)
-	      obstack_copy0 (identifiers->strings, s, before_len);
-	}
-      else
-	{
-	  /* The identifier table expects NULL entries to have
-	     a length of -1U.  */
-	  identifiers->entries[j].before_len = -1U;
-	  identifiers->entries[j].before_str = NULL;
-	}
-
-      s = pph_in_string (stream);
-      if (s)
-	{
-	  after_len = strlen (s);
-	  identifiers->entries[j].after_len = after_len;
-	  identifiers->entries[j].after_str = (const char *)
-	      obstack_copy0 (identifiers->strings, s, after_len);
-	}
-      else
-	{
-	  /* The identifier table expects NULL entries to have
-	     a length of -1U.  */
-	  identifiers->entries[j].after_len = -1U;
-	  identifiers->entries[j].after_str = NULL;
-	}
-    }
-}
-
-
-/* Read global bindings from STREAM into scope_chain->bindings.  Note
-   that this does not call pph_in_binding_level because that would
-   overwrite the fields merged by pph_in_merge_keys.  */
-
-static void
-pph_in_global_binding (pph_stream *stream)
-{
-  unsigned image_ix, ix;
-  enum pph_record_marker marker;
-  cp_binding_level *bl;
-
-  bl = scope_chain->bindings;
-  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cp_binding_level);
-  gcc_assert (marker != PPH_RECORD_END);
-
-  if (pph_is_reference_marker (marker))
-    {
-      /* If we found a reference to BL, it should be the same.  This happens
-	 when we pull BL from a nested PPH image.  */
-      cp_binding_level *other_bl;
-      other_bl = (cp_binding_level *) pph_cache_find (stream, marker, image_ix,
-						      ix, PPH_cp_binding_level);
-      gcc_assert (other_bl == bl);
-    }
-  else
-    {
-      /* Note that here we do not allocate a new binding level.  Since we
-	 are reading into the global one, we register the current
-	 scope_chain->bindings into the cache.  Otherwise, we would be
-	 associating these symbols into the global binding level from
-	 STREAM, instead of the current translation unit.  */
-      pph_cache_insert_at (&stream->cache, bl, ix, PPH_cp_binding_level);
-    }
-
-  /* Read the merge keys and merge them into the current compilation
-     context.  Since we have registered scope_chain->bindings in the
-     same slot IX that the writer used, the trees read now will be
-     bound to scope_chain->bindings.  */
-  pph_in_binding_merge_keys (stream, bl);
-  pph_in_binding_merge_bodies_1 (stream, bl);
-}
-
-
-/* Helper for pph_read_file.  Read contents of PPH file in STREAM.  */
-
-static void
-pph_read_file_1 (pph_stream *stream)
-{
-  bool verified;
-  cpp_ident_use *bad_use;
-  const char *cur_def;
-  cpp_idents_used idents_used;
-  tree t, file_keyed_classes, file_static_aggregates;
-  unsigned i;
-  VEC(tree,gc) *file_unemitted_tinfo_decls;
-  source_location cpp_token_replay_loc;
-
-  /* If we have read STREAM before, we do not need to re-read the rest
-     of its body.  We only needed to read its line table.  */
-  if (stream->in_memory_p)
-    return;
-
-  if (flag_pph_tracer >= 1)
-    fprintf (pph_logfile, "PPH: Reading %s\n", stream->name);
-
-  /* Read in STREAM's line table and merge it in the current line table.
-     At the same time, read in includes in the order they were originally
-     read.  */
-  cpp_token_replay_loc = pph_in_line_table_and_includes (stream);
-
-  /* Read all the identifiers and pre-processor symbols in the global
-     namespace.  */
-  pph_in_identifiers (stream, &idents_used);
-
-  /* FIXME pph: This validation is weak.  */
-  verified = cpp_lt_verify_1 (parse_in, &idents_used, &bad_use, &cur_def, true);
-  if (!verified)
-    report_validation_error (stream->name, bad_use->ident_str, cur_def,
-                             bad_use->before_str, bad_use->after_str);
-
-  /* Re-instantiate all the pre-processor symbols defined by STREAM.  Force
-     their source_location to line 1 / column 0 of the file they were included
-     in.  This avoids shifting all of the line_table's locations as we would by
-     adding locations which wouldn't be there in the non-pph compile; thus
-     working towards an identical line_table in pph and non-pph.  */
-  cpp_lt_replay (parse_in, &idents_used, &cpp_token_replay_loc);
-
-  /* Read the bindings from STREAM.  */
-  pph_in_global_binding (stream);
-
-  /* Read and merge the other global state collected during parsing of
-     the original header.  */
-  file_keyed_classes = pph_in_tree (stream);
-  keyed_classes = chainon (file_keyed_classes, keyed_classes);
-
-  file_unemitted_tinfo_decls = pph_in_tree_vec (stream);
-  FOR_EACH_VEC_ELT (tree, file_unemitted_tinfo_decls, i, t)
-    VEC_safe_push (tree, gc, unemitted_tinfo_decls, t);
-
-  pph_in_pending_templates_list (stream);
-  pph_in_spec_entry_tables (stream);
-
-  file_static_aggregates = pph_in_tree (stream);
-  static_aggregates = chainon (file_static_aggregates, static_aggregates);
-
-  /* Read and process the symbol table.  */
-  pph_in_symtab (stream);
-
-  /* Mark this file as read.  If other images need to access its contents,
-     we will not need to actually read it again.  */
-  pph_mark_stream_read (stream);
-
-  if (flag_pph_dump_tree)
-    pph_dump_namespace (pph_logfile, global_namespace);
-}
-
-
-/* Read PPH file FILENAME.  Return the in-memory pph_stream instance.  */
-
-pph_stream *
-pph_read_file (const char *filename)
-{
-  pph_stream *stream = pph_stream_open (filename, "rb");
-  if (stream == NULL)
-    fatal_error ("cannot open PPH file %s for reading: %m", filename);
-
-  pph_read_file_1 (stream);
-
-  return stream;
-}
-
-
-/********************************************************* stream operations */
-
-
-/* Initialize the reader.  */
-
-void
-pph_reader_init (void)
-{
-  merge_toc = htab_create (551, htab_merge_key_hash, htab_merge_key_eq, free);
-}
-
-
-/* Finalize the reader.  */
-
-void
-pph_reader_finish (void)
-{
-  htab_delete (merge_toc);
-}
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 181815)
+++ gcc/cp/pt.c	(working copy)
@@ -46,7 +46,6 @@ along with GCC; see the file COPYING3.  
 #include "timevar.h"
 #include "tree-iterator.h"
 #include "vecprim.h"
-#include "pph-streamer.h"
 
 /* The type of functions taking a tree, and some additional data, and
    returning an int.  */
Index: gcc/cp/pph-streamer.c
===================================================================
--- gcc/cp/pph-streamer.c	(revision 181815)
+++ gcc/cp/pph-streamer.c	(working copy)
@@ -1,674 +0,0 @@
-/* Routines for streaming PPH data.
-   Copyright (C) 2011 Free Software Foundation, Inc.
-   Contributed by Diego Novillo <dnovillo@google.com>.
-
-   This file is part of GCC.
-
-   GCC is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3, or (at your option)
-   any later version.
-
-   GCC is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "pph.h"
-#include "tree.h"
-#include "langhooks.h"
-#include "tree-iterator.h"
-#include "tree-pretty-print.h"
-#include "lto-streamer.h"
-#include "pph-streamer.h"
-#include "tree-pass.h"
-#include "version.h"
-#include "cppbuiltin.h"
-#include "streamer-hooks.h"
-
-/* List of PPH images opened for reading.  Images opened during #include
-   processing and opened from pph_in_includes cannot be closed
-   immediately after reading, because the pickle cache contained in
-   them may be referenced from other images.  We delay closing all of
-   them until the end of parsing (when pph_streamer_finish is called).  */
-static VEC(pph_stream_ptr, heap) *pph_read_images = NULL;
-
-/* A cache of pre-loaded common tree nodes.  */
-static pph_cache *pph_preloaded_cache;
-
-/* Pre-load common tree nodes into CACHE.  These nodes are always built by the
-   front end, so there is no need to pickle them.  */
-
-static void
-pph_cache_preload (pph_cache *cache)
-{
-  unsigned i;
-
-  for (i = itk_char; i < itk_none; i++)
-    pph_cache_add (cache, integer_types[i], NULL,
-                   pph_tree_code_to_tag (integer_types[i]));
-
-  for (i = 0; i < TYPE_KIND_LAST; i++)
-    pph_cache_add (cache, sizetype_tab[i], NULL,
-                   pph_tree_code_to_tag (sizetype_tab[i]));
-
-  /* global_trees[] can have NULL entries in it.  Skip them.  */
-  for (i = 0; i < TI_MAX; i++)
-    if (global_trees[i])
-      pph_cache_add (cache, global_trees[i], NULL,
-                     pph_tree_code_to_tag (global_trees[i]));
-
-  /* c_global_trees[] can have NULL entries in it.  Skip them.  */
-  for (i = 0; i < CTI_MAX; i++)
-    if (c_global_trees[i])
-      pph_cache_add (cache, c_global_trees[i], NULL,
-                     pph_tree_code_to_tag (c_global_trees[i]));
-
-  /* cp_global_trees[] can have NULL entries in it.  Skip them.  */
-  for (i = 0; i < CPTI_MAX; i++)
-    {
-      /* Also skip trees which are generated while parsing.  */
-      if (i == CPTI_KEYED_CLASSES)
-	continue;
-
-      if (cp_global_trees[i])
-	pph_cache_add (cache, cp_global_trees[i], NULL,
-                       pph_tree_code_to_tag (cp_global_trees[i]));
-    }
-
-  /* Add other well-known nodes that should always be taken from the
-     current compilation context.  */
-  pph_cache_add (cache, global_namespace, NULL,
-                 pph_tree_code_to_tag (global_namespace));
-  pph_cache_add (cache, DECL_CONTEXT (global_namespace), NULL,
-                 pph_tree_code_to_tag (DECL_CONTEXT (global_namespace)));
-}
-
-
-/* Callback for writing ASTs to a stream.  Write EXPR to the PPH stream
-   in OB.  */
-
-static void
-pph_write_tree (struct output_block *ob, tree expr, bool ref_p ATTRIBUTE_UNUSED)
-{
-  pph_out_tree ((pph_stream *) ob->sdata, expr);
-}
-
-
-/* Callback for reading ASTs from a stream.  Instantiate and return a
-   new tree from the PPH stream in DATA_IN.  */
-
-static tree
-pph_read_tree (struct lto_input_block *ib ATTRIBUTE_UNUSED,
-	       struct data_in *data_in)
-{
-  return pph_in_tree ((pph_stream *) data_in->sdata);
-}
-
-
-/* Callback for streamer_hooks.input_location.  An offset is applied to
-   the location_t read in according to the properties of the merged
-   line_table.  IB and DATA_IN are as in lto_input_location.  This function
-   should only be called after pph_in_and_merge_line_table was called as
-   we expect pph_loc_offset to be set.  */
-
-static location_t
-pph_input_location (struct lto_input_block *ib ATTRIBUTE_UNUSED,
-                    struct data_in *data_in)
-{
-  return pph_in_location ((pph_stream *) data_in->sdata);
-}
-
-
-/* Callback for streamer_hooks.output_location.  Output the LOC directly,
-   an offset will be applied on input after rebuilding the line_table.
-   OB and LOC are as in lto_output_location.  */
-
-static void
-pph_output_location (struct output_block *ob, location_t loc)
-{
-  pph_out_location ((pph_stream *) ob->sdata, loc);
-}
-
-
-/* Initialize all the streamer hooks used for streaming ASTs.  */
-
-static void
-pph_hooks_init (void)
-{
-  streamer_hooks_init ();
-  streamer_hooks.write_tree = pph_write_tree;
-  streamer_hooks.read_tree = pph_read_tree;
-  streamer_hooks.input_location = pph_input_location;
-  streamer_hooks.output_location = pph_output_location;
-}
-
-
-/* Initialize an empty pickle CACHE.  */
-
-static void
-pph_cache_init (pph_cache *cache)
-{
-  cache->v = NULL;
-  cache->m = pointer_map_create ();
-}
-
-
-/* Initialize the pre-loaded cache.  This contains all the common
-   tree nodes built by the compiler on startup.  */
-
-static void
-pph_init_preloaded_cache (void)
-{
-  pph_preloaded_cache = XCNEW (pph_cache);
-  pph_cache_init (pph_preloaded_cache);
-  pph_cache_preload (pph_preloaded_cache);
-}
-
-
-/* Initialize the streamer.  */
-
-void
-pph_streamer_init (void)
-{
-  pph_hooks_init ();
-  pph_init_preloaded_cache ();
-}
-
-
-/* Finalize the streamer.  */
-
-void
-pph_streamer_finish (void)
-{
-  unsigned i;
-  pph_stream *image;
-
-  /* Finalize the writer.  */
-  pph_writer_finish ();
-
-  /* Finalize the reader.  */
-  pph_reader_finish ();
-
-  /* Close any images read during parsing.  */
-  FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, i, image)
-    pph_stream_close (image);
-
-  VEC_free (pph_stream_ptr, heap, pph_read_images);
-}
-
-
-/* If FILENAME has already been read, return the stream associated with it.  */
-
-static pph_stream *
-pph_find_stream_for (const char *filename)
-{
-  pph_stream *include;
-  unsigned i;
-
-  /* FIXME pph, implement a hash map to avoid this linear search.  */
-  FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, i, include)
-    if (strcmp (include->name, filename) == 0)
-      return include;
-
-  return NULL;
-}
-
-
-/* Add STREAM to the list of read images.  */
-
-void
-pph_mark_stream_read (pph_stream *stream)
-{
-  stream->in_memory_p = true;
-  VEC_safe_push (pph_stream_ptr, heap, pph_read_images, stream);
-}
-
-
-/* Create a new PPH stream to be stored on the file called NAME.
-   MODE is passed to fopen directly.  */
-
-pph_stream *
-pph_stream_open (const char *name, const char *mode)
-{
-  pph_stream *stream;
-  FILE *f;
-
-  /* If we have already opened a PPH stream named NAME, just return
-     its associated stream.  */
-  stream = pph_find_stream_for (name);
-  if (stream)
-    {
-      gcc_assert (stream->in_memory_p);
-      return stream;
-    }
-
-  f = fopen (name, mode);
-  if (!f)
-    return NULL;
-
-  stream = XCNEW (pph_stream);
-  stream->file = f;
-  stream->name = xstrdup (name);
-  stream->write_p = (strchr (mode, 'w') != NULL);
-  pph_cache_init (&stream->cache);
-  stream->preloaded_cache = pph_preloaded_cache;
-  if (stream->write_p)
-    pph_init_write (stream);
-  else
-    pph_init_read (stream);
-
-  return stream;
-}
-
-
-
-/* Close PPH stream STREAM.  */
-
-void
-pph_stream_close (pph_stream *stream)
-{
-  /* STREAM can be NULL if it could not be properly opened.  An error
-     has already been emitted, so avoid crashing here.  */
-  if (stream == NULL)
-    return;
-
-  if (flag_pph_tracer >= 1)
-    fprintf (pph_logfile, "PPH: Closing %s\n", stream->name);
-
-  /* If we were writing to STREAM, flush all the memory buffers.  This
-     does the actual writing of all the pickled data structures.  */
-  if (stream->write_p)
-    pph_flush_buffers (stream);
-
-  fclose (stream->file);
-
-  /* Deallocate all memory used.  */
-  stream->file = NULL;
-  VEC_free (pph_cache_entry, heap, stream->cache.v);
-  pointer_map_destroy (stream->cache.m);
-  VEC_free (pph_symtab_entry, heap, stream->symtab.v);
-  VEC_free (pph_stream_ptr, heap, stream->includes);
-
-  if (stream->write_p)
-    {
-      destroy_output_block (stream->encoder.w.ob);
-      free (stream->encoder.w.decl_state_stream);
-      lto_delete_out_decl_state (stream->encoder.w.out_state);
-    }
-  else
-    {
-      unsigned i;
-
-      free (stream->encoder.r.ib);
-      lto_data_in_delete (stream->encoder.r.data_in);
-      for (i = 0; i < PPH_NUM_SECTIONS; i++)
-	free (stream->encoder.r.pph_sections[i]);
-      free (stream->encoder.r.pph_sections);
-      free (stream->encoder.r.file_data);
-    }
-
-  free (stream);
-}
-
-
-/* Add INCLUDE, and the images included by it, to the list of files
-   included by STREAM.  */
-
-void
-pph_add_include (pph_stream *stream, pph_stream *include)
-{
-  pph_stream *include_child;
-  unsigned i;
-
-  include->parent = stream;
-  VEC_safe_push (pph_stream_ptr, heap, stream->includes, include);
-  FOR_EACH_VEC_ELT (pph_stream_ptr, include->includes, i, include_child)
-    VEC_safe_push (pph_stream_ptr, heap, stream->includes, include_child);
-}
-
-
-/* Trace a record MARKER and TAG.  */
-
-static const char *marker_strings[] =
-{
-  "PPH_RECORD_START",
-  "PPH_RECORD_START_NO_CACHE",
-  "PPH_RECORD_START_MUTATED",
-  "PPH_RECORD_START_MERGE_KEY",
-  "PPH_RECORD_START_MERGE_BODY",
-  "PPH_RECORD_END",
-  "PPH_RECORD_IREF",
-  "PPH_RECORD_XREF",
-  "PPH_RECORD_PREF"
-};
-
-static const char *tag_strings[] =
-{
-  "PPH_any_tree",
-  "PPH_binding_entry",
-  "PPH_binding_table",
-  "PPH_cgraph_node",
-  "PPH_cp_binding_level",
-  "PPH_cp_class_binding",
-  "PPH_cp_label_binding",
-  "PPH_cxx_binding",
-  "PPH_function",
-  "PPH_lang_decl",
-  "PPH_lang_type",
-  "PPH_language_function",
-  "PPH_sorted_fields_type"
-};
-
-void
-pph_trace_marker (enum pph_record_marker marker, enum pph_tag tag)
-{
-  fprintf (pph_logfile, "marker ");
-  if (PPH_RECORD_START <= marker && marker <= PPH_RECORD_PREF)
-    fprintf (pph_logfile, "%s", marker_strings[marker - PPH_RECORD_START]);
-  else
-    fprintf (pph_logfile, "unknown");
-  fprintf (pph_logfile, " tag ");
-  if (tag == PPH_null)
-    fprintf (pph_logfile, "PPH_null\n");
-  else if (tag < PPH_any_tree)
-    fprintf (pph_logfile, "%s\n", tree_code_name[tag]);
-  else if (tag < PPH_NUM_TAGS)
-    fprintf (pph_logfile, "%s\n", tag_strings[tag - PPH_any_tree]);
-  else
-    fprintf (pph_logfile, "unknown\n");
-}
-
-
-/* Print tracing information for a possibly MERGEABLE tree T.  */
-
-void
-pph_trace_tree (tree t, enum pph_trace_end end, enum pph_trace_kind kind)
-{
-  char end_char, kind_char, decl_char;
-  bool is_merge, is_decl;
-  bool emit = false;
-
-  switch (kind)
-    {
-      case pph_trace_key_out:
-	kind_char = 'K';
-	is_merge = true;
-	break;
-      case pph_trace_unmerged_key:
-	kind_char = 'U';
-	is_merge = true;
-	break;
-      case pph_trace_merged_key:
-	kind_char = 'M';
-	is_merge = true;
-	break;
-      case pph_trace_merge_body:
-	kind_char = 'B';
-	is_merge = true;
-	break;
-      case pph_trace_mutate:
-	kind_char = '=';
-	is_merge = false;
-	break;
-      case pph_trace_normal:
-	kind_char = '.';
-	is_merge = false;
-	break;
-      default:
-	kind_char = '?';
-	is_merge = false;
-    }
-
-  end_char = end == pph_trace_front ? '{' : '}';
-
-  is_decl = DECL_P (t);
-  if (is_decl)
-    decl_char = 'D';
-  else if (TYPE_P (t))
-    decl_char = 'T';
-  else
-    decl_char = '.';
-
-  if (is_merge && is_decl && flag_pph_tracer >= 2)
-    emit = true;
-  else if ((is_merge || is_decl) && flag_pph_tracer >= 3)
-    emit = true;
-  else if (!EXPR_P (t) && flag_pph_tracer >= 4)
-    emit = true;
-
-  if (emit)
-    {
-      fprintf (pph_logfile, "PPH: %c%c%c ", end_char, kind_char, decl_char);
-      if (kind == pph_trace_unmerged_key || end == pph_trace_front)
-	fprintf (pph_logfile, "%s -------\n",
-			      pph_tree_code_text (TREE_CODE (t)));
-      else
-        pph_dump_tree_name (pph_logfile, t, 0);
-    }
-}
-
-
-/* Insert DATA in CACHE at slot IX.  TAG represents the data structure
-   pointed-to by DATA.  As a restriction to prevent stomping on cache
-   entries, this will not allow inserting into the same slot more than
-   once.  Return the newly added entry.  */
-
-pph_cache_entry *
-pph_cache_insert_at (pph_cache *cache, void *data, unsigned ix,
-                     enum pph_tag tag)
-{
-  void **map_slot;
-  pph_cache_entry e = { data, tag, false, 0, 0 };
-
-  map_slot = pointer_map_insert (cache->m, data);
-
-  /* We should not be trying to insert the same data more than once.
-     This indicates that the same DATA pointer has been given two
-     different cache locations.  This almost always points to a
-     problem with merging data structures read from different files.  */
-  gcc_assert (*map_slot == NULL);
-
-  *map_slot = (void *) (intptr_t) ix;
-  if (ix + 1 > VEC_length (pph_cache_entry, cache->v))
-    VEC_safe_grow_cleared (pph_cache_entry, heap, cache->v, ix + 1);
-  VEC_replace (pph_cache_entry, cache->v, ix, &e);
-
-  return pph_cache_get_entry (cache, ix);
-}
-
-
-/* If DATA exists in CACHE, return the cache entry holding it.  If
-   IX_P is not NULL, store the cache slot where DATA resides in *IX_P
-   (or (unsigned)-1 if DATA is not found). If CACHE is NULL use
-   pph_preloaded_cache.
-
-   If a cache hit is found, the data type tag for the entry must match
-   TAG.  */
-
-pph_cache_entry *
-pph_cache_lookup (pph_cache *cache, void *data, unsigned *ix_p,
-                  enum pph_tag tag)
-{
-  void **map_slot;
-  unsigned ix;
-  pph_cache_entry *e;
-
-  if (cache == NULL)
-    cache = pph_preloaded_cache;
-
-  map_slot = pointer_map_contains (cache->m, data);
-  if (map_slot == NULL)
-    {
-      e = NULL;
-      ix = (unsigned) -1;
-    }
-  else
-    {
-      intptr_t slot_ix = (intptr_t) *map_slot;
-      gcc_assert (slot_ix == (intptr_t)(unsigned) slot_ix);
-      ix = (unsigned) slot_ix;
-      e = pph_cache_get_entry (cache, ix);
-
-      /* If the caller is looking for a specific TAG, make sure
-         it matches the tag we pulled from the cache.  */
-      if (tag != PPH_null)
-	gcc_assert (tag == e->tag);
-    }
-
-  if (ix_p)
-    *ix_p = ix;
-
-  return e;
-}
-
-
-/* Return true if DATA is in the pickle cache of one of STREAM's
-   included images.  TAG is the expected data type TAG for data.
-
-   If DATA is found:
-      - the index for INCLUDE_P into IMAGE->INCLUDES is returned in
-	*INCLUDE_IX_P (if INCLUDE_IX_P is not NULL),
-      - the cache slot index for DATA into *INCLUDE_P's pickle cache
-	is returned in *IX_P (if IX_P is not NULL), and,
-      - the function returns true.
-
-   If DATA is not found:
-      - *INCLUDE_IX_P is set to -1 (if INCLUDE_IX_P is not NULL),
-      - *IX_P is set to -1 (if IX_P is not NULL), and,
-      - the function returns false.  */
-
-pph_cache_entry *
-pph_cache_lookup_in_includes (pph_stream *stream, void *data,
-			      unsigned *include_ix_p, unsigned *ix_p,
-			      enum pph_tag tag)
-{
-  unsigned include_ix, ix;
-  pph_stream *include;
-  pph_cache_entry *e;
-
-  /* When searching the external caches, do not try to find a match
-     for TAG.  Since this is an external cache, the parser may have
-     re-allocated the object pointed by DATA (e.g., when merging
-     decls).  In this case, TAG will be different from the tag we find
-     in the cache, so instead of ICEing, we ignore the match to force
-     the caller to pickle DATA.  */
-  e = NULL;
-  FOR_EACH_VEC_ELT (pph_stream_ptr, stream->includes, include_ix, include)
-    {
-      e = pph_cache_lookup (&include->cache, data, &ix, PPH_null);
-      if (e)
-	{
-	  /* Only consider DATA found if its data type matches TAG.  If
-	     not, it means that the object pointed by DATA has changed,
-	     so DATA will need to be re-pickled.  */
-	  if (e->tag != tag)
-	    e = NULL;
-	  break;
-	}
-    }
-
-  if (e == NULL)
-    {
-      include_ix = ix = (unsigned) -1;
-      ix = (unsigned) -1;
-    }
-
-  if (include_ix_p)
-    *include_ix_p = include_ix;
-
-  if (ix_p)
-    *ix_p = ix;
-
-  return e;
-}
-
-
-/* Add pointer DATA with data type TAG to CACHE.  If IX_P is not NULL,
-   on exit *IX_P will contain the slot number where DATA is stored.
-   Return the newly added entry.  */
-
-pph_cache_entry *
-pph_cache_add (pph_cache *cache, void *data, unsigned *ix_p, enum pph_tag tag)
-{
-  unsigned ix;
-  pph_cache_entry *e;
-
-  e = pph_cache_lookup (cache, data, &ix, tag);
-  if (e == NULL)
-    {
-      ix = VEC_length (pph_cache_entry, cache->v);
-      e = pph_cache_insert_at (cache, data, ix, tag);
-    }
-
-  if (ix_p)
-    *ix_p = ix;
-
-  return e;
-}
-
-
-/* Associate signature CRC with the first NBYTES of the area memory
-   pointed to by slot IX of CACHE.  */
-
-void
-pph_cache_sign (pph_cache *cache, unsigned ix, unsigned crc, size_t nbytes)
-{
-  pph_cache_entry *e;
-
-  /* Needed because xcrc32 requires an int to specify the length but
-     tree_size returns size_t values.  */
-  gcc_assert (nbytes == (size_t) (int) nbytes);
-
-  e = pph_cache_get_entry (cache, ix);
-  e->crc = crc;
-  e->crc_nbytes = nbytes;
-}
-
-
-/* Return a signature for tree T.  Store the length of the signed area
-   in *NBYTES_P.  */
-
-unsigned
-pph_get_signature (tree t, size_t *nbytes_p)
-{
-  tree prev_chain = NULL;
-  rtx prev_rtl = NULL;
-  int prev_used;
-  size_t nbytes;
-  unsigned crc;
-
-  nbytes = tree_size (t);
-  if (nbytes_p)
-    *nbytes_p = nbytes;
-
-  /* Preserve the value of the fields not included in the signature.  */
-  prev_chain = (DECL_P (t)) ? DECL_CHAIN (t) : NULL;
-  prev_rtl = (HAS_RTL_P (t)) ? DECL_RTL_IF_SET (t) : NULL;
-  prev_used = TREE_USED (t);
-
-  /* Clear the fields not included in the signature.  */
-  if (DECL_P (t))
-    DECL_CHAIN (t) = NULL;
-  if (HAS_RTL_P (t))
-    SET_DECL_RTL (t, NULL);
-  TREE_USED (t) = 0;
-
-  crc = xcrc32 ((const unsigned char *) t, nbytes, -1);
-
-  /* Restore fields we did not include in the signature.  */
-  if (DECL_P (t))
-    DECL_CHAIN (t) = prev_chain;
-  if (HAS_RTL_P (t))
-    SET_DECL_RTL (t, prev_rtl);
-  TREE_USED (t) = prev_used;
-
-  return crc;
-}
Index: gcc/cp/config-lang.in
===================================================================
--- gcc/cp/config-lang.in	(revision 181815)
+++ gcc/cp/config-lang.in	(working copy)
@@ -30,4 +30,4 @@ compilers="cc1plus\$(exeext)"
 
 target_libs="target-libstdc++-v3"
 
-gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/cp-lang.c \$(srcdir)/cp/pph.h \$(srcdir)/cp/pph.c \$(srcdir)/cp/except.c"
+gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/cp-lang.c \$(srcdir)/cp/pph.h \$(srcdir)/cp/pph-core.c \$(srcdir)/cp/except.c"
Index: gcc/cp/pph-streamer-out.c
===================================================================
--- gcc/cp/pph-streamer-out.c	(revision 181815)
+++ gcc/cp/pph-streamer-out.c	(working copy)
@@ -1,2629 +0,0 @@
-/* Routines for writing PPH data.
-   Copyright (C) 2011 Free Software Foundation, Inc.
-   Contributed by Diego Novillo <dnovillo@google.com>.
-
-   This file is part of GCC.
-
-   GCC is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3, or (at your option)
-   any later version.
-
-   GCC is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "pph.h"
-#include "tree.h"
-#include "langhooks.h"
-#include "tree-iterator.h"
-#include "tree-pretty-print.h"
-#include "lto-streamer.h"
-#include "pph-streamer.h"
-#include "tree-pass.h"
-#include "version.h"
-#include "cppbuiltin.h"
-#include "cgraph.h"
-#include "parser.h"
-
-
-/****************************************************** forward declarations */
-
-
-/* Forward declarations to avoid circular references.  */
-static void pph_out_merge_key_tree (pph_stream *, tree);
-
-
-/***************************************************** stream initialization */
-
-
-/* PPH stream that we are currently generating.  FIXME pph, this
-   global is needed because we call back from various parts of the
-   compiler that do not know about PPH (e.g., some LTO callbacks,
-   cp_rest_of_decl_compilation).  */
-static pph_stream *pph_out_stream = NULL;
-
-
-/* Initialize buffers and tables in STREAM for writing.  */
-
-void
-pph_init_write (pph_stream *stream)
-{
-  stream->encoder.w.out_state = lto_new_out_decl_state ();
-  lto_push_out_decl_state (stream->encoder.w.out_state);
-  stream->encoder.w.decl_state_stream = XCNEW (struct lto_output_stream);
-  stream->encoder.w.ob = create_output_block (LTO_section_decls);
-
-  /* Associate STREAM with stream->encoder.w.ob so we can recover it from the
-     streamer hooks.  */
-  stream->encoder.w.ob->sdata = (void *) stream;
-}
-
-
-/* Initialize the PPH writer.  */
-
-void
-pph_writer_init (void)
-{
-  gcc_assert (pph_out_stream == NULL);
-  pph_out_stream = pph_stream_open (pph_out_file, "wb");
-  if (pph_out_stream == NULL)
-    fatal_error ("Cannot open PPH file %s for writing: %m", pph_out_file);
-}
-
-
-/********************************************************** primitive values */
-
-
-/* Write an unsigned char VALUE to STREAM.  */
-
-static void
-pph_out_uchar (pph_stream *stream, unsigned char value)
-{
-  streamer_write_char_stream (stream->encoder.w.ob->main_stream, 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);
-}
-
-
-/* Write an int VALUE to stream.  */
-
-static inline void
-pph_out_int (pph_stream *stream, int value)
-{
-  streamer_write_hwi (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 an unsigned int VALUE to STREAM.  */
-
-void
-pph_out_uint (pph_stream *stream, unsigned int value)
-{
-  streamer_write_uhwi (stream->encoder.w.ob, value);
-}
-
-
-/* Write N bytes from P to STREAM.  */
-
-static void
-pph_out_bytes (pph_stream *stream, const void *p, size_t n)
-{
-  lto_output_data_stream (stream->encoder.w.ob->main_stream, p, n);
-}
-
-
-/* Write string STR to STREAM.  */
-
-static inline void
-pph_out_string (pph_stream *stream, const char *str)
-{
-  streamer_write_string (stream->encoder.w.ob,
-                         stream->encoder.w.ob->main_stream, str, false);
-}
-
-
-/* Write string STR of length LEN to STREAM.  */
-static inline void
-pph_out_string_with_length (pph_stream *stream, const char *str,
-                            unsigned int len)
-{
-  streamer_write_string_with_length (stream->encoder.w.ob,
-                                     stream->encoder.w.ob->main_stream,
-                                     str, len + 1, false);
-}
-
-
-/* Write a bitpack BP to STREAM.  */
-
-static inline void
-pph_out_bitpack (pph_stream *stream, struct bitpack_d *bp)
-{
-  gcc_assert (stream->encoder.w.ob->main_stream == bp->stream);
-  streamer_write_bitpack (bp);
-}
-
-
-/******************************************************** source information */
-
-
-/* Emit linenum_type LN to STREAM.  */
-
-static inline void
-pph_out_linenum_type (pph_stream *stream, linenum_type ln)
-{
-  pph_out_uint (stream, ln);
-}
-
-
-/* Emit source_location SL to STREAM.  */
-
-static inline void
-pph_out_source_location (pph_stream *stream, source_location sl)
-{
-  pph_out_uint (stream, sl);
-}
-
-
-/* Emit line table MARKER to STREAM.  */
-
-static inline void
-pph_out_linetable_marker (pph_stream *stream, enum pph_linetable_marker marker)
-{
-  gcc_assert (marker == (enum pph_linetable_marker)(unsigned char) marker);
-  pph_out_uchar (stream, marker);
-}
-
-
-/* Emit all the fields of struct line_map_ordinary LM to STREAM.  IX
-   is the slot number in the line table where LM is stored.  */
-
-static void
-pph_out_line_map_ordinary (pph_stream *stream, struct line_map *lm, int ix)
-{
-  struct bitpack_d bp;
-  int rel_includer_ix, includer_ix;
-
-  pph_out_string (stream, ORDINARY_MAP_FILE_NAME (lm));
-  pph_out_linenum_type (stream, ORDINARY_MAP_STARTING_LINE_NUMBER (lm));
-
-  /* To support relocating this table into other translation units,
-     emit a relative index to LM's includer.  All the relative indices
-     are positive values indicating the distance from LM to the line
-     map for its includer.  */
-  includer_ix = ORDINARY_MAP_INCLUDER_FILE_INDEX (lm);
-  if (includer_ix >= 0)
-    {
-      gcc_assert (includer_ix < ix);
-      rel_includer_ix = ix - includer_ix;
-    }
-  else
-    {
-      /* If LM is included by index -1, it means that this is a line map
-	 entry for the top level file being compiled (i.e., the PPH that
-	 we are currently generating).  The first time we find this index,
-	 the reader will remember the index of the current parent file
-	 and replace all the -1 entries with it.  */
-      gcc_assert (includer_ix == -1);
-      rel_includer_ix = includer_ix;
-    }
-
-  pph_out_int (stream, rel_includer_ix);
-
-  bp = bitpack_create (stream->encoder.w.ob->main_stream);
-  bp_pack_value (&bp, ORDINARY_MAP_IN_SYSTEM_HEADER_P (lm), CHAR_BIT);
-  bp_pack_value (&bp, ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (lm), COLUMN_BITS_BIT);
-  pph_out_bitpack (stream, &bp);
-}
-
-
-/* Emit all information contained in LM to STREAM.  IX is the slot number
-   in the line table where LM is stored.  */
-
-static void
-pph_out_line_map (pph_stream *stream, struct line_map *lm, int ix)
-{
-  struct output_block *ob = stream->encoder.w.ob;
-
-  pph_out_source_location (stream, lm->start_location);
-  streamer_write_enum (ob->main_stream, lc_reason, LC_ENTER_MACRO, lm->reason);
-
-  /* FIXME pph.  We currently do not support location tracking for
-     macros in PPH images.  */
-  gcc_assert (lm->reason != LC_ENTER_MACRO);
-  pph_out_line_map_ordinary (stream, lm, ix);
-}
-
-
-/* Write a reference of INCLUDE to STREAM.  Also write the START_LOCATION of
-   this include in the current line_table.  */
-
-static void
-pph_out_include (pph_stream *stream, pph_stream *include,
-                 source_location start_location)
-{
-  pph_out_source_location (stream, start_location);
-  pph_out_string (stream, include->name);
-}
-
-
-/* Compare filenames of a header and it's potentially corresponding pph file,
-   stripping the path passed in and the extension. Returns true if HEADER_PATH
-   and PPH_PATH end with the same filename. We expect HEADER_PATH to end in .h
-   and PPH_PATH to end in .pph.
-
-   FIXME pph: We should not need to do this if we handled include paths
-   correctly, but for now the linemap holds full paths and the stream's includes
-   list only holds the include name.  Also, the stream's includes hold pph
-   filenames where as the line_table as header filenames.  */
-
-static bool
-pph_filename_eq_ignoring_path (const char *header_path, const char *pph_path)
-{
-  const char *header_name = lbasename (header_path);
-  const char *pph_name = lbasename (pph_path);
-
-  const char *header_ext = strchr (header_name, '.');
-  const char *pph_ext = strchr (pph_name, '.');
-
-  unsigned int name_length;
-
-  if (header_ext != NULL)
-    {
-      name_length = header_ext - header_name;
-      gcc_assert (strcmp (header_ext, ".h") == 0);
-    }
-  else
-    /* Some headers do not have a .h suffix, but will still
-       have a .pph suffix after being pph'ed.  */
-    name_length = strlen (header_name);
-
-  gcc_assert (strcmp (pph_ext, ".pph") == 0);
-
-  /* Compare the filenames without their extension.  */
-  return pph_ext - pph_name == name_length
-         && strncmp (header_name, pph_name, name_length) == 0;
-}
-
-
-/* Return the *NEXT_INCLUDE_IX'th pph_stream in STREAM's list of includes.
-   Returns NULL if we have read all includes.  Increments *NEXT_INCLUDE_IX
-   when sucessful.  */
-
-static inline pph_stream *
-pph_get_next_include (pph_stream *stream, unsigned int *next_incl_ix)
-{
-  if (*next_incl_ix < VEC_length (pph_stream_ptr, stream->includes))
-    return VEC_index (pph_stream_ptr, stream->includes, (*next_incl_ix)++);
-  else
-    return NULL;
-}
-
-
-/* Emit the required line_map entry (those directly related to this include)
-   and some properties in the line_table to STREAM, ignoring builtin and
-   command-line entries.  We will write references to our direct includes
-   children and skip their actual line_map entries (unless they are non-pph
-   children in which case we have to write out their line_map entries as well).
-   We assume stream->encoder.w.includes contains the pph headers included in the
-   same order they are seen in the line_table.  */
-
-static void
-pph_out_line_table_and_includes (pph_stream *stream)
-{
-  unsigned int next_incl_ix = 0;
-  int ix;
-  pph_stream *current_include;
-
-  /* Any #include should have been fully parsed and exited at this point.  */
-  gcc_assert (line_table->depth == 0);
-
-  current_include = pph_get_next_include (stream, &next_incl_ix);
-
-  for (ix = PPH_NUM_IGNORED_LINE_TABLE_ENTRIES;
-       ix < (int) LINEMAPS_ORDINARY_USED (line_table);
-       ix++)
-    {
-      struct line_map *lm = LINEMAPS_ORDINARY_MAP_AT (line_table, ix);
-
-      /* FIXME pph.  We currently do not support location tracking for
-	 macros in PPH images.  */
-      gcc_assert (lm->reason != LC_ENTER_MACRO);
-
-      if (ix == PPH_NUM_IGNORED_LINE_TABLE_ENTRIES)
-        {
-	  /* The first non-ignored entry should be an LC_RENAME back
-	     in the header after inserting the builtin and
-	     command-line entries.  When reading the pph we want this
-	     to be a simple LC_ENTER as the builtin and command_line
-	     entries will already exist and we are now entering a
-             #include.  */
-          gcc_assert (lm->reason == LC_RENAME);
-          lm->reason = LC_ENTER;
-        }
-
-      /* If LM is an entry for an included PPH image, output a line table
-	 reference to it, so the reader can load the included image at
-	 this point.  */
-      if (current_include != NULL
-	  && pph_filename_eq_ignoring_path (LINEMAP_FILE (lm),
-	                                    current_include->name))
-	{
-	  struct line_map *included_from;
-
-	  /* Assert that we are entering a new header file from another.  */
-	  gcc_assert (lm->reason == LC_ENTER);
-	  gcc_assert (ORDINARY_MAP_INCLUDER_FILE_INDEX (lm) != -1);
-
-	  pph_out_linetable_marker (stream, PPH_LINETABLE_REFERENCE);
-
-	  pph_out_include (stream, current_include, lm->start_location);
-
-	  /* Since all the line table entries corresponding to
-	     CURRENT_INCLUDE and its #include children are emitted
-	     inside CURRENT_INCLUDE, we need to skip them so they do
-	     not get emitted in STREAM.
-
-	     To do this, we look for the next line map table that
-	     corresponds to an LC_LEAVE event back to the file that
-	     includes CURRENT_INCLUDE (which is represented by the
-	     line map LM).  */
-	  included_from = INCLUDED_FROM (line_table, lm);
-	  for (ix++; ix < (int) LINEMAPS_ORDINARY_USED (line_table); ix++)
-	    {
-	      struct line_map *map = LINEMAPS_ORDINARY_MAP_AT (line_table, ix);
-
-	      /* When we find an LC_LEAVE map, we have two ways of
-		 deciding if it is an LC_LEAVE event back to
-		 INCLUDED_FROM.  Either MAP goes to the same file name
-		 as INCLUDED_FROM or both MAP and INCLUDED_FROM are
-		 included by the same line map.  Since the latter is
-		 faster, we check it instead of doing a string
-		 comparison.  */
-	      if (map->reason == LC_LEAVE
-		  && ORDINARY_MAP_INCLUDER_FILE_INDEX (included_from)
-		     == ORDINARY_MAP_INCLUDER_FILE_INDEX (map))
-		break;
-	    }
-
-	    /* We should always leave this loop before the end of the
-		current line_table entries.  */
-	    gcc_assert (ix < (int) LINEMAPS_ORDINARY_USED (line_table));
-
-	  current_include = pph_get_next_include (stream, &next_incl_ix);
-	}
-      else
-	{
-	  pph_out_linetable_marker (stream, PPH_LINETABLE_ENTRY);
-	  pph_out_line_map (stream, lm, ix);
-	}
-
-      /* Restore changes made to the first entry above, if needed.  */
-      if (ix == PPH_NUM_IGNORED_LINE_TABLE_ENTRIES)
-	lm->reason = LC_RENAME;
-    }
-
-  pph_out_linetable_marker (stream, PPH_LINETABLE_END);
-
-  /* Output the number of entries written to validate on input.  */
-  pph_out_uint (stream, LINEMAPS_ORDINARY_USED (line_table)
-                        - PPH_NUM_IGNORED_LINE_TABLE_ENTRIES);
-
-  /* Every PPH header included should have been seen and skipped in the
-     line_table streaming above.  */
-  gcc_assert (next_incl_ix == VEC_length (pph_stream_ptr, stream->includes));
-
-  pph_out_source_location (stream, line_table->highest_location);
-  pph_out_source_location (stream, line_table->highest_line);
-
-  pph_out_uint (stream, line_table->max_column_hint);
-}
-
-
-/*********************************************************** record handling */
-
-
-/* Return a PPH record marker according to whether DATA is NULL or
-   it can be found in one of the caches associated with STREAM.  TAG
-   is the data type for DATA.
-
-   If DATA is in any of the caches, return the corresponding slot in
-   *IX_P.  If DATA is in the cache of an image included by STREAM,
-   return the image's index in *INCLUDE_IX_P.
-
-   Caches are consulted in order of preference: preloaded, internal
-   and external.
-
-   If DATA is not found anywhere, return PPH_RECORD_START and, if
-   given, set *IX_P and *INCLUDE_IX_P to -1.  */
-
-static enum pph_record_marker
-pph_get_marker_for (pph_stream *stream, void *data, unsigned *include_ix_p,
-                    unsigned *ix_p, enum pph_tag tag)
-{
-  if (ix_p)
-    *ix_p = -1u;
-
-  if (include_ix_p)
-    *include_ix_p = -1u;
-
-  /* We represent NULL pointers with PPH_RECORD_END.  */
-  if (data == NULL)
-    return PPH_RECORD_END;
-
-  /* If DATA is a pre-loaded tree node, return a pre-loaded reference
-     marker.  */
-  if (pph_cache_lookup (NULL, data, ix_p, tag))
-    return PPH_RECORD_PREF;
-
-  /* If DATA is in STREAM's cache, return an internal reference marker.  */
-  if (pph_cache_lookup (&stream->cache, data, ix_p, tag))
-    return PPH_RECORD_IREF;
-
-  /* If DATA is in the cache of an included image, return an external
-     reference marker.  */
-  if (pph_cache_lookup_in_includes (stream, data, include_ix_p, ix_p, tag))
-    return PPH_RECORD_XREF;
-
-  /* DATA is in none of the caches.  It should be pickled out.  */
-  return PPH_RECORD_START;
-}
-
-
-/* Write record MARKER for data type TAG to STREAM.  */
-void
-pph_out_record_marker (pph_stream *stream, enum pph_record_marker marker,
-                       enum pph_tag tag)
-{
-  gcc_assert (marker == (enum pph_record_marker)(unsigned char) marker);
-  pph_out_uchar (stream, marker);
-
-  gcc_assert (tag == (enum pph_tag)(unsigned) tag);
-  pph_out_uint (stream, tag);
-
-  if (flag_pph_tracer >= 5)
-    pph_trace_marker (marker, tag);
-}
-
-
-/* Write a reference record on STREAM.  MARKER is the tag indicating
-   what kind of reference to write.  TAG indicates the data type to be
-   stored in this record.  IX is the cache slot index to write.
-   INCLUDE_IX is used for PPH_RECORD_XREF records.  */
-
-static inline void
-pph_out_reference_record (pph_stream *stream, enum pph_record_marker marker,
-                          unsigned include_ix, unsigned ix, enum pph_tag tag)
-{
-  gcc_assert (marker == PPH_RECORD_END || pph_is_reference_marker (marker));
-
-  pph_out_record_marker (stream, marker, tag);
-
-  if (pph_is_reference_marker (marker))
-    {
-      if (marker == PPH_RECORD_XREF)
-        {
-          gcc_assert (include_ix != -1u);
-          pph_out_uint (stream, include_ix);
-        }
-
-      gcc_assert (ix != -1u);
-      pph_out_uint (stream, ix);
-    }
-  else
-    gcc_assert (marker == PPH_RECORD_END);
-}
-
-
-/* Start a new record in STREAM for DATA with data type TAG.  If DATA
-   is NULL write an end-of-record marker and return true.
-
-   If DATA is not NULL and did not exist in the pickle cache, add it,
-   write a start-of-record marker and return true.  This means that we
-   could not write a reference marker to DATA and the caller should
-   pickle out DATA's physical representation.
-
-   If DATA existed in the cache, write a reference-record marker and
-   return true.  This means that we could write a reference marker to
-   DATA.  */
-
-static inline bool
-pph_out_start_record (pph_stream *stream, void *data, enum pph_tag tag)
-{
-  unsigned include_ix, ix;
-  enum pph_record_marker marker;
-
-  /* Try to write a reference record first.  */
-  marker = pph_get_marker_for (stream, data, &include_ix, &ix, tag);
-  if (marker == PPH_RECORD_END || pph_is_reference_marker (marker))
-    {
-      pph_out_reference_record (stream, marker, include_ix, ix, tag);
-      return true;
-    }
-
-  /* DATA is in none of the pickle caches.  Add DATA to STREAM's
-     pickle cache and write the slot where we stored it in.  */
-  pph_cache_add (&stream->cache, data, &ix, tag);
-  pph_out_record_marker (stream, PPH_RECORD_START, tag);
-  pph_out_uint (stream, ix);
-
-  /* The caller will have to write a physical representation for DATA.  */
-  return false;
-}
-
-
-/* Return true if tree node T should be added to the pickle cache.  */
-
-static inline bool
-pph_cache_should_handle (tree t)
-{
-  if (t)
-    {
-      if (TREE_CODE (t) == INTEGER_CST)
-        {
-          /* With the exception of some special constants that are
-            pointer-compared everywhere (e.g., integer_zero_node), we
-            do not want constants in the cache.  Their physical
-            representation is smaller than a cache reference record
-            and they can also trick the cache in similar ways to
-            builtins (read below).  */
-          return false;
-        }
-      else if (streamer_handle_as_builtin_p (t))
-        {
-          /* We do not want builtins in the cache for two reasons:
-
-            - They never need pickling.  Much like pre-loaded tree
-              nodes, builtins are pre-built by the compiler and
-              accessible with their class and code.
-
-            - They can trick the cache.  When possible, user-provided
-              functions are generally replaced by their builtin
-              counterparts (e.g., strcmp, malloc, etc).  When this
-              happens, the writer cache will store in its cache two
-              different expressions, one for the user provided
-              function and another for the builtin itself.  However,
-              when written out to the PPH image, they both get
-              emitted as a reference to the builtin.  Therefore, when
-              the reader tries to instantiate the second copy, it
-              tries to store the same tree in two different cache
-              slots (and proceeds to ICE in pph_cache_insert_at).  */
-          return false;
-        }
-    }
-
-  return true;
-}
-
-
-/* Start a record for tree node T in STREAM.  This is like
-   pph_out_start_record, but it filters certain special trees that
-   should never be added to the cache.  Additionally, instead of
-   returning a boolean value indicating whether pickling should be
-   done, it returns the actual marker used to start the record.  */
-
-static inline enum pph_record_marker
-pph_out_start_tree_record (pph_stream *stream, tree t)
-{
-  unsigned include_ix, ix;
-  enum pph_record_marker marker;
-  enum pph_tag tag;
-
-  /* Determine what kind of record we will be writing.  */
-  tag = pph_tree_code_to_tag (t);
-  marker = pph_get_marker_for (stream, t, &include_ix, &ix, tag);
-
-  /* Signed tree nodes that have been read from an external PPH image
-     may have mutated while parsing this header.  In that case,
-     we need to write a mutated reference record and re-pickle the
-     tree.  */
-  if (marker == PPH_RECORD_XREF && tree_needs_signature (t))
-    {
-      pph_cache *cache = pph_cache_select (stream, marker, include_ix);
-      pph_cache_entry *e = pph_cache_get_entry (cache, ix);
-      unsigned crc = pph_get_signature (t, NULL);
-      if (crc != e->crc)
-        marker = PPH_RECORD_START_MUTATED;
-    }
-
-  /* If we are about to write an internal reference for a mergeable
-     tree, it means that we have already written the merge key for it.
-     Check whether we still need to write its merge body.  If so,
-     MARKER should be PPH_RECORD_START_MERGE_BODY.  */
-  if (marker == PPH_RECORD_IREF && pph_tree_is_mergeable (t))
-    {
-      pph_cache_entry *e = pph_cache_get_entry (&stream->cache, ix);
-      if (e->needs_merge_body)
-	{
-	  marker = PPH_RECORD_START_MERGE_BODY;
-	  e->needs_merge_body = false;
-	}
-    }
-
-  /* Write a record header according to the value of MARKER.  */
-  if (marker == PPH_RECORD_END || pph_is_reference_marker (marker))
-    pph_out_reference_record (stream, marker, include_ix, ix, tag);
-  else if (marker == PPH_RECORD_START || marker == PPH_RECORD_START_MERGE_BODY)
-    {
-      /* We want to prevent some trees from hitting the cache.
-         For example, we do not want to cache regular constants (as
-         their representation is actually smaller than a cache
-         reference), but some constants are special and need to
-         always be shared (e.g., integer_zero_node).  Those special
-         constants are pre-loaded in STREAM->PRELOADED_CACHE.  */
-      if (!pph_cache_should_handle (t))
-        marker = PPH_RECORD_START_NO_CACHE;
-
-      pph_out_record_marker (stream, marker, tag);
-
-      if (marker == PPH_RECORD_START || marker == PPH_RECORD_START_MERGE_BODY)
-        {
-          unsigned ix;
-          pph_cache_add (&stream->cache, t, &ix, tag);
-          pph_out_uint (stream, ix);
-        }
-    }
-  else if (marker == PPH_RECORD_START_MUTATED)
-    {
-      unsigned int internal_ix;
-
-      /* We found T in an external PPH file, but it has mutated since
-         we originally read it.  We are going to write out T again,
-         but the reader should not re-allocate T, rather it should
-         read the contents of T on top of the existing address.
-
-         We also add T to STREAM's internal cache so further
-         references go to it rather than the external version.
-         Note that although we add an entry for T in STREAM's internal
-         cache, the reference we write to the stream is to the
-         external version of T.  This way the reader will get the
-         location of T from the external reference and overwrite it
-         with the contents that we are going to write here.  */
-      pph_cache_add (&stream->cache, t, &internal_ix, tag);
-      pph_out_record_marker (stream, marker, tag);
-
-      /* Write the location of T in the external cache.  */
-      gcc_assert (include_ix != -1u);
-      pph_out_uint (stream, include_ix);
-
-      gcc_assert (ix != -1u);
-      pph_out_uint (stream, ix);
-
-      /* Now write the location of the new version of T in the
-         internal cache.  */
-      pph_out_uint (stream, internal_ix);
-    }
-  else
-    gcc_unreachable ();
-
-  return marker;
-}
-
-
-/* Start a merge key record for EXPR on STREAM.  */
-
-static bool
-pph_out_start_merge_key_record (pph_stream *stream, tree expr)
-{
-  enum pph_tag tag;
-  enum pph_record_marker marker;
-  pph_cache_entry *e;
-  unsigned include_ix, ix;
-
-  tag = pph_tree_code_to_tag (expr);
-  marker = pph_get_marker_for (stream, expr, &include_ix, &ix, tag);
-
-  if (marker == PPH_RECORD_END || pph_is_reference_marker (marker))
-    {
-      pph_out_reference_record (stream, marker, include_ix, ix, tag);
-      return true;
-    }
-
-  /* This should be the first time that we try to write EXPR.  */
-  gcc_assert (marker == PPH_RECORD_START);
-
-  pph_out_record_marker (stream, PPH_RECORD_START_MERGE_KEY, tag);
-  e = pph_cache_add (&stream->cache, expr, &ix, tag);
-  e->needs_merge_body = true;
-  pph_out_uint (stream, ix);
-  return false;
-}
-
-
-
-/********************************************************** lexical elements */
-
-
-/* Write location LOC of length to STREAM.  */
-
-void
-pph_out_location (pph_stream *stream, location_t loc)
-{
-  /* FIXME pph: we are streaming builtin locations, which implies that we are
-     streaming some builtins, we probably want to figure out what those are and
-     simply add them to the cache in the preload.  */
-  struct bitpack_d bp;
-  struct line_map *map;
-  location_t first_non_builtin_loc;
-
-  map = LINEMAPS_ORDINARY_MAP_AT (line_table,
-				  PPH_NUM_IGNORED_LINE_TABLE_ENTRIES);
-  first_non_builtin_loc = MAP_START_LOCATION (map);
-
-  bp = bitpack_create (stream->encoder.w.ob->main_stream);
-  if (loc < first_non_builtin_loc)
-    {
-      /* We should never stream out trees with locations between builtins
-	 and user locations (e.g. <command-line>).  */
-      gcc_assert (loc <= BUILTINS_LOCATION);
-      bp_pack_value (&bp, true, 1);
-    }
-  else
-    bp_pack_value (&bp, false, 1);
-
-  pph_out_bitpack (stream, &bp);
-  pph_out_uhwi (stream, loc);
-}
-
-
-/* Save the tree associated with TOKEN to STREAM.  */
-
-static void
-pph_out_token_value (pph_stream *stream, cp_token *token)
-{
-  tree val;
-
-  val = token->u.value;
-  switch (token->type)
-    {
-      case CPP_TEMPLATE_ID:
-      case CPP_NESTED_NAME_SPECIFIER:
-	/* FIXME pph - Need to handle struct tree_check.  */
-	break;
-
-      case CPP_KEYWORD:
-	/* Nothing to do.  We will reconstruct the keyword from
-	   ridpointers[token->keyword] at load time.  */
-	break;
-
-      case CPP_NAME:
-      case CPP_CHAR:
-      case CPP_WCHAR:
-      case CPP_CHAR16:
-      case CPP_CHAR32:
-      case CPP_NUMBER:
-      case CPP_STRING:
-      case CPP_WSTRING:
-      case CPP_STRING16:
-      case CPP_STRING32:
-	pph_out_tree (stream, val);
-	break;
-
-      case CPP_PRAGMA:
-	/* Nothing to do.  Field pragma_kind has already been written.  */
-	break;
-
-      default:
-	gcc_assert (token->u.value == NULL);
-	pph_out_bytes (stream, &token->u.value, sizeof (token->u.value));
-    }
-}
-
-
-/* Save TOKEN on file F.  Return the number of bytes written on F.  */
-
-static void
-pph_out_token (pph_stream *f, cp_token *token)
-{
-  /* Do not write out the final field in TOKEN.  It contains
-     pointers that need to be pickled separately.
-
-     FIXME pph - Need to also emit the location_t table so we can
-     reconstruct it when reading the PTH state.  */
-  pph_out_bytes (f, token, sizeof (cp_token) - sizeof (void *));
-  pph_out_token_value (f, token);
-}
-
-
-/* Save all the tokens in CACHE to PPH stream F.  */
-
-static void
-pph_out_token_cache (pph_stream *f, cp_token_cache *cache)
-{
-  unsigned i, num;
-  cp_token *tok;
-
-  if (cache == NULL)
-    {
-      pph_out_uint (f, 0);
-      return;
-    }
-
-  for (num = 0, tok = cache->first; tok != cache->last; tok++)
-    num++;
-
-  pph_out_uint (f, num);
-  for (i = 0, tok = cache->first; i < num; tok++, i++)
-    pph_out_token (f, tok);
-}
-
-
-/******************************************************************* vectors */
-
-/* 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.  */
-
-/* Return true if T matches FILTER for STREAM.  */
-
-static inline bool
-pph_tree_matches (pph_stream *stream, tree t, unsigned filter)
-{
-  if ((filter & PPHF_NO_BUILTINS)
-      && DECL_P (t)
-      && DECL_IS_BUILTIN (t))
-    return false;
-
-  if ((filter & PPHF_NO_PREFS)
-      && pph_cache_lookup (NULL, t, NULL, pph_tree_code_to_tag (t)))
-    return false;
-
-  if ((filter & PPHF_NO_XREFS)
-      && pph_cache_lookup_in_includes (stream, t, NULL, NULL,
-	                               pph_tree_code_to_tag (t)))
-    return false;
-
-  return true;
-}
-
-
-/* Return a heap vector with all the trees in V that match FILTER.
-   The caller is responsible for freeing the returned vector.  */
-
-static inline VEC(tree,heap) *
-vec2vec_filter (pph_stream *stream, VEC(tree,gc) *v, unsigned filter)
-{
-  unsigned i;
-  tree t;
-  VEC(tree, heap) *filtered_v = NULL;
-
-  /* Do not accept the nil filter.  The caller is responsible for
-     freeing the returned vector and they may inadvertently free
-     a vector they assumed to be allocated by this function.  */
-  gcc_assert (filter != PPHF_NONE);
-
-  /* Collect all the nodes that match the filter.  */
-  FOR_EACH_VEC_ELT (tree, v, i, t)
-    if (pph_tree_matches (stream, t, filter))
-      VEC_safe_push (tree, heap, filtered_v, t);
-
-  return filtered_v;
-}
-
-
-/* Write all the trees in VEC V to STREAM.  */
-
-static void
-pph_out_tree_vec (pph_stream *stream, VEC(tree,gc) *v)
-{
-  unsigned i;
-  tree t;
-  pph_out_hwi (stream, VEC_length (tree, v));
-  FOR_EACH_VEC_ELT (tree, v, i, t)
-    pph_out_tree (stream, t);
-}
-
-
-/* Write all the trees in VEC V to STREAM.
-   Clear TREE_CHAIN on every element written out (this is to support
-   writing chains, as they are supposed to be re-chained by the reader).  */
-
-static void
-pph_out_tree_vec_unchain (pph_stream *stream, VEC(tree,gc) *v)
-{
-  unsigned i;
-  tree t;
-  pph_out_hwi (stream, VEC_length (tree, v));
-  FOR_EACH_VEC_ELT (tree, v, i, t)
-    {
-      tree prev = TREE_CHAIN (t);
-      TREE_CHAIN (t) = NULL;
-      pph_out_tree (stream, t);
-      TREE_CHAIN (t) = prev;
-    }
-}
-
-
-/* Write all the merge keys for trees in VEC V to STREAM.  The keys
-   must go out in declaration order, i.e. reversed.  */
-
-static void
-pph_out_merge_key_vec (pph_stream *stream, VEC(tree,gc) *v)
-{
-  unsigned i;
-  tree t;
-  pph_out_hwi (stream, VEC_length (tree, v));
-  FOR_EACH_VEC_ELT_REVERSE (tree, v, i, t)
-    pph_out_merge_key_tree (stream, t);
-}
-
-
-/* Write all the merge bodies for trees in VEC V to STREAM.  The bodies
-   should/must go out in declaration order, i.e. reversed.  */
-
-static void
-pph_out_merge_body_vec (pph_stream *stream, VEC(tree,gc) *v)
-{
-  unsigned i;
-  tree t;
-  pph_out_hwi (stream, VEC_length (tree, v));
-  FOR_EACH_VEC_ELT_REVERSE (tree, v, i, t)
-    pph_out_tree (stream, t);
-}
-
-
-/* Write all the trees in VEC V that match FILTER to STREAM.  */
-
-static void
-pph_out_tree_vec_filtered (pph_stream *stream, VEC(tree,gc) *v, unsigned filter)
-{
-  if (filter == PPHF_NONE)
-    pph_out_tree_vec (stream, v);
-  else
-    {
-      VEC(tree,heap) *w = vec2vec_filter (stream, v, filter);
-      pph_out_tree_vec (stream, (VEC(tree,gc) *)w);
-      VEC_free (tree, heap, w);
-    }
-}
-
-
-/* Write all the qualified_typedef_usage_t in VEC V to STREAM.  */
-
-static void
-pph_out_qual_use_vec (pph_stream *stream, VEC(qualified_typedef_usage_t,gc) *v)
-{
-  unsigned i;
-  qualified_typedef_usage_t *q;
-
-  pph_out_uint (stream, VEC_length (qualified_typedef_usage_t, v));
-  FOR_EACH_VEC_ELT (qualified_typedef_usage_t, v, i, q)
-    {
-      pph_out_tree (stream, q->typedef_decl);
-      pph_out_tree (stream, q->context);
-      pph_out_location (stream, q->locus);
-    }
-}
-
-
-/* Write the vector V of tree_pair_s instances to STREAM.  */
-
-static void
-pph_out_tree_pair_vec (pph_stream *stream, VEC(tree_pair_s,gc) *v)
-{
-  unsigned i;
-  tree_pair_s *p;
-
-  pph_out_uint (stream, VEC_length (tree_pair_s, v));
-  FOR_EACH_VEC_ELT (tree_pair_s, v, i, p)
-    {
-      pph_out_tree (stream, p->purpose);
-      pph_out_tree (stream, p->value);
-    }
-}
-
-
-/******************************************************************** chains */
-
-/* Convert a CHAIN to a VEC by copying only the nodes that match FILTER
-   for STREAM.  */
-
-static VEC(tree,heap) *
-chain2vec_filter (pph_stream *stream, tree chain, unsigned filter)
-{
-  tree t;
-  VEC(tree,heap) *v = NULL;
-
-  /* Do not accept the nil filter.  The caller is responsible for
-     freeing the returned vector and they may inadvertently free
-     a vector they assumed to be allocated by this function.  */
-  /* FIXME crowl: gcc_assert (filter != PPHF_NONE); */
-
-  for (t = chain; t; t = TREE_CHAIN (t))
-    if (pph_tree_matches (stream, t, filter))
-      VEC_safe_push (tree, heap, v, t);
-
-  return v;
-}
-
-
-/* Convert a CHAIN to a VEC by copying the nodes.  */
-
-static VEC(tree,heap) *
-chain2vec (tree chain)
-{
-  tree t;
-  VEC(tree,heap) *v = NULL;
-
-  for (t = chain; t; t = TREE_CHAIN (t))
-    VEC_safe_push (tree, heap, v, t);
-
-  return v;
-}
-
-
-/* Write a chain of trees to STREAM starting with FIRST.  */
-
-static void
-pph_out_chain (pph_stream *stream, tree first)
-{
-  streamer_write_chain (stream->encoder.w.ob, first, false);
-}
-
-
-/* Write a chain of trees to stream starting with FIRST.  Only write
-   the trees that match FILTER.  */
-
-static void
-pph_out_chain_filtered (pph_stream *stream, tree first, unsigned filter)
-{
-  VEC(tree,heap) *w = chain2vec_filter (stream, first, filter);
-  pph_out_tree_vec_unchain (stream, (VEC(tree,gc) *)w);
-  VEC_free (tree, heap, w);
-}
-
-
-/* Write, in reverse, a chain of merge keys to STREAM starting
-   with the last element of CHAIN.  Only write the trees that match
-   FILTER.  */
-
-static void
-pph_out_merge_key_chain (pph_stream *stream, tree chain, unsigned filter)
-{
-  VEC(tree,heap) *w;
-  if (filter == PPHF_NONE)
-    w = chain2vec (chain);
-  else
-    w = chain2vec_filter (stream, chain, filter);
-  pph_out_merge_key_vec (stream, (VEC(tree,gc) *)w);
-  VEC_free (tree, heap, w);
-}
-
-
-/* Write, in reverse, a chain of merge bodies to STREAM starting
-   with the last element of CHAIN.  Only write the trees that match
-   FILTER.  */
-
-static void
-pph_out_merge_body_chain (pph_stream *stream, tree chain, unsigned filter)
-{
-  VEC(tree,heap) *w;
-  if (filter == PPHF_NONE)
-    w = chain2vec (chain);
-  else
-    w = chain2vec_filter (stream, chain, filter);
-  pph_out_merge_body_vec (stream, (VEC(tree,gc) *)w);
-  VEC_free (tree, heap, w);
-}
-
-
-/****************************************************************** bindings */
-
-
-/* Forward declaration to break cyclic dependencies.  */
-static void pph_out_binding_level (pph_stream *, cp_binding_level *, unsigned);
-
-
-/* Helper for pph_out_cxx_binding.  STREAM and CB are as in
-   pph_out_cxx_binding.  */
-
-static void
-pph_out_cxx_binding_1 (pph_stream *stream, cxx_binding *cb)
-{
-  struct bitpack_d bp;
-
-  if (pph_out_start_record (stream, cb, PPH_cxx_binding))
-    return;
-
-  pph_out_tree (stream, cb->value);
-  pph_out_tree (stream, cb->type);
-  pph_out_binding_level (stream, cb->scope, PPHF_NONE);
-  bp = bitpack_create (stream->encoder.w.ob->main_stream);
-  bp_pack_value (&bp, cb->value_is_inherited, 1);
-  bp_pack_value (&bp, cb->is_local, 1);
-  pph_out_bitpack (stream, &bp);
-}
-
-
-/* Write all the fields of cxx_binding instance CB to STREAM.  */
-
-static void
-pph_out_cxx_binding (pph_stream *stream, cxx_binding *cb)
-{
-  cxx_binding *prev;
-
-  /* Write the current binding first.  */
-  pph_out_cxx_binding_1 (stream, cb);
-
-  /* Write the list of previous bindings.  */
-  for (prev = cb ? cb->previous : NULL; prev; prev = prev->previous)
-    pph_out_cxx_binding_1 (stream, prev);
-
-  /* Mark the end of the list (if there was a list).  */
-  if (cb)
-    pph_out_cxx_binding_1 (stream, NULL);
-}
-
-
-/* Write all the fields of cp_class_binding instance CB to STREAM.  */
-
-static void
-pph_out_class_binding (pph_stream *stream, cp_class_binding *cb)
-{
-  if (pph_out_start_record (stream, cb, PPH_cp_class_binding))
-    return;
-
-  pph_out_cxx_binding (stream, cb->base);
-  pph_out_tree (stream, cb->identifier);
-}
-
-
-/* Write all the fields of cp_label_binding instance LB to STREAM.  */
-
-static void
-pph_out_label_binding (pph_stream *stream, cp_label_binding *lb)
-{
-  if (pph_out_start_record (stream, lb, PPH_cp_label_binding))
-    return;
-
-  pph_out_tree (stream, lb->label);
-  pph_out_tree (stream, lb->prev_value);
-}
-
-
-/* Helper for pph_out_binding_level.  Write the fields of BL to
-   STREAM.  Do not emit any nodes in BL that do not match FILTER.  */
-
-static void
-pph_out_binding_level_1 (pph_stream *stream, cp_binding_level *bl,
-		         unsigned filter)
-{
-  unsigned i;
-  cp_class_binding *cs;
-  cp_label_binding *sl;
-  struct bitpack_d bp;
-
-  pph_out_tree (stream, bl->this_entity);
-
-  pph_out_uint (stream, VEC_length (cp_class_binding, bl->class_shadowed));
-  FOR_EACH_VEC_ELT (cp_class_binding, bl->class_shadowed, i, cs)
-    pph_out_class_binding (stream, cs);
-
-  pph_out_tree (stream, bl->type_shadowed);
-
-  pph_out_uint (stream, VEC_length (cp_label_binding, bl->shadowed_labels));
-  FOR_EACH_VEC_ELT (cp_label_binding, bl->shadowed_labels, i, sl)
-    pph_out_label_binding (stream, sl);
-
-  pph_out_tree (stream, bl->blocks);
-  pph_out_binding_level (stream, bl->level_chain, filter);
-  pph_out_tree_vec (stream, bl->dead_vars_from_for);
-  pph_out_chain (stream, bl->statement_list);
-  pph_out_uint (stream, bl->binding_depth);
-
-  bp = bitpack_create (stream->encoder.w.ob->main_stream);
-  bp_pack_value (&bp, bl->kind, 4);
-  bp_pack_value (&bp, bl->keep, 1);
-  bp_pack_value (&bp, bl->more_cleanups_ok, 1);
-  bp_pack_value (&bp, bl->have_cleanups, 1);
-  pph_out_bitpack (stream, &bp);
-}
-
-
-/* Write all the fields of cp_binding_level instance BL to STREAM for the
-   non-merging case.  Do not emit any nodes in BL that do not match FILTER.  */
-
-static void
-pph_out_binding_level (pph_stream *stream, cp_binding_level *bl,
-		       unsigned filter)
-{
-  if (pph_out_start_record (stream, bl, PPH_cp_binding_level))
-    return;
-
-  pph_out_chain_filtered (stream, bl->names, filter);
-  pph_out_chain_filtered (stream, bl->namespaces, filter);
-  pph_out_chain_filtered (stream, bl->usings, filter);
-  pph_out_chain_filtered (stream, bl->using_directives, filter);
-  pph_out_tree_vec_filtered (stream, bl->static_decls, filter);
-  pph_out_binding_level_1 (stream, bl, filter);
-}
-
-
-/* Write an index of mergeable objects from cp_binding_level BL to STREAM.  */
-
-static void
-pph_out_binding_merge_keys (pph_stream *stream, cp_binding_level *bl)
-{
-  unsigned filter = PPHF_NO_XREFS | PPHF_NO_PREFS | PPHF_NO_BUILTINS;
-  pph_out_merge_key_chain (stream, bl->names, filter);
-  pph_out_merge_key_chain (stream, bl->namespaces, filter);
-  pph_out_merge_key_chain (stream, bl->usings, filter);
-  pph_out_merge_key_chain (stream, bl->using_directives, filter);
-}
-
-
-/* Write bodies of mergeable objects from cp_binding_level BL to STREAM.  */
-
-static void
-pph_out_binding_merge_bodies (pph_stream *stream, cp_binding_level *bl)
-{
-  unsigned filter = PPHF_NO_XREFS | PPHF_NO_PREFS | PPHF_NO_BUILTINS;
-  pph_out_merge_body_chain (stream, bl->names, filter);
-  pph_out_merge_body_chain (stream, bl->namespaces, filter);
-  pph_out_merge_body_chain (stream, bl->usings, filter);
-  pph_out_merge_body_chain (stream, bl->using_directives, filter);
-  pph_out_tree_vec_filtered (stream, bl->static_decls, filter);
-  pph_out_binding_level_1 (stream, bl, filter);
-}
-
-
-/********************************************************** tree aux classes */
-
-
-/* Write all the fields of language_function instance LF to STREAM.  */
-
-static void
-pph_out_language_function (pph_stream *stream, struct language_function *lf)
-{
-  struct bitpack_d bp;
-
-  if (pph_out_start_record (stream, lf, PPH_language_function))
-    return;
-
-  pph_out_tree_vec (stream, lf->base.x_stmt_tree.x_cur_stmt_list);
-  pph_out_uint (stream, lf->base.x_stmt_tree.stmts_are_full_exprs_p);
-  pph_out_tree (stream, lf->x_cdtor_label);
-  pph_out_tree (stream, lf->x_current_class_ptr);
-  pph_out_tree (stream, lf->x_current_class_ref);
-  pph_out_tree (stream, lf->x_eh_spec_block);
-  pph_out_tree (stream, lf->x_in_charge_parm);
-  pph_out_tree (stream, lf->x_vtt_parm);
-  pph_out_tree (stream, lf->x_return_value);
-  bp = bitpack_create (stream->encoder.w.ob->main_stream);
-  bp_pack_value (&bp, lf->returns_value, 1);
-  bp_pack_value (&bp, lf->returns_null, 1);
-  bp_pack_value (&bp, lf->returns_abnormally, 1);
-  bp_pack_value (&bp, lf->x_in_function_try_handler, 1);
-  bp_pack_value (&bp, lf->x_in_base_initializer, 1);
-  bp_pack_value (&bp, lf->can_throw, 1);
-  pph_out_bitpack (stream, &bp);
-
-  /* FIXME pph.  We are not writing lf->x_named_labels.  */
-
-  pph_out_binding_level (stream, lf->bindings, PPHF_NONE);
-  pph_out_tree_vec (stream, lf->x_local_names);
-
-  /* FIXME pph.  We are not writing lf->extern_decl_map.  */
-}
-
-
-/* A callback of htab_traverse. Just extracts a (type) tree from SLOT
-   and writes it out for PPH. */
-
-struct pph_tree_info {
-  pph_stream *stream;
-};
-
-static int
-pph_out_used_types_slot (void **slot, void *aux)
-{
-  struct pph_tree_info *pti = (struct pph_tree_info *) aux;
-  pph_out_tree (pti->stream, (tree) *slot);
-  return 1;
-}
-
-
-/* Write applicable fields of struct function instance FN to STREAM.  */
-
-static void
-pph_out_struct_function (pph_stream *stream, struct function *fn)
-{
-  struct pph_tree_info pti;
-
-  if (pph_out_start_record (stream, fn, PPH_function))
-    return;
-
-  pph_out_tree (stream, fn->decl);
-  output_struct_function_base (stream->encoder.w.ob, fn);
-
-  /* struct eh_status *eh;					-- ignored */
-  gcc_assert (fn->cfg == NULL);
-  gcc_assert (fn->gimple_body == NULL);
-  gcc_assert (fn->gimple_df == NULL);
-  gcc_assert (fn->x_current_loops == NULL);
-  gcc_assert (fn->su == NULL);
-  /* htab_t value_histograms;					-- ignored */
-  /* tree decl;							-- ignored */
-  /* tree static_chain_decl;					-- in base */
-  /* tree nonlocal_goto_save_area;				-- in base */
-  /* VEC(tree,gc) *local_decls;					-- in base */
-  /* struct machine_function *machine;				-- ignored */
-  pph_out_language_function (stream, fn->language);
-
-  /* FIXME pph: We would like to detect improper sharing here.  */
-  if (fn->used_types_hash)
-    {
-      /* FIXME pph: This write may be unstable.  */
-      pph_out_uint (stream, htab_elements (fn->used_types_hash));
-      pti.stream = stream;
-      htab_traverse_noresize (fn->used_types_hash, pph_out_used_types_slot,
-			      &pti);
-    }
-  else
-    pph_out_uint (stream, 0);
-
-  gcc_assert (fn->last_stmt_uid == 0);
-  /* int funcdef_no;						-- ignored */
-  /* location_t function_start_locus;				-- in base */
-  /* location_t function_end_locus;				-- in base */
-  /* unsigned int curr_properties;				-- in base */
-  /* unsigned int last_verified;				-- ignored */
-  /* const char *cannot_be_copied_reason;			-- ignored */
-
-  /* unsigned int va_list_gpr_size : 8;				-- in base */
-  /* unsigned int va_list_fpr_size : 8;				-- in base */
-  /* unsigned int calls_setjmp : 1;				-- in base */
-  /* unsigned int calls_alloca : 1;				-- in base */
-  /* unsigned int has_nonlocal_label : 1;			-- in base */
-  /* unsigned int cannot_be_copied_set : 1;			-- ignored */
-  /* unsigned int stdarg : 1;					-- in base */
-  /* unsigned int after_inlining : 1;				-- in base */
-  /* unsigned int always_inline_functions_inlined : 1;		-- in base */
-  /* unsigned int can_throw_non_call_exceptions : 1;		-- in base */
-  /* unsigned int returns_struct : 1;				-- in base */
-  /* unsigned int returns_pcc_struct : 1;			-- in base */
-  /* 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 */
-}
-
-
-/* Write all the fields in lang_decl_base instance LDB to OB.  */
-
-static void
-pph_out_ld_base (pph_stream *stream, struct lang_decl_base *ldb)
-{
-  struct bitpack_d bp;
-
-  bp = bitpack_create (stream->encoder.w.ob->main_stream);
-  bp_pack_value (&bp, ldb->selector, 16);
-  bp_pack_value (&bp, ldb->language, 4);
-  bp_pack_value (&bp, ldb->use_template, 2);
-  bp_pack_value (&bp, ldb->not_really_extern, 1);
-  bp_pack_value (&bp, ldb->initialized_in_class, 1);
-  bp_pack_value (&bp, ldb->repo_available_p, 1);
-  bp_pack_value (&bp, ldb->threadprivate_or_deleted_p, 1);
-  bp_pack_value (&bp, ldb->anticipated_p, 1);
-  bp_pack_value (&bp, ldb->friend_attr, 1);
-  bp_pack_value (&bp, ldb->template_conv_p, 1);
-  bp_pack_value (&bp, ldb->odr_used, 1);
-  bp_pack_value (&bp, ldb->u2sel, 1);
-  pph_out_bitpack (stream, &bp);
-}
-
-
-/* Write all the fields in lang_decl_min instance LDM to STREAM.  */
-
-static void
-pph_out_ld_min (pph_stream *stream, struct lang_decl_min *ldm)
-{
-  pph_out_tree (stream, ldm->template_info);
-  if (ldm->base.u2sel == 0)
-    pph_out_tree (stream, ldm->u2.access);
-  else if (ldm->base.u2sel == 1)
-    pph_out_uint (stream, ldm->u2.discriminator);
-  else
-    gcc_unreachable ();
-}
-
-
-/* Write all the fields of lang_decl_fn instance LDF to STREAM.  */
-
-static void
-pph_out_ld_fn (pph_stream *stream, struct lang_decl_fn *ldf)
-{
-  struct bitpack_d bp;
-
-  /* Write all the fields in lang_decl_min.  */
-  pph_out_ld_min (stream, &ldf->min);
-
-  bp = bitpack_create (stream->encoder.w.ob->main_stream);
-  bp_pack_value (&bp, ldf->operator_code, 16);
-  bp_pack_value (&bp, ldf->global_ctor_p, 1);
-  bp_pack_value (&bp, ldf->global_dtor_p, 1);
-  bp_pack_value (&bp, ldf->constructor_attr, 1);
-  bp_pack_value (&bp, ldf->destructor_attr, 1);
-  bp_pack_value (&bp, ldf->assignment_operator_p, 1);
-  bp_pack_value (&bp, ldf->static_function, 1);
-  bp_pack_value (&bp, ldf->pure_virtual, 1);
-  bp_pack_value (&bp, ldf->defaulted_p, 1);
-  bp_pack_value (&bp, ldf->has_in_charge_parm_p, 1);
-  bp_pack_value (&bp, ldf->has_vtt_parm_p, 1);
-  bp_pack_value (&bp, ldf->pending_inline_p, 1);
-  bp_pack_value (&bp, ldf->nonconverting, 1);
-  bp_pack_value (&bp, ldf->thunk_p, 1);
-  bp_pack_value (&bp, ldf->this_thunk_p, 1);
-  bp_pack_value (&bp, ldf->hidden_friend_p, 1);
-  pph_out_bitpack (stream, &bp);
-
-  pph_out_tree (stream, ldf->befriending_classes);
-  pph_out_tree (stream, ldf->context);
-
-  if (ldf->thunk_p == 0)
-    pph_out_tree (stream, ldf->u5.cloned_function);
-  else if (ldf->thunk_p == 1)
-    pph_out_uint (stream, ldf->u5.fixed_offset);
-  else
-    gcc_unreachable ();
-
-  if (ldf->pending_inline_p == 1)
-    pph_out_token_cache (stream, ldf->u.pending_inline_info);
-  else if (ldf->pending_inline_p == 0)
-    pph_out_language_function (stream, ldf->u.saved_language_function);
-}
-
-
-/* Write all the fields of lang_decl_ns instance LDNS to STREAM.  */
-
-static void
-pph_out_ld_ns (pph_stream *stream, struct lang_decl_ns *ldns)
-{
-  pph_out_binding_level (stream, ldns->level, PPHF_NONE);
-}
-
-
-/* Write all the fields of lang_decl_parm instance LDP to STREAM.  */
-
-static void
-pph_out_ld_parm (pph_stream *stream, struct lang_decl_parm *ldp)
-{
-  pph_out_uint (stream, ldp->level);
-  pph_out_uint (stream, ldp->index);
-}
-
-
-/* Write all the lang-specific data in DECL to STREAM.  */
-
-static void
-pph_out_lang_specific (pph_stream *stream, tree decl)
-{
-  struct lang_decl *ld;
-  struct lang_decl_base *ldb;
-
-  ld = DECL_LANG_SPECIFIC (decl);
-  if (pph_out_start_record (stream, ld, PPH_lang_decl))
-    return;
-
-  /* Write all the fields in lang_decl_base.  */
-  ldb = &ld->u.base;
-  pph_out_ld_base (stream, ldb);
-
-  if (ldb->selector == 0)
-    {
-      /* Write all the fields in lang_decl_min.  */
-      pph_out_ld_min (stream, &ld->u.min);
-    }
-  else if (ldb->selector == 1)
-    {
-      /* Write all the fields in lang_decl_fn.  */
-      pph_out_ld_fn (stream, &ld->u.fn);
-    }
-  else if (ldb->selector == 2)
-    {
-      /* Write all the fields in lang_decl_ns.  */
-      pph_out_ld_ns (stream, &ld->u.ns);
-    }
-  else if (ldb->selector == 3)
-    {
-      /* Write all the fields in lang_decl_parm.  */
-      pph_out_ld_parm (stream, &ld->u.parm);
-    }
-  else
-    gcc_unreachable ();
-}
-
-
-/********************************************************* tree base classes */
-
-
-/* Write out the tree_common fields from T to STREAM.  */
-
-static void
-pph_out_tree_common (pph_stream *stream, tree t)
-{
-  /* The chain field in DECLs is handled separately.  Make sure this
-     is never called with a DECL.  */
-  gcc_assert (!DECL_P (t));
-
-  /* The 'struct tree_typed typed' base class is handled in LTO.  */
-  pph_out_tree (stream, TREE_CHAIN (t));
-}
-
-
-/* Write all the fields in lang_type_header instance LTH to STREAM.  */
-
-static void
-pph_out_lang_type_header (pph_stream *stream, struct lang_type_header *lth)
-{
-  struct bitpack_d bp;
-
-  bp = bitpack_create (stream->encoder.w.ob->main_stream);
-  bp_pack_value (&bp, lth->is_lang_type_class, 1);
-  bp_pack_value (&bp, lth->has_type_conversion, 1);
-  bp_pack_value (&bp, lth->has_copy_ctor, 1);
-  bp_pack_value (&bp, lth->has_default_ctor, 1);
-  bp_pack_value (&bp, lth->const_needs_init, 1);
-  bp_pack_value (&bp, lth->ref_needs_init, 1);
-  bp_pack_value (&bp, lth->has_const_copy_assign, 1);
-  pph_out_bitpack (stream, &bp);
-}
-
-
-/* Write a struct sorted_fields_type instance SFT to STREAM.  */
-
-static void
-pph_out_sorted_fields_type (pph_stream *stream, struct sorted_fields_type *sft)
-{
-  int i;
-
-  if (pph_out_start_record (stream, sft, PPH_sorted_fields_type))
-    return;
-
-  pph_out_uint (stream, sft->len);
-  for (i = 0; i < sft->len; i++)
-    pph_out_tree (stream, sft->elts[i]);
-}
-
-
-/* Write all the fields in lang_type_class instance LTC to STREAM.  */
-
-static void
-pph_out_lang_type_class (pph_stream *stream, struct lang_type_class *ltc)
-{
-  struct bitpack_d bp;
-
-  pph_out_uchar (stream, ltc->align);
-
-  bp = bitpack_create (stream->encoder.w.ob->main_stream);
-  bp_pack_value (&bp, ltc->has_mutable, 1);
-  bp_pack_value (&bp, ltc->com_interface, 1);
-  bp_pack_value (&bp, ltc->non_pod_class, 1);
-  bp_pack_value (&bp, ltc->nearly_empty_p, 1);
-  bp_pack_value (&bp, ltc->user_align, 1);
-  bp_pack_value (&bp, ltc->has_copy_assign, 1);
-  bp_pack_value (&bp, ltc->has_new, 1);
-  bp_pack_value (&bp, ltc->has_array_new, 1);
-  bp_pack_value (&bp, ltc->gets_delete, 2);
-  bp_pack_value (&bp, ltc->interface_only, 1);
-  bp_pack_value (&bp, ltc->interface_unknown, 1);
-  bp_pack_value (&bp, ltc->contains_empty_class_p, 1);
-  bp_pack_value (&bp, ltc->anon_aggr, 1);
-  bp_pack_value (&bp, ltc->non_zero_init, 1);
-  bp_pack_value (&bp, ltc->empty_p, 1);
-  bp_pack_value (&bp, ltc->vec_new_uses_cookie, 1);
-  bp_pack_value (&bp, ltc->declared_class, 1);
-  bp_pack_value (&bp, ltc->diamond_shaped, 1);
-  bp_pack_value (&bp, ltc->repeated_base, 1);
-  bp_pack_value (&bp, ltc->being_defined, 1);
-  bp_pack_value (&bp, ltc->java_interface, 1);
-  bp_pack_value (&bp, ltc->debug_requested, 1);
-  bp_pack_value (&bp, ltc->fields_readonly, 1);
-  bp_pack_value (&bp, ltc->use_template, 2);
-  bp_pack_value (&bp, ltc->ptrmemfunc_flag, 1);
-  bp_pack_value (&bp, ltc->was_anonymous, 1);
-  bp_pack_value (&bp, ltc->lazy_default_ctor, 1);
-  bp_pack_value (&bp, ltc->lazy_copy_ctor, 1);
-  bp_pack_value (&bp, ltc->lazy_copy_assign, 1);
-  bp_pack_value (&bp, ltc->lazy_destructor, 1);
-  bp_pack_value (&bp, ltc->has_const_copy_ctor, 1);
-  bp_pack_value (&bp, ltc->has_complex_copy_ctor, 1);
-  bp_pack_value (&bp, ltc->has_complex_copy_assign, 1);
-  bp_pack_value (&bp, ltc->non_aggregate, 1);
-  bp_pack_value (&bp, ltc->has_complex_dflt, 1);
-  bp_pack_value (&bp, ltc->has_list_ctor, 1);
-  bp_pack_value (&bp, ltc->non_std_layout, 1);
-  bp_pack_value (&bp, ltc->is_literal, 1);
-  bp_pack_value (&bp, ltc->lazy_move_ctor, 1);
-  bp_pack_value (&bp, ltc->lazy_move_assign, 1);
-  bp_pack_value (&bp, ltc->has_complex_move_ctor, 1);
-  bp_pack_value (&bp, ltc->has_complex_move_assign, 1);
-  bp_pack_value (&bp, ltc->has_constexpr_ctor, 1);
-  pph_out_bitpack (stream, &bp);
-
-  pph_out_tree (stream, ltc->primary_base);
-  pph_out_tree_pair_vec (stream, ltc->vcall_indices);
-  pph_out_tree (stream, ltc->vtables);
-  pph_out_tree (stream, ltc->typeinfo_var);
-  pph_out_tree_vec (stream, ltc->vbases);
-  if (!pph_out_start_record (stream, ltc->nested_udts, PPH_binding_table))
-    pph_out_binding_table (stream, ltc->nested_udts);
-  pph_out_tree (stream, ltc->as_base);
-  pph_out_tree_vec (stream, ltc->pure_virtuals);
-  pph_out_tree (stream, ltc->friend_classes);
-  pph_out_tree_vec (stream, ltc->methods);
-  pph_out_tree (stream, ltc->key_method);
-  pph_out_tree (stream, ltc->decl_list);
-  pph_out_tree (stream, ltc->template_info);
-  pph_out_tree (stream, ltc->befriending_classes);
-  pph_out_tree (stream, ltc->objc_info);
-  pph_out_sorted_fields_type (stream, ltc->sorted_fields);
-  pph_out_tree (stream, ltc->lambda_expr);
-}
-
-
-/* Write struct lang_type_ptrmem instance LTP to STREAM.  */
-
-static void
-pph_out_lang_type_ptrmem (pph_stream *stream, struct lang_type_ptrmem *ltp)
-{
-  pph_out_tree (stream, ltp->record);
-}
-
-
-/* Write all the lang-specific fields of TYPE to STREAM.  */
-
-static void
-pph_out_lang_type (pph_stream *stream, tree type)
-{
-  struct lang_type *lt;
-
-  lt = TYPE_LANG_SPECIFIC (type);
-  if (pph_out_start_record (stream, lt, PPH_lang_type))
-    return;
-
-  pph_out_lang_type_header (stream, &lt->u.h);
-  if (lt->u.h.is_lang_type_class)
-    pph_out_lang_type_class (stream, &lt->u.c);
-  else
-    pph_out_lang_type_ptrmem (stream, &lt->u.ptrmem);
-}
-
-
-/* Write to STREAM the body of tcc_type node TYPE.  */
-
-static void
-pph_out_tcc_type (pph_stream *stream, tree type)
-{
-  pph_out_lang_type (stream, type);
-  pph_out_tree (stream, TYPE_POINTER_TO (type));
-  pph_out_tree (stream, TYPE_REFERENCE_TO (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
-     other purposes.  */
-  switch (TREE_CODE (type))
-    {
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
-    case DECLTYPE_TYPE:
-    case TEMPLATE_TEMPLATE_PARM:
-    case TEMPLATE_TYPE_PARM:
-    case TYPENAME_TYPE:
-    case TYPEOF_TYPE:
-      pph_out_tree (stream, TYPE_VALUES_RAW (type));
-      break;
-
-    default:
-      break;
-    }
-}
-
-
-/* Write to STREAM the body of tcc_declaration tree DECL.  */
-
-static void
-pph_out_tcc_declaration (pph_stream *stream, tree decl)
-{
-  pph_out_lang_specific (stream, decl);
-  pph_out_tree (stream, DECL_INITIAL (decl));
-
-  /* The tree streamer only writes DECL_CHAIN for PARM_DECL nodes.
-     We need to write DECL_CHAIN for variables and functions because
-     they are sometimes chained together in places other than regular
-     tree chains.  For example in BINFO_VTABLEs, the decls are chained
-     together).  */
-  if (TREE_CODE (decl) == VAR_DECL
-      || TREE_CODE (decl) == FUNCTION_DECL)
-    pph_out_tree (stream, DECL_CHAIN (decl));
-
-  /* Handle some individual decl nodes.  */
-  switch (TREE_CODE (decl))
-    {
-    case FUNCTION_DECL:
-      /* Note that for FUNCTION_DECLs we do not output
-	 DECL_STRUCT_FUNCTION here.  This is emitted at the end of the
-	 PPH file in pph_out_symtab. This way, we will be able to
-	 re-instantiate them in the same order when reading the image
-	 (the allocation of DECL_STRUCT_FUNCTION has the side effect
-	 of generating function sequence numbers
-	 (function.funcdef_no).  */
-      pph_out_tree (stream, DECL_SAVED_TREE (decl));
-      break;
-
-    case TYPE_DECL:
-      pph_out_tree (stream, DECL_ORIGINAL_TYPE (decl));
-      break;
-
-    case TEMPLATE_DECL:
-      pph_out_tree (stream, DECL_TEMPLATE_RESULT (decl));
-      pph_out_tree (stream, DECL_TEMPLATE_PARMS (decl));
-      break;
-
-    default:
-      break;
-    }
-}
-
-
-/******************************************************** tree head and body */
-
-
-/* Write the body of EXPR to STREAM.  This writes out all fields not
-   written by the generic tree streaming routines.  */
-
-static void
-pph_out_tree_body (pph_stream *stream, tree expr)
-{
-  bool handled_p;
-
-  /* Write the language-independent parts of EXPR's body.  */
-  streamer_write_tree_body (stream->encoder.w.ob, expr, false);
-
-  /* Handle common tree code classes first.  */
-  handled_p = true;
-  switch (TREE_CODE_CLASS (TREE_CODE (expr)))
-    {
-      case tcc_declaration:
-	pph_out_tcc_declaration (stream, expr);
-	break;
-
-      case tcc_type:
-	pph_out_tcc_type (stream, expr);
-	break;
-
-      case tcc_constant:
-	if (TREE_CODE (expr) == PTRMEM_CST)
-	  {
-	    pph_out_tree_common (stream, expr);
-	    pph_out_tree (stream, PTRMEM_CST_MEMBER (expr));
-	  }
-	break;
-
-      case tcc_expression:
-      case tcc_unary:
-      case tcc_binary:
-      case tcc_vl_exp:
-      case tcc_reference:
-      case tcc_comparison:
-      case tcc_statement:
-	/* These tree classes are completely handled by the tree streamer.  */
-	break;
-
-      default:
-	handled_p = false;
-	break;
-    }
-
-  /* If we've already handled the tree, we are done.  */
-  if (handled_p)
-    return;
-
-  /* Only tcc_exceptional tree codes are left to handle.  */
-  gcc_assert (TREE_CODE_CLASS (TREE_CODE (expr)) == tcc_exceptional);
-
-  switch (TREE_CODE (expr))
-    {
-    case STATEMENT_LIST:
-      {
-        tree_stmt_iterator i;
-        unsigned num_stmts;
-
-        /* Compute and write the number of statements in the list.  */
-        for (num_stmts = 0, i = tsi_start (expr); !tsi_end_p (i); tsi_next (&i))
-	  num_stmts++;
-
-        pph_out_uint (stream, num_stmts);
-
-        /* Write the statements.  */
-        for (i = tsi_start (expr); !tsi_end_p (i); tsi_next (&i))
-	  pph_out_tree (stream, tsi_stmt (i));
-      }
-      break;
-
-    case OVERLOAD:
-      pph_out_tree_common (stream, expr);
-      pph_out_tree (stream, OVL_CURRENT (expr));
-      break;
-
-    case IDENTIFIER_NODE:
-      pph_out_cxx_binding (stream, IDENTIFIER_NAMESPACE_BINDINGS (expr));
-      pph_out_cxx_binding (stream, IDENTIFIER_BINDING (expr));
-      pph_out_tree (stream, IDENTIFIER_TEMPLATE (expr));
-      pph_out_tree (stream, IDENTIFIER_LABEL_VALUE (expr));
-      pph_out_tree (stream, REAL_IDENTIFIER_TYPE_VALUE (expr));
-      break;
-
-    case BASELINK:
-      pph_out_tree_common (stream, expr);
-      pph_out_tree (stream, BASELINK_BINFO (expr));
-      pph_out_tree (stream, BASELINK_FUNCTIONS (expr));
-      pph_out_tree (stream, BASELINK_ACCESS_BINFO (expr));
-      break;
-
-    case TEMPLATE_INFO:
-      pph_out_tree_common (stream, expr);
-      pph_out_qual_use_vec (stream, TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (expr));
-      break;
-
-    case DEFAULT_ARG:
-      pph_out_tree_common (stream, expr);
-      pph_out_token_cache (stream, DEFARG_TOKENS (expr));
-      pph_out_tree_vec (stream, DEFARG_INSTANTIATIONS (expr));
-      break;
-
-    case STATIC_ASSERT:
-      pph_out_tree_common (stream, expr);
-      pph_out_tree (stream, STATIC_ASSERT_CONDITION (expr));
-      pph_out_tree (stream, STATIC_ASSERT_MESSAGE (expr));
-      pph_out_location (stream, STATIC_ASSERT_SOURCE_LOCATION (expr));
-      break;
-
-    case ARGUMENT_PACK_SELECT:
-      pph_out_tree_common (stream, expr);
-      pph_out_tree (stream, ARGUMENT_PACK_SELECT_FROM_PACK (expr));
-      pph_out_uint (stream, ARGUMENT_PACK_SELECT_INDEX (expr));
-      break;
-
-    case TRAIT_EXPR:
-      pph_out_tree_common (stream, expr);
-      pph_out_tree (stream, TRAIT_EXPR_TYPE1 (expr));
-      pph_out_tree (stream, TRAIT_EXPR_TYPE2 (expr));
-      pph_out_uint (stream, TRAIT_EXPR_KIND (expr));
-      break;
-
-    case LAMBDA_EXPR:
-      pph_out_tree_common (stream, expr);
-      pph_out_location (stream, LAMBDA_EXPR_LOCATION (expr));
-      pph_out_tree (stream, LAMBDA_EXPR_CAPTURE_LIST (expr));
-      pph_out_tree (stream, LAMBDA_EXPR_THIS_CAPTURE (expr));
-      pph_out_tree (stream, LAMBDA_EXPR_RETURN_TYPE (expr));
-      pph_out_tree (stream, LAMBDA_EXPR_EXTRA_SCOPE (expr));
-      pph_out_uint (stream, LAMBDA_EXPR_DISCRIMINATOR (expr));
-      break;
-
-    case TREE_VEC:
-      /* TREE_VECs hold template argument lists.  */
-      pph_out_tree (stream, NON_DEFAULT_TEMPLATE_ARGS_COUNT (expr));
-      break;
-
-    case PLACEHOLDER_EXPR:
-      pph_out_tree (stream, TREE_TYPE (expr));
-      break;
-
-    case TEMPLATE_PARM_INDEX:
-      pph_out_tree_common (stream, expr);
-      pph_out_uint (stream, TEMPLATE_PARM_IDX (expr));
-      pph_out_uint (stream, TEMPLATE_PARM_LEVEL (expr));
-      pph_out_uint (stream, TEMPLATE_PARM_ORIG_LEVEL (expr));
-      pph_out_uint (stream, TEMPLATE_PARM_NUM_SIBLINGS (expr));
-      pph_out_tree (stream, TEMPLATE_PARM_DECL (expr));
-      break;
-
-    case DEFERRED_NOEXCEPT:
-      pph_out_tree (stream, DEFERRED_NOEXCEPT_PATTERN (expr));
-      pph_out_tree (stream, DEFERRED_NOEXCEPT_ARGS (expr));
-      break;
-
-    /* TREES ALREADY HANDLED */
-    case ERROR_MARK:
-    case TREE_LIST:
-    case BLOCK:
-    case CONSTRUCTOR:
-    case SSA_NAME:
-    case TREE_BINFO:
-      break;
-
-    /* TREES UNIMPLEMENTED */
-    case OMP_CLAUSE:
-    case OPTIMIZATION_NODE:
-    case TARGET_OPTION_NODE:
-      fatal_error ("PPH: unimplemented tree node '%s'",
-		   pph_tree_code_text (TREE_CODE (expr)));
-      break;
-
-    /* TREES UNRECOGNIZED */
-    default:
-      fatal_error ("PPH: unrecognized tree node '%s'",
-                   pph_tree_code_text (TREE_CODE (expr)));
-    }
-}
-
-
-/* Pack all the bitfields of EXPR into BP.  */
-
-static void
-pph_pack_value_fields (struct bitpack_d *bp, tree expr)
-{
-  /* First pack all the language-independent bitfields.  */
-  streamer_pack_tree_bitfields (bp, expr);
-
-  /* Now pack all the bitfields not handled by the generic packer.  */
-  if (TYPE_P (expr))
-    {
-      bp_pack_value (bp, TYPE_LANG_FLAG_0 (expr), 1);
-      bp_pack_value (bp, TYPE_LANG_FLAG_1 (expr), 1);
-      bp_pack_value (bp, TYPE_LANG_FLAG_2 (expr), 1);
-      bp_pack_value (bp, TYPE_LANG_FLAG_3 (expr), 1);
-      bp_pack_value (bp, TYPE_LANG_FLAG_4 (expr), 1);
-      bp_pack_value (bp, TYPE_LANG_FLAG_5 (expr), 1);
-      bp_pack_value (bp, TYPE_LANG_FLAG_6 (expr), 1);
-    }
-  else if (DECL_P (expr))
-    {
-      bp_pack_value (bp, DECL_LANG_FLAG_0 (expr), 1);
-      bp_pack_value (bp, DECL_LANG_FLAG_1 (expr), 1);
-      bp_pack_value (bp, DECL_LANG_FLAG_2 (expr), 1);
-      bp_pack_value (bp, DECL_LANG_FLAG_3 (expr), 1);
-      bp_pack_value (bp, DECL_LANG_FLAG_4 (expr), 1);
-      bp_pack_value (bp, DECL_LANG_FLAG_5 (expr), 1);
-      bp_pack_value (bp, DECL_LANG_FLAG_6 (expr), 1);
-      bp_pack_value (bp, DECL_LANG_FLAG_7 (expr), 1);
-      bp_pack_value (bp, DECL_LANG_FLAG_8 (expr), 1);
-    }
-
-  bp_pack_value (bp, TREE_LANG_FLAG_0 (expr), 1);
-  bp_pack_value (bp, TREE_LANG_FLAG_1 (expr), 1);
-  bp_pack_value (bp, TREE_LANG_FLAG_2 (expr), 1);
-  bp_pack_value (bp, TREE_LANG_FLAG_3 (expr), 1);
-  bp_pack_value (bp, TREE_LANG_FLAG_4 (expr), 1);
-  bp_pack_value (bp, TREE_LANG_FLAG_5 (expr), 1);
-  bp_pack_value (bp, TREE_LANG_FLAG_6 (expr), 1);
-}
-
-
-/* Write the header fields for EXPR to STREAM.  This header contains
-   all the data needed to rematerialize EXPR on the reader side and
-   a bitpack with all the bitfield values in EXPR.  */
-
-static void
-pph_out_tree_header (pph_stream *stream, tree expr)
-{
-  struct bitpack_d bp;
-  struct output_block *ob = stream->encoder.w.ob;
-
-  /* Write the header, containing everything needed to materialize EXPR
-     on the reading side.  */
-  streamer_write_tree_header (ob, expr);
-
-  /* Process C++ specific codes that need more data in the header
-     for the reader to allocate them.  */
-  if (TREE_CODE (expr) == AGGR_INIT_EXPR)
-    pph_out_uint (stream, aggr_init_expr_nargs (expr));
-
-  /* Pack all the non-pointer fields in EXPR into a bitpack and write
-     the resulting bitpack.  */
-  bp = bitpack_create (ob->main_stream);
-  pph_pack_value_fields (&bp, expr);
-  pph_out_bitpack (stream, &bp);
-}
-
-
-/* Return the merge name string identifier tree for a decl EXPR.  The
-   caller is responsible of freeing the returned string.  */
-
-static char *
-pph_merge_name (tree expr)
-{
-  char *retval;
-  size_t len;
-  const char *mangled_str, *name_str;
-  tree name;
-
-  unsigned flags = TFF_PLAIN_IDENTIFIER
-		   | TFF_SCOPE
-		   | TFF_DECL_SPECIFIERS
-		   | TFF_CLASS_KEY_OR_ENUM
-		   | TFF_RETURN_TYPE;
-
-  if (TYPE_P (expr))
-    expr = TYPE_NAME (expr);
-
-  name_str = decl_as_string (expr, flags);
-
-  name = DECL_NAME (expr);
-  if (name)
-    {
-      if (TREE_CODE (expr) == FUNCTION_DECL)
-	flags |= TFF_RETURN_TYPE
-		 | TFF_FUNCTION_DEFAULT_ARGUMENTS
-		 | TFF_EXCEPTION_SPECIFICATION;
-      else if (TREE_CODE (expr) == TEMPLATE_DECL)
-	flags |= TFF_TEMPLATE_HEADER
-		 | TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS;
-      mangled_str = IDENTIFIER_POINTER (get_mangled_id (expr));
-      len = strlen (name_str) + sizeof("|") + strlen (mangled_str);
-      retval = XNEWVEC (char, len + 1);
-      sprintf (retval, "%s|%s", name_str, mangled_str);
-    }
-  else
-    {
-      location_t locus = DECL_SOURCE_LOCATION (expr);
-      expanded_location xloc = expand_location (locus);
-      /* There are at most 20 digits in size_t.  Add :| for 22 characters.  */
-      len = strlen (name_str) + strlen (xloc.file) + 22;
-      retval = XNEWVEC (char, len + 1);
-      sprintf (retval, "%s|%s:%u", name_str, xloc.file, xloc.line);
-    }
-
-  return retval;
-}
-
-
-/* Write the merge name string for a decl EXPR.  */
-
-static void
-pph_out_merge_name (pph_stream *stream, tree expr)
-{
-  char *name = pph_merge_name (expr);
-  pph_out_string (stream, name);
-  free (name);
-}
-
-
-/* Write the merge key for tree EXPR to STREAM.  */
-
-static void
-pph_out_merge_key_tree (pph_stream *stream, tree expr)
-{
-  gcc_assert (pph_tree_is_mergeable (expr));
-
-  if (pph_out_start_merge_key_record (stream, expr))
-    return;
-
-  if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_front, pph_trace_key_out);
-
-  /* Write merge key information.  This includes EXPR's header (needed
-     to re-allocate EXPR in the reader) and the merge key, used to
-     lookup EXPR in the reader's context and merge if necessary.  */
-  pph_out_tree_header (stream, expr);
-  pph_out_merge_name (stream, expr);
-  if (DECL_P (expr))
-    {
-      if (TREE_CODE (expr) == NAMESPACE_DECL)
-        pph_out_binding_merge_keys (stream, NAMESPACE_LEVEL (expr));
-#if 0
-/* FIXME pph: Distable tree merging for the moment.  */
-      else if (TREE_CODE (expr) == TYPE_DECL)
-        pph_out_merge_key_tree (stream, TREE_TYPE (expr));
-    }
-  else if (CLASS_TYPE_P (expr))
-    {
-      unsigned filter = PPHF_NO_XREFS | PPHF_NO_PREFS | PPHF_NO_BUILTINS;
-      pph_out_merge_key_chain (stream, TYPE_FIELDS (expr), filter);
-      pph_out_merge_key_chain (stream, TYPE_METHODS (expr), filter);
-      /* FIXME pph: Nested types are broken.
-      pph_out_binding_table (stream, CLASSTYPE_NESTED_UTDS (expr));
-      pph_out_merge_key_chain (stream, CLASSTYPE_DECL_LIST (expr), filter);
-      */
-#endif
-    }
-
-  if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_back, pph_trace_key_out);
-}
-
-
-/* Write a tree EXPR to STREAM.  */
-
-void
-pph_out_tree (pph_stream *stream, tree expr)
-{
-  enum pph_record_marker marker;
-
-  marker = pph_out_start_tree_record (stream, expr);
-
-  /* If EXPR is NULL or it already existed in the pickle cache,
-     nothing else needs to be done.  */
-  if (marker == PPH_RECORD_END || pph_is_reference_marker (marker))
-    return;
-
-  if (streamer_handle_as_builtin_p (expr))
-    {
-      /* MD and NORMAL builtins do not need to be written out
-         completely as they are always instantiated by the compiler on
-         startup.  The only builtins that need to be written out are
-         BUILT_IN_FRONTEND.  For all other builtins, we simply write
-         the class and code.  */
-      gcc_assert (marker == PPH_RECORD_START_NO_CACHE);
-      streamer_write_builtin (stream->encoder.w.ob, expr);
-      return;
-    }
-  else if (TREE_CODE (expr) == INTEGER_CST)
-    {
-      /* INTEGER_CST nodes are special because they need their
-	 original type to be materialized by the reader (to implement
-	 TYPE_CACHED_VALUES).  */
-      gcc_assert (marker == PPH_RECORD_START_NO_CACHE);
-      streamer_write_integer_cst (stream->encoder.w.ob, expr, false);
-      return;
-    }
-
-  if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_front,
-	marker == PPH_RECORD_START_MERGE_BODY ? pph_trace_merge_body
-	: marker == PPH_RECORD_START_MUTATED ? pph_trace_mutate
-	: pph_trace_normal);
-
-  if (marker == PPH_RECORD_START || marker == PPH_RECORD_START_MUTATED)
-    {
-
-      /* This is the first time we see EXPR, write it out.  */
-      if (marker == PPH_RECORD_START)
-        {
-          /* We only need to write EXPR's header if it needs to be
-             re-allocated when reading.  If we are writing the mutated
-             state of an existing tree, then we only need to write its
-             body.  */
-          pph_out_tree_header (stream, expr);
-        }
-
-      pph_out_tree_body (stream, expr);
-    }
-  else if (marker == PPH_RECORD_START_MERGE_BODY)
-    {
-      gcc_assert (pph_tree_is_mergeable (expr));
-
-      /* When writing a merge body, we do not need to write EXPR's
-	 header, since that was written out when we wrote the merge
-	 key record for it.  */
-      pph_out_tree_body (stream, expr);
-    }
-  else
-    gcc_unreachable ();
-
-  if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_back,
-	marker == PPH_RECORD_START_MERGE_BODY ? pph_trace_merge_body
-	: marker == PPH_RECORD_START_MUTATED ? pph_trace_mutate
-	: pph_trace_normal);
-}
-
-
-/************************************************************* file contents */
-
-
-/* Emit symbol table ACTION to STREAM.  */
-
-static inline void
-pph_out_symtab_action (pph_stream *stream, enum pph_symtab_action action)
-{
-  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, PPH_cgraph_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);
-}
-
-
-/* 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, enum pph_symtab_action action,
-			bool top_level, bool at_end)
-{
-  pph_symtab_entry entry;
-
-  if (decl == NULL || pph_out_stream == NULL)
-    return;
-
-  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);
-}
-
-
-/* Emit the symbol table for 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
-   that they were instantiated when we generated this image.
-
-   With this, we can generate code in the same order out of the
-   original header files and out of PPH images.  */
-
-static void
-pph_out_symtab (pph_stream *stream)
-{
-  pph_symtab_entry *entry;
-  unsigned i;
-
-  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 ();
-    }
-}
-
-
-/* Save the IDENTIFIERS to the STREAM.  */
-
-static void
-pph_out_identifiers (pph_stream *stream, cpp_idents_used *identifiers)
-{
-  unsigned int num_entries, active_entries, id;
-
-  num_entries = identifiers->num_entries;
-  pph_out_uint (stream, identifiers->max_ident_len);
-  pph_out_uint (stream, identifiers->max_value_len);
-
-  active_entries = 0;
-  for ( id = 0; id < num_entries; ++id )
-    {
-      cpp_ident_use *entry = identifiers->entries + id;
-      if (!(entry->used_by_directive || entry->expanded_to_text))
-        continue;
-      ++active_entries;
-    }
-
-  pph_out_uint (stream, active_entries);
-
-  for ( id = 0; id < num_entries; ++id )
-    {
-      cpp_ident_use *entry = identifiers->entries + id;
-
-      if (!(entry->used_by_directive || entry->expanded_to_text))
-        continue;
-
-      /* FIXME pph: We are wasting space; ident_len, used_by_directive
-      and expanded_to_text together could fit into a single uint. */
-
-      pph_out_uint (stream, entry->used_by_directive);
-      pph_out_uint (stream, entry->expanded_to_text);
-
-      gcc_assert (entry->ident_len <= identifiers->max_ident_len);
-      pph_out_string_with_length (stream, entry->ident_str,
-				     entry->ident_len);
-
-      gcc_assert (entry->before_len <= identifiers->max_value_len);
-      pph_out_string_with_length (stream, entry->before_str,
-				     entry->before_len);
-
-      gcc_assert (entry->after_len <= identifiers->max_value_len);
-      pph_out_string_with_length (stream, entry->after_str,
-				     entry->after_len);
-    }
-}
-
-
-/* Write the global bindings in scope_chain to STREAM.  */
-
-static void
-pph_out_global_binding (pph_stream *stream)
-{
-  cp_binding_level *bl;
-
-  /* We only need to write out the scope_chain->bindings, everything
-     else should be NULL or be some temporary disposable state.
-     old_namespace should be global_namespace and all entries listed
-     below should be NULL or 0; otherwise the header parsed was
-     incomplete.  */
-  gcc_assert (scope_chain->old_namespace == global_namespace
-	      && !(scope_chain->class_name
-		   || scope_chain->class_type
-		   || scope_chain->access_specifier
-		   || scope_chain->function_decl
-		   || scope_chain->template_parms
-		   || scope_chain->x_saved_tree
-		   || scope_chain->class_bindings
-		   || scope_chain->prev
-		   || scope_chain->unevaluated_operand
-		   || scope_chain->inhibit_evaluation_warnings
-		   || scope_chain->x_processing_template_decl
-		   || scope_chain->x_processing_specialization
-		   || scope_chain->x_processing_explicit_instantiation
-		   || scope_chain->need_pop_function_context
-		   || scope_chain->x_stmt_tree.x_cur_stmt_list
-		   || scope_chain->x_stmt_tree.stmts_are_full_exprs_p));
-
-  /* We need to write a record for BL before emitting the merge keys
-     so that the reader can associate the merge keys to it.  */
-  bl = scope_chain->bindings;
-  pph_out_start_record (stream, bl, PPH_cp_binding_level);
-
-  /* Emit all the merge keys for objects that need to be merged when reading
-     multiple PPH images.  */
-  pph_out_binding_merge_keys (stream, bl);
-  pph_out_binding_merge_bodies (stream, bl);
-}
-
-
-/* Write all the contents of STREAM.  */
-
-static void
-pph_write_file (pph_stream *stream)
-{
-  cpp_idents_used idents_used;
-
-  if (flag_pph_tracer >= 1)
-    fprintf (pph_logfile, "PPH: Writing %s\n", pph_out_file);
-
-  /* Emit the line table entries and references to our direct includes.   */
-  pph_out_line_table_and_includes (stream);
-
-  /* Emit all the identifiers and pre-processor symbols in the global
-     namespace.  */
-  idents_used = cpp_lt_capture (parse_in);
-  pph_out_identifiers (stream, &idents_used);
-
-  /* Emit the bindings for the global namespace.  */
-  pph_out_global_binding (stream);
-
-  /* Emit other global state kept by the parser.  FIXME pph, these
-     globals should be fields in struct cp_parser.  */
-  pph_out_tree (stream, keyed_classes);
-  pph_out_tree_vec (stream, unemitted_tinfo_decls);
-
-  pph_out_pending_templates_list (stream);
-  pph_out_spec_entry_tables (stream);
-
-  pph_out_tree (stream, static_aggregates);
-
-  /* Emit the symbol table.  */
-  pph_out_symtab (stream);
-
-  if (flag_pph_dump_tree)
-    pph_dump_namespace (pph_logfile, global_namespace);
-}
-
-
-/******************************************************* stream finalization */
-
-
-/* Callback for lang_hooks.lto.begin_section.  Open file NAME.  */
-
-static void
-pph_begin_section (const char *name ATTRIBUTE_UNUSED)
-{
-}
-
-
-/* Callback for lang_hooks.lto.append_data.  Write LEN bytes from DATA
-   into pph_out_stream.  BLOCK is currently unused.  */
-
-static void
-pph_out_data (const void *data, size_t len, void *block ATTRIBUTE_UNUSED)
-{
-  if (data)
-    {
-      size_t written = fwrite (data, 1, len, pph_out_stream->file);
-      gcc_assert (written == len);
-    }
-}
-
-
-/* Callback for lang_hooks.lto.end_section.  */
-
-static void
-pph_end_section (void)
-{
-}
-
-/* Write the header for the PPH file represented by STREAM.  */
-
-static void
-pph_out_header (pph_stream *stream)
-{
-  pph_file_header header;
-  struct lto_output_stream header_stream;
-  int major, minor, patchlevel;
-
-  /* Collect version information.  */
-  parse_basever (&major, &minor, &patchlevel);
-  gcc_assert (major == (char) major);
-  gcc_assert (minor == (char) minor);
-  gcc_assert (patchlevel == (char) patchlevel);
-
-  /* Write the header for the PPH file.  */
-  memset (&header, 0, sizeof (header));
-  strcpy (header.id_str, pph_id_str);
-  header.major_version = (char) major;
-  header.minor_version = (char) minor;
-  header.patchlevel = (char) patchlevel;
-  header.strtab_size = stream->encoder.w.ob->string_stream->total_size;
-
-  memset (&header_stream, 0, sizeof (header_stream));
-  lto_output_data_stream (&header_stream, &header, sizeof (header));
-  lto_write_stream (&header_stream);
-}
-
-
-/* Write the body of the PPH file represented by STREAM.  */
-
-static void
-pph_out_body (pph_stream *stream)
-{
-  /* Write the string table.  */
-  lto_write_stream (stream->encoder.w.ob->string_stream);
-
-  /* Write the main stream where we have been pickling the parse trees.  */
-  lto_write_stream (stream->encoder.w.ob->main_stream);
-}
-
-
-/* Flush all the in-memory buffers for STREAM to disk.  */
-
-void
-pph_flush_buffers (pph_stream *stream)
-{
-  /* Redirect the LTO basic I/O langhooks.  */
-  lang_hooks.lto.begin_section = pph_begin_section;
-  lang_hooks.lto.append_data = pph_out_data;
-  lang_hooks.lto.end_section = pph_end_section;
-
-  /* Write the state buffers built by pph_out_*() calls.  */
-  lto_begin_section (stream->name, false);
-  pph_out_header (stream);
-  pph_out_body (stream);
-  lto_end_section ();
-}
-
-
-/* Finalize the PPH writer.  */
-
-void
-pph_writer_finish (void)
-{
-  const char *offending_file;
-
-  if (pph_out_stream == NULL)
-    return;
-
-  offending_file = cpp_main_missing_guard (parse_in);
-  if (offending_file == NULL)
-    pph_write_file (pph_out_stream);
-  else
-    error ("header lacks guard for PPH: %s", offending_file);
-
-  pph_stream_close (pph_out_stream);
-  pph_out_stream = NULL;
-}
-
-
-/* Add INCLUDE to the list of images included by pph_out_stream.  */
-
-void
-pph_writer_add_include (pph_stream *include)
-{
-  pph_add_include (pph_out_stream, include);
-}
Index: gcc/cp/pph-streamer.h
===================================================================
--- gcc/cp/pph-streamer.h	(revision 181815)
+++ gcc/cp/pph-streamer.h	(working copy)
@@ -226,13 +226,6 @@ struct pph_stream {
 #define PPHF_NO_XREFS		(1 << 1)
 #define PPHF_NO_PREFS		(1 << 2)
 
-/* In pph.c  */
-extern const char *pph_tree_code_text (enum tree_code code);
-extern void pph_dump_min_decl (FILE *file, tree decl);
-extern void pph_dump_chain (FILE *, tree chain);
-extern void pph_dump_binding (FILE *, cp_binding_level *level);
-extern void pph_dump_namespace (FILE *, tree ns);
-
 enum pph_trace_kind
 {
   pph_trace_key_out, pph_trace_unmerged_key, pph_trace_merged_key,
@@ -244,9 +237,9 @@ enum pph_trace_end
   pph_trace_front, pph_trace_back
 };
 
-/* In pph-streamer.c.  */
-void pph_streamer_init (void);
-void pph_streamer_finish (void);
+/* In pph-core.c.  */
+const char *pph_tree_code_text (enum tree_code code);
+void pph_dump_namespace (FILE *, tree ns);
 pph_stream *pph_stream_open (const char *, const char *);
 void pph_mark_stream_read (pph_stream *);
 void pph_stream_close (pph_stream *);
@@ -265,7 +258,7 @@ void pph_cache_sign (pph_cache *, unsign
 unsigned pph_get_signature (tree, size_t *);
 void pph_writer_add_include (pph_stream *);
 
-/* In pph-streamer-out.c.  */
+/* In pph-out.c.  */
 void pph_flush_buffers (pph_stream *);
 void pph_init_write (pph_stream *);
 void pph_write_mergeable_chain (pph_stream *, tree);
@@ -274,7 +267,7 @@ void pph_writer_finish (void);
 void pph_out_location (pph_stream *, location_t);
 void pph_out_tree (pph_stream *, tree);
 
-/* In pph-streamer-in.c.  */
+/* In pph-in.c.  */
 void pph_init_read (pph_stream *);
 location_t pph_in_location (pph_stream *);
 pph_stream *pph_read_file (const char *);

--
This patch is available for review at http://codereview.appspot.com/5440063


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]