diff mbox

[pph] Stream merging information (issue5090041)

Message ID 20110920015240.D2203222675@jade.mtv.corp.google.com
State New
Headers show

Commit Message

Lawrence Crowl Sept. 20, 2011, 1:52 a.m. UTC
Prepare for merging symbols.  When writing a cp_binding_level, we emit
this_entity first, so that we can identify the context of the bindings
early.  If this_entity is a namespace, we call alternate routines that
track the namespace.  These ultimately call pph_write_namespace_tree,
which adds additional information needed for decl merging.  Reads take
the corresponding actions.  We do not yet to symbol lookup or merging.

Tested on x64.



--
This patch is available for review at http://codereview.appspot.com/5090041
diff mbox

Patch

Index: gcc/cp/ChangeLog.pph

2011-09-19   Lawrence Crowl  <crowl@google.com>

	* pph-streamer-out.c (pph_out_binding_level_1): Read this_entity first.
	Call different routines when it is a namespace.
	(pph_write_tree): Move most of body to pph_write_namespace_tree.
	(pph_write_namespace_tree): As above.  If there is an enclosing
	namespace, write additional information needed for merging.
	(pph_out_namespace_tree_vec) New.
	(pph_out_namespace_tree_vec_filtered) New.
	(pph_write_namespace_chain) New.
	(pph_out_namespace_chain_filtered) New.
	* pph-streamer-in.c (pph_in_binding_level): Read this_entity first.
	Call different routines when it is a namespace.
	(pph_read_tree): Move most of body to pph_read_namespace_tree.
	(pph_read_namespace_tree): As above.  If there is an enclosing
	namespace, read additional information needed for merging.
	Merging is currently not done.
	(pph_read_namespace_chain): New.
	(pph_in_namespace_tree_vec): New.
	* pph-streamer.h (pph_write_namespace_tree): New.
	(pph_write_namespace_chain): New.
	(pph_read_namespace_tree): New.
	(pph_read_namespace_chain): New.
	(pph_out_namespace_tree_1): New.
	(pph_out_namespace_tree): New.
	(pph_out_tree_VEC): Deleted, redundant with pph-streamer-out.c.
	(pph_out_namespace_chain): New.
	(pph_in_namespace_tree): New.
	(pph_in_namespace_chain): New.


Index: gcc/cp/pph-streamer-in.c
===================================================================
--- gcc/cp/pph-streamer-in.c	(revision 178988)
+++ gcc/cp/pph-streamer-in.c	(working copy)
@@ -376,6 +376,26 @@  pph_in_tree_vec (pph_stream *stream)
 }
 
 
+/* Read and return a gc VEC of trees in ENCLOSING_NAMESPACE from STREAM.  */
+
+static VEC(tree,gc) *
+pph_in_namespace_tree_vec (pph_stream *stream, tree enclosing_namespace)
+{
+  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_namespace_tree (stream, enclosing_namespace);
+      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) *
@@ -529,6 +549,7 @@  pph_in_binding_level (pph_stream *stream
   cp_binding_level *bl;
   struct bitpack_d bp;
   enum pph_record_marker marker;
+  tree entity;
 
   marker = pph_in_start_record (stream, &image_ix, &ix);
   if (marker == PPH_RECORD_END)
@@ -547,13 +568,23 @@  pph_in_binding_level (pph_stream *stream
 				  ggc_alloc_cleared_cp_binding_level (),
 				  to_register);
 
-  bl->names = pph_in_chain (stream);
-  bl->namespaces = pph_in_chain (stream);
-
-  bl->static_decls = pph_in_tree_vec (stream);
-
-  bl->usings = pph_in_chain (stream);
-  bl->using_directives = pph_in_chain (stream);
+  entity = bl->this_entity = pph_in_tree (stream);
+  if (NAMESPACE_SCOPE_P (entity))
+    {
+      bl->names = pph_in_namespace_chain (stream, entity);
+      bl->namespaces = pph_in_namespace_chain (stream, entity);
+      bl->static_decls = pph_in_namespace_tree_vec (stream, entity);
+      bl->usings = pph_in_namespace_chain (stream, entity);
+      bl->using_directives = pph_in_namespace_chain (stream, entity);
+    }
+  else
+    {
+      bl->names = pph_in_chain (stream);
+      bl->namespaces = pph_in_chain (stream);
+      bl->static_decls = pph_in_tree_vec (stream);
+      bl->usings = pph_in_chain (stream);
+      bl->using_directives = pph_in_chain (stream);
+    }
 
   num = pph_in_uint (stream);
   bl->class_shadowed = NULL;
@@ -574,7 +605,6 @@  pph_in_binding_level (pph_stream *stream
     }
 
   bl->blocks = pph_in_tree (stream);
-  bl->this_entity = pph_in_tree (stream);
   bl->level_chain = pph_in_binding_level (stream, NULL);
   bl->dead_vars_from_for = pph_in_tree_vec (stream);
   bl->statement_list = pph_in_chain (stream);
@@ -2042,6 +2072,15 @@  pph_read_tree (struct lto_input_block *i
 {
   /* Find data.  */
   pph_stream *stream = (pph_stream *) root_data_in->sdata;
+  return pph_read_namespace_tree (stream, NULL);
+}
+
+/* Read a tree from the STREAM.  It ENCLOSING_NAMESPACE is not null,
+   the tree may be unified with an existing tree in that namespace.  */
+
+tree
+pph_read_namespace_tree (pph_stream *stream, tree enclosing_namespace)
+{
   struct lto_input_block *ib = stream->encoder.r.ib;
   struct data_in *data_in = stream->encoder.r.data_in;
 
@@ -2081,6 +2120,18 @@  pph_read_tree (struct lto_input_block *i
       /* Otherwise, materialize a new node from IB.  This will also read
          all the language-independent bitfields for the new tree.  */
       expr = pph_read_tree_header (stream, tag);
+      if (enclosing_namespace && DECL_P (expr))
+        {
+          /* We may need to unify two declarations.  */
+          /* FIXME crowl: location_t where = pph_in_location (stream); */
+          const char *idstr = pph_in_string (stream);
+          /* But we only search if we have a name.  */
+          if (!idstr)
+            {
+              /* FIXME crowl search for idstr in namespace.  */
+              expr = expr;
+            }
+        }
       pph_cache_insert_at (&stream->cache, expr, ix);
       pph_read_tree_body (stream, expr);
     }
@@ -2088,6 +2139,33 @@  pph_read_tree (struct lto_input_block *i
 }
 
 
+/* Read a chain of tree nodes from input block IB. DATA_IN contains
+   tables and descriptors for the file being read.  */
+
+tree
+pph_read_namespace_chain (pph_stream *stream, tree enclosing_namespace)
+{
+  int i, count;
+  tree first, prev, curr;
+
+  first = prev = NULL_TREE;
+  count = streamer_read_hwi (stream->encoder.r.ib);
+  for (i = 0; i < count; i++)
+    {
+      curr = pph_in_namespace_tree (stream, enclosing_namespace);
+      if (prev)
+        TREE_CHAIN (prev) = curr;
+      else
+        first = curr;
+
+      TREE_CHAIN (curr) = NULL_TREE;
+      prev = curr;
+    }
+
+  return first;
+}
+
+
 /* Finalize the PPH reader.  */
 
 void
Index: gcc/cp/pph-streamer-out.c
===================================================================
--- gcc/cp/pph-streamer-out.c	(revision 178988)
+++ gcc/cp/pph-streamer-out.c	(working copy)
@@ -400,6 +400,26 @@  pph_out_tree_vec (pph_stream *stream, VE
 }
 
 
+/* Write all the trees (from ENCLOSING_NAMESPACE) in VEC V to STREAM.  */
+
+static void
+pph_out_namespace_tree_vec (pph_stream *stream, VEC(tree,gc) *v,
+                            tree enclosing_namespace)
+{
+  unsigned i;
+  tree t;
+
+  /* Note that we use the same format used by streamer_write_chain.
+     This is to support pph_out_chain_filtered, which writes the
+     filtered chain as a VEC.  Since the reader always reads chains
+     using streamer_read_chain, we have to write VECs in exactly the
+     same way as tree chains.  */
+  pph_out_hwi (stream, VEC_length (tree, v));
+  FOR_EACH_VEC_ELT (tree, v, i, t)
+    pph_out_namespace_tree (stream, t, enclosing_namespace);
+}
+
+
 /* Write all the trees matching FILTER in VEC V to STREAM.  */
 
 static void
@@ -428,6 +448,37 @@  pph_out_tree_vec_filtered (pph_stream *s
 }
 
 
+/* Write all the trees in ENCLOSING_NAMESPACE matching FILTER
+   in VEC V to STREAM.  */
+
+static void
+pph_out_namespace_tree_vec_filtered (pph_stream *stream, VEC(tree,gc) *v,
+                                     tree enclosing_namespace, unsigned filter)
+{
+  unsigned i;
+  tree t;
+  VEC(tree, heap) *to_write = NULL;
+
+  /* Special case.  If the caller wants no filtering, it is much
+     faster to just call pph_out_tree_vec.  */
+  if (filter == PPHF_NONE)
+    {
+      pph_out_namespace_tree_vec (stream, v, enclosing_namespace);
+      return;
+    }
+
+  /* Collect all the nodes that match the filter.  */
+  FOR_EACH_VEC_ELT (tree, v, i, t)
+    if (pph_tree_matches (t, filter))
+      VEC_safe_push (tree, heap, to_write, t);
+
+  /* Write them.  */
+  pph_out_namespace_tree_vec (stream, (VEC(tree,gc) *)to_write,
+                                      enclosing_namespace);
+  VEC_free (tree, heap, to_write);
+}
+
+
 /* Write all the qualified_typedef_usage_t in VEC V to STREAM.  */
 
 static void
@@ -517,6 +568,36 @@  pph_out_label_binding (pph_stream *strea
 }
 
 
+/* Emit the chain of tree nodes from ENCLOSING_NAMESPACE starting at T
+   to STREAM.
+   OB is the output block
+   to write to.  REF_P is true if chain elements should be emitted
+   as references.  */
+
+void
+pph_write_namespace_chain (pph_stream *stream, tree t, tree enclosing_namespace)
+{
+  int i, count;
+
+  count = list_length (t);
+  streamer_write_hwi (stream->encoder.w.ob, count);
+  for (i = 0; i < count; i++)
+    {
+      tree saved_chain;
+
+      /* Clear TREE_CHAIN to avoid blindly recursing into the rest
+         of the list.  */
+      saved_chain = TREE_CHAIN (t);
+      TREE_CHAIN (t) = NULL_TREE;
+
+      pph_write_namespace_tree (stream, t, enclosing_namespace);
+
+      TREE_CHAIN (t) = saved_chain;
+      t = TREE_CHAIN (t);
+    }
+}
+
+
 /* Output a chain of nodes to STREAM starting with FIRST.  Skip any
    nodes that do not match FILTER.  */
 
@@ -545,6 +626,36 @@  pph_out_chain_filtered (pph_stream *stre
 }
 
 
+/* Output a chain of nodes in ENCLOSING_NAMESPACE to STREAM
+   starting with FIRST.  Skip any nodes that do not match FILTER.  */
+
+static void
+pph_out_namespace_chain_filtered (pph_stream *stream, tree first,
+                                  tree enclosing_namespace, unsigned filter)
+{
+  tree t;
+  VEC(tree, heap) *to_write = NULL;
+
+  /* Special case.  If the caller wants no filtering, it is much
+     faster to just call pph_out_chain directly.  */
+  if (filter == PPHF_NONE)
+    {
+      pph_out_namespace_chain (stream, first, enclosing_namespace);
+      return;
+    }
+
+  /* Collect all the nodes that match the filter.  */
+  for (t = first; t; t = TREE_CHAIN (t))
+    if (pph_tree_matches (t, filter))
+      VEC_safe_push (tree, heap, to_write, t);
+
+  /* Write them.  */
+  pph_out_namespace_tree_vec (stream, (VEC(tree,gc) *)to_write,
+                                      enclosing_namespace);
+  VEC_free (tree, heap, to_write);
+}
+
+
 /* Helper for pph_out_binding_level.  Write all the fields of BL to
    STREAM, without checking whether BL was in the streamer cache or not.
    Do not emit any nodes in BL that do not match FILTER.  */
@@ -557,15 +668,30 @@  pph_out_binding_level_1 (pph_stream *str
   cp_class_binding *cs;
   cp_label_binding *sl;
   struct bitpack_d bp;
-
-  pph_out_chain_filtered (stream, bl->names, PPHF_NO_BUILTINS | filter);
-  pph_out_chain_filtered (stream, bl->namespaces, PPHF_NO_BUILTINS | filter);
-
-  pph_out_tree_vec_filtered (stream, bl->static_decls, filter);
-
-  pph_out_chain_filtered (stream, bl->usings, PPHF_NO_BUILTINS | filter);
-  pph_out_chain_filtered (stream, bl->using_directives,
-			  PPHF_NO_BUILTINS | filter);
+  unsigned aux_filter = PPHF_NO_BUILTINS | filter;
+  tree entity = bl->this_entity;
+  pph_out_tree (stream, entity);
+  if (NAMESPACE_SCOPE_P (entity))
+    {
+      pph_out_namespace_chain_filtered (stream, bl->names,
+                                                entity, aux_filter);
+      pph_out_namespace_chain_filtered (stream, bl->namespaces,
+                                                entity, aux_filter);
+      pph_out_namespace_tree_vec_filtered (stream, bl->static_decls,
+                                                   entity, filter);
+      pph_out_namespace_chain_filtered (stream, bl->usings,
+                                                entity, aux_filter);
+      pph_out_namespace_chain_filtered (stream, bl->using_directives,
+                                                entity, aux_filter);
+    }
+  else
+    {
+      pph_out_chain_filtered (stream, bl->names, aux_filter);
+      pph_out_chain_filtered (stream, bl->namespaces, aux_filter);
+      pph_out_tree_vec_filtered (stream, bl->static_decls, filter);
+      pph_out_chain_filtered (stream, bl->usings, aux_filter);
+      pph_out_chain_filtered (stream, bl->using_directives, aux_filter);
+    }
 
   pph_out_uint (stream, VEC_length (cp_class_binding, bl->class_shadowed));
   FOR_EACH_VEC_ELT (cp_class_binding, bl->class_shadowed, i, cs)
@@ -578,7 +704,6 @@  pph_out_binding_level_1 (pph_stream *str
     pph_out_label_binding (stream, sl);
 
   pph_out_tree (stream, bl->blocks);
-  pph_out_tree (stream, bl->this_entity);
   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);
@@ -1791,7 +1916,13 @@  void
 pph_write_tree (struct output_block *ob, tree expr, bool ref_p ATTRIBUTE_UNUSED)
 {
   pph_stream *stream = (pph_stream *) ob->sdata;
+  pph_write_namespace_tree (stream, expr, NULL);
+}
 
+void
+pph_write_namespace_tree (pph_stream *stream, tree expr,
+                          tree enclosing_namespace )
+{
   /* If EXPR is NULL or it already existed in the pickle cache,
      nothing else needs to be done.  */
   if (!pph_out_start_record (stream, expr))
@@ -1804,19 +1935,30 @@  pph_write_tree (struct output_block *ob,
 	 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.  */
-      streamer_write_builtin (ob, expr);
+      streamer_write_builtin (stream->encoder.w.ob, expr);
     }
   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).  */
-      streamer_write_integer_cst (ob, expr, ref_p);
+      streamer_write_integer_cst (stream->encoder.w.ob, expr, false);
     }
   else
     {
       /* This is the first time we see EXPR, write it out.  */
       pph_write_tree_header (stream, expr);
+      if (enclosing_namespace && DECL_P (expr))
+        {
+          /* We may need to unify two declarations.  */
+          /* FIXME crowl: pph_out_location (stream, DECL_SOURCE_LOCATION (expr)); */
+          tree name = DECL_NAME (expr);
+          if (name)
+            pph_out_string_with_length (stream, IDENTIFIER_POINTER (name),
+                                        IDENTIFIER_LENGTH (name));
+          else
+            pph_out_string (stream, NULL);
+        }
       pph_write_tree_body (stream, expr);
     }
 }
Index: gcc/cp/pph-streamer.h
===================================================================
--- gcc/cp/pph-streamer.h	(revision 178987)
+++ gcc/cp/pph-streamer.h	(working copy)
@@ -254,6 +254,8 @@  void *pph_cache_get (pph_pickle_cache *,
 void pph_flush_buffers (pph_stream *);
 void pph_init_write (pph_stream *);
 void pph_write_tree (struct output_block *, tree, bool);
+void pph_write_namespace_tree (pph_stream *, tree, tree);
+void pph_write_namespace_chain (pph_stream *, tree, tree);
 void pph_add_decl_to_symtab (tree, enum pph_symtab_action, bool, bool);
 void pph_add_include (pph_stream *);
 void pph_writer_init (void);
@@ -268,6 +270,8 @@  struct binding_table_s *pph_in_binding_t
 /* In pph-streamer-in.c.  */
 void pph_init_read (pph_stream *);
 tree pph_read_tree (struct lto_input_block *, struct data_in *);
+tree pph_read_namespace_tree (pph_stream *, tree);
+tree pph_read_namespace_chain (pph_stream *, tree);
 location_t pph_read_location (struct lto_input_block *, struct data_in *);
 void pph_read_file (const char *);
 void pph_reader_finish (void);
@@ -329,6 +333,25 @@  pph_out_tree (pph_stream *stream, tree t
   pph_out_tree_1 (stream, t, 2);
 }
 
+/* Output AST T from ENCLOSING_NAMESPACE to STREAM.
+   If -fpph-tracer is set to TLEVEL or higher, T is sent to pph_trace_tree.  */
+static inline void
+pph_out_namespace_tree_1 (pph_stream *stream, tree t, int tlevel,
+                          tree enclosing_namespace)
+{
+  if (flag_pph_tracer >= tlevel)
+    pph_trace_tree (stream, t);
+  pph_write_namespace_tree (stream, t, enclosing_namespace);
+}
+
+/* Output AST T from ENCLOSING_NAMESPACE to STREAM.
+   Trigger tracing at -fpph-tracer=2.  */
+static inline void
+pph_out_namespace_tree (pph_stream *stream, tree t, tree enclosing_namespace)
+{
+  pph_out_namespace_tree_1 (stream, t, 2, enclosing_namespace);
+}
+
 /* Write an unsigned int VALUE to STREAM.  */
 static inline void
 pph_out_uint (pph_stream *stream, unsigned int value)
@@ -392,25 +415,6 @@  pph_out_string_with_length (pph_stream *
 				     str, len + 1, false);
 }
 
-/* Output VEC V of ASTs to STREAM.  */
-/* FIXME pph: hold for alternate routine. */
-#if 0
-static inline void
-pph_out_tree_VEC (pph_stream *stream, VEC(tree,gc) *v)
-{
-  tree t;
-  size_t i;
-  size_t c = VEC_length (tree, v);
-  pph_out_uint (stream, c);
-  FOR_EACH_VEC_ELT (tree, v, i, t)
-    {
-      if (flag_pph_tracer >= 1)
-        pph_trace_tree (stream, t);
-      pph_write_tree (stream->encoder.w.ob, t);
-    }
-}
-#endif
-
 /* Write location LOC of length to STREAM.  */
 static inline void
 pph_out_location (pph_stream *stream, location_t loc)
@@ -429,6 +433,16 @@  pph_out_chain (pph_stream *stream, tree 
   streamer_write_chain (stream->encoder.w.ob, first, false);
 }
 
+/* Write a chain of ASTs to STREAM starting with FIRST.  */
+static inline void
+pph_out_namespace_chain (pph_stream *stream, tree first,
+                         tree enclosing_namespace)
+{
+  if (flag_pph_tracer >= 2)
+    pph_trace_chain (stream, first);
+  pph_write_namespace_chain (stream, first, enclosing_namespace);
+}
+
 /* Write a bitpack BP to STREAM.  */
 static inline void
 pph_out_bitpack (pph_stream *stream, struct bitpack_d *bp)
@@ -521,6 +535,17 @@  pph_in_tree (pph_stream *stream)
   return t;
 }
 
+/* Load an AST in an ENCLOSING_NAMESPACE from STREAM.
+   Return the corresponding tree.  */
+static inline tree
+pph_in_namespace_tree (pph_stream *stream, tree enclosing_namespace)
+{
+  tree t = pph_read_namespace_tree (stream, enclosing_namespace);
+  if (flag_pph_tracer >= 4)
+    pph_trace_tree (stream, t);
+  return t;
+}
+
 /* Load into an array A of cardinality C of AST from STREAM.  */
 /* FIXME pph: Hold for later use. */
 #if 0
@@ -567,6 +592,16 @@  pph_in_chain (pph_stream *stream)
   return t;
 }
 
+/* Read a chain of ASTs in ENCLOSING_NAMESPACE from STREAM.  */
+static inline tree
+pph_in_namespace_chain (pph_stream *stream, tree enclosing_namespace)
+{
+  tree t = pph_read_namespace_chain (stream, enclosing_namespace);
+  if (flag_pph_tracer >= 2)
+    pph_trace_chain (stream, t);
+  return t;
+}
+
 /* Read a bitpack from STREAM.  */
 static inline struct bitpack_d
 pph_in_bitpack (pph_stream *stream)