From patchwork Tue Sep 20 01:52:40 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lawrence Crowl X-Patchwork-Id: 115404 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 3EE1EB70BE for ; Tue, 20 Sep 2011 11:53:10 +1000 (EST) Received: (qmail 27645 invoked by alias); 20 Sep 2011 01:53:07 -0000 Received: (qmail 27625 invoked by uid 22791); 20 Sep 2011 01:53:04 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RP_MATCHES_RCVD, SPF_HELO_PASS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.44.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 20 Sep 2011 01:52:46 +0000 Received: from hpaq11.eem.corp.google.com (hpaq11.eem.corp.google.com [172.25.149.11]) by smtp-out.google.com with ESMTP id p8K1qhb6029274; Mon, 19 Sep 2011 18:52:44 -0700 Received: from jade.mtv.corp.google.com (jade.mtv.corp.google.com [172.18.110.116]) by hpaq11.eem.corp.google.com with ESMTP id p8K1qfQ4005230; Mon, 19 Sep 2011 18:52:41 -0700 Received: by jade.mtv.corp.google.com (Postfix, from userid 21482) id D2203222675; Mon, 19 Sep 2011 18:52:40 -0700 (PDT) To: reply@codereview.appspotmail.com, dnovillo@google.com, gcc-patches@gcc.gnu.org Subject: [pph] Stream merging information (issue5090041) Message-Id: <20110920015240.D2203222675@jade.mtv.corp.google.com> Date: Mon, 19 Sep 2011 18:52:40 -0700 (PDT) From: crowl@google.com (Lawrence Crowl) X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Prepare for merging symbols. When writing a cp_binding_level, we emit this_entity first, so that we can identify the context of the bindings early. If this_entity is a namespace, we call alternate routines that track the namespace. These ultimately call pph_write_namespace_tree, which adds additional information needed for decl merging. Reads take the corresponding actions. We do not yet to symbol lookup or merging. Tested on x64. --- This patch is available for review at http://codereview.appspot.com/5090041 Index: gcc/cp/ChangeLog.pph 2011-09-19 Lawrence Crowl * pph-streamer-out.c (pph_out_binding_level_1): Read this_entity first. Call different routines when it is a namespace. (pph_write_tree): Move most of body to pph_write_namespace_tree. (pph_write_namespace_tree): As above. If there is an enclosing namespace, write additional information needed for merging. (pph_out_namespace_tree_vec) New. (pph_out_namespace_tree_vec_filtered) New. (pph_write_namespace_chain) New. (pph_out_namespace_chain_filtered) New. * pph-streamer-in.c (pph_in_binding_level): Read this_entity first. Call different routines when it is a namespace. (pph_read_tree): Move most of body to pph_read_namespace_tree. (pph_read_namespace_tree): As above. If there is an enclosing namespace, read additional information needed for merging. Merging is currently not done. (pph_read_namespace_chain): New. (pph_in_namespace_tree_vec): New. * pph-streamer.h (pph_write_namespace_tree): New. (pph_write_namespace_chain): New. (pph_read_namespace_tree): New. (pph_read_namespace_chain): New. (pph_out_namespace_tree_1): New. (pph_out_namespace_tree): New. (pph_out_tree_VEC): Deleted, redundant with pph-streamer-out.c. (pph_out_namespace_chain): New. (pph_in_namespace_tree): New. (pph_in_namespace_chain): New. Index: gcc/cp/pph-streamer-in.c =================================================================== --- gcc/cp/pph-streamer-in.c (revision 178988) +++ gcc/cp/pph-streamer-in.c (working copy) @@ -376,6 +376,26 @@ pph_in_tree_vec (pph_stream *stream) } +/* Read and return a gc VEC of trees in ENCLOSING_NAMESPACE from STREAM. */ + +static VEC(tree,gc) * +pph_in_namespace_tree_vec (pph_stream *stream, tree enclosing_namespace) +{ + HOST_WIDE_INT i, num; + VEC(tree,gc) *v; + + num = pph_in_hwi (stream); + v = NULL; + for (i = 0; i < num; i++) + { + tree t = pph_in_namespace_tree (stream, enclosing_namespace); + VEC_safe_push (tree, gc, v, t); + } + + return v; +} + + /* Read and return a gc VEC of qualified_typedef_usage_t from STREAM. */ static VEC(qualified_typedef_usage_t,gc) * @@ -529,6 +549,7 @@ pph_in_binding_level (pph_stream *stream cp_binding_level *bl; struct bitpack_d bp; enum pph_record_marker marker; + tree entity; marker = pph_in_start_record (stream, &image_ix, &ix); if (marker == PPH_RECORD_END) @@ -547,13 +568,23 @@ pph_in_binding_level (pph_stream *stream ggc_alloc_cleared_cp_binding_level (), to_register); - bl->names = pph_in_chain (stream); - bl->namespaces = pph_in_chain (stream); - - bl->static_decls = pph_in_tree_vec (stream); - - bl->usings = pph_in_chain (stream); - bl->using_directives = pph_in_chain (stream); + entity = bl->this_entity = pph_in_tree (stream); + if (NAMESPACE_SCOPE_P (entity)) + { + bl->names = pph_in_namespace_chain (stream, entity); + bl->namespaces = pph_in_namespace_chain (stream, entity); + bl->static_decls = pph_in_namespace_tree_vec (stream, entity); + bl->usings = pph_in_namespace_chain (stream, entity); + bl->using_directives = pph_in_namespace_chain (stream, entity); + } + else + { + bl->names = pph_in_chain (stream); + bl->namespaces = pph_in_chain (stream); + bl->static_decls = pph_in_tree_vec (stream); + bl->usings = pph_in_chain (stream); + bl->using_directives = pph_in_chain (stream); + } num = pph_in_uint (stream); bl->class_shadowed = NULL; @@ -574,7 +605,6 @@ pph_in_binding_level (pph_stream *stream } bl->blocks = pph_in_tree (stream); - bl->this_entity = pph_in_tree (stream); bl->level_chain = pph_in_binding_level (stream, NULL); bl->dead_vars_from_for = pph_in_tree_vec (stream); bl->statement_list = pph_in_chain (stream); @@ -2042,6 +2072,15 @@ pph_read_tree (struct lto_input_block *i { /* Find data. */ pph_stream *stream = (pph_stream *) root_data_in->sdata; + return pph_read_namespace_tree (stream, NULL); +} + +/* Read a tree from the STREAM. It ENCLOSING_NAMESPACE is not null, + the tree may be unified with an existing tree in that namespace. */ + +tree +pph_read_namespace_tree (pph_stream *stream, tree enclosing_namespace) +{ struct lto_input_block *ib = stream->encoder.r.ib; struct data_in *data_in = stream->encoder.r.data_in; @@ -2081,6 +2120,18 @@ pph_read_tree (struct lto_input_block *i /* Otherwise, materialize a new node from IB. This will also read all the language-independent bitfields for the new tree. */ expr = pph_read_tree_header (stream, tag); + if (enclosing_namespace && DECL_P (expr)) + { + /* We may need to unify two declarations. */ + /* FIXME crowl: location_t where = pph_in_location (stream); */ + const char *idstr = pph_in_string (stream); + /* But we only search if we have a name. */ + if (!idstr) + { + /* FIXME crowl search for idstr in namespace. */ + expr = expr; + } + } pph_cache_insert_at (&stream->cache, expr, ix); pph_read_tree_body (stream, expr); } @@ -2088,6 +2139,33 @@ pph_read_tree (struct lto_input_block *i } +/* Read a chain of tree nodes from input block IB. DATA_IN contains + tables and descriptors for the file being read. */ + +tree +pph_read_namespace_chain (pph_stream *stream, tree enclosing_namespace) +{ + int i, count; + tree first, prev, curr; + + first = prev = NULL_TREE; + count = streamer_read_hwi (stream->encoder.r.ib); + for (i = 0; i < count; i++) + { + curr = pph_in_namespace_tree (stream, enclosing_namespace); + if (prev) + TREE_CHAIN (prev) = curr; + else + first = curr; + + TREE_CHAIN (curr) = NULL_TREE; + prev = curr; + } + + return first; +} + + /* Finalize the PPH reader. */ void Index: gcc/cp/pph-streamer-out.c =================================================================== --- gcc/cp/pph-streamer-out.c (revision 178988) +++ gcc/cp/pph-streamer-out.c (working copy) @@ -400,6 +400,26 @@ pph_out_tree_vec (pph_stream *stream, VE } +/* Write all the trees (from ENCLOSING_NAMESPACE) in VEC V to STREAM. */ + +static void +pph_out_namespace_tree_vec (pph_stream *stream, VEC(tree,gc) *v, + tree enclosing_namespace) +{ + unsigned i; + tree t; + + /* Note that we use the same format used by streamer_write_chain. + This is to support pph_out_chain_filtered, which writes the + filtered chain as a VEC. Since the reader always reads chains + using streamer_read_chain, we have to write VECs in exactly the + same way as tree chains. */ + pph_out_hwi (stream, VEC_length (tree, v)); + FOR_EACH_VEC_ELT (tree, v, i, t) + pph_out_namespace_tree (stream, t, enclosing_namespace); +} + + /* Write all the trees matching FILTER in VEC V to STREAM. */ static void @@ -428,6 +448,37 @@ pph_out_tree_vec_filtered (pph_stream *s } +/* Write all the trees in ENCLOSING_NAMESPACE matching FILTER + in VEC V to STREAM. */ + +static void +pph_out_namespace_tree_vec_filtered (pph_stream *stream, VEC(tree,gc) *v, + tree enclosing_namespace, unsigned filter) +{ + unsigned i; + tree t; + VEC(tree, heap) *to_write = NULL; + + /* Special case. If the caller wants no filtering, it is much + faster to just call pph_out_tree_vec. */ + if (filter == PPHF_NONE) + { + pph_out_namespace_tree_vec (stream, v, enclosing_namespace); + return; + } + + /* Collect all the nodes that match the filter. */ + FOR_EACH_VEC_ELT (tree, v, i, t) + if (pph_tree_matches (t, filter)) + VEC_safe_push (tree, heap, to_write, t); + + /* Write them. */ + pph_out_namespace_tree_vec (stream, (VEC(tree,gc) *)to_write, + enclosing_namespace); + VEC_free (tree, heap, to_write); +} + + /* Write all the qualified_typedef_usage_t in VEC V to STREAM. */ static void @@ -517,6 +568,36 @@ pph_out_label_binding (pph_stream *strea } +/* Emit the chain of tree nodes from ENCLOSING_NAMESPACE starting at T + to STREAM. + OB is the output block + to write to. REF_P is true if chain elements should be emitted + as references. */ + +void +pph_write_namespace_chain (pph_stream *stream, tree t, tree enclosing_namespace) +{ + int i, count; + + count = list_length (t); + streamer_write_hwi (stream->encoder.w.ob, count); + for (i = 0; i < count; i++) + { + tree saved_chain; + + /* Clear TREE_CHAIN to avoid blindly recursing into the rest + of the list. */ + saved_chain = TREE_CHAIN (t); + TREE_CHAIN (t) = NULL_TREE; + + pph_write_namespace_tree (stream, t, enclosing_namespace); + + TREE_CHAIN (t) = saved_chain; + t = TREE_CHAIN (t); + } +} + + /* Output a chain of nodes to STREAM starting with FIRST. Skip any nodes that do not match FILTER. */ @@ -545,6 +626,36 @@ pph_out_chain_filtered (pph_stream *stre } +/* Output a chain of nodes in ENCLOSING_NAMESPACE to STREAM + starting with FIRST. Skip any nodes that do not match FILTER. */ + +static void +pph_out_namespace_chain_filtered (pph_stream *stream, tree first, + tree enclosing_namespace, unsigned filter) +{ + tree t; + VEC(tree, heap) *to_write = NULL; + + /* Special case. If the caller wants no filtering, it is much + faster to just call pph_out_chain directly. */ + if (filter == PPHF_NONE) + { + pph_out_namespace_chain (stream, first, enclosing_namespace); + return; + } + + /* Collect all the nodes that match the filter. */ + for (t = first; t; t = TREE_CHAIN (t)) + if (pph_tree_matches (t, filter)) + VEC_safe_push (tree, heap, to_write, t); + + /* Write them. */ + pph_out_namespace_tree_vec (stream, (VEC(tree,gc) *)to_write, + enclosing_namespace); + VEC_free (tree, heap, to_write); +} + + /* Helper for pph_out_binding_level. Write all the fields of BL to STREAM, without checking whether BL was in the streamer cache or not. Do not emit any nodes in BL that do not match FILTER. */ @@ -557,15 +668,30 @@ pph_out_binding_level_1 (pph_stream *str cp_class_binding *cs; cp_label_binding *sl; struct bitpack_d bp; - - pph_out_chain_filtered (stream, bl->names, PPHF_NO_BUILTINS | filter); - pph_out_chain_filtered (stream, bl->namespaces, PPHF_NO_BUILTINS | filter); - - pph_out_tree_vec_filtered (stream, bl->static_decls, filter); - - pph_out_chain_filtered (stream, bl->usings, PPHF_NO_BUILTINS | filter); - pph_out_chain_filtered (stream, bl->using_directives, - PPHF_NO_BUILTINS | filter); + unsigned aux_filter = PPHF_NO_BUILTINS | filter; + tree entity = bl->this_entity; + pph_out_tree (stream, entity); + if (NAMESPACE_SCOPE_P (entity)) + { + pph_out_namespace_chain_filtered (stream, bl->names, + entity, aux_filter); + pph_out_namespace_chain_filtered (stream, bl->namespaces, + entity, aux_filter); + pph_out_namespace_tree_vec_filtered (stream, bl->static_decls, + entity, filter); + pph_out_namespace_chain_filtered (stream, bl->usings, + entity, aux_filter); + pph_out_namespace_chain_filtered (stream, bl->using_directives, + entity, aux_filter); + } + else + { + pph_out_chain_filtered (stream, bl->names, aux_filter); + pph_out_chain_filtered (stream, bl->namespaces, aux_filter); + pph_out_tree_vec_filtered (stream, bl->static_decls, filter); + pph_out_chain_filtered (stream, bl->usings, aux_filter); + pph_out_chain_filtered (stream, bl->using_directives, aux_filter); + } pph_out_uint (stream, VEC_length (cp_class_binding, bl->class_shadowed)); FOR_EACH_VEC_ELT (cp_class_binding, bl->class_shadowed, i, cs) @@ -578,7 +704,6 @@ pph_out_binding_level_1 (pph_stream *str pph_out_label_binding (stream, sl); pph_out_tree (stream, bl->blocks); - pph_out_tree (stream, bl->this_entity); pph_out_binding_level (stream, bl->level_chain, filter); pph_out_tree_vec (stream, bl->dead_vars_from_for); pph_out_chain (stream, bl->statement_list); @@ -1791,7 +1916,13 @@ void pph_write_tree (struct output_block *ob, tree expr, bool ref_p ATTRIBUTE_UNUSED) { pph_stream *stream = (pph_stream *) ob->sdata; + pph_write_namespace_tree (stream, expr, NULL); +} +void +pph_write_namespace_tree (pph_stream *stream, tree expr, + tree enclosing_namespace ) +{ /* If EXPR is NULL or it already existed in the pickle cache, nothing else needs to be done. */ if (!pph_out_start_record (stream, expr)) @@ -1804,19 +1935,30 @@ pph_write_tree (struct output_block *ob, compiler on startup. The only builtins that need to be written out are BUILT_IN_FRONTEND. For all other builtins, we simply write the class and code. */ - streamer_write_builtin (ob, expr); + streamer_write_builtin (stream->encoder.w.ob, expr); } else if (TREE_CODE (expr) == INTEGER_CST) { /* INTEGER_CST nodes are special because they need their original type to be materialized by the reader (to implement TYPE_CACHED_VALUES). */ - streamer_write_integer_cst (ob, expr, ref_p); + streamer_write_integer_cst (stream->encoder.w.ob, expr, false); } else { /* This is the first time we see EXPR, write it out. */ pph_write_tree_header (stream, expr); + if (enclosing_namespace && DECL_P (expr)) + { + /* We may need to unify two declarations. */ + /* FIXME crowl: pph_out_location (stream, DECL_SOURCE_LOCATION (expr)); */ + tree name = DECL_NAME (expr); + if (name) + pph_out_string_with_length (stream, IDENTIFIER_POINTER (name), + IDENTIFIER_LENGTH (name)); + else + pph_out_string (stream, NULL); + } pph_write_tree_body (stream, expr); } } Index: gcc/cp/pph-streamer.h =================================================================== --- gcc/cp/pph-streamer.h (revision 178987) +++ gcc/cp/pph-streamer.h (working copy) @@ -254,6 +254,8 @@ void *pph_cache_get (pph_pickle_cache *, void pph_flush_buffers (pph_stream *); void pph_init_write (pph_stream *); void pph_write_tree (struct output_block *, tree, bool); +void pph_write_namespace_tree (pph_stream *, tree, tree); +void pph_write_namespace_chain (pph_stream *, tree, tree); void pph_add_decl_to_symtab (tree, enum pph_symtab_action, bool, bool); void pph_add_include (pph_stream *); void pph_writer_init (void); @@ -268,6 +270,8 @@ struct binding_table_s *pph_in_binding_t /* In pph-streamer-in.c. */ void pph_init_read (pph_stream *); tree pph_read_tree (struct lto_input_block *, struct data_in *); +tree pph_read_namespace_tree (pph_stream *, tree); +tree pph_read_namespace_chain (pph_stream *, tree); location_t pph_read_location (struct lto_input_block *, struct data_in *); void pph_read_file (const char *); void pph_reader_finish (void); @@ -329,6 +333,25 @@ pph_out_tree (pph_stream *stream, tree t pph_out_tree_1 (stream, t, 2); } +/* Output AST T from ENCLOSING_NAMESPACE to STREAM. + If -fpph-tracer is set to TLEVEL or higher, T is sent to pph_trace_tree. */ +static inline void +pph_out_namespace_tree_1 (pph_stream *stream, tree t, int tlevel, + tree enclosing_namespace) +{ + if (flag_pph_tracer >= tlevel) + pph_trace_tree (stream, t); + pph_write_namespace_tree (stream, t, enclosing_namespace); +} + +/* Output AST T from ENCLOSING_NAMESPACE to STREAM. + Trigger tracing at -fpph-tracer=2. */ +static inline void +pph_out_namespace_tree (pph_stream *stream, tree t, tree enclosing_namespace) +{ + pph_out_namespace_tree_1 (stream, t, 2, enclosing_namespace); +} + /* Write an unsigned int VALUE to STREAM. */ static inline void pph_out_uint (pph_stream *stream, unsigned int value) @@ -392,25 +415,6 @@ pph_out_string_with_length (pph_stream * str, len + 1, false); } -/* Output VEC V of ASTs to STREAM. */ -/* FIXME pph: hold for alternate routine. */ -#if 0 -static inline void -pph_out_tree_VEC (pph_stream *stream, VEC(tree,gc) *v) -{ - tree t; - size_t i; - size_t c = VEC_length (tree, v); - pph_out_uint (stream, c); - FOR_EACH_VEC_ELT (tree, v, i, t) - { - if (flag_pph_tracer >= 1) - pph_trace_tree (stream, t); - pph_write_tree (stream->encoder.w.ob, t); - } -} -#endif - /* Write location LOC of length to STREAM. */ static inline void pph_out_location (pph_stream *stream, location_t loc) @@ -429,6 +433,16 @@ pph_out_chain (pph_stream *stream, tree streamer_write_chain (stream->encoder.w.ob, first, false); } +/* Write a chain of ASTs to STREAM starting with FIRST. */ +static inline void +pph_out_namespace_chain (pph_stream *stream, tree first, + tree enclosing_namespace) +{ + if (flag_pph_tracer >= 2) + pph_trace_chain (stream, first); + pph_write_namespace_chain (stream, first, enclosing_namespace); +} + /* Write a bitpack BP to STREAM. */ static inline void pph_out_bitpack (pph_stream *stream, struct bitpack_d *bp) @@ -521,6 +535,17 @@ pph_in_tree (pph_stream *stream) return t; } +/* Load an AST in an ENCLOSING_NAMESPACE from STREAM. + Return the corresponding tree. */ +static inline tree +pph_in_namespace_tree (pph_stream *stream, tree enclosing_namespace) +{ + tree t = pph_read_namespace_tree (stream, enclosing_namespace); + if (flag_pph_tracer >= 4) + pph_trace_tree (stream, t); + return t; +} + /* Load into an array A of cardinality C of AST from STREAM. */ /* FIXME pph: Hold for later use. */ #if 0 @@ -567,6 +592,16 @@ pph_in_chain (pph_stream *stream) return t; } +/* Read a chain of ASTs in ENCLOSING_NAMESPACE from STREAM. */ +static inline tree +pph_in_namespace_chain (pph_stream *stream, tree enclosing_namespace) +{ + tree t = pph_read_namespace_chain (stream, enclosing_namespace); + if (flag_pph_tracer >= 2) + pph_trace_chain (stream, t); + return t; +} + /* Read a bitpack from STREAM. */ static inline struct bitpack_d pph_in_bitpack (pph_stream *stream)