@@ -4757,6 +4757,7 @@ extern tree check_for_out_of_scope_variable (tree);
extern void print_other_binding_stack (struct cp_binding_level *);
extern tree maybe_push_decl (tree);
extern tree current_decl_namespace (void);
+extern cxx_binding *cxx_binding_make (tree, tree);
/* decl.c */
extern tree poplevel (int, int, int);
@@ -285,7 +285,7 @@ cxx_binding_init (cxx_binding *binding, tree value, tree type)
/* (GC)-allocate a binding object with VALUE and TYPE member initialized. */
-static cxx_binding *
+cxx_binding *
cxx_binding_make (tree value, tree type)
{
cxx_binding *binding;
@@ -230,9 +230,6 @@ static void cp_lexer_print_token
(FILE *, cp_token *);
#endif /* ENABLE_CHECKING */
-static cp_token_cache *cp_token_cache_new
- (cp_token *, cp_token *);
-
static void cp_parser_initial_pragma
(cp_token *);
@@ -1003,7 +1000,7 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
/* Create a new cp_token_cache, representing a range of tokens. */
-static cp_token_cache *
+cp_token_cache *
cp_token_cache_new (cp_token *first, cp_token *last)
{
cp_token_cache *cache = ggc_alloc_cp_token_cache ();
@@ -374,5 +374,6 @@ extern void cp_lexer_dump_tokens (FILE *, VEC(cp_token,gc) *, unsigned);
extern void cp_lexer_get_tokens (cp_lexer *);
extern cp_token_position cp_lexer_token_position (cp_lexer *, bool);
extern void cp_lexer_debug_tokens (VEC(cp_token,gc) *);
+extern cp_token_cache *cp_token_cache_new (cp_token *, cp_token *);
#endif /* GCC_CP_PARSER_H */
@@ -32,6 +32,16 @@ along with GCC; see the file COPYING3. If not see
#include "version.h"
#include "cppbuiltin.h"
+/* Callback for unpacking value fields in ASTs. BP is the bitpack
+ we are unpacking from. EXPR is the tree to unpack. */
+
+void
+pph_stream_unpack_value_fields (struct bitpack_d *bp ATTRIBUTE_UNUSED,
+ tree expr ATTRIBUTE_UNUSED)
+{
+ /* Do nothing for now. */
+}
+
/* Get the section with name NAME and type SECTION_TYPE from FILE_DATA.
Return a pointer to the start of the section contents and store
@@ -82,6 +92,8 @@ pph_stream_init_read (pph_stream *stream)
pph_file_header *header;
const char *strtab, *body;
+ lto_reader_init ();
+
/* Read STREAM->NAME into the memory buffer STREAM->FILE_DATA.
FIXME pph, we are reading the whole file at once. This seems
wasteful. */
@@ -118,6 +130,436 @@ pph_stream_init_read (pph_stream *stream)
LTO_INIT_INPUT_BLOCK_PTR (stream->ib, body, 0, body_size);
stream->data_in = lto_data_in_create (stream->pph_sections[0], strtab,
strtab_size, NULL);
+
+ /* Associate STREAM with STREAM->DATA_IN so we can recover it from
+ the streamer hooks. */
+ stream->data_in->sdata = (void *) stream;
+}
+
+
+/* Read and return a record marker from STREAM. The marker
+ must be one of PPH_RECORD_START or PPH_RECORD_END. If PPH_RECORD_END
+ is read, return false. Otherwise, return true. */
+
+static inline bool
+pph_start_record (pph_stream *stream)
+{
+ unsigned char marker = pph_input_uchar (stream);
+ gcc_assert (marker == PPH_RECORD_START || marker == PPH_RECORD_END);
+ return (marker == PPH_RECORD_START);
+}
+
+
+/* Read all fields in lang_decl_base instance LDB from STREAM. */
+
+static void
+pph_stream_read_ld_base (pph_stream *stream, struct lang_decl_base *ldb)
+{
+ struct bitpack_d bp;
+
+ if (!pph_start_record (stream))
+ return;
+
+ bp = pph_input_bitpack (stream);
+ ldb->selector = bp_unpack_value (&bp, 16);
+ ldb->language = (enum languages) bp_unpack_value (&bp, 4);
+ ldb->use_template = bp_unpack_value (&bp, 2);
+ ldb->not_really_extern = bp_unpack_value (&bp, 1);
+ ldb->initialized_in_class = bp_unpack_value (&bp, 1);
+ ldb->repo_available_p = bp_unpack_value (&bp, 1);
+ ldb->threadprivate_or_deleted_p = bp_unpack_value (&bp, 1);
+ ldb->anticipated_p = bp_unpack_value (&bp, 1);
+ ldb->friend_attr = bp_unpack_value (&bp, 1);
+ ldb->template_conv_p = bp_unpack_value (&bp, 1);
+ ldb->odr_used = bp_unpack_value (&bp, 1);
+ ldb->u2sel = bp_unpack_value (&bp, 1);
+}
+
+
+/* Read all the fields in lang_decl_min instance LDM from STREAM. */
+
+static void
+pph_stream_read_ld_min (pph_stream *stream, struct lang_decl_min *ldm)
+{
+ if (!pph_start_record (stream))
+ return;
+
+ gcc_assert (ldm->base.selector == 0);
+
+ ldm->template_info = pph_input_tree (stream);
+ if (ldm->base.u2sel == 0)
+ ldm->u2.access = pph_input_tree (stream);
+ else if (ldm->base.u2sel == 1)
+ ldm->u2.discriminator = pph_input_uint (stream);
+ else
+ gcc_unreachable ();
+}
+
+
+/* Read and return a VEC of trees from STREAM. */
+
+static VEC(tree,gc) *
+pph_stream_read_tree_vec (pph_stream *stream)
+{
+ unsigned i, num;
+ VEC(tree,gc) *v;
+
+ num = pph_input_uint (stream);
+ v = NULL;
+ for (i = 0; i < num; i++)
+ {
+ tree t = pph_input_tree (stream);
+ VEC_safe_push (tree, gc, v, t);
+ }
+
+ return v;
+}
+
+/* Forward declaration to break cyclic dependencies. */
+static struct cp_binding_level *pph_stream_read_binding_level (pph_stream *);
+
+/* Helper for pph_stream_read_cxx_binding. Read and return a cxx_binding
+ instance from STREAM. */
+
+static cxx_binding *
+pph_stream_read_cxx_binding_1 (pph_stream *stream)
+{
+ struct bitpack_d bp;
+ cxx_binding *cb;
+ tree value, type;
+
+ if (!pph_start_record (stream))
+ return NULL;
+
+ value = pph_input_tree (stream);
+ type = pph_input_tree (stream);
+ cb = cxx_binding_make (value, type);
+ cb->scope = pph_stream_read_binding_level (stream);
+ bp = pph_input_bitpack (stream);
+ cb->value_is_inherited = bp_unpack_value (&bp, 1);
+ cb->is_local = bp_unpack_value (&bp, 1);
+
+ return cb;
+}
+
+
+/* Read and return an instance of cxx_binding from STREAM. */
+
+static cxx_binding *
+pph_stream_read_cxx_binding (pph_stream *stream)
+{
+ unsigned i, num_bindings;
+ cxx_binding *curr, *cb;
+
+ if (!pph_start_record (stream))
+ return NULL;
+
+ /* Read the list of previous bindings. */
+ num_bindings = pph_input_uint (stream);
+ for (curr = NULL, i = 0; i < num_bindings; i++)
+ {
+ cxx_binding *prev = pph_stream_read_cxx_binding_1 (stream);
+ if (curr)
+ curr->previous = prev;
+ curr = prev;
+ }
+
+ /* Read the current binding at the end. */
+ cb = pph_stream_read_cxx_binding_1 (stream);
+ cb->previous = curr;
+
+ return cb;
+}
+
+
+/* Read all the fields of cp_class_binding instance CB to OB. REF_P
+ is true if the tree fields should be written as references. */
+
+static cp_class_binding *
+pph_stream_read_class_binding (pph_stream *stream)
+{
+ cp_class_binding *cb;
+
+ if (!pph_start_record (stream))
+ return NULL;
+
+ cb = ggc_alloc_cleared_cp_class_binding ();
+ memcpy (&cb->base, pph_stream_read_cxx_binding (stream),
+ sizeof (cxx_binding));
+ cb->identifier = pph_input_tree (stream);
+
+ return cb;
+}
+
+
+/* Read and return an instance of cp_label_binding from STREAM. */
+
+static cp_label_binding *
+pph_stream_read_label_binding (pph_stream *stream)
+{
+ cp_label_binding *lb;
+
+ if (!pph_start_record (stream))
+ return NULL;
+
+ lb = ggc_alloc_cleared_cp_label_binding ();
+ lb->label = pph_input_tree (stream);
+ lb->prev_value = pph_input_tree (stream);
+
+ return lb;
+}
+
+
+/* Read and return an instance of cp_binding_level from STREAM. */
+
+static struct cp_binding_level *
+pph_stream_read_binding_level (pph_stream *stream)
+{
+ unsigned i, num;
+ cp_label_binding *sl;
+ struct cp_binding_level *bl;
+ struct bitpack_d bp;
+
+ if (!pph_start_record (stream))
+ return NULL;
+
+ bl = ggc_alloc_cleared_cp_binding_level ();
+ bl->names = pph_input_chain (stream);
+ bl->names_size = pph_input_uint (stream);
+ bl->namespaces = pph_input_chain (stream);
+
+ bl->static_decls = pph_stream_read_tree_vec (stream);
+
+ bl->usings = pph_input_chain (stream);
+ bl->using_directives = pph_input_chain (stream);
+
+ num = pph_input_uint (stream);
+ bl->class_shadowed = NULL;
+ for (i = 0; i < num; i++)
+ {
+ cp_class_binding *cb = pph_stream_read_class_binding (stream);
+ VEC_safe_push (cp_class_binding, gc, bl->class_shadowed, cb);
+ }
+
+ bl->type_shadowed = pph_input_tree (stream);
+
+ num = pph_input_uint (stream);
+ bl->shadowed_labels = NULL;
+ for (i = 0; VEC_iterate (cp_label_binding, bl->shadowed_labels, i, sl); i++)
+ {
+ cp_label_binding *sl = pph_stream_read_label_binding (stream);
+ VEC_safe_push (cp_label_binding, gc, bl->shadowed_labels, sl);
+ }
+
+ bl->blocks = pph_input_chain (stream);
+ bl->this_entity = pph_input_tree (stream);
+ bl->level_chain = pph_stream_read_binding_level (stream);
+ bl->dead_vars_from_for = pph_stream_read_tree_vec (stream);
+ bl->statement_list = pph_input_chain (stream);
+ bl->binding_depth = pph_input_uint (stream);
+
+ bp = pph_input_bitpack (stream);
+ bl->kind = (enum scope_kind) bp_unpack_value (&bp, 4);
+ bl->keep = bp_unpack_value (&bp, 1);
+ bl->more_cleanups_ok = bp_unpack_value (&bp, 1);
+ bl->have_cleanups = bp_unpack_value (&bp, 1);
+
+ return bl;
+}
+
+
+/* Read and return an instance of struct c_language_function from STREAM. */
+
+static struct c_language_function *
+pph_stream_read_c_language_function (pph_stream *stream)
+{
+ struct c_language_function *clf;
+
+ if (!pph_start_record (stream))
+ return NULL;
+
+ clf = ggc_alloc_cleared_c_language_function ();
+ clf->x_stmt_tree.x_cur_stmt_list = pph_input_tree (stream);
+ clf->x_stmt_tree.stmts_are_full_exprs_p = pph_input_uint (stream);
+
+ return clf;
+}
+
+
+/* Read and return an instance of struct language_function from STREAM. */
+
+static struct language_function *
+pph_stream_read_language_function (pph_stream *stream)
+{
+ struct bitpack_d bp;
+ struct language_function *lf;
+
+ if (!pph_start_record (stream))
+ return NULL;
+
+ lf = ggc_alloc_cleared_language_function ();
+ memcpy (&lf->base, pph_stream_read_c_language_function (stream),
+ sizeof (struct c_language_function));
+ lf->x_cdtor_label = pph_input_tree (stream);
+ lf->x_current_class_ptr = pph_input_tree (stream);
+ lf->x_current_class_ref = pph_input_tree (stream);
+ lf->x_eh_spec_block = pph_input_tree (stream);
+ lf->x_in_charge_parm = pph_input_tree (stream);
+ lf->x_vtt_parm = pph_input_tree (stream);
+ lf->x_return_value = pph_input_tree (stream);
+ bp = pph_input_bitpack (stream);
+ lf->x_returns_value = bp_unpack_value (&bp, 1);
+ lf->x_returns_null = bp_unpack_value (&bp, 1);
+ lf->x_returns_abnormally = bp_unpack_value (&bp, 1);
+ lf->x_in_function_try_handler = bp_unpack_value (&bp, 1);
+ lf->x_in_base_initializer = bp_unpack_value (&bp, 1);
+ lf->can_throw = bp_unpack_value (&bp, 1);
+
+ /* FIXME pph. We are not reading lf->x_named_labels. */
+
+ lf->bindings = pph_stream_read_binding_level (stream);
+ lf->x_local_names = pph_stream_read_tree_vec (stream);
+
+ /* FIXME pph. We are not reading lf->extern_decl_map. */
+
+ return lf;
+}
+
+
+/* Read all the fields of lang_decl_fn instance LDF from STREAM. */
+
+static void
+pph_stream_read_ld_fn (pph_stream *stream, struct lang_decl_fn *ldf)
+{
+ struct bitpack_d bp;
+
+ if (!pph_start_record (stream))
+ return;
+
+ bp = pph_input_bitpack (stream);
+ ldf->operator_code = (enum tree_code) bp_unpack_value (&bp, 16);
+ ldf->global_ctor_p = bp_unpack_value (&bp, 1);
+ ldf->global_dtor_p = bp_unpack_value (&bp, 1);
+ ldf->constructor_attr = bp_unpack_value (&bp, 1);
+ ldf->destructor_attr = bp_unpack_value (&bp, 1);
+ ldf->assignment_operator_p = bp_unpack_value (&bp, 1);
+ ldf->static_function = bp_unpack_value (&bp, 1);
+ ldf->pure_virtual = bp_unpack_value (&bp, 1);
+ ldf->defaulted_p = bp_unpack_value (&bp, 1);
+ ldf->has_in_charge_parm_p = bp_unpack_value (&bp, 1);
+ ldf->has_vtt_parm_p = bp_unpack_value (&bp, 1);
+ ldf->pending_inline_p = bp_unpack_value (&bp, 1);
+ ldf->nonconverting = bp_unpack_value (&bp, 1);
+ ldf->thunk_p = bp_unpack_value (&bp, 1);
+ ldf->this_thunk_p = bp_unpack_value (&bp, 1);
+ ldf->hidden_friend_p = bp_unpack_value (&bp, 1);
+
+ ldf->befriending_classes = pph_input_tree (stream);
+ ldf->context = pph_input_tree (stream);
+
+ if (ldf->thunk_p == 0)
+ ldf->u5.cloned_function = pph_input_tree (stream);
+ else if (ldf->thunk_p == 1)
+ ldf->u5.fixed_offset = pph_input_uint (stream);
+ else
+ gcc_unreachable ();
+
+ if (ldf->pending_inline_p == 1)
+ ldf->u.pending_inline_info = pth_load_token_cache (stream);
+ else if (ldf->pending_inline_p == 0)
+ ldf->u.saved_language_function = pph_stream_read_language_function (stream);
+}
+
+
+/* Read all the fields of lang_decl_ns instance LDNS from STREAM. */
+
+static void
+pph_stream_read_ld_ns (pph_stream *stream, struct lang_decl_ns *ldns)
+{
+ if (!pph_start_record (stream))
+ return;
+
+ ldns->level = pph_stream_read_binding_level (stream);
+}
+
+
+/* Read all the fields of lang_decl_parm instance LDP from STREAM. */
+
+static void
+pph_stream_read_ld_parm (pph_stream *stream, struct lang_decl_parm *ldp)
+{
+ if (!pph_start_record (stream))
+ return;
+
+ ldp->level = pph_input_uint (stream);
+ ldp->index = pph_input_uint (stream);
+}
+
+
+/* Read language specific data in DECL from STREAM. */
+
+static void
+pph_stream_read_lang_specific_data (pph_stream *stream, tree decl)
+{
+ struct lang_decl *ld;
+ struct lang_decl_base *ldb;
+
+ if (!pph_start_record (stream))
+ return;
+
+ /* Allocate a lang_decl structure for DECL. */
+ retrofit_lang_decl (decl);
+
+ ld = DECL_LANG_SPECIFIC (decl);
+ ldb = &ld->u.base;
+
+ /* Read all the fields in lang_decl_base. */
+ pph_stream_read_ld_base (stream, ldb);
+
+ if (ldb->selector == 0)
+ {
+ /* Read all the fields in lang_decl_min. */
+ pph_stream_read_ld_min (stream, &ld->u.min);
+ }
+ else if (ldb->selector == 1)
+ {
+ /* Read all the fields in lang_decl_fn. */
+ pph_stream_read_ld_fn (stream, &ld->u.fn);
+ }
+ else if (ldb->selector == 2)
+ {
+ /* Read all the fields in lang_decl_ns. */
+ pph_stream_read_ld_ns (stream, &ld->u.ns);
+ }
+ else if (ldb->selector == 3)
+ {
+ /* Read all the fields in lang_decl_parm. */
+ pph_stream_read_ld_parm (stream, &ld->u.parm);
+ }
+ else
+ gcc_unreachable ();
+}
+
+
+/* Allocate a tree node with code CODE. IB and DATA_IN are used to
+ read more data from the stream, if needed to build this node.
+ Return NULL if we did not want to handle this node. In that case,
+ the caller will call make_node to allocate this tree. */
+
+tree
+pph_stream_alloc_tree (enum tree_code code,
+ struct lto_input_block *ib ATTRIBUTE_UNUSED,
+ struct data_in *data_in)
+{
+ pph_stream *stream = (pph_stream *) data_in->sdata;
+
+ if (code == CALL_EXPR)
+ {
+ unsigned nargs = pph_input_uint (stream);
+ return build_vl_exp (CALL_EXPR, nargs + 3);
+ }
+
+ return NULL_TREE;
}
@@ -127,29 +569,30 @@ pph_stream_init_read (pph_stream *stream)
tree. */
void
-pph_stream_read_tree (struct lto_input_block *ib, struct data_in *data_in,
- tree expr)
+pph_stream_read_tree (struct lto_input_block *ib ATTRIBUTE_UNUSED,
+ struct data_in *data_in, tree expr)
{
- if (TREE_CODE (expr) == FUNCTION_DECL)
- DECL_SAVED_TREE (expr) = lto_input_tree (ib, data_in);
+ pph_stream *stream = (pph_stream *) data_in->sdata;
+
+ if (DECL_P (expr))
+ {
+ if (TREE_CODE (expr) == FUNCTION_DECL
+ || TREE_CODE (expr) == NAMESPACE_DECL
+ || TREE_CODE (expr) == PARM_DECL
+ || LANG_DECL_HAS_MIN (expr))
+ {
+ pph_stream_read_lang_specific_data (stream, expr);
+ if (TREE_CODE (expr) == FUNCTION_DECL)
+ DECL_SAVED_TREE (expr) = pph_input_tree (stream);
+ }
+ }
else if (TREE_CODE (expr) == STATEMENT_LIST)
{
- HOST_WIDE_INT i, num_trees = lto_input_sleb128 (ib);
+ HOST_WIDE_INT i, num_trees = pph_input_uint (stream);
for (i = 0; i < num_trees; i++)
{
- tree stmt = lto_input_tree (ib, data_in);
+ tree stmt = pph_input_tree (stream);
append_to_statement_list (stmt, &expr);
}
}
}
-
-
-/* Callback for unpacking value fields in ASTs. BP is the bitpack
- we are unpacking from. EXPR is the tree to unpack. */
-
-void
-pph_stream_unpack_value_fields (struct bitpack_d *bp ATTRIBUTE_UNUSED,
- tree expr ATTRIBUTE_UNUSED)
-{
- /* Do nothing for now. */
-}
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
not allow passing a FILE handle to them. */
static FILE *current_pph_file = NULL;
+
/* Callback for packing value fields in ASTs. BP is the bitpack
we are packing into. EXPR is the tree to pack. */
@@ -53,11 +54,15 @@ pph_stream_pack_value_fields (struct bitpack_d *bp ATTRIBUTE_UNUSED,
void
pph_stream_init_write (pph_stream *stream)
{
+ lto_writer_init ();
stream->out_state = lto_new_out_decl_state ();
lto_push_out_decl_state (stream->out_state);
stream->decl_state_stream = XCNEW (struct lto_output_stream);
stream->ob = create_output_block (LTO_section_decls);
- pph_set_pph_stream (stream->ob, stream);
+
+ /* Associate STREAM with STREAM->OB so we can recover it from the
+ streamer hooks. */
+ stream->ob->sdata = (void *) stream;
}
@@ -160,20 +165,37 @@ pph_stream_flush_buffers (pph_stream *stream)
}
+/* Start a new record in STREAM for data in DATA. If DATA is NULL,
+ write an end-of-record marker and return false. Otherwise, write a
+ start-of-record marker and return true. */
+
+static inline bool
+pph_start_record (pph_stream *stream, void *data)
+{
+ if (data)
+ {
+ pph_output_uchar (stream, PPH_RECORD_START);
+ return true;
+ }
+ else
+ {
+ pph_output_uchar (stream, PPH_RECORD_END);
+ return false;
+ }
+}
+
+
/* Write all the fields in lang_decl_base instance LDB to OB. */
static void
-pph_stream_write_ld_base (struct output_block *ob, struct lang_decl_base *ldb)
+pph_stream_write_ld_base (pph_stream *stream, struct lang_decl_base *ldb)
{
struct bitpack_d bp;
- if (ldb == NULL)
- {
- pph_output_uint (pph_get_pph_stream (ob), 0);
- return;
- }
+ if (!pph_start_record (stream, ldb))
+ return;
- bp = bitpack_create (ob->main_stream);
+ bp = bitpack_create (stream->ob->main_stream);
bp_pack_value (&bp, ldb->selector, 16);
bp_pack_value (&bp, ldb->language, 4);
bp_pack_value (&bp, ldb->use_template, 2);
@@ -186,277 +208,245 @@ pph_stream_write_ld_base (struct output_block *ob, struct lang_decl_base *ldb)
bp_pack_value (&bp, ldb->template_conv_p, 1);
bp_pack_value (&bp, ldb->odr_used, 1);
bp_pack_value (&bp, ldb->u2sel, 1);
- lto_output_bitpack (&bp);
+ pph_output_bitpack (stream, &bp);
}
-/* Write all the fields in lang_decl_min instance LDM to OB. If REF_P
+/* Write all the fields in lang_decl_min instance LDM to STREAM. If REF_P
is true, all tree fields should be written as references. */
static void
-pph_stream_write_ld_min (struct output_block *ob, struct lang_decl_min *ldm,
+pph_stream_write_ld_min (pph_stream *stream, struct lang_decl_min *ldm,
bool ref_p)
{
- if (ldm == 0)
- {
- pph_output_uint (pph_get_pph_stream (ob), 0);
- return;
- }
+ if (!pph_start_record (stream, ldm))
+ return;
gcc_assert (ldm->base.selector == 0);
- lto_output_tree_or_ref (ob, ldm->template_info, ref_p);
+ pph_output_tree_or_ref (stream, ldm->template_info, ref_p);
if (ldm->base.u2sel == 0)
- lto_output_tree_or_ref (ob, ldm->u2.access, ref_p);
+ pph_output_tree_or_ref (stream, ldm->u2.access, ref_p);
else if (ldm->base.u2sel == 1)
- lto_output_sleb128_stream (ob->main_stream, ldm->u2.discriminator);
+ pph_output_uint (stream, ldm->u2.discriminator);
else
gcc_unreachable ();
}
-/* Write all the trees in VEC V to OB. REF_P is true if the trees should
+/* Write all the trees in VEC V to STREAM. REF_P is true if the trees should
be written as references. */
static void
-pph_stream_write_tree_vec (struct output_block *ob, VEC(tree,gc) *v, bool ref_p)
+pph_stream_write_tree_vec (pph_stream *stream, VEC(tree,gc) *v, bool ref_p)
{
unsigned i;
tree t;
- lto_output_uleb128_stream (ob->main_stream, VEC_length (tree, v));
+ pph_output_uint (stream, VEC_length (tree, v));
for (i = 0; VEC_iterate (tree, v, i, t); i++)
- lto_output_tree_or_ref (ob, t, ref_p);
+ pph_output_tree_or_ref (stream, t, ref_p);
}
/* Forward declaration to break cyclic dependencies. */
-static void pph_stream_write_binding_level (struct output_block *,
+static void pph_stream_write_binding_level (pph_stream *,
struct cp_binding_level *, bool);
-/* Helper for pph_stream_write_cxx_binding. OB, CB and REF_P are as in
+/* Helper for pph_stream_write_cxx_binding. STREAM, CB and REF_P are as in
pph_stream_write_cxx_binding. */
static void
-pph_stream_write_cxx_binding_1 (struct output_block *ob, cxx_binding *cb,
- bool ref_p)
+pph_stream_write_cxx_binding_1 (pph_stream *stream, cxx_binding *cb, bool ref_p)
{
struct bitpack_d bp;
- if (cb == NULL)
- {
- pph_output_uint (pph_get_pph_stream (ob), 0);
- return;
- }
+ if (!pph_start_record (stream, cb))
+ return;
- lto_output_tree_or_ref (ob, cb->value, ref_p);
- lto_output_tree_or_ref (ob, cb->type, ref_p);
- pph_stream_write_binding_level (ob, cb->scope, ref_p);
- bp = bitpack_create (ob->main_stream);
+ pph_output_tree_or_ref (stream, cb->value, ref_p);
+ pph_output_tree_or_ref (stream, cb->type, ref_p);
+ pph_stream_write_binding_level (stream, cb->scope, ref_p);
+ bp = bitpack_create (stream->ob->main_stream);
bp_pack_value (&bp, cb->value_is_inherited, 1);
bp_pack_value (&bp, cb->is_local, 1);
- lto_output_bitpack (&bp);
+ pph_output_bitpack (stream, &bp);
}
-/* Write all the fields of cxx_binding instance CB to OB. REF_P is
+/* Write all the fields of cxx_binding instance CB to STREAM. REF_P is
true if the tree fields should be written as references. */
static void
-pph_stream_write_cxx_binding (struct output_block *ob, cxx_binding *cb,
- bool ref_p)
+pph_stream_write_cxx_binding (pph_stream *stream, cxx_binding *cb, bool ref_p)
{
unsigned num_bindings;
cxx_binding *prev;
- if (cb == NULL)
- {
- pph_output_uint (pph_get_pph_stream (ob), 0);
- return;
- }
+ if (!pph_start_record (stream, cb))
+ return;
for (num_bindings = 0, prev = cb->previous; prev; prev = prev->previous)
num_bindings++;
/* Write the list of previous bindings. */
- lto_output_sleb128_stream (ob->main_stream, num_bindings);
+ pph_output_uint (stream, num_bindings);
for (prev = cb->previous; prev; prev = prev->previous)
- pph_stream_write_cxx_binding_1 (ob, prev, ref_p);
+ pph_stream_write_cxx_binding_1 (stream, prev, ref_p);
/* Write the current binding at the end. */
- pph_stream_write_cxx_binding_1 (ob, cb, ref_p);
+ pph_stream_write_cxx_binding_1 (stream, cb, ref_p);
}
-/* Write all the fields of cp_class_binding instance CB to OB. REF_P
+/* Write all the fields of cp_class_binding instance CB to STREAM. REF_P
is true if the tree fields should be written as references. */
static void
-pph_stream_write_class_binding (struct output_block *ob,
- cp_class_binding *cb, bool ref_p)
+pph_stream_write_class_binding (pph_stream *stream, cp_class_binding *cb,
+ bool ref_p)
{
- if (cb == NULL)
- {
- pph_output_uint (pph_get_pph_stream (ob), 0);
- return;
- }
+ if (!pph_start_record (stream, cb))
+ return;
- pph_stream_write_cxx_binding (ob, &cb->base, ref_p);
- lto_output_tree_or_ref (ob, cb->identifier, ref_p);
+ pph_stream_write_cxx_binding (stream, &cb->base, ref_p);
+ pph_output_tree_or_ref (stream, cb->identifier, ref_p);
}
-/* Write all the fields of cp_label_binding instance LB to OB. If
+/* Write all the fields of cp_label_binding instance LB to STREAM. If
REF_P is true, tree fields will be written as references. */
static void
-pph_stream_write_label_binding (struct output_block *ob,
- cp_label_binding *lb, bool ref_p)
+pph_stream_write_label_binding (pph_stream *stream, cp_label_binding *lb,
+ bool ref_p)
{
- if (lb == NULL)
- {
- pph_output_uint (pph_get_pph_stream (ob), 0);
- return;
- }
+ if (!pph_start_record (stream, lb))
+ return;
- lto_output_tree_or_ref (ob, lb->label, ref_p);
- lto_output_tree_or_ref (ob, lb->prev_value, ref_p);
+ pph_output_tree_or_ref (stream, lb->label, ref_p);
+ pph_output_tree_or_ref (stream, lb->prev_value, ref_p);
}
-/* Write all the fields of cp_binding_level instance BL to OB. If
+/* Write all the fields of cp_binding_level instance BL to STREAM. If
REF_P is true, tree fields will be written as references. */
static void
-pph_stream_write_binding_level (struct output_block *ob,
- struct cp_binding_level *bl, bool ref_p)
+pph_stream_write_binding_level (pph_stream *stream, struct cp_binding_level *bl,
+ bool ref_p)
{
unsigned i;
cp_class_binding *cs;
cp_label_binding *sl;
struct bitpack_d bp;
- if (bl == NULL)
- {
- pph_output_uint (pph_get_pph_stream (ob), 0);
- return;
- }
+ if (!pph_start_record (stream, bl))
+ return;
- lto_output_chain (ob, bl->names, ref_p);
- lto_output_uleb128_stream (ob->main_stream, bl->names_size);
- lto_output_chain (ob, bl->namespaces, ref_p);
+ pph_output_chain (stream, bl->names, ref_p);
+ pph_output_uint (stream, bl->names_size);
+ pph_output_chain (stream, bl->namespaces, ref_p);
- pph_stream_write_tree_vec (ob, bl->static_decls, ref_p);
+ pph_stream_write_tree_vec (stream, bl->static_decls, ref_p);
- lto_output_chain (ob, bl->usings, ref_p);
- lto_output_chain (ob, bl->using_directives, ref_p);
+ pph_output_chain (stream, bl->usings, ref_p);
+ pph_output_chain (stream, bl->using_directives, ref_p);
- lto_output_uleb128_stream (ob->main_stream, VEC_length (cp_class_binding,
- bl->class_shadowed));
+ pph_output_uint (stream, VEC_length (cp_class_binding, bl->class_shadowed));
for (i = 0; VEC_iterate (cp_class_binding, bl->class_shadowed, i, cs); i++)
- pph_stream_write_class_binding (ob, cs, ref_p);
+ pph_stream_write_class_binding (stream, cs, ref_p);
- lto_output_tree_or_ref (ob, bl->type_shadowed, ref_p);
+ pph_output_tree_or_ref (stream, bl->type_shadowed, ref_p);
- lto_output_uleb128_stream (ob->main_stream, VEC_length (cp_label_binding,
- bl->shadowed_labels));
+ pph_output_uint (stream, VEC_length (cp_label_binding, bl->shadowed_labels));
for (i = 0; VEC_iterate (cp_label_binding, bl->shadowed_labels, i, sl); i++)
- pph_stream_write_label_binding (ob, sl, ref_p);
+ pph_stream_write_label_binding (stream, sl, ref_p);
- lto_output_chain (ob, bl->blocks, ref_p);
- lto_output_tree_or_ref (ob, bl->this_entity, ref_p);
- pph_stream_write_binding_level (ob, bl->level_chain, ref_p);
- pph_stream_write_tree_vec (ob, bl->dead_vars_from_for, ref_p);
- lto_output_chain (ob, bl->statement_list, ref_p);
- lto_output_sleb128_stream (ob->main_stream, bl->binding_depth);
+ pph_output_chain (stream, bl->blocks, ref_p);
+ pph_output_tree_or_ref (stream, bl->this_entity, ref_p);
+ pph_stream_write_binding_level (stream, bl->level_chain, ref_p);
+ pph_stream_write_tree_vec (stream, bl->dead_vars_from_for, ref_p);
+ pph_output_chain (stream, bl->statement_list, ref_p);
+ pph_output_uint (stream, bl->binding_depth);
- bp = bitpack_create (ob->main_stream);
+ bp = bitpack_create (stream->ob->main_stream);
bp_pack_value (&bp, bl->kind, 4);
bp_pack_value (&bp, bl->keep, 1);
bp_pack_value (&bp, bl->more_cleanups_ok, 1);
bp_pack_value (&bp, bl->have_cleanups, 1);
- lto_output_bitpack (&bp);
+ pph_output_bitpack (stream, &bp);
}
-/* Write all the fields of c_language_function instance CLF to OB. If
+/* Write all the fields of c_language_function instance CLF to STREAM. If
REF_P is true, all tree fields should be written as references. */
static void
-pph_stream_write_c_language_function (struct output_block *ob,
+pph_stream_write_c_language_function (pph_stream *stream,
struct c_language_function *clf,
bool ref_p)
{
- if (clf == NULL)
- {
- pph_output_uint (pph_get_pph_stream (ob), 0);
- return;
- }
+ if (!pph_start_record (stream, clf))
+ return;
- lto_output_tree_or_ref (ob, clf->x_stmt_tree.x_cur_stmt_list, ref_p);
- lto_output_sleb128_stream (ob->main_stream,
- clf->x_stmt_tree.stmts_are_full_exprs_p);
+ pph_output_tree_or_ref (stream, clf->x_stmt_tree.x_cur_stmt_list, ref_p);
+ pph_output_uint (stream, clf->x_stmt_tree.stmts_are_full_exprs_p);
}
-/* Write all the fields of language_function instance LF to OB. If
+/* Write all the fields of language_function instance LF to STREAM. If
REF_P is true, all tree fields should be written as references. */
static void
-pph_stream_write_language_function (struct output_block *ob,
+pph_stream_write_language_function (pph_stream *stream,
struct language_function *lf,
bool ref_p)
{
struct bitpack_d bp;
- if (lf == NULL)
- {
- pph_output_uint (pph_get_pph_stream (ob), 0);
- return;
- }
-
- pph_stream_write_c_language_function (ob, &lf->base, ref_p);
- lto_output_tree_or_ref (ob, lf->x_cdtor_label, ref_p);
- lto_output_tree_or_ref (ob, lf->x_current_class_ptr, ref_p);
- lto_output_tree_or_ref (ob, lf->x_current_class_ref, ref_p);
- lto_output_tree_or_ref (ob, lf->x_eh_spec_block, ref_p);
- lto_output_tree_or_ref (ob, lf->x_in_charge_parm, ref_p);
- lto_output_tree_or_ref (ob, lf->x_vtt_parm, ref_p);
- lto_output_tree_or_ref (ob, lf->x_return_value, ref_p);
- bp = bitpack_create (ob->main_stream);
+ if (!pph_start_record (stream, lf))
+ return;
+
+ pph_stream_write_c_language_function (stream, &lf->base, ref_p);
+ pph_output_tree_or_ref (stream, lf->x_cdtor_label, ref_p);
+ pph_output_tree_or_ref (stream, lf->x_current_class_ptr, ref_p);
+ pph_output_tree_or_ref (stream, lf->x_current_class_ref, ref_p);
+ pph_output_tree_or_ref (stream, lf->x_eh_spec_block, ref_p);
+ pph_output_tree_or_ref (stream, lf->x_in_charge_parm, ref_p);
+ pph_output_tree_or_ref (stream, lf->x_vtt_parm, ref_p);
+ pph_output_tree_or_ref (stream, lf->x_return_value, ref_p);
+ bp = bitpack_create (stream->ob->main_stream);
bp_pack_value (&bp, lf->x_returns_value, 1);
bp_pack_value (&bp, lf->x_returns_null, 1);
bp_pack_value (&bp, lf->x_returns_abnormally, 1);
bp_pack_value (&bp, lf->x_in_function_try_handler, 1);
bp_pack_value (&bp, lf->x_in_base_initializer, 1);
bp_pack_value (&bp, lf->can_throw, 1);
- lto_output_bitpack (&bp);
+ pph_output_bitpack (stream, &bp);
/* FIXME pph. We are not writing lf->x_named_labels. */
- pph_stream_write_binding_level (ob, lf->bindings, ref_p);
- pph_stream_write_tree_vec (ob, lf->x_local_names, ref_p);
+ pph_stream_write_binding_level (stream, lf->bindings, ref_p);
+ pph_stream_write_tree_vec (stream, lf->x_local_names, ref_p);
/* FIXME pph. We are not writing lf->extern_decl_map. */
}
-/* Write all the fields of lang_decl_fn instance LDF to OB. If REF_P
+/* Write all the fields of lang_decl_fn instance LDF to STREAM. If REF_P
is true, all tree fields should be written as references. */
static void
-pph_stream_write_ld_fn (struct output_block *ob, struct lang_decl_fn *ldf,
+pph_stream_write_ld_fn (pph_stream *stream, struct lang_decl_fn *ldf,
bool ref_p)
{
struct bitpack_d bp;
- if (ldf == NULL)
- {
- pph_output_uint (pph_get_pph_stream (ob), 0);
- return;
- }
+ if (!pph_start_record (stream, ldf))
+ return;
- bp = bitpack_create (ob->main_stream);
+ bp = bitpack_create (stream->ob->main_stream);
bp_pack_value (&bp, ldf->operator_code, 16);
bp_pack_value (&bp, ldf->global_ctor_p, 1);
bp_pack_value (&bp, ldf->global_dtor_p, 1);
@@ -473,107 +463,116 @@ pph_stream_write_ld_fn (struct output_block *ob, struct lang_decl_fn *ldf,
bp_pack_value (&bp, ldf->thunk_p, 1);
bp_pack_value (&bp, ldf->this_thunk_p, 1);
bp_pack_value (&bp, ldf->hidden_friend_p, 1);
- lto_output_bitpack (&bp);
+ pph_output_bitpack (stream, &bp);
- lto_output_tree_or_ref (ob, ldf->befriending_classes, ref_p);
- lto_output_tree_or_ref (ob, ldf->context, ref_p);
+ pph_output_tree_or_ref (stream, ldf->befriending_classes, ref_p);
+ pph_output_tree_or_ref (stream, ldf->context, ref_p);
if (ldf->thunk_p == 0)
- lto_output_tree_or_ref (ob, ldf->u5.cloned_function, ref_p);
+ pph_output_tree_or_ref (stream, ldf->u5.cloned_function, ref_p);
else if (ldf->thunk_p == 1)
- lto_output_sleb128_stream (ob->main_stream, ldf->u5.fixed_offset);
+ pph_output_uint (stream, ldf->u5.fixed_offset);
else
gcc_unreachable ();
if (ldf->pending_inline_p == 1)
- pth_save_token_cache (ldf->u.pending_inline_info, pph_get_pph_stream (ob));
+ pth_save_token_cache (ldf->u.pending_inline_info, stream);
else if (ldf->pending_inline_p == 0)
- pph_stream_write_language_function (ob, ldf->u.saved_language_function,
+ pph_stream_write_language_function (stream, ldf->u.saved_language_function,
ref_p);
}
-/* Write all the fields of lang_decl_ns instance LDNS to OB. If REF_P
+/* Write all the fields of lang_decl_ns instance LDNS to STREAM. If REF_P
is true, all tree fields should be written as references. */
static void
-pph_stream_write_ld_ns (struct output_block *ob, struct lang_decl_ns *ldns,
+pph_stream_write_ld_ns (pph_stream *stream, struct lang_decl_ns *ldns,
bool ref_p)
{
struct cp_binding_level *level;
- if (ldns == NULL)
- {
- pph_output_uint (pph_get_pph_stream (ob), 0);
- return;
- }
+ if (!pph_start_record (stream, ldns))
+ return;
level = ldns->level;
- pph_stream_write_binding_level (ob, level, ref_p);
+ pph_stream_write_binding_level (stream, level, ref_p);
}
-/* Write all the fields of lang_decl_parm instance LDP to OB. If REF_P
+/* Write all the fields of lang_decl_parm instance LDP to STREAM. If REF_P
is true, all tree fields should be written as references. */
static void
-pph_stream_write_ld_parm (struct output_block *ob, struct lang_decl_parm *ldp)
+pph_stream_write_ld_parm (pph_stream *stream, struct lang_decl_parm *ldp)
{
- if (ldp == NULL)
- {
- pph_output_uint (pph_get_pph_stream (ob), 0);
- return;
- }
+ if (!pph_start_record (stream, ldp))
+ return;
- lto_output_sleb128_stream (ob->main_stream, ldp->level);
- lto_output_sleb128_stream (ob->main_stream, ldp->index);
+ pph_output_uint (stream, ldp->level);
+ pph_output_uint (stream, ldp->index);
}
-/* Write all the lang-specific data in DECL to OB. REF_P is true if
+/* Write all the lang-specific data in DECL to STREAM. REF_P is true if
the trees referenced in lang-specific fields should be written as
references. */
static void
-pph_stream_write_lang_specific_data (struct output_block *ob,
- tree decl, bool ref_p)
+pph_stream_write_lang_specific_data (pph_stream *stream, tree decl, bool ref_p)
{
struct lang_decl *ld;
struct lang_decl_base *ldb;
- gcc_assert (DECL_P (decl) && DECL_LANG_SPECIFIC (decl));
+ gcc_assert (DECL_P (decl));
ld = DECL_LANG_SPECIFIC (decl);
- ldb = &ld->u.base;
-
+ if (!pph_start_record (stream, ld))
+ return;
+
/* Write all the fields in lang_decl_base. */
- pph_stream_write_ld_base (ob, ldb);
+ ldb = &ld->u.base;
+ pph_stream_write_ld_base (stream, ldb);
if (ldb->selector == 0)
{
/* Write all the fields in lang_decl_min. */
- pph_stream_write_ld_min (ob, &ld->u.min, ref_p);
+ pph_stream_write_ld_min (stream, &ld->u.min, ref_p);
}
else if (ldb->selector == 1)
{
/* Write all the fields in lang_decl_fn. */
- pph_stream_write_ld_fn (ob, &ld->u.fn, ref_p);
+ pph_stream_write_ld_fn (stream, &ld->u.fn, ref_p);
}
else if (ldb->selector == 2)
{
/* Write all the fields in lang_decl_ns. */
- pph_stream_write_ld_ns (ob, &ld->u.ns, ref_p);
+ pph_stream_write_ld_ns (stream, &ld->u.ns, ref_p);
}
else if (ldb->selector == 3)
{
/* Write all the fields in lang_decl_parm. */
- pph_stream_write_ld_parm (ob, &ld->u.parm);
+ pph_stream_write_ld_parm (stream, &ld->u.parm);
}
else
gcc_unreachable ();
}
+/* Write header information for some AST nodes not handled by the
+ common streamer code. EXPR is the tree to write to output block
+ OB. If EXPR does not need to be handled specially, do nothing. */
+
+void
+pph_stream_output_tree_header (struct output_block *ob, tree expr)
+{
+ pph_stream *stream = (pph_stream *) ob->sdata;
+
+ if (TREE_CODE (expr) == CALL_EXPR)
+ pph_output_uint (stream, call_expr_nargs (expr));
+}
+
+
/* Callback for writing ASTs to a stream. This writes all the fields
that are not processed by default by the common tree pickler.
OB and REF_P are as in lto_write_tree. EXPR is the tree to write. */
@@ -581,13 +580,20 @@ pph_stream_write_lang_specific_data (struct output_block *ob,
void
pph_stream_write_tree (struct output_block *ob, tree expr, bool ref_p)
{
+ pph_stream *stream = (pph_stream *) ob->sdata;
+
if (DECL_P (expr))
{
- if (DECL_LANG_SPECIFIC (expr))
- pph_stream_write_lang_specific_data (ob, expr, ref_p);
-
- if (TREE_CODE (expr) == FUNCTION_DECL)
- lto_output_tree_or_ref (ob, DECL_SAVED_TREE (expr), ref_p);
+ if (TREE_CODE (expr) == FUNCTION_DECL
+ || TREE_CODE (expr) == NAMESPACE_DECL
+ || TREE_CODE (expr) == PARM_DECL
+ || LANG_DECL_HAS_MIN (expr))
+ {
+ pph_stream_write_lang_specific_data (stream, expr, ref_p);
+
+ if (TREE_CODE (expr) == FUNCTION_DECL)
+ pph_output_tree (stream, DECL_SAVED_TREE (expr), ref_p);
+ }
}
else if (TREE_CODE (expr) == STATEMENT_LIST)
{
@@ -598,10 +604,10 @@ pph_stream_write_tree (struct output_block *ob, tree expr, bool ref_p)
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);
+ pph_output_uint (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);
+ pph_output_tree (stream, tsi_stmt (i), ref_p);
}
}
@@ -68,6 +68,8 @@ pph_stream_hooks_init (void)
h->pack_value_fields = pph_stream_pack_value_fields;
h->indexable_with_decls_p = pph_indexable_with_decls_p;
h->unpack_value_fields = pph_stream_unpack_value_fields;
+ h->alloc_tree = pph_stream_alloc_tree;
+ h->output_tree_header = pph_stream_output_tree_header;
}
@@ -118,7 +120,9 @@ enum pph_trace_type
PPH_TRACE_TREE,
PPH_TRACE_UINT,
PPH_TRACE_BYTES,
- PPH_TRACE_STRING
+ PPH_TRACE_STRING,
+ PPH_TRACE_CHAIN,
+ PPH_TRACE_BITPACK
};
@@ -131,7 +135,8 @@ pph_stream_trace (pph_stream *stream, const void *data, unsigned int nbytes,
enum pph_trace_type type)
{
const char *op = (stream->write_p) ? "write" : "read";
- const char *type_s[] = { "tree", "uint", "bytes", "string" };
+ const char *type_s[] = { "tree", "uint", "bytes", "string", "chain",
+ "bitpack" };
fprintf (pph_logfile, "*** %s: op=%s, type=%s, size=%u, value=",
stream->name, op, type_s[type], (unsigned) nbytes);
@@ -174,6 +179,22 @@ pph_stream_trace (pph_stream *stream, const void *data, unsigned int nbytes,
fprintf (pph_logfile, "<nil>");
break;
+ case PPH_TRACE_CHAIN:
+ {
+ const_tree t = (const_tree) data;
+ print_generic_expr (pph_logfile, CONST_CAST (union tree_node *, t),
+ TDF_SLIM);
+ fprintf (pph_logfile, " (%d nodes in chain)", list_length (t));
+ }
+ break;
+
+ case PPH_TRACE_BITPACK:
+ {
+ const struct bitpack_d *bp = (const struct bitpack_d *) data;
+ fprintf (pph_logfile, "0x%lx", bp->word);
+ }
+ break;
+
default:
gcc_unreachable ();
}
@@ -187,7 +208,8 @@ pph_stream_trace (pph_stream *stream, const void *data, unsigned int nbytes,
void
pph_stream_trace_tree (pph_stream *stream, tree t)
{
- pph_stream_trace (stream, t, tree_code_size (TREE_CODE (t)), PPH_TRACE_TREE);
+ pph_stream_trace (stream, t, t ? tree_code_size (TREE_CODE (t)) : 0,
+ PPH_TRACE_TREE);
}
@@ -227,3 +249,22 @@ pph_stream_trace_string_with_length (pph_stream *stream, const char *s,
{
pph_stream_trace (stream, s, len, PPH_TRACE_STRING);
}
+
+
+/* Show tracing information for a tree chain starting with T on STREAM. */
+
+void
+pph_stream_trace_chain (pph_stream *stream, tree t)
+{
+ pph_stream_trace (stream, t, t ? tree_code_size (TREE_CODE (t)) : 0,
+ PPH_TRACE_CHAIN);
+}
+
+
+/* Show tracing information for a bitpack BP on STREAM. */
+
+void
+pph_stream_trace_bitpack (pph_stream *stream, struct bitpack_d *bp)
+{
+ pph_stream_trace (stream, bp, sizeof (*bp), PPH_TRACE_BITPACK);
+}
@@ -24,6 +24,10 @@ along with GCC; see the file COPYING3. If not see
#include "lto-streamer.h"
#include "tree.h"
+/* Record markers. */
+static const unsigned char PPH_RECORD_START = 0xff;
+static const unsigned char PPH_RECORD_END = 0xfe;
+
/* Number of sections in a PPH file. FIXME, currently only one section
is supported. To add more, it will also be necessary to handle
section names in pph_get_section_data and pph_free_section_data. */
@@ -91,34 +95,49 @@ void pph_stream_trace_uint (pph_stream *, unsigned int);
void pph_stream_trace_bytes (pph_stream *, const void *, size_t);
void pph_stream_trace_string (pph_stream *, const char *);
void pph_stream_trace_string_with_length (pph_stream *, const char *, unsigned);
+void pph_stream_trace_chain (pph_stream *, tree);
+void pph_stream_trace_bitpack (pph_stream *, struct bitpack_d *);
/* In pph-streamer-out.c. */
void pph_stream_flush_buffers (pph_stream *);
void pph_stream_init_write (pph_stream *);
void pph_stream_write_tree (struct output_block *, tree, bool ref_p);
void pph_stream_pack_value_fields (struct bitpack_d *, tree);
+void pph_stream_output_tree_header (struct output_block *, tree);
/* In pph-streamer-in.c. */
void pph_stream_init_read (pph_stream *);
void pph_stream_read_tree (struct lto_input_block *, struct data_in *, tree);
void pph_stream_unpack_value_fields (struct bitpack_d *, tree);
-
-/* In pph.c. FIXME move these to pph-streamer.c. */
+tree pph_stream_alloc_tree (enum tree_code, struct lto_input_block *,
+ struct data_in *);
+/* In pph.c. FIXME pph move these to pph-streamer.c. */
struct cp_token_cache;
void pth_save_token_cache (struct cp_token_cache *, pph_stream *);
+struct cp_token_cache *pth_load_token_cache (pph_stream *);
/* Inline functions. */
-/* Output AST T to STREAM. */
+/* Output AST T to STREAM. If REF_P is true, output all the leaves of T
+ as references. */
+static inline void
+pph_output_tree (pph_stream *stream, tree t, bool ref_p)
+{
+ if (flag_pph_tracer)
+ pph_stream_trace_tree (stream, t);
+ lto_output_tree (stream->ob, t, ref_p);
+}
+
+/* Output AST T to STREAM. If REF_P is true, output a reference to T. */
static inline void
-pph_output_tree (pph_stream *stream, tree t)
+pph_output_tree_or_ref (pph_stream *stream, tree t, bool ref_p)
{
if (flag_pph_tracer)
pph_stream_trace_tree (stream, t);
- lto_output_tree (stream->ob, t, true);
+ lto_output_tree_or_ref (stream->ob, t, ref_p);
}
-/* Write a uint VALUE to STREAM. */
+/* Write an unsigned int VALUE to STREAM. */
static inline void
pph_output_uint (pph_stream *stream, unsigned int value)
{
@@ -127,6 +146,15 @@ pph_output_uint (pph_stream *stream, unsigned int value)
lto_output_sleb128_stream (stream->ob->main_stream, value);
}
+/* Write an unsigned char VALUE to STREAM. */
+static inline void
+pph_output_uchar (pph_stream *stream, unsigned char value)
+{
+ if (flag_pph_tracer)
+ pph_stream_trace_uint (stream, value);
+ lto_output_1_stream (stream->ob->main_stream, value);
+}
+
/* Write N bytes from P to STREAM. */
static inline void
pph_output_bytes (pph_stream *stream, const void *p, size_t n)
@@ -151,17 +179,38 @@ pph_output_string_with_length (pph_stream *stream, const char *str,
unsigned int len)
{
if (str)
- lto_output_string_with_length (stream->ob, stream->ob->main_stream,
- str, len + 1);
+ {
+ lto_output_string_with_length (stream->ob, stream->ob->main_stream,
+ str, len + 1);
+ if (flag_pph_tracer)
+ pph_stream_trace_string_with_length (stream, str, len);
+ }
else
{
/* lto_output_string_with_length does not handle NULL strings,
but lto_output_string does. */
pph_output_string (stream, NULL);
}
+}
+/* Write a chain of ASTs to STREAM starting with FIRST. REF_P is true
+ if the nodes should be emitted as references. */
+static inline void
+pph_output_chain (pph_stream *stream, tree first, bool ref_p)
+{
+ lto_output_chain (stream->ob, first, ref_p);
if (flag_pph_tracer)
- pph_stream_trace_string_with_length (stream, str, len);
+ pph_stream_trace_chain (stream, first);
+}
+
+/* Write a bitpack BP to STREAM. */
+static inline void
+pph_output_bitpack (pph_stream *stream, struct bitpack_d *bp)
+{
+ gcc_assert (stream->ob->main_stream == bp->stream);
+ if (flag_pph_tracer)
+ pph_stream_trace_bitpack (stream, bp);
+ lto_output_bitpack (bp);
}
/* Read an unsigned HOST_WIDE_INT integer from STREAM. */
@@ -175,6 +224,16 @@ pph_input_uint (pph_stream *stream)
return (unsigned) n;
}
+/* Read an unsigned char VALUE to STREAM. */
+static inline unsigned char
+pph_input_uchar (pph_stream *stream)
+{
+ unsigned char n = lto_input_1_unsigned (stream->ib);
+ if (flag_pph_tracer)
+ pph_stream_trace_uint (stream, n);
+ return n;
+}
+
/* Read N bytes from STREAM into P. The caller is responsible for
allocating a sufficiently large buffer. */
static inline void
@@ -199,7 +258,6 @@ pph_input_string (pph_stream *stream)
}
/* Load an AST from STREAM. Return the corresponding tree. */
-
static inline tree
pph_input_tree (pph_stream *stream)
{
@@ -209,22 +267,24 @@ pph_input_tree (pph_stream *stream)
return t;
}
-/* Return the PPH stream object associated with output block OB. */
-
-static inline pph_stream *
-pph_get_pph_stream (struct output_block *ob)
+/* Read a chain of ASTs from STREAM. */
+static inline tree
+pph_input_chain (pph_stream *stream)
{
- /* FIXME pph - Do not overload OB fields this way. */
- return ((pph_stream *) ob->cfg_stream);
+ tree t = lto_input_chain (stream->ib, stream->data_in);
+ if (flag_pph_tracer)
+ pph_stream_trace_chain (stream, t);
+ return t;
}
-/* Set the PPH stream object F associated with output block OB. */
-
-static inline void
-pph_set_pph_stream (struct output_block *ob, pph_stream *f)
+/* Read a bitpack from STREAM. */
+static inline struct bitpack_d
+pph_input_bitpack (pph_stream *stream)
{
- /* FIXME pph - Do not overload OB fields this way. */
- ob->cfg_stream = (struct lto_output_stream *) f;
+ struct bitpack_d bp = lto_input_bitpack (stream->ib);
+ if (flag_pph_tracer)
+ pph_stream_trace_bitpack (stream, &bp);
+ return bp;
}
#endif /* GCC_CP_PPH_STREAMER_H */
@@ -427,6 +427,7 @@ pth_save_token (cp_token *token, pph_stream *f)
pth_save_token_value (f, token);
}
+
/* Save all the tokens in CACHE to PPH stream F. */
void
@@ -990,6 +991,50 @@ pth_load_token_value (cp_token *token, pph_stream *f)
}
+/* Read and return a token from STREAM. */
+
+static cp_token *
+pth_load_token (pph_stream *stream)
+{
+ cp_token *token = ggc_alloc_cleared_cp_token ();
+
+ /* Do not read the whole structure, the token value has
+ dynamic size as it contains swizzled pointers.
+ FIXME pph, restructure to allow bulk reads of the whole
+ section. */
+ pph_input_bytes (stream, token, sizeof (cp_token) - sizeof (void *));
+
+ /* FIXME pph. Use an arbitrary (but valid) location to avoid
+ confusing the rest of the compiler for now. */
+ token->location = input_location;
+
+ /* FIXME pph: verify that pth_load_token_value works with no tokens. */
+ pth_load_token_value (token, stream);
+
+ return token;
+}
+
+
+/* Read and return a cp_token_cache instance from STREAM. */
+
+cp_token_cache *
+pth_load_token_cache (pph_stream *stream)
+{
+ unsigned i, num;
+ cp_token *first, *last;
+
+ num = pph_input_uint (stream);
+ for (last = first = NULL, i = 0; i < num; i++)
+ {
+ last = pth_load_token (stream);
+ if (first == NULL)
+ first = last;
+ }
+
+ return cp_token_cache_new (first, last);
+}
+
+
/* Load the IDENTIFERS for a hunk from a STREAM. */
static void
@@ -1078,20 +1123,8 @@ pth_load_hunk (pth_image *image, pph_stream *stream)
hunk->buffer = VEC_alloc (cp_token, gc, num_tokens);
for (j = 0; j < num_tokens; j++)
{
- cp_token *token = VEC_quick_push (cp_token, hunk->buffer, NULL);
-
- /* Do not read the whole structure, the token value has
- dynamic size as it contains swizzled pointers.
- FIXME pph, restructure to allow bulk reads of the whole
- section. */
- pph_input_bytes (stream, token, sizeof (cp_token) - sizeof (void *));
-
- /* FIXME pph. Use an arbitrary (but valid) location to avoid
- confusing the rest of the compiler for now. */
- token->location = input_location;
-
- /* FIXME pph: verify that pth_load_token_value works with no tokens. */
- pth_load_token_value (token, stream);
+ cp_token *token = pth_load_token (stream);
+ VEC_quick_push (cp_token, hunk->buffer, token);
}
gcc_assert (num_tokens == VEC_length (cp_token, hunk->buffer));
@@ -1807,7 +1840,7 @@ static void
pph_write_file_contents (pph_stream *stream, cpp_idents_used *idents_used)
{
pth_save_identifiers (idents_used, stream);
- pph_output_tree (stream, global_namespace);
+ pph_output_tree (stream, global_namespace, false);
}
@@ -1898,7 +1931,7 @@ pph_read_file_contents (pph_stream *stream)
cpp_lt_replay (parse_in, &idents_used);
*/
- /* FIXME pph: Also read decls. */
+ pph_input_tree (stream);
}
@@ -1852,9 +1852,15 @@ lto_materialize_tree (struct lto_input_block *ib, struct data_in *data_in,
}
else
{
- /* All other nodes can be materialized with a raw make_node
- call. */
- result = make_node (code);
+ /* For all other nodes, see if the streamer knows how to allocate
+ it. */
+ if (streamer_hooks ()->alloc_tree)
+ result = streamer_hooks ()->alloc_tree (code, ib, data_in);
+
+ /* If the hook did not handle it, materialize the tree with a raw
+ make_node call. */
+ if (result == NULL_TREE)
+ result = make_node (code);
}
#ifdef LTO_STREAMER_DEBUG
@@ -2360,38 +2366,15 @@ lto_input_tree_pointers (struct lto_input_block *ib, struct data_in *data_in,
if (CODE_CONTAINS_STRUCT (code, TS_EXP))
lto_input_ts_exp_tree_pointers (ib, data_in, 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_BLOCK))
lto_input_ts_block_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
lto_input_ts_binfo_tree_pointers (ib, data_in, expr);
- if (CODE_CONTAINS_STRUCT (code, TS_STATEMENT_LIST))
- {
- /* This should only appear in GENERIC. */
- gcc_unreachable ();
- }
-
if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
lto_input_ts_constructor_tree_pointers (ib, data_in, expr);
- if (CODE_CONTAINS_STRUCT (code, TS_OMP_CLAUSE))
- {
- /* This should only appear in High GIMPLE. */
- gcc_unreachable ();
- }
-
- if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION))
- {
- sorry ("optimization options not supported yet");
- }
-
if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION))
lto_input_ts_target_option (ib, expr);
@@ -2622,10 +2605,13 @@ lto_read_tree (struct lto_input_block *ib, struct data_in *data_in,
if (TREE_CODE (result) == FUNCTION_DECL)
gcc_assert (!lto_stream_as_builtin_p (result));
- if (TREE_CODE (result) == VAR_DECL)
- lto_register_var_decl_in_symtab (data_in, result);
- else if (TREE_CODE (result) == FUNCTION_DECL && !DECL_BUILT_IN (result))
- lto_register_function_decl_in_symtab (data_in, result);
+ if (streamer_hooks ()->register_decls_in_symtab_p)
+ {
+ if (TREE_CODE (result) == VAR_DECL)
+ lto_register_var_decl_in_symtab (data_in, result);
+ else if (TREE_CODE (result) == FUNCTION_DECL && !DECL_BUILT_IN (result))
+ lto_register_function_decl_in_symtab (data_in, result);
+ }
/* end_marker = */ lto_input_1_unsigned (ib);
@@ -2739,6 +2725,8 @@ void
lto_reader_init (void)
{
lto_streamer_init ();
+ file_name_hash_table = htab_create (37, hash_string_slot_node,
+ eq_string_slot_node, free);
if (streamer_hooks ()->reader_init)
streamer_hooks ()->reader_init ();
}
@@ -2751,8 +2739,6 @@ 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 ();
}
@@ -1206,7 +1206,6 @@ lto_output_tree_header (struct output_block *ob, tree expr, int ix)
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 (h->is_streamable && !h->is_streamable (expr))
@@ -1218,6 +1217,7 @@ lto_output_tree_header (struct output_block *ob, tree expr, int ix)
EXPR on the reading side (such as the number of slots in
variable sized nodes). */
tag = lto_tree_code_to_tag (code);
+ gcc_assert ((unsigned) tag < (unsigned) LTO_NUM_TAGS);
output_record_start (ob, tag);
output_sleb128 (ob, ix);
@@ -1241,6 +1241,11 @@ lto_output_tree_header (struct output_block *ob, tree expr, int ix)
output_sleb128 (ob, TREE_VEC_LENGTH (expr));
else if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
output_uleb128 (ob, BINFO_N_BASE_BINFOS (expr));
+
+ /* Allow the streamer to write any streamer-specific information
+ needed to instantiate the node when reading. */
+ if (streamer_hooks ()->output_tree_header)
+ streamer_hooks ()->output_tree_header (ob, expr);
}
@@ -843,6 +843,7 @@ gimple_streamer_hooks_init (void)
h->is_streamable = lto_is_streamable;
h->write_tree = gimple_streamer_write_tree;
h->read_tree = gimple_streamer_read_tree;
+ h->register_decls_in_symtab_p = true;
}
@@ -98,6 +98,28 @@ typedef struct lto_streamer_hooks {
/* 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);
+
+ /* Non-zero if the streamer should register decls in the LTO
+ global symbol tables. */
+ unsigned register_decls_in_symtab_p : 1;
+
+ /* Called by lto_materialize_tree for tree nodes that it does not
+ know how to allocate memory for. If defined, this hook should
+ return a new tree node of the given code. The data_in and
+ input_block arguments are passed in case the hook needs to
+ read more data from the stream to allocate the node.
+ If this hook returns NULL, then lto_materialize_tree will attempt
+ to allocate the tree by calling make_node directly. */
+ tree (*alloc_tree) (enum tree_code, struct lto_input_block *,
+ struct data_in *);
+
+ /* Called by lto_output_tree_header to write any streamer-specific
+ information needed to allocate the tree. This hook may assume
+ that the basic header data (tree code, etc) has already been
+ written. It should only write any extra data needed to allocate
+ the node (e.g., in the case of CALL_EXPR, this hook would write
+ the number of arguments to the CALL_EXPR). */
+ void (*output_tree_header) (struct output_block *, tree);
} lto_streamer_hooks;
@@ -298,9 +320,10 @@ enum LTO_tags
LTO_imported_decl_ref,
LTO_translation_unit_decl_ref,
LTO_global_decl_ref, /* Do not change. */
+ LTO_LAST_TAG,
/* This tag must always be last. */
- LTO_NUM_TAGS
+ LTO_NUM_TAGS = LTO_LAST_TAG + MAX_TREE_CODES + LAST_AND_UNUSED_GIMPLE_CODE
};
@@ -673,6 +696,9 @@ struct GTY(()) lto_file_decl_data
VEC(ld_plugin_symbol_resolution_t,heap) * GTY((skip)) resolutions;
struct gcov_ctr_summary GTY((skip)) profile_info;
+
+ /* Any other streamer-specific data needed by the streamer. */
+ void * GTY((skip)) sdata;
};
typedef struct lto_file_decl_data *lto_file_decl_data_ptr;
@@ -768,6 +794,9 @@ struct output_block
/* Cache of nodes written in this section. */
struct lto_streamer_cache_d *writer_cache;
+
+ /* Any other streamer-specific data needed by the streamer. */
+ void *sdata;
};
@@ -802,6 +831,9 @@ struct data_in
/* Cache of pickled nodes. */
struct lto_streamer_cache_d *reader_cache;
+
+ /* Any other streamer-specific data needed by the streamer. */
+ void *sdata;
};
@@ -1029,7 +1061,7 @@ extern VEC(lto_out_decl_state_ptr, heap) *lto_function_decl_states;
static inline bool
lto_tag_is_tree_code_p (enum LTO_tags tag)
{
- return tag > LTO_null && (unsigned) tag <= NUM_TREE_CODES;
+ return tag > LTO_null && (unsigned) tag <= MAX_TREE_CODES;
}