diff mbox

[pph] Add streaming hooks (issue4271074)

Message ID 20110325160816.73ABC1DA1B8@topo.tor.corp.google.com
State New
Headers show

Commit Message

Diego Novillo March 25, 2011, 4:08 p.m. UTC
This patch adds streamer hooks for writing and reading trees. It is
still very much WIP.  In particular, the hooks for reading and writing
may change.
    
These callbacks are called from lto_write_tree and lto_read_tree after
the common fields in the tree have been processed.  They are
responsible from writing any fields that the common code may not have
processed.  I have defined callbacks for gimple and moved the code
that was causing problem with the pph streamer.

Fields not processed by common code are documented by each handler.
As I start testing more FE trees, I will find out what other
gimple-specific bits are in the current lto-streamer* functions.
Those are candidates for the call backs.

Richi, Michael, Jan, while this is very incomplete, it shows the
initial idea I had earlier this week.  Feel free to poke holes in it.
I expect to change it substantially in the next few weeks.  Once I
have something I'm content with, I'll send you a more complete patch
with better documentation for discussion.

This setup should also make it easy to strip things out of gimple that
we do not want to write in LTO files, but are needed when streaming
ASTs.  Over time, I expect most of the existing tree pickling to move
into the FE call backs.

Tested on x86_64.  Committed to the branch.


Diego.

cp/ChangeLog.pph

2011-03-25  Diego Novillo  <dnovillo@google.com>

	* pph-streamer.c (pph_stream_hooks_init): New.
	(pph_stream_open): Call it.


ChangeLog.pph
2011-03-25  Diego Novillo  <dnovillo@google.com>

	* lto-streamer-in.c (lto_reader_init): Rename from
	lto_init_reader.  Update all users.
	If streamer_hooks.reader_init exists, call it.
	Move gimple-specific initialization ...
	(gimple_streamer_init_reader): ... to this new function.
	(lto_input_ts_decl_common_tree_pointers): Document unhandled fields.
	Do not handle DECL_INITIAL.
	(lto_input_ts_decl_non_common_tree_pointers): Document
	unhandled fields.
	Do not handle DECL_SAVED_TREE.
	(lto_read_tree): If streamer_hooks.read_tree is defined, call
	it.
	(gimple_streamer_read_tree): New.  Handle DECL_INITIAL.
	(gimple_streamer_reader_init): Rename from
	gimple_streamer_init_reader.  Update all users.
	* lto-streamer-out.c (lto_writer_init): Make extern.
	(lto_output): Call gimple_streamer_hooks_init.
	(lto_output_ts_decl_common_tree_pointers): Document unhandled fields.
	Do not handle DECL_INITIAL.
	(lto_output_ts_decl_non_common_tree_pointers): Document
	unhandled fields.
	Do not handle DECL_SAVED_TREE.
	(lto_write_tree): If streamer_hooks.write_tree is defined,
	call it.
	(gimple_streamer_write_tree): New.  Handle DECL_INITIAL and
	DECL_SAVED_TREE.
	* lto-streamer.c (gimple_streamer_hooks_init): New.
	(streamer_hooks): New.
	(streamer_hooks_init): New.
	* lto-streamer.h (lto_streamer_hooks): Declare.
	(streamer_hooks): Declare
	(streamer_hooks_init): Declare
	(gimple_streamer_hooks_init): Declare.
	(gimple_streamer_init_reader): Declare.
	(lto_writer_init): Declare.
	(struct output_block): Forward declare.
	(struct lto_input_block): Likewise.
	(struct data_in): Likewise.


lto/ChangeLog.pph

2011-03-25  Diego Novillo  <dnovillo@google.com>

	* lto.c (lto_main): Call gimple_streamer_hooks_init.





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

Patch

diff --git a/gcc/cp/pph-streamer.c b/gcc/cp/pph-streamer.c
index cca42e6..07438bd 100644
--- a/gcc/cp/pph-streamer.c
+++ b/gcc/cp/pph-streamer.c
@@ -137,6 +137,17 @@  pph_stream_init_write (pph_stream *stream)
 }
 
 
+/* Initialize all the streamer hooks used for streaming ASTs.  */
+
+static void
+pph_streamer_hooks_init (void)
+{
+  lto_streamer_hooks *h = streamer_hooks_init ();
+  h->reader_init = NULL;
+  h->writer_init = NULL;
+}
+
+
 /* Create a new PPH stream to be stored on the file called NAME.
    MODE is passed to fopen directly.  */
 
@@ -150,6 +161,7 @@  pph_stream_open (const char *name, const char *mode)
   f = fopen (name, mode);
   if (f)
     {
+      pph_streamer_hooks_init ();
       stream = XCNEW (pph_stream);
       stream->file = f;
       stream->name = xstrdup (name);
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index d2f0075..5d2761e 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -1983,7 +1983,11 @@  lto_input_ts_decl_minimal_tree_pointers (struct lto_input_block *ib,
 
 /* Read all pointer fields in the TS_DECL_COMMON structure of EXPR from
    input block IB.  DATA_IN contains tables and descriptors for the
-   file being read.  */
+   file being read.
+
+   Fields that should be handled by a callback:
+	DECL_INITIAL
+	DECL_ABSTRACT_ORIGIN.  */
 
 static void
 lto_input_ts_decl_common_tree_pointers (struct lto_input_block *ib,
@@ -1991,12 +1995,8 @@  lto_input_ts_decl_common_tree_pointers (struct lto_input_block *ib,
 {
   DECL_SIZE (expr) = lto_input_tree (ib, data_in);
   DECL_SIZE_UNIT (expr) = lto_input_tree (ib, data_in);
-
-  if (TREE_CODE (expr) != FUNCTION_DECL
-      && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
-    DECL_INITIAL (expr) = lto_input_tree (ib, data_in);
-
   DECL_ATTRIBUTES (expr) = lto_input_tree (ib, data_in);
+
   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
      for early inlining so drop it on the floor instead of ICEing in
      dwarf2out.c.  */
@@ -2020,7 +2020,10 @@  lto_input_ts_decl_common_tree_pointers (struct lto_input_block *ib,
 
 /* Read all pointer fields in the TS_DECL_NON_COMMON structure of
    EXPR from input block IB.  DATA_IN contains tables and descriptors for the
-   file being read.  */
+   file being read.
+
+   Fields that should be handled by a callback:
+	DECL_SAVED_TREE.  */
 
 static void
 lto_input_ts_decl_non_common_tree_pointers (struct lto_input_block *ib,
@@ -2028,10 +2031,6 @@  lto_input_ts_decl_non_common_tree_pointers (struct lto_input_block *ib,
 {
   if (TREE_CODE (expr) == FUNCTION_DECL)
     {
-      /* FIXME pph - Hookize.  */
-#if 1
-      DECL_SAVED_TREE (expr) = lto_input_tree (ib, data_in);
-#endif
       DECL_ARGUMENTS (expr) = lto_input_tree (ib, data_in);
       DECL_RESULT (expr) = lto_input_tree (ib, data_in);
     }
@@ -2636,6 +2635,11 @@  lto_read_tree (struct lto_input_block *ib, struct data_in *data_in,
   /* Read all the pointer fields in RESULT.  */
   lto_input_tree_pointers (ib, data_in, result);
 
+  /* Call back into the streaming module to read anything else it
+     may need.  */
+  if (streamer_hooks ()->read_tree)
+    streamer_hooks ()->read_tree (ib, data_in, result);
+
   /* We should never try to instantiate an MD or NORMAL builtin here.  */
   if (TREE_CODE (result) == FUNCTION_DECL)
     gcc_assert (!lto_stream_as_builtin_p (result));
@@ -2657,6 +2661,22 @@  lto_read_tree (struct lto_input_block *ib, struct data_in *data_in,
 }
 
 
+/* LTO streamer hook for reading GIMPLE trees.  IB and DATA_IN are as in
+   lto_read_tree.  EXPR is the tree was materialized by lto_read_tree and
+   needs GIMPLE specific data to be filled in.  */
+
+void
+gimple_streamer_read_tree (struct lto_input_block *ib,
+			   struct data_in *data_in,
+			   tree expr)
+{
+  if (DECL_P (expr)
+      && TREE_CODE (expr) != FUNCTION_DECL
+      && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
+    DECL_INITIAL (expr) = lto_input_tree (ib, data_in);
+}
+
+
 /* Read and INTEGER_CST node from input block IB using the per-file
    context in DATA_IN.  */
 
@@ -2738,16 +2758,23 @@  lto_input_tree (struct lto_input_block *ib, struct data_in *data_in)
 /* Initialization for the LTO reader.  */
 
 void
-lto_init_reader (void)
+lto_reader_init (void)
 {
   lto_streamer_init ();
+  if (streamer_hooks ()->reader_init)
+    streamer_hooks ()->reader_init ();
+}
 
+
+/* GIMPLE streamer hook for initializing the LTO reader.  */
+
+void
+gimple_streamer_reader_init (void)
+{
   memset (&lto_stats, 0, sizeof (lto_stats));
   bitmap_obstack_initialize (NULL);
-
   file_name_hash_table = htab_create (37, hash_string_slot_node,
 				      eq_string_slot_node, free);
-
   gimple_register_cfg_hooks ();
 }
 
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index d3d8294..81beb07 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -835,7 +835,11 @@  lto_output_ts_decl_minimal_tree_pointers (struct output_block *ob, tree expr,
 
 /* Write all pointer fields in the TS_DECL_COMMON structure of EXPR to
    output block OB.  If REF_P is true, write a reference to EXPR's
-   pointer fields.  */
+   pointer fields.
+
+   Fields that should be handled by a callback:
+	DECL_INITIAL
+	DECL_ABSTRACT_ORIGIN.  */
 
 static void
 lto_output_ts_decl_common_tree_pointers (struct output_block *ob, tree expr,
@@ -844,30 +848,10 @@  lto_output_ts_decl_common_tree_pointers (struct output_block *ob, tree expr,
   lto_output_tree_or_ref (ob, DECL_SIZE (expr), ref_p);
   lto_output_tree_or_ref (ob, DECL_SIZE_UNIT (expr), ref_p);
 
-  if (TREE_CODE (expr) != FUNCTION_DECL
-      && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
-    {
-      tree initial = DECL_INITIAL (expr);
-      /* FIXME pph - Hookize.  */
-#if 0
-      if (TREE_CODE (expr) == VAR_DECL
-	  && (TREE_STATIC (expr) || DECL_EXTERNAL (expr))
-	  && initial)
-	{
-	  lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
-	  struct varpool_node *vnode = varpool_get_node (expr);
-	  if (!vnode)
-	    initial = error_mark_node;
-	  else if (!lto_varpool_encoder_encode_initializer_p (varpool_encoder,
-							      vnode))
-	    initial = NULL;
-	}
-#endif
-    
-      lto_output_tree_or_ref (ob, initial, ref_p);
-    }
+  /* Do not stream DECL_INITIAL.  */
 
   lto_output_tree_or_ref (ob, DECL_ATTRIBUTES (expr), ref_p);
+
   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
      for early inlining so drop it on the floor instead of ICEing in
      dwarf2out.c.  */
@@ -887,7 +871,10 @@  lto_output_ts_decl_common_tree_pointers (struct output_block *ob, tree expr,
 
 /* Write all pointer fields in the TS_DECL_NON_COMMON structure of
    EXPR to output block OB.  If REF_P is true, write a reference to EXPR's
-   pointer fields.  */
+   pointer fields.
+
+   Fields that should be handled by a callback:
+	DECL_SAVED_TREE.  */
 
 static void
 lto_output_ts_decl_non_common_tree_pointers (struct output_block *ob,
@@ -895,16 +882,6 @@  lto_output_ts_decl_non_common_tree_pointers (struct output_block *ob,
 {
   if (TREE_CODE (expr) == FUNCTION_DECL)
     {
-#if 0
-      /* DECL_SAVED_TREE holds the GENERIC representation for DECL.
-	 At this point, it should not exist.  Either because it was
-	 converted to gimple or because DECL didn't have a GENERIC
-	 representation in this TU.  */
-      gcc_assert (DECL_SAVED_TREE (expr) == NULL_TREE);
-#else
-      /* FIXME pph - Hookize and handle FE ASTs.  */
-      lto_output_tree_or_ref (ob, NULL, ref_p);
-#endif
       lto_output_tree_or_ref (ob, DECL_ARGUMENTS (expr), ref_p);
       lto_output_tree_or_ref (ob, DECL_RESULT (expr), ref_p);
     }
@@ -1355,11 +1332,58 @@  lto_write_tree (struct output_block *ob, tree expr, bool ref_p, int ix)
   /* Write all the pointer fields in EXPR.  */
   lto_output_tree_pointers (ob, expr, ref_p);
 
+  /* Call back into the streaming module to see if it needs to write
+     anything that was not written by the common streamer.  */
+  if (streamer_hooks ()->write_tree)
+    streamer_hooks ()->write_tree (ob, expr, ref_p);
+
   /* Mark the end of EXPR.  */
   output_zero (ob);
 }
 
 
+/* GIMPLE hook for writing GIMPLE-specific parts of trees.  OB, EXPR
+   and REF_P are as in lto_write_tree.  */
+
+void
+gimple_streamer_write_tree (struct output_block *ob, tree expr, bool ref_p)
+{
+  if (TREE_CODE (expr) == FUNCTION_DECL)
+    {
+      /* DECL_SAVED_TREE holds the GENERIC representation for DECL.
+	 At this point, it should not exist.  Either because it was
+	 converted to gimple or because DECL didn't have a GENERIC
+	 representation in this TU.  */
+      gcc_assert (DECL_SAVED_TREE (expr) == NULL_TREE);
+    }
+
+  if (DECL_P (expr)
+      && TREE_CODE (expr) != FUNCTION_DECL
+      && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
+    {
+      /* Handle DECL_INITIAL for symbols.  */
+      tree initial = DECL_INITIAL (expr);
+      if (TREE_CODE (expr) == VAR_DECL
+	  && (TREE_STATIC (expr) || DECL_EXTERNAL (expr))
+	  && initial)
+	{
+	  lto_varpool_encoder_t varpool_encoder;
+	  struct varpool_node *vnode;
+
+	  varpool_encoder = ob->decl_state->varpool_node_encoder;
+	  vnode = varpool_get_node (expr);
+	  if (!vnode)
+	    initial = error_mark_node;
+	  else if (!lto_varpool_encoder_encode_initializer_p (varpool_encoder,
+							      vnode))
+	    initial = NULL;
+	}
+
+      lto_output_tree_or_ref (ob, initial, ref_p);
+    }
+}
+
+
 /* Emit the integer constant CST to output block OB.  If REF_P is true,
    CST's type will be emitted as a reference.  */
 
@@ -2203,10 +2227,12 @@  copy_function (struct cgraph_node *node)
 
 /* Initialize the LTO writer.  */
 
-static void
+void
 lto_writer_init (void)
 {
   lto_streamer_init ();
+  if (streamer_hooks ()->writer_init)
+    streamer_hooks ()->writer_init ();
 }
 
 
@@ -2223,6 +2249,7 @@  lto_output (cgraph_node_set set, varpool_node_set vset)
   int i, n_nodes;
   lto_cgraph_encoder_t encoder = lto_get_out_decl_state ()->cgraph_node_encoder;
 
+  gimple_streamer_hooks_init ();
   lto_writer_init ();
 
   n_nodes = lto_cgraph_encoder_size (encoder);
diff --git a/gcc/lto-streamer.c b/gcc/lto-streamer.c
index ff4fc05..f9b5285 100644
--- a/gcc/lto-streamer.c
+++ b/gcc/lto-streamer.c
@@ -802,3 +802,39 @@  lto_check_version (int major, int minor)
 		 major, minor,
 		 LTO_major_version, LTO_minor_version);
 }
+
+
+/* Initialize all the streamer hooks used for streaming GIMPLE.  */
+
+void
+gimple_streamer_hooks_init (void)
+{
+  lto_streamer_hooks *h = streamer_hooks_init ();
+  h->reader_init = gimple_streamer_reader_init;
+  h->writer_init = NULL;
+  h->write_tree = gimple_streamer_write_tree;
+  h->read_tree = gimple_streamer_read_tree;
+}
+
+
+/* Return the current set of streamer hooks.  Note that only one set
+   of streamer hooks can be active at a time.  */
+
+static lto_streamer_hooks streamer_hooks_;
+
+lto_streamer_hooks *
+streamer_hooks (void)
+{
+  return &streamer_hooks_;
+}
+
+
+/* Initialize and return the current set of streamer hooks.  */
+
+lto_streamer_hooks *
+streamer_hooks_init (void)
+{
+  lto_streamer_hooks *h = streamer_hooks ();
+  memset (h, 0, sizeof (lto_streamer_hooks));
+  return h;
+}
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index c7c865d..8ab0714 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -33,6 +33,11 @@  along with GCC; see the file COPYING3.  If not see
 #include "alloc-pool.h"
 #include "gcov-io.h"
 
+/* Forward declarations to avoid included unnecessary headers.  */
+struct output_block;
+struct lto_input_block;
+struct data_in;
+
 /* Define when debugging the LTO streamer.  This causes the writer
    to output the numeric value for the memory address of the tree node
    being emitted.  When debugging a problem in the reader, check the
@@ -41,6 +46,31 @@  along with GCC; see the file COPYING3.  If not see
    to trace how the faulty node is being emitted.  */
 /* #define LTO_STREAMER_DEBUG	1  */
 
+/* Streamer hooks.  These functions do additional processing as
+   needed by the module.  There are two types of callbacks, those that
+   replace the default behavior and those that supplement it.  Any
+   or all of these hooks can be NULL.  */
+typedef struct lto_streamer_hooks {
+  /* Called by lto_reader_init after it does basic initialization.  */
+  void (*reader_init) (void);
+
+  /* Called by lto_writer_init after it does basic initalization.  */
+  void (*writer_init) (void);
+
+  /* Called by lto_write_tree after writing all the common parts of
+     a tree.  If defined, the callback is in charge of writing all
+     the fields that lto_write_tree did not write out.  Arguments
+     are as in lto_write_tree.  */
+  void (*write_tree) (struct output_block *, tree, bool);
+
+  /* Called by lto_read_tree after reading all the common parts of
+     a tree.  If defined, the callback is in charge of reading all
+     the fields that lto_read_tree did not read in.  Arguments
+     are as in lto_read_tree.  */
+  void (*read_tree) (struct lto_input_block *, struct data_in *, tree);
+} lto_streamer_hooks;
+
+
 /* The encoding for a function consists of the following sections:
 
    1)    The header.
@@ -847,17 +877,21 @@  extern intptr_t lto_orig_address_get (tree);
 extern void lto_orig_address_remove (tree);
 #endif
 extern void lto_check_version (int, int);
-
+extern void gimple_streamer_hooks_init (void);
+extern void gimple_streamer_write_tree (struct output_block *, tree, bool);
+extern void gimple_streamer_read_tree (struct lto_input_block *,
+				       struct data_in *, tree);
+extern lto_streamer_hooks *streamer_hooks (void);
+extern lto_streamer_hooks *streamer_hooks_init (void);
 
 /* In lto-streamer-in.c */
 extern void lto_input_cgraph (struct lto_file_decl_data *, const char *);
-extern void lto_init_reader (void);
+extern void lto_reader_init (void);
 extern tree lto_input_tree (struct lto_input_block *, struct data_in *);
 extern void lto_input_function_body (struct lto_file_decl_data *, tree,
 				     const char *);
 extern void lto_input_constructors_and_inits (struct lto_file_decl_data *,
 					      const char *);
-extern void lto_init_reader (void);
 extern struct data_in *lto_data_in_create (struct lto_file_decl_data *,
 				    const char *, unsigned,
 				    VEC(ld_plugin_symbol_resolution_t,heap) *);
@@ -865,9 +899,11 @@  extern void lto_data_in_delete (struct data_in *);
 extern const char *lto_input_string (struct data_in *,
 				     struct lto_input_block *);
 extern void lto_input_data_block (struct lto_input_block *, void *, size_t);
+extern void gimple_streamer_reader_init (void);
 
 
 /* In lto-streamer-out.c  */
+extern void lto_writer_init (void);
 extern void lto_register_decl_definition (tree, struct lto_file_decl_data *);
 extern struct output_block *create_output_block (enum lto_section_type);
 extern void destroy_output_block (struct output_block *);
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 71c8cdb..56e376e 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -2446,8 +2446,8 @@  void
 lto_main (void)
 {
   lto_process_name ();
-
-  lto_init_reader ();
+  gimple_streamer_hooks_init ();
+  lto_reader_init ();
 
   /* Read all the symbols and call graph from all the files in the
      command line.  */