@@ -336,4 +336,4 @@ cp/pph.o: cp/pph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(CPPLIB_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
+ $(CXX_PPH_H) $(TREE_PASS_H) version.h cppbuiltin.h tree-iterator.h
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tree.h"
#include "langhooks.h"
+#include "tree-iterator.h"
#include "tree-pretty-print.h"
#include "lto-streamer.h"
#include "pph-streamer.h"
@@ -146,6 +147,21 @@ pph_stream_write_tree (struct output_block *ob, tree expr, bool ref_p)
{
if (TREE_CODE (expr) == FUNCTION_DECL)
lto_output_tree_or_ref (ob, DECL_SAVED_TREE (expr), ref_p);
+ else if (TREE_CODE (expr) == 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++;
+
+ lto_output_sleb128_stream (ob->main_stream, num_stmts);
+
+ /* Write the statements. */
+ for (i = tsi_start (expr); !tsi_end_p (i); tsi_next (&i))
+ lto_output_tree_or_ref (ob, tsi_stmt (i), ref_p);
+ }
}
@@ -160,17 +176,64 @@ pph_stream_read_tree (struct lto_input_block *ib, struct data_in *data_in,
{
if (TREE_CODE (expr) == FUNCTION_DECL)
DECL_SAVED_TREE (expr) = lto_input_tree (ib, data_in);
+ else if (TREE_CODE (expr) == STATEMENT_LIST)
+ {
+ HOST_WIDE_INT i, num_trees = lto_input_sleb128 (ib);
+ for (i = 0; i < num_trees; i++)
+ {
+ tree stmt = lto_input_tree (ib, data_in);
+ append_to_statement_list (stmt, &expr);
+ }
+ }
+}
+
+
+/* Return true if the given tree T is streamable. */
+
+static bool
+pph_is_streamable (tree t ATTRIBUTE_UNUSED)
+{
+ /* We accept most trees. */
+ return TREE_CODE (t) != SSA_NAME
+ && (TREE_CODE (t) < OMP_PARALLEL
+ || TREE_CODE (t) > OMP_CRITICAL);
+}
+
+
+/* Callback for packing value fields in ASTs. BP is the bitpack
+ we are packing into. EXPR is the tree to pack. */
+
+static void
+pph_stream_pack_value_fields (struct bitpack_d *bp ATTRIBUTE_UNUSED,
+ tree expr ATTRIBUTE_UNUSED)
+{
+ /* Do nothing for now. */
+}
+
+
+/* Callback for unpacking value fields in ASTs. BP is the bitpack
+ we are unpacking from. EXPR is the tree to unpack. */
+
+static void
+pph_stream_unpack_value_fields (struct bitpack_d *bp ATTRIBUTE_UNUSED,
+ tree expr ATTRIBUTE_UNUSED)
+{
+ /* Do nothing for now. */
}
/* Initialize all the streamer hooks used for streaming ASTs. */
static void
-pph_streamer_hooks_init (void)
+pph_stream_hooks_init (void)
{
lto_streamer_hooks *h = streamer_hooks_init ();
+ h->name = "C++ AST";
+ h->is_streamable = pph_is_streamable;
h->write_tree = pph_stream_write_tree;
h->read_tree = pph_stream_read_tree;
+ h->pack_value_fields = pph_stream_pack_value_fields;
+ h->unpack_value_fields = pph_stream_unpack_value_fields;
}
@@ -187,7 +250,7 @@ pph_stream_open (const char *name, const char *mode)
f = fopen (name, mode);
if (f)
{
- pph_streamer_hooks_init ();
+ pph_stream_hooks_init ();
stream = XCNEW (pph_stream);
stream->file = f;
stream->name = xstrdup (name);
@@ -1790,26 +1790,11 @@ unpack_value_fields (struct bitpack_d *bp, tree expr)
if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
unpack_ts_block_value_fields (bp, expr);
- if (CODE_CONTAINS_STRUCT (code, TS_SSA_NAME))
- {
- /* We only stream the version number of SSA names. */
- gcc_unreachable ();
- }
-
- if (CODE_CONTAINS_STRUCT (code, TS_STATEMENT_LIST))
- {
- /* This is only used by GENERIC. */
- gcc_unreachable ();
- }
-
- if (CODE_CONTAINS_STRUCT (code, TS_OMP_CLAUSE))
- {
- /* This is only used by High GIMPLE. */
- gcc_unreachable ();
- }
-
if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
unpack_ts_translation_unit_decl_value_fields (bp, expr);
+
+ if (streamer_hooks ()->unpack_value_fields)
+ streamer_hooks ()->unpack_value_fields (bp, expr);
}
@@ -574,26 +574,11 @@ pack_value_fields (struct bitpack_d *bp, tree expr)
if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
pack_ts_block_value_fields (bp, expr);
- if (CODE_CONTAINS_STRUCT (code, TS_SSA_NAME))
- {
- /* We only stream the version number of SSA names. */
- gcc_unreachable ();
- }
-
- if (CODE_CONTAINS_STRUCT (code, TS_STATEMENT_LIST))
- {
- /* This is only used by GENERIC. */
- gcc_unreachable ();
- }
-
- if (CODE_CONTAINS_STRUCT (code, TS_OMP_CLAUSE))
- {
- /* This is only used by High GIMPLE. */
- gcc_unreachable ();
- }
-
if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
pack_ts_translation_unit_decl_value_fields (bp, expr);
+
+ if (streamer_hooks ()->pack_value_fields)
+ streamer_hooks ()->pack_value_fields (bp, expr);
}
@@ -1229,12 +1214,14 @@ lto_output_tree_header (struct output_block *ob, tree expr, int ix)
{
enum LTO_tags tag;
enum tree_code code;
+ lto_streamer_hooks *h = streamer_hooks ();
+
/* We should not see any non-GIMPLE tree nodes here. */
code = TREE_CODE (expr);
- if (!lto_is_streamable (expr))
- internal_error ("tree code %qs is not supported in gimple streams",
- tree_code_name[code]);
+ if (h->is_streamable && !h->is_streamable (expr))
+ internal_error ("tree code %qs is not supported in %s streams",
+ h->name, tree_code_name[code]);
/* The header of a tree node consists of its tag, the size of
the node, and any other information needed to instantiate
@@ -804,14 +804,41 @@ lto_check_version (int major, int minor)
}
+/* Return true if EXPR is a tree node that can be written to disk. */
+
+static inline bool
+lto_is_streamable (tree expr)
+{
+ enum tree_code code = TREE_CODE (expr);
+
+ /* Notice that we reject SSA_NAMEs as well. We only emit the SSA
+ name version in lto_output_tree_ref (see output_ssa_names). */
+ return !is_lang_specific (expr)
+ && code != SSA_NAME
+ && code != CALL_EXPR
+ && code != LANG_TYPE
+ && code != MODIFY_EXPR
+ && code != INIT_EXPR
+ && code != TARGET_EXPR
+ && code != BIND_EXPR
+ && code != WITH_CLEANUP_EXPR
+ && code != STATEMENT_LIST
+ && (code == CASE_LABEL_EXPR
+ || code == DECL_EXPR
+ || TREE_CODE_CLASS (code) != tcc_statement);
+}
+
+
/* Initialize all the streamer hooks used for streaming GIMPLE. */
void
gimple_streamer_hooks_init (void)
{
lto_streamer_hooks *h = streamer_hooks_init ();
+ h->name = "gimple";
h->reader_init = gimple_streamer_reader_init;
h->writer_init = NULL;
+ h->is_streamable = lto_is_streamable;
h->write_tree = gimple_streamer_write_tree;
h->read_tree = gimple_streamer_read_tree;
}
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
struct output_block;
struct lto_input_block;
struct data_in;
+struct bitpack_d;
/* Define when debugging the LTO streamer. This causes the writer
to output the numeric value for the memory address of the tree node
@@ -51,12 +52,18 @@ struct data_in;
replace the default behavior and those that supplement it. Any
or all of these hooks can be NULL. */
typedef struct lto_streamer_hooks {
+ /* A string identifying this streamer. */
+ const char *name;
+
/* 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);
+ /* Return true if the given tree is supported by this streamer. */
+ bool (*is_streamable) (tree);
+
/* 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
@@ -78,6 +85,14 @@ typedef struct lto_streamer_hooks {
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);
+
+ /* Called by pack_value_fields to store any non-pointer fields
+ in the tree structure. The arguments are as in pack_value_fields. */
+ void (*pack_value_fields) (struct bitpack_d *, tree);
+
+ /* Called by unpack_value_fields to retrieve any non-pointer fields
+ in the tree structure. The arguments are as in unpack_value_fields. */
+ void (*unpack_value_fields) (struct bitpack_d *, tree);
} lto_streamer_hooks;
@@ -1113,29 +1128,6 @@ lto_stream_as_builtin_p (tree expr)
|| DECL_BUILT_IN_CLASS (expr) == BUILT_IN_MD));
}
-/* Return true if EXPR is a tree node that can be written to disk. */
-static inline bool
-lto_is_streamable (tree expr)
-{
- enum tree_code code = TREE_CODE (expr);
-
- /* Notice that we reject SSA_NAMEs as well. We only emit the SSA
- name version in lto_output_tree_ref (see output_ssa_names). */
- return !is_lang_specific (expr)
- && code != SSA_NAME
- && code != CALL_EXPR
- && code != LANG_TYPE
- && code != MODIFY_EXPR
- && code != INIT_EXPR
- && code != TARGET_EXPR
- && code != BIND_EXPR
- && code != WITH_CLEANUP_EXPR
- && code != STATEMENT_LIST
- && (code == CASE_LABEL_EXPR
- || code == DECL_EXPR
- || TREE_CODE_CLASS (code) != tcc_statement);
-}
-
DEFINE_DECL_STREAM_FUNCS (TYPE, type)
DEFINE_DECL_STREAM_FUNCS (FIELD_DECL, field_decl)
DEFINE_DECL_STREAM_FUNCS (FN_DECL, fn_decl)