|
|
Created:
14 years ago by Diego Novillo Modified:
13 years, 10 months ago Reviewers:
CC:
Lawrence Crowl, gcc-patches_gcc.gnu.org Visibility:
Public. |
Patch Set 1 #
MessagesTotal messages: 1
This patch implements the writing of DECL_LANG_SPECIFIC fields. It's needed to write global_namespace. The reading part is still incomplete, but I wanted to flush this out before it got too big. The main changes: - We can now write out references to TEMPLATE_DECLs. They are stored in the same index table as all other DECLs. To implement this, I added a streamer hook that's called from lto_output_tree_ref. When it does not recognize the decl, it calls the hook which tells it whether the decl can be added to the index table. - We stream out everything in DECL_LANG_SPECIFIC, which in C++ is quite a bit. This will cover global_namespace since it goes through all the data stored for NAMESPACE_DECLs. - Since DECL_LANG_SPECIFIC can contains tokens, we need to save token caches. Since we are inside a streamer callback, we do not have a pointer to a PPH stream, so I've added a pretty hacky way of getting back to it. When we initially open the PPH stream and associate with it an output_block object, I take an unused field from output_block and use it as my pointer back to the PPH stream. This is awful, but it works for now. I'll clean this up in a future patch. The next patch will add the reader side, which will allow me to reconstruct global_namespace. This will uncover what other tree types we need to handle. With this I'm down to two failures in pph.exp. No changes for pth.exp. ChangeLog.pph 2011-03-30 Diego Novillo <dnovillo@google.com> * lto-streamer-in.c (lto_input_chain): Make extern. * lto-streamer-out.c (lto_output_tree_ref): Call streamer_hook->indexable_with_decls_p, if it exists. If it returns true, emit a reference to EXPR in the VAR_DECL index. (lto_output_chain): Make extern. (lto_output_tree_pointers): Move checks for invalid gimple trees ... * lto-streamer.c (lto_is_streamable): ... here. * lto-streamer.h (lto_streamer_hooks): Add indexable_with_decls_p. (lto_output_chain): Declare. (lto_input_chain): Declare. c-family/ChangeLog.pph 2011-03-30 Diego Novillo <dnovillo@google.com> * c-family/c.opt (fpph-fmt): Remove. Update all users. cp/ChangeLog.pph 2011-03-30 Diego Novillo <dnovillo@google.com> * cp-tree.h (struct language_function): Add prefix 'x_' to fields returns_value, returns_null, returns_abnormally, in_function_try_handler, in_base_initializer. Update all users. * pph-streamer.c (pph_stream_write_ld_base): New. (pph_stream_write_ld_min): New. (pph_stream_write_tree_vec): New. (pph_stream_write_cxx_binding_1): New. (pph_stream_write_cxx_binding): New. (pph_stream_write_class_binding): New. (pph_stream_write_label_binding): New. (pph_stream_write_binding_level): New. (pph_stream_write_c_language_function): New. (pph_stream_write_language_function): New. (pph_stream_write_ld_fn): New. (pph_stream_write_ld_ns): New. (pph_stream_write_ld_parm): New. (pph_stream_write_lang_specific_data): New. (pph_indexable_with_decls_p): New. (pph_stream_hooks_init): Initialize h->indexable_with_decls_p with pph_indexable_with_decls_p. (pph_stream_begin_section): Do not free BLOCK. * pph-streamer.h (pth_save_token_cache): Declare. (pph_get_ob_stream): New. (pph_set_ob_stream): New. * pph.c (pth_save_token_cache): New. (pph_print_macro_defs_before): Remove. (pph_print_macro_defs_after): Remove. (pph_write_namespace): Remove. (pph_write_format): Remove. (pph_write_print): Remove. (pph_write_dump): Remove. (pph_write_symbol): Remove. (declvisitor): Remove. (pph_write_namespace_1): Remove. (pph_write_namespace): Remove. (pph_write_file_contents): Rename from pph_write_file_object. Output global_namespace. (pph_write_file): Call it. (pph_write_file_summary): Remove. (pph_read_file_contents): Rename from pph_file_read_object. (pph_read_file): Rename from pph_file_read. diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 54e7461..12d4f06 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -933,10 +933,6 @@ fpph-decls= C++ Joined RejectNegative UInteger Var(flag_pph_decls) -fpph-decls=N Enable declaration identifier output at level N from PPH support -fpph-fmt= -C++ Joined RejectNegative UInteger Var(flag_pph_fmt) --fpph-fmt=N Output format is (0) normal (1) pretty summary (2) dump - fpph-hdr= C++ ObjC++ Joined MissingArgError(missing filename after %qs) -fpph-hdr=<base-name> A mapping from <base-name>.h to <base-name>.pph diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 6ef6e6e..aedcab2 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1012,11 +1012,11 @@ struct GTY(()) language_function { tree x_vtt_parm; tree x_return_value; - BOOL_BITFIELD returns_value : 1; - BOOL_BITFIELD returns_null : 1; - BOOL_BITFIELD returns_abnormally : 1; - BOOL_BITFIELD in_function_try_handler : 1; - BOOL_BITFIELD in_base_initializer : 1; + BOOL_BITFIELD x_returns_value : 1; + BOOL_BITFIELD x_returns_null : 1; + BOOL_BITFIELD x_returns_abnormally : 1; + BOOL_BITFIELD x_in_function_try_handler : 1; + BOOL_BITFIELD x_in_base_initializer : 1; /* True if this function can throw an exception. */ BOOL_BITFIELD can_throw : 1; @@ -1067,23 +1067,23 @@ struct GTY(()) language_function { /* Set to 0 at beginning of a function definition, set to 1 if a return statement that specifies a return value is seen. */ -#define current_function_returns_value cp_function_chain->returns_value +#define current_function_returns_value cp_function_chain->x_returns_value /* Set to 0 at beginning of a function definition, set to 1 if a return statement with no argument is seen. */ -#define current_function_returns_null cp_function_chain->returns_null +#define current_function_returns_null cp_function_chain->x_returns_null /* Set to 0 at beginning of a function definition, set to 1 if a call to a noreturn function is seen. */ #define current_function_returns_abnormally \ - cp_function_chain->returns_abnormally + cp_function_chain->x_returns_abnormally /* Nonzero if we are processing a base initializer. Zero elsewhere. */ -#define in_base_initializer cp_function_chain->in_base_initializer +#define in_base_initializer cp_function_chain->x_in_base_initializer -#define in_function_try_handler cp_function_chain->in_function_try_handler +#define in_function_try_handler cp_function_chain->x_in_function_try_handler /* Expression always returned from function, or error_mark_node otherwise, for use by the automatic named return value optimization. */ diff --git a/gcc/cp/pph-streamer.c b/gcc/cp/pph-streamer.c index d2790fc..125c4e7 100644 --- a/gcc/cp/pph-streamer.c +++ b/gcc/cp/pph-streamer.c @@ -135,6 +135,421 @@ pph_stream_init_write (pph_stream *stream) 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_ob_stream (stream->ob, stream); +} + + +/* 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) +{ + struct bitpack_d bp; + + if (ldb == NULL) + { + pph_output_uint (pph_get_ob_stream (ob), 0); + return; + } + + bp = bitpack_create (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); + bp_pack_value (&bp, ldb->not_really_extern, 1); + bp_pack_value (&bp, ldb->initialized_in_class, 1); + bp_pack_value (&bp, ldb->repo_available_p, 1); + bp_pack_value (&bp, ldb->threadprivate_or_deleted_p, 1); + bp_pack_value (&bp, ldb->anticipated_p, 1); + bp_pack_value (&bp, ldb->friend_attr, 1); + 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); +} + + +/* Write all the fields in lang_decl_min instance LDM to OB. 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, + bool ref_p) +{ + if (ldm == 0) + { + pph_output_uint (pph_get_ob_stream (ob), 0); + return; + } + + gcc_assert (ldm->base.selector == 0); + + lto_output_tree_or_ref (ob, ldm->template_info, ref_p); + if (ldm->base.u2sel == 0) + lto_output_tree_or_ref (ob, ldm->u2.access, ref_p); + else if (ldm->base.u2sel == 1) + lto_output_sleb128_stream (ob->main_stream, ldm->u2.discriminator); + else + gcc_unreachable (); +} + + +/* Write all the trees in VEC V to OB. 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) +{ + unsigned i; + tree t; + + lto_output_uleb128_stream (ob->main_stream, VEC_length (tree, v)); + for (i = 0; VEC_iterate (tree, v, i, t); i++) + lto_output_tree_or_ref (ob, t, ref_p); +} + +/* Forward declaration to break cyclic dependencies. */ +static void pph_stream_write_binding_level (struct output_block *, + struct cp_binding_level *, bool); + + +/* Helper for pph_stream_write_cxx_binding. OB, 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) +{ + struct bitpack_d bp; + + if (cb == NULL) + { + pph_output_uint (pph_get_ob_stream (ob), 0); + 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); + bp_pack_value (&bp, cb->value_is_inherited, 1); + bp_pack_value (&bp, cb->is_local, 1); + lto_output_bitpack (&bp); +} + + +/* Write all the fields of cxx_binding instance CB to OB. 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) +{ + unsigned num_bindings; + cxx_binding *prev; + + if (cb == NULL) + { + pph_output_uint (pph_get_ob_stream (ob), 0); + 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); + for (prev = cb->previous; prev; prev = prev->previous) + pph_stream_write_cxx_binding_1 (ob, prev, ref_p); + + /* Write the current binding at the end. */ + pph_stream_write_cxx_binding_1 (ob, cb, ref_p); +} + + +/* Write 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 void +pph_stream_write_class_binding (struct output_block *ob, + cp_class_binding *cb, bool ref_p) +{ + if (cb == NULL) + { + pph_output_uint (pph_get_ob_stream (ob), 0); + return; + } + + pph_stream_write_cxx_binding (ob, &cb->base, ref_p); + lto_output_tree_or_ref (ob, cb->identifier, ref_p); +} + + +/* Write all the fields of cp_label_binding instance LB to OB. 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) +{ + if (lb == NULL) + { + pph_output_uint (pph_get_ob_stream (ob), 0); + return; + } + + lto_output_tree_or_ref (ob, lb->label, ref_p); + lto_output_tree_or_ref (ob, lb->prev_value, ref_p); +} + + +/* Write all the fields of cp_binding_level instance BL to OB. 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) +{ + unsigned i; + cp_class_binding *cs; + cp_label_binding *sl; + struct bitpack_d bp; + + if (bl == NULL) + { + pph_output_uint (pph_get_ob_stream (ob), 0); + 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_stream_write_tree_vec (ob, bl->static_decls, ref_p); + + lto_output_chain (ob, bl->usings, ref_p); + lto_output_chain (ob, bl->using_directives, ref_p); + + lto_output_uleb128_stream (ob->main_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); + + lto_output_tree_or_ref (ob, bl->type_shadowed, ref_p); + + lto_output_uleb128_stream (ob->main_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); + + 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); + + bp = bitpack_create (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); +} + + +/* Write all the fields of c_language_function instance CLF to OB. 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, + struct c_language_function *clf, + bool ref_p) +{ + if (clf == NULL) + { + pph_output_uint (pph_get_ob_stream (ob), 0); + 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); +} + + +/* Write all the fields of language_function instance LF to OB. If + REF_P is true, all tree fields should be written as references. */ + +static void +pph_stream_write_language_function (struct output_block *ob, + struct language_function *lf, + bool ref_p) +{ + struct bitpack_d bp; + + if (lf == NULL) + { + pph_output_uint (pph_get_ob_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); + 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); + + /* 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); + + /* 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 + 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, + bool ref_p) +{ + struct bitpack_d bp; + + if (ldf == NULL) + { + pph_output_uint (pph_get_ob_stream (ob), 0); + return; + } + + bp = bitpack_create (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); + bp_pack_value (&bp, ldf->constructor_attr, 1); + bp_pack_value (&bp, ldf->destructor_attr, 1); + bp_pack_value (&bp, ldf->assignment_operator_p, 1); + bp_pack_value (&bp, ldf->static_function, 1); + bp_pack_value (&bp, ldf->pure_virtual, 1); + bp_pack_value (&bp, ldf->defaulted_p, 1); + bp_pack_value (&bp, ldf->has_in_charge_parm_p, 1); + bp_pack_value (&bp, ldf->has_vtt_parm_p, 1); + bp_pack_value (&bp, ldf->pending_inline_p, 1); + bp_pack_value (&bp, ldf->nonconverting, 1); + 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); + + lto_output_tree_or_ref (ob, ldf->befriending_classes, ref_p); + lto_output_tree_or_ref (ob, ldf->context, ref_p); + + if (ldf->thunk_p == 0) + lto_output_tree_or_ref (ob, ldf->u5.cloned_function, ref_p); + else if (ldf->thunk_p == 1) + lto_output_sleb128_stream (ob->main_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_ob_stream (ob)); + else if (ldf->pending_inline_p == 0) + pph_stream_write_language_function (ob, ldf->u.saved_language_function, + ref_p); +} + + +/* Write all the fields of lang_decl_ns instance LDNS to OB. 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, + bool ref_p) +{ + struct cp_binding_level *level; + + if (ldns == NULL) + { + pph_output_uint (pph_get_ob_stream (ob), 0); + return; + } + + level = ldns->level; + pph_stream_write_binding_level (ob, level, ref_p); +} + + +/* Write all the fields of lang_decl_parm instance LDP to OB. 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) +{ + if (ldp == NULL) + { + pph_output_uint (pph_get_ob_stream (ob), 0); + return; + } + + lto_output_sleb128_stream (ob->main_stream, ldp->level); + lto_output_sleb128_stream (ob->main_stream, ldp->index); +} + + +/* Write all the lang-specific data in DECL to OB. 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) +{ + struct lang_decl *ld; + struct lang_decl_base *ldb; + + gcc_assert (DECL_P (decl) && DECL_LANG_SPECIFIC (decl)); + + ld = DECL_LANG_SPECIFIC (decl); + ldb = &ld->u.base; + + /* Write all the fields in lang_decl_base. */ + pph_stream_write_ld_base (ob, ldb); + + if (ldb->selector == 0) + { + /* Write all the fields in lang_decl_min. */ + pph_stream_write_ld_min (ob, &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); + } + else if (ldb->selector == 2) + { + /* Write all the fields in lang_decl_ns. */ + pph_stream_write_ld_ns (ob, &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); + } + else + gcc_unreachable (); } @@ -145,8 +560,14 @@ pph_stream_init_write (pph_stream *stream) static void 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); + 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); + } else if (TREE_CODE (expr) == STATEMENT_LIST) { tree_stmt_iterator i; @@ -222,6 +643,17 @@ pph_stream_unpack_value_fields (struct bitpack_d *bp ATTRIBUTE_UNUSED, } +/* Return true if T can be emitted in the decls table as a reference. + This should only handle C++ specific declarations. All others are + handled by the LTO streamer directly. */ + +static bool +pph_indexable_with_decls_p (tree t) +{ + return TREE_CODE (t) == TEMPLATE_DECL; +} + + /* Initialize all the streamer hooks used for streaming ASTs. */ static void @@ -233,6 +665,7 @@ pph_stream_hooks_init (void) h->write_tree = pph_stream_write_tree; h->read_tree = pph_stream_read_tree; 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; } @@ -274,15 +707,13 @@ pph_stream_begin_section (const char *name ATTRIBUTE_UNUSED) /* Callback for lang_hooks.lto.append_data. Write LEN bytes from DATA - into current_pph_file. BLOCK is currently unused, but this hook is - required to free it. */ + into current_pph_file. BLOCK is currently unused. */ static void -pph_stream_write (const void *data, size_t len, void *block) +pph_stream_write (const void *data, size_t len, void *block ATTRIBUTE_UNUSED) { if (data) fwrite (data, len, 1, current_pph_file); - free (block); } diff --git a/gcc/cp/pph-streamer.h b/gcc/cp/pph-streamer.h index afffe35..5d888b3 100644 --- a/gcc/cp/pph-streamer.h +++ b/gcc/cp/pph-streamer.h @@ -92,6 +92,9 @@ 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); +/* In pph.c. FIXME move these to pph-streamer.c. */ +struct cp_token_cache; +extern void pth_save_token_cache (struct cp_token_cache *, pph_stream *); /* Inline functions. */ @@ -195,4 +198,22 @@ pph_input_tree (pph_stream *stream ATTRIBUTE_UNUSED) return t; } +/* Return the PPH stream object associated with output block OB. */ + +static inline pph_stream * +pph_get_ob_stream (struct output_block *ob) +{ + /* FIXME pph - Do not overload OB fields this way. */ + return ((pph_stream *) ob->cfg_stream); +} + +/* Set the PPH stream object F associated with output block OB. */ + +static inline void +pph_set_ob_stream (struct output_block *ob, pph_stream *f) +{ + /* FIXME pph - Do not overload OB fields this way. */ + ob->cfg_stream = (struct lto_output_stream *) f; +} + #endif /* GCC_CP_PPH_STREAMER_H */ diff --git a/gcc/cp/pph.c b/gcc/cp/pph.c index 8c46665..c397751 100644 --- a/gcc/cp/pph.c +++ b/gcc/cp/pph.c @@ -427,84 +427,44 @@ 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. */ -/* Write header information for IMAGE to STREAM. */ - -static void -pth_write_header (pth_image *image, pph_stream *stream) +void +pth_save_token_cache (cp_token_cache *cache, pph_stream *f) { - const char *id = pth_id_str (); + unsigned i, num; + cp_token *tok; - if (!image->digest_computed_p) + if (cache == NULL) { - pth_get_md5_digest (image->fname, image->digest); - image->digest_computed_p = true; + pph_output_uint (f, 0); + return; } - pph_output_bytes (stream, id, strlen (id)); - pph_output_bytes (stream, image->digest, DIGEST_LEN); -} - - -/* Pretty print the previous macro definitions in the table of IDENTIFIERS to - the STREAM. */ - -static void -pph_print_macro_defs_before (pph_stream *stream, cpp_idents_used *identifiers) -{ - unsigned int idx; - - for (idx = 0; idx < identifiers->num_entries; ++idx) - { - cpp_ident_use *entry = identifiers->entries + idx; - const char *ident = entry->ident_str; - const char *before = entry->before_str; + for (num = 0, tok = cache->first; tok != cache->last; tok++) + num++; - if (before) - { - pph_output_string (stream, "#define "); - pph_output_string (stream, ident); - pph_output_string (stream, before); - } - else - { - pph_output_string (stream, "#undef "); - pph_output_string (stream, ident); - } - } + pph_output_uint (f, num); + for (i = 0, tok = cache->first; i < num; tok++, i++) + pth_save_token (tok, f); } -/* Pretty print the subsequent macro definitions in the table of IDENTIFIERS to - the STREAM. */ +/* Write header information for IMAGE to STREAM. */ static void -pph_print_macro_defs_after (pph_stream *stream, cpp_idents_used *identifiers) +pth_write_header (pth_image *image, pph_stream *stream) { - unsigned int idx; + const char *id = pth_id_str (); - for (idx = 0; idx < identifiers->num_entries; ++idx) + if (!image->digest_computed_p) { - cpp_ident_use *entry = identifiers->entries + idx; - const char *ident = entry->ident_str; - const char *before = entry->before_str; - const char *after = entry->after_str; - - if (before != after) - { - if (after && (!before || strcmp (after, before) != 0)) - { - pph_output_string (stream, "#define "); - pph_output_string (stream, ident); - pph_output_string (stream, after); - } - else if (before) - { - pph_output_string (stream, "#undef "); - pph_output_string (stream, ident); - } - } + pth_get_md5_digest (image->fname, image->digest); + image->digest_computed_p = true; } + + pph_output_bytes (stream, id, strlen (id)); + pph_output_bytes (stream, image->digest, DIGEST_LEN); } @@ -1841,105 +1801,13 @@ pth_file_change (cpp_reader *reader, const struct line_map *map) } -/* Write PPH output file. */ - -typedef void (*pph_write_format)(pph_stream *stream, tree decl, int flags); - -/* Forward declarations to break cyclic references. */ -static void -pph_write_namespace (pph_stream *, tree, pph_write_format, int); - - -/* Write symbol to PPH output file like C. */ - -static void -pph_write_print (pph_stream *stream, tree decl, int flags ATTRIBUTE_UNUSED) -{ - pph_output_tree (stream, decl); -} - - -/* Write symbol to PPH output file as a dump. */ - -static void -pph_write_dump (pph_stream *stream, tree decl, int flags) -{ - dump_node (decl, flags, stream->file); -} - - -/* Write symbol to PPH output file. */ - -static void -pph_write_symbol (pph_stream *stream, tree decl, pph_write_format fmt, - int flags) -{ - if (TREE_CODE (decl) == NAMESPACE_DECL) - pph_write_namespace (stream, decl, fmt, flags); - else if (!DECL_IS_BUILTIN (decl)) - fmt (stream, decl, flags); -} - - -/* Write namespace to PPH output file. */ - -typedef void (*declvisitor)(pph_stream *, tree, pph_write_format, int); - -static void -pph_write_namespace_1 (declvisitor vtor, pph_stream *stream, tree decl, - pph_write_format fmt, int flags) -{ - tree prior = TREE_CHAIN (decl); - if (prior) - pph_write_namespace_1 (vtor, stream, prior, fmt, flags); - vtor (stream, decl, fmt, flags); -} - -static void -pph_write_namespace (pph_stream *stream, tree decl, pph_write_format fmt, - int flags) -{ - struct cp_binding_level *level = NAMESPACE_LEVEL (decl); - decl = level->namespaces; - if (decl) - pph_write_namespace_1 (pph_write_namespace, stream, decl, fmt, flags); - decl = level->names; - if (decl) - pph_write_namespace_1 (pph_write_symbol, stream, decl, fmt, flags); -} - - /* Write PPH output symbols and IDENTS_USED to STREAM as an object. */ static void -pph_write_file_object (pph_stream *stream, cpp_idents_used *idents_used) +pph_write_file_contents (pph_stream *stream, cpp_idents_used *idents_used) { - int flags = 0; pth_save_identifiers (idents_used, stream); - pph_write_namespace (stream, global_namespace, pph_write_print, flags); -} - - -/* Write PPH output symbols and IDENTS_USED to STREAM as a pretty summary. */ - -static void -pph_write_file_summary (pph_stream *stream, cpp_idents_used *idents_used) -{ - int flags = 0; - pph_print_macro_defs_before (stream, idents_used); - pph_write_namespace (stream, global_namespace, pph_write_print, flags); - pph_print_macro_defs_after (stream, idents_used); -} - - -/* Write PPH output symbols and IDENTS_USED to STREAM as a textual dump. */ - -static void -pph_write_file_dump (pph_stream *stream, cpp_idents_used *idents_used) -{ - int flags = TDF_UID | TDF_LINENO; - pth_dump_identifiers (stream->file, idents_used); - pph_write_namespace (stream, global_namespace, pph_write_dump, flags); + pph_output_tree (stream, global_namespace); } @@ -1959,17 +1827,8 @@ pph_write_file (void) fatal_error ("Cannot open PPH file for writing: %s: %m", pph_out_file); idents_used = cpp_lt_capture (parse_in); + pph_write_file_contents (stream, &idents_used); - if (flag_pph_fmt == 0) - pph_write_file_object (stream, &idents_used); - else if (flag_pph_fmt == 1) - pph_write_file_summary (stream, &idents_used); - else if (flag_pph_fmt == 2) - pph_write_file_dump (stream, &idents_used); - else - error ("unrecognized -fpph-fmt value: %d", flag_pph_fmt); - - /*FIX pph: double free or corruption: cpp_lt_idents_destroy (&idents_used); */ pph_stream_close (stream); } @@ -2016,10 +1875,10 @@ report_validation_error (const char *filename, } -/* Read PPH FILENAME from STREAM as an object. */ +/* Read contents of PPH file in STREAM. */ static void -pph_file_read_object (const char *filename, pph_stream *stream) +pph_read_file_contents (pph_stream *stream) { bool verified; cpp_ident_use *bad_use; @@ -2027,24 +1886,26 @@ pph_file_read_object (const char *filename, pph_stream *stream) cpp_idents_used idents_used; pth_load_identifiers (&idents_used, stream); + /*FIXME pph: This validation is weak. */ verified = cpp_lt_verify_1 (parse_in, &idents_used, &bad_use, &cur_def, true); if (!verified) - report_validation_error (filename, bad_use->ident_str, cur_def, + report_validation_error (stream->name, bad_use->ident_str, cur_def, bad_use->before_str, bad_use->after_str); - /* FIX pph: We cannot replay the macro definitions + + /* FIXME pph: We cannot replay the macro definitions as long as we are still reading the actual file. cpp_lt_replay (parse_in, &idents_used); */ - /* FIX pph: Also read decls. */ + /* FIXME pph: Also read decls. */ } /* Read PPH file. */ static void -pph_file_read (const char *filename) +pph_read_file (const char *filename) { pph_stream *stream; @@ -2055,8 +1916,7 @@ pph_file_read (const char *filename) if (!stream) fatal_error ("Cannot open PPH file for reading: %s: %m", filename); - if (flag_pph_fmt == 0) - pph_file_read_object (filename, stream); + pph_read_file_contents (stream); pph_stream_close (stream); } @@ -2113,7 +1973,7 @@ pph_include_handler (cpp_reader *reader, pph_file = query_pph_include_map (name); if (pph_file != NULL && !cpp_included_before (reader, name, input_location)) - pph_file_read (pph_file); + pph_read_file (pph_file); } diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index 2347ffa..f982329 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -1889,7 +1889,7 @@ lto_materialize_tree (struct lto_input_block *ib, struct data_in *data_in, /* Read a chain of tree nodes from input block IB. DATA_IN contains tables and descriptors for the file being read. */ -static tree +tree lto_input_chain (struct lto_input_block *ib, struct data_in *data_in) { int i, count; diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index f41cf0c..24543b2 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -718,9 +718,20 @@ lto_output_tree_ref (struct output_block *ob, tree expr) break; default: - /* No other node is indexable, so it should have been handled - by lto_output_tree. */ - gcc_unreachable (); + /* See if streamer hooks allows this node to be indexable with + VAR_DECLs. */ + if (streamer_hooks ()->indexable_with_decls_p + && streamer_hooks ()->indexable_with_decls_p (expr)) + { + output_record_start (ob, LTO_global_decl_ref); + lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr); + } + else + { + /* No other node is indexable, so it should have been + handled by lto_output_tree. */ + gcc_unreachable (); + } } } @@ -742,7 +753,7 @@ lto_output_tree_or_ref (struct output_block *ob, tree expr, bool ref_p) to write to. REF_P is true if chain elements should be emitted as references. */ -static void +void lto_output_chain (struct output_block *ob, tree t, bool ref_p) { int i, count; @@ -1166,12 +1177,6 @@ lto_output_tree_pointers (struct output_block *ob, tree expr, bool ref_p) if (CODE_CONTAINS_STRUCT (code, TS_EXP)) lto_output_ts_exp_tree_pointers (ob, expr, ref_p); - 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_output_ts_block_tree_pointers (ob, expr, ref_p); @@ -1181,21 +1186,6 @@ lto_output_tree_pointers (struct output_block *ob, tree expr, bool ref_p) if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR)) lto_output_ts_constructor_tree_pointers (ob, expr, ref_p); - if (CODE_CONTAINS_STRUCT (code, TS_STATEMENT_LIST)) - { - /* This should only appear in GENERIC. */ - gcc_unreachable (); - } - - 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 ("gimple bytecode streams do not support the optimization attribute"); - if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION)) lto_output_ts_target_option (ob, expr); diff --git a/gcc/lto-streamer.c b/gcc/lto-streamer.c index 7b51763..be8d36d 100644 --- a/gcc/lto-streamer.c +++ b/gcc/lto-streamer.c @@ -823,6 +823,8 @@ lto_is_streamable (tree expr) && code != BIND_EXPR && code != WITH_CLEANUP_EXPR && code != STATEMENT_LIST + && code != OMP_CLAUSE + && code != OPTIMIZATION_NODE && (code == CASE_LABEL_EXPR || code == DECL_EXPR || TREE_CODE_CLASS (code) != tcc_statement); diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 242850f..8e49a55 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -86,6 +86,11 @@ typedef struct lto_streamer_hooks { are as in lto_read_tree. */ void (*read_tree) (struct lto_input_block *, struct data_in *, tree); + /* Called by lto_output_tree_ref to determine if the given tree node + should be emitted as a reference to the table of declarations + (the same table that holds VAR_DECLs). */ + bool (*indexable_with_decls_p) (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); @@ -913,6 +918,7 @@ extern lto_streamer_hooks *streamer_hooks_init (void); extern void lto_input_cgraph (struct lto_file_decl_data *, const char *); extern void lto_reader_init (void); extern tree lto_input_tree (struct lto_input_block *, struct data_in *); +extern tree lto_input_chain (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 *, @@ -934,6 +940,7 @@ extern struct output_block *create_output_block (enum lto_section_type); extern void destroy_output_block (struct output_block *); extern void lto_output_tree (struct output_block *, tree, bool); extern void lto_output_tree_or_ref (struct output_block *, tree, bool); +extern void lto_output_chain (struct output_block *, tree, bool); extern void produce_asm (struct output_block *ob, tree fn); extern void lto_output_string (struct output_block *, struct lto_output_stream *, -- This patch is available for review at http://codereview.appspot.com/4331046
Sign in to reply to this message.
|