@@ -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);
@@ -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 (<o_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 ();
}
@@ -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);
@@ -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;
+}
@@ -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 *);
@@ -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. */