Patchwork [pph] Re-organize pph_write_tree/pph_read_tree (issue4934045)

login
register
mail settings
Submitter Diego Novillo
Date Aug. 22, 2011, 3:27 p.m.
Message ID <20110822152715.A9BB31DA1CF@topo.tor.corp.google.com>
Download mbox | patch
Permalink /patch/110937/
State New
Headers show

Comments

Diego Novillo - Aug. 22, 2011, 3:27 p.m.
This patch refactors pph_write_tree and pph_read_tree so that we can
reduce the amount of special casing we were doing.  It first tries to
handle nodes based on their tree code class.  The only class that
cannot be handled this way is tcc_exceptional, so we only deal with
those nodes individually.

This fixes no testcases but it simplifies the logic of the AST
streamer.  I think we can now get rid of flag_pph_untree now since we 
are unconditionally ICEing if a node is not handled.

Tested on x86_64.  Applied to branch.

	* pph-streamer-in.c (pph_in_tcc_declaration): Factor out
 	of pph_read_tree_body.  Handle all decls.
 	(pph_in_tcc_type): Factor out of pph_read_tree_body.  Handle
 	all types.
 	(pph_read_tree_body): Issue a fatal error if a node has not
 	been handled.
 	* pph-streamer-out.c (pph_out_tcc_declaration): Factor out of
 	pph_write_tree_body.  Handle all decls.
 	(pph_out_tcc_type): Factor out of pph_write_tree_body.  Handle
 	all types.
 	(pph_write_tree_body): Issue a fatal error if a node has not
 	been handled.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/pph@177960 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/cp/ChangeLog.pph      |   15 ++
 gcc/cp/pph-streamer-in.c  |  342 ++++++++++++++++--------------------------
 gcc/cp/pph-streamer-out.c |  359 +++++++++++++++++----------------------------
 3 files changed, 284 insertions(+), 432 deletions(-)

Patch

diff --git a/gcc/cp/pph-streamer-in.c b/gcc/cp/pph-streamer-in.c
index ae3ede9..07e1135 100644
--- a/gcc/cp/pph-streamer-in.c
+++ b/gcc/cp/pph-streamer-in.c
@@ -1538,119 +1538,129 @@  pph_read_file (const char *filename)
 }
 
 
-/* Read the attributes for a FUNCTION_DECL FNDECL.  If FNDECL had
-   a body, mark it for expansion.  */
+/* Read from STREAM the body of tcc_declaration tree DECL.  */
 
 static void
-pph_in_function_decl (pph_stream *stream, tree fndecl)
+pph_in_tcc_declaration (pph_stream *stream, tree decl)
 {
-  DECL_INITIAL (fndecl) = pph_in_tree (stream);
-  pph_in_lang_specific (stream, fndecl);
-  DECL_SAVED_TREE (fndecl) = pph_in_tree (stream);
-  DECL_CHAIN (fndecl) = pph_in_tree (stream);
-}
-
+  pph_in_lang_specific (stream, decl);
+  DECL_INITIAL (decl) = pph_in_tree (stream);
 
+  /* The tree streamer only writes DECL_CHAIN for PARM_DECL nodes.  */
+  if (TREE_CODE (decl) == VAR_DECL
+      || TREE_CODE (decl) == FUNCTION_DECL)
+    DECL_CHAIN (decl) = pph_in_tree (stream);
 
-/* Read the body fields of EXPR from STREAM.  */
-
-static void
-pph_read_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;
-
-  /* Read the language-independent parts of EXPR's body.  */
-  streamer_read_tree_body (ib, data_in, expr);
-
-  /* Read all the language-dependent fields.  */
-  switch (TREE_CODE (expr))
+  /* Handle some individual decl nodes.  */
+  switch (TREE_CODE (decl))
     {
-    /* TREES NEEDING EXTRA WORK */
-
-    /* tcc_declaration */
-
-    case DEBUG_EXPR_DECL:
-    case IMPORTED_DECL:
-    case LABEL_DECL:
-    case RESULT_DECL:
-      DECL_INITIAL (expr) = pph_in_tree (stream);
-      break;
-
-    case CONST_DECL:
-    case FIELD_DECL:
-    case NAMESPACE_DECL:
-    case PARM_DECL:
-    case USING_DECL:
-    case VAR_DECL:
-      /* FIXME pph: Should we merge DECL_INITIAL into lang_specific? */
-      DECL_INITIAL (expr) = pph_in_tree (stream);
-      pph_in_lang_specific (stream, expr);
-      /* DECL_CHAIN is handled by generic code, except for VAR_DECLs.  */
-      if (TREE_CODE (expr) == VAR_DECL)
-	DECL_CHAIN (expr) = pph_in_tree (stream);
-      break;
-
     case FUNCTION_DECL:
-      pph_in_function_decl (stream, expr);
+      DECL_SAVED_TREE (decl) = pph_in_tree (stream);
       break;
 
     case TYPE_DECL:
-      DECL_INITIAL (expr) = pph_in_tree (stream);
-      pph_in_lang_specific (stream, expr);
-      DECL_ORIGINAL_TYPE (expr) = pph_in_tree (stream);
+      DECL_ORIGINAL_TYPE (decl) = pph_in_tree (stream);
       break;
 
     case TEMPLATE_DECL:
-      DECL_INITIAL (expr) = pph_in_tree (stream);
-      pph_in_lang_specific (stream, expr);
-      DECL_TEMPLATE_RESULT (expr) = pph_in_tree (stream);
-      DECL_TEMPLATE_PARMS (expr) = pph_in_tree (stream);
-      DECL_CONTEXT (expr) = pph_in_tree (stream);
+      DECL_TEMPLATE_RESULT (decl) = pph_in_tree (stream);
+      DECL_TEMPLATE_PARMS (decl) = pph_in_tree (stream);
       break;
 
-    /* tcc_type */
-
-    case ARRAY_TYPE:
-    case BOOLEAN_TYPE:
-    case COMPLEX_TYPE:
-    case ENUMERAL_TYPE:
-    case FIXED_POINT_TYPE:
-    case FUNCTION_TYPE:
-    case INTEGER_TYPE:
-    case LANG_TYPE:
-    case METHOD_TYPE:
-    case NULLPTR_TYPE:
-    case OFFSET_TYPE:
-    case POINTER_TYPE:
-    case REAL_TYPE:
-    case REFERENCE_TYPE:
-    case VECTOR_TYPE:
-    case VOID_TYPE:
-      TYPE_LANG_SPECIFIC (expr) = pph_in_lang_type (stream);
+    default:
       break;
+    }
+}
 
-    case QUAL_UNION_TYPE:
-    case RECORD_TYPE:
-    case UNION_TYPE:
-      TYPE_LANG_SPECIFIC (expr) = pph_in_lang_type (stream);
-      TYPE_BINFO (expr) = pph_in_tree (stream);
-      break;
 
+/* 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?  */
+
+  /* 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_LANG_SPECIFIC (expr) = pph_in_lang_type (stream);
-      TYPE_CACHED_VALUES (expr) = pph_in_tree (stream);
-      /* Note that we are using TYPED_CACHED_VALUES for it access to 
-         the generic .values field of types. */
+      TYPE_VALUES_RAW (type) = pph_in_tree (stream);
       break;
 
-    /* tcc_statement */
+    default:
+      break;
+    }
+}
+
+
+/* Read the body fields of EXPR from STREAM.  */
+
+static void
+pph_read_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);
@@ -1662,18 +1672,6 @@  pph_read_tree_body (pph_stream *stream, tree expr)
       }
       break;
 
-    /* tcc_expression */
-
-    /* tcc_unary */
-
-    /* tcc_vl_exp */
-
-    /* tcc_reference */
-
-    /* tcc_constant */
-
-    /* tcc_exceptional */
-
     case OVERLOAD:
       pph_in_tree_common (stream, expr);
       OVL_FUNCTION (expr) = pph_in_tree (stream);
@@ -1703,27 +1701,6 @@  pph_read_tree_body (pph_stream *stream, tree expr)
           = pph_in_qual_use_vec (stream);
       break;
 
-    case TEMPLATE_PARM_INDEX:
-      {
-        template_parm_index *p = TEMPLATE_PARM_INDEX_CAST (expr);
-        pph_in_tree_common (stream, expr);
-        p->index = pph_in_uint (stream);
-        p->level = pph_in_uint (stream);
-        p->orig_level = pph_in_uint (stream);
-        p->num_siblings = pph_in_uint (stream);
-        p->decl = pph_in_tree (stream);
-      }
-      break;
-
-    /* tcc_constant */
-
-    case PTRMEM_CST:
-      pph_in_tree_common (stream, expr);
-      PTRMEM_CST_MEMBER (expr) = pph_in_tree (stream);
-      break;
-
-    /* tcc_exceptional */
-
     case DEFAULT_ARG:
       pph_in_tree_common (stream, expr);
       DEFARG_TOKENS (expr) = pph_in_token_cache (stream);
@@ -1764,110 +1741,53 @@  pph_read_tree_body (pph_stream *stream, tree expr)
       }
       break;
 
+    case TREE_VEC:
+      /* TREE_VECs hold template argument lists.  */
+      NON_DEFAULT_TEMPLATE_ARGS_COUNT (expr) = pph_in_tree (stream);
+      break;
 
-    /* TREES ALREADY HANDLED */
-
-    /* tcc_declaration */
+    case PLACEHOLDER_EXPR:
+      TREE_TYPE (expr) = pph_in_tree (stream);
+      break;
 
-    case TRANSLATION_UNIT_DECL:
+    case TEMPLATE_PARM_INDEX:
+      {
+        template_parm_index *p = TEMPLATE_PARM_INDEX_CAST (expr);
+        pph_in_tree_common (stream, expr);
+        p->index = pph_in_uint (stream);
+        p->level = pph_in_uint (stream);
+        p->orig_level = pph_in_uint (stream);
+        p->num_siblings = pph_in_uint (stream);
+        p->decl = pph_in_tree (stream);
+      }
+      break;
 
-    /* tcc_exceptional */
+    case DEFERRED_NOEXCEPT:
+      DEFERRED_NOEXCEPT_PATTERN (expr) = pph_in_tree (stream);
+      DEFERRED_NOEXCEPT_ARGS (expr) = pph_in_tree (stream);
+      break;
 
-    case TREE_BINFO:
+    /* TREES ALREADY HANDLED */
+    case ERROR_MARK:
     case TREE_LIST:
-    case TREE_VEC:
-
+    case BLOCK:
+    case CONSTRUCTOR:
+    case SSA_NAME:
+    case TREE_BINFO:
       break;
 
-
     /* TREES UNIMPLEMENTED */
-
-    /* tcc_declaration */
-
-    /* tcc_type */
-
-    case TYPE_ARGUMENT_PACK:
-    case TYPE_PACK_EXPANSION:
-    case UNBOUND_CLASS_TEMPLATE:
-
-    /* tcc_statement */
-
-    case USING_STMT:
-    case TRY_BLOCK:
-    case EH_SPEC_BLOCK:
-    case HANDLER:
-    case CLEANUP_STMT:
-    case IF_STMT:
-    case FOR_STMT:
-    case RANGE_FOR_STMT:
-    case WHILE_STMT:
-    case DO_STMT:
-    case BREAK_STMT:
-    case CONTINUE_STMT:
-    case SWITCH_STMT:
-
-    /* tcc_expression */
-
-    case NEW_EXPR:
-    case VEC_NEW_EXPR:
-    case DELETE_EXPR:
-    case VEC_DELETE_EXPR:
-    case TYPE_EXPR:
-    case VEC_INIT_EXPR:
-    case THROW_EXPR:
-    case EMPTY_CLASS_EXPR:
-    case TEMPLATE_ID_EXPR:
-    case PSEUDO_DTOR_EXPR:
-    case MODOP_EXPR:
-    case DOTSTAR_EXPR:
-    case TYPEID_EXPR:
-    case NON_DEPENDENT_EXPR:
-    case CTOR_INITIALIZER:
-    case MUST_NOT_THROW_EXPR:
-    case EXPR_STMT:
-    case TAG_DEFN:
-    case OFFSETOF_EXPR:
-    case SIZEOF_EXPR:
-    case ARROW_EXPR:
-    case ALIGNOF_EXPR:
-    case AT_ENCODE_EXPR:
-    case STMT_EXPR:
-    case NONTYPE_ARGUMENT_PACK:
-    case EXPR_PACK_EXPANSION:
-
-    /* tcc_unary */
-
-    case CAST_EXPR:
-    case REINTERPRET_CAST_EXPR:
-    case CONST_CAST_EXPR:
-    case STATIC_CAST_EXPR:
-    case DYNAMIC_CAST_EXPR:
-    case NOEXCEPT_EXPR:
-    case UNARY_PLUS_EXPR:
-
-    /* tcc_reference */
-
-    case MEMBER_REF:
-    case OFFSET_REF:
-    case SCOPE_REF:
-
-    /* tcc_vl_exp */
-
-    case AGGR_INIT_EXPR:
-
-
-      if (flag_pph_untree)
-        fprintf (pph_logfile, "PPH: unimplemented tree node %s\n",
-                 tree_code_name[TREE_CODE (expr)]);
+    case OMP_CLAUSE:
+    case OPTIMIZATION_NODE:
+    case TARGET_OPTION_NODE:
+      fatal_error ("PPH: unimplemented tree node '%s'",
+		   tree_code_name[TREE_CODE (expr)]);
       break;
 
-
     /* TREES UNRECOGNIZED */
-
     default:
-      if (flag_pph_untree)
-        fprintf (pph_logfile, "PPH: unrecognized tree node %s\n",
-                 tree_code_name[TREE_CODE (expr)]);
+      fatal_error ("PPH: unrecognized tree node '%s'",
+                   tree_code_name[TREE_CODE (expr)]);
     }
 }
 
diff --git a/gcc/cp/pph-streamer-out.c b/gcc/cp/pph-streamer-out.c
index fe0758f..024de38 100644
--- a/gcc/cp/pph-streamer-out.c
+++ b/gcc/cp/pph-streamer-out.c
@@ -1374,128 +1374,135 @@  pph_write_file (pph_stream *stream)
 }
 
 
-/* Emit the fields of FUNCTION_DECL FNDECL to STREAM.  */
+/* Write to STREAM the body of tcc_declaration tree DECL.  */
 
 static void
-pph_out_function_decl (pph_stream *stream, tree fndecl)
+pph_out_tcc_declaration (pph_stream *stream, tree decl)
 {
-  /* Note that 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_1 (stream, DECL_INITIAL (fndecl), 3);
-  pph_out_lang_specific (stream, fndecl);
-  pph_out_tree_1 (stream, DECL_SAVED_TREE (fndecl), 3);
-  pph_out_tree_1 (stream, DECL_CHAIN (fndecl), 3);
-}
-
-
-/* Write the body of EXPR to STREAM.  This writes out all fields not
-   written by the generic tree streaming routines.  */
-
-static void
-pph_write_tree_body (pph_stream *stream, tree expr)
-{
-  /* Write the language-independent parts of EXPR's body.  */
-  streamer_write_tree_body (stream->encoder.w.ob, expr, false);
+  pph_out_lang_specific (stream, decl);
+  pph_out_tree (stream, DECL_INITIAL (decl));
 
-  /* The following trees have language-dependent information that is
-     not written by the generic tree streaming routines.  Handle them
-     here.
+  /* The tree streamer only writes DECL_CHAIN for PARM_DECL nodes.  */
+  if (TREE_CODE (decl) == VAR_DECL
+      || TREE_CODE (decl) == FUNCTION_DECL)
+    pph_out_tree (stream, DECL_CHAIN (decl));
 
-     FIXME pph.  This could be handled using TS_* markers in
-     treestruct.def but those markers are not complete.  To fix this,
-     embed the TS_* directly in the tree node definitions in tree.def
-     and cp/cp-tree.def.  */
-  switch (TREE_CODE (expr))
+  /* Handle some individual decl nodes.  */
+  switch (TREE_CODE (decl))
     {
-    /* TREES NEEDING EXTRA WORK */
-
-    /* tcc_declaration */
-
-    case DEBUG_EXPR_DECL:
-    case IMPORTED_DECL:
-    case LABEL_DECL:
-    case RESULT_DECL:
-      pph_out_tree_1 (stream, DECL_INITIAL (expr), 3);
-      break;
-
-    case CONST_DECL:
-    case FIELD_DECL:
-    case NAMESPACE_DECL:
-    case PARM_DECL:
-    case USING_DECL:
-    case VAR_DECL:
-      /* FIXME pph: Should we merge DECL_INITIAL into lang_specific? */
-      pph_out_tree_1 (stream, DECL_INITIAL (expr), 3);
-      pph_out_lang_specific (stream, expr);
-      /* DECL_CHAIN is handled by generic code, except for VAR_DECLs.  */
-      if (TREE_CODE (expr) == VAR_DECL)
-	pph_out_tree_1 (stream, DECL_CHAIN (expr), 3);
-      break;
-
     case FUNCTION_DECL:
-      pph_out_function_decl (stream, expr);
+      /* 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_1 (stream, DECL_INITIAL (expr), 3);
-      pph_out_lang_specific (stream, expr);
-      pph_out_tree_1 (stream, DECL_ORIGINAL_TYPE (expr), 3);
+      pph_out_tree (stream, DECL_ORIGINAL_TYPE (decl));
       break;
 
     case TEMPLATE_DECL:
-      pph_out_tree_1 (stream, DECL_INITIAL (expr), 3);
-      pph_out_lang_specific (stream, expr);
-      pph_out_tree_1 (stream, DECL_TEMPLATE_RESULT (expr), 3);
-      pph_out_tree_1 (stream, DECL_TEMPLATE_PARMS (expr), 3);
-      pph_out_tree_1 (stream, DECL_CONTEXT (expr), 3);
+      pph_out_tree (stream, DECL_TEMPLATE_RESULT (decl));
+      pph_out_tree (stream, DECL_TEMPLATE_PARMS (decl));
       break;
 
-    /* tcc_type */
-
-    case ARRAY_TYPE:
-    case BOOLEAN_TYPE:
-    case COMPLEX_TYPE:
-    case ENUMERAL_TYPE:
-    case FIXED_POINT_TYPE:
-    case FUNCTION_TYPE:
-    case INTEGER_TYPE:
-    case LANG_TYPE:
-    case METHOD_TYPE:
-    case NULLPTR_TYPE:
-    case OFFSET_TYPE:
-    case POINTER_TYPE:
-    case REAL_TYPE:
-    case REFERENCE_TYPE:
-    case VECTOR_TYPE:
-    case VOID_TYPE:
-      pph_out_lang_type (stream, expr);
+    default:
       break;
+    }
+}
 
-    case QUAL_UNION_TYPE:
-    case RECORD_TYPE:
-    case UNION_TYPE:
-      pph_out_lang_type (stream, expr);
-      pph_out_tree_1 (stream, TYPE_BINFO (expr), 3);
-      break;
 
+/* 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?  */
+
+  /* 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_lang_type (stream, expr);
-      pph_out_tree_1 (stream, TYPE_CACHED_VALUES (expr), 3);
-      /* Note that we are using TYPED_CACHED_VALUES for it access to
-         the generic .values field of types. */
+      pph_out_tree (stream, TYPE_VALUES_RAW (type));
+      break;
+
+    default:
       break;
+    }
+}
+
+
+/* Write the body of EXPR to STREAM.  This writes out all fields not
+   written by the generic tree streaming routines.  */
 
-    /* tcc_statement */
+static void
+pph_write_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_1 (stream, PTRMEM_CST_MEMBER (expr), 3);
+	  }
+	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;
@@ -1513,18 +1520,6 @@  pph_write_tree_body (pph_stream *stream, tree expr)
       }
       break;
 
-    /* tcc_expression */
-
-    /* tcc_unary */
-
-    /* tcc_vl_exp */
-
-    /* tcc_reference */
-
-    /* tcc_constant */
-
-    /* tcc_exceptional */
-
     case OVERLOAD:
       pph_out_tree_common (stream, expr);
       pph_out_tree_1 (stream, OVL_CURRENT (expr), 3);
@@ -1550,31 +1545,9 @@  pph_write_tree_body (pph_stream *stream, tree expr)
 
     case TEMPLATE_INFO:
       pph_out_tree_common (stream, expr);
-      pph_out_qual_use_vec (stream,
-          TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (expr));
-      break;
-
-    case TEMPLATE_PARM_INDEX:
-      {
-        template_parm_index *p = TEMPLATE_PARM_INDEX_CAST (expr);
-        pph_out_tree_common (stream, expr);
-        pph_out_uint (stream, p->index);
-        pph_out_uint (stream, p->level);
-        pph_out_uint (stream, p->orig_level);
-        pph_out_uint (stream, p->num_siblings);
-        pph_out_tree_1 (stream, p->decl, 3);
-      }
-      break;
-
-    /* tcc_constant */
-
-    case PTRMEM_CST:
-      pph_out_tree_common (stream, expr);
-      pph_out_tree_1 (stream, PTRMEM_CST_MEMBER (expr), 3);
+      pph_out_qual_use_vec (stream, TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (expr));
       break;
 
-    /* tcc_exceptional */
-
     case DEFAULT_ARG:
       pph_out_tree_common (stream, expr);
       pph_out_token_cache (stream, DEFARG_TOKENS (expr));
@@ -1615,109 +1588,53 @@  pph_write_tree_body (pph_stream *stream, tree expr)
       }
       break;
 
+    case TREE_VEC:
+      /* TREE_VECs hold template argument lists.  */
+      pph_out_tree (stream, NON_DEFAULT_TEMPLATE_ARGS_COUNT (expr));
+      break;
 
-    /* TREES ALREADY HANDLED */
-
-    /* tcc_declaration */
+    case PLACEHOLDER_EXPR:
+      pph_out_tree (stream, TREE_TYPE (expr));
+      break;
 
-    case TRANSLATION_UNIT_DECL:
+    case TEMPLATE_PARM_INDEX:
+      {
+        template_parm_index *p = TEMPLATE_PARM_INDEX_CAST (expr);
+        pph_out_tree_common (stream, expr);
+        pph_out_uint (stream, p->index);
+        pph_out_uint (stream, p->level);
+        pph_out_uint (stream, p->orig_level);
+        pph_out_uint (stream, p->num_siblings);
+        pph_out_tree_1 (stream, p->decl, 3);
+      }
+      break;
 
-    /* tcc_exceptional */
+    case DEFERRED_NOEXCEPT:
+      pph_out_tree (stream, DEFERRED_NOEXCEPT_PATTERN (expr));
+      pph_out_tree (stream, DEFERRED_NOEXCEPT_ARGS (expr));
+      break;
 
-    case TREE_BINFO:
+    /* TREES ALREADY HANDLED */
+    case ERROR_MARK:
     case TREE_LIST:
-    case TREE_VEC:
-
+    case BLOCK:
+    case CONSTRUCTOR:
+    case SSA_NAME:
+    case TREE_BINFO:
       break;
 
     /* TREES UNIMPLEMENTED */
-
-    /* tcc_declaration */
-
-    /* tcc_type */
-
-    case TYPE_ARGUMENT_PACK:
-    case TYPE_PACK_EXPANSION:
-    case UNBOUND_CLASS_TEMPLATE:
-
-    /* tcc_statement */
-
-    case USING_STMT:
-    case TRY_BLOCK:
-    case EH_SPEC_BLOCK:
-    case HANDLER:
-    case CLEANUP_STMT:
-    case IF_STMT:
-    case FOR_STMT:
-    case RANGE_FOR_STMT:
-    case WHILE_STMT:
-    case DO_STMT:
-    case BREAK_STMT:
-    case CONTINUE_STMT:
-    case SWITCH_STMT:
-
-    /* tcc_expression */
-
-    case NEW_EXPR:
-    case VEC_NEW_EXPR:
-    case DELETE_EXPR:
-    case VEC_DELETE_EXPR:
-    case TYPE_EXPR:
-    case VEC_INIT_EXPR:
-    case THROW_EXPR:
-    case EMPTY_CLASS_EXPR:
-    case TEMPLATE_ID_EXPR:
-    case PSEUDO_DTOR_EXPR:
-    case MODOP_EXPR:
-    case DOTSTAR_EXPR:
-    case TYPEID_EXPR:
-    case NON_DEPENDENT_EXPR:
-    case CTOR_INITIALIZER:
-    case MUST_NOT_THROW_EXPR:
-    case EXPR_STMT:
-    case TAG_DEFN:
-    case OFFSETOF_EXPR:
-    case SIZEOF_EXPR:
-    case ARROW_EXPR:
-    case ALIGNOF_EXPR:
-    case AT_ENCODE_EXPR:
-    case STMT_EXPR:
-    case NONTYPE_ARGUMENT_PACK:
-    case EXPR_PACK_EXPANSION:
-
-    /* tcc_unary */
-
-    case CAST_EXPR:
-    case REINTERPRET_CAST_EXPR:
-    case CONST_CAST_EXPR:
-    case STATIC_CAST_EXPR:
-    case DYNAMIC_CAST_EXPR:
-    case NOEXCEPT_EXPR:
-    case UNARY_PLUS_EXPR:
-
-    /* tcc_reference */
-
-    case MEMBER_REF:
-    case OFFSET_REF:
-    case SCOPE_REF:
-
-    /* tcc_vl_exp */
-
-    case AGGR_INIT_EXPR:
-
-
-      if (flag_pph_untree)
-        fprintf (pph_logfile, "PPH: unimplemented tree node %s\n",
-                 tree_code_name[TREE_CODE (expr)]);
+    case OMP_CLAUSE:
+    case OPTIMIZATION_NODE:
+    case TARGET_OPTION_NODE:
+      fatal_error ("PPH: unimplemented tree node '%s'",
+		   tree_code_name[TREE_CODE (expr)]);
       break;
 
-
     /* TREES UNRECOGNIZED */
-
     default:
-      if (flag_pph_untree)
-        fprintf (pph_logfile, "PPH: unrecognized tree node %s\n",
-                 tree_code_name[TREE_CODE (expr)]);
+      fatal_error ("PPH: unrecognized tree node '%s'",
+                   tree_code_name[TREE_CODE (expr)]);
     }
 }