From patchwork Thu Oct 6 21:04:48 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lawrence Crowl X-Patchwork-Id: 118166 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 4CBFCB700E for ; Fri, 7 Oct 2011 08:05:31 +1100 (EST) Received: (qmail 22911 invoked by alias); 6 Oct 2011 21:05:24 -0000 Received: (qmail 22876 invoked by uid 22791); 6 Oct 2011 21:05:14 -0000 X-SWARE-Spam-Status: No, hits=-1.4 required=5.0 tests=AWL, BAYES_05, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RP_MATCHES_RCVD, SPF_HELO_PASS, TW_CX 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; Thu, 06 Oct 2011 21:04:53 +0000 Received: from hpaq5.eem.corp.google.com (hpaq5.eem.corp.google.com [172.25.149.5]) by smtp-out.google.com with ESMTP id p96L4pL2025476; Thu, 6 Oct 2011 14:04:51 -0700 Received: from jade.mtv.corp.google.com (jade.mtv.corp.google.com [172.18.110.116]) by hpaq5.eem.corp.google.com with ESMTP id p96L4nHs005509; Thu, 6 Oct 2011 14:04:49 -0700 Received: by jade.mtv.corp.google.com (Postfix, from userid 21482) id E06AC222606; Thu, 6 Oct 2011 14:04:48 -0700 (PDT) To: reply@codereview.appspotmail.com, dnovillo@google.com, gcc-patches@gcc.gnu.org Subject: [pph] More merging. (issue5222045) Message-Id: <20111006210448.E06AC222606@jade.mtv.corp.google.com> Date: Thu, 6 Oct 2011 14:04:48 -0700 (PDT) From: crowl@google.com (Lawrence Crowl) 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 Merge symbols. This patch doesn't actually fix anything, but it does reorganize to address known issues. In particular, the code shifts from merging into a namespace to merging into a particular chain. This prevents a latent bug in merging into inappropriate chains. It also sets us up to merge structs, which we may need due to users binding directly to members. --- This patch is available for review at http://codereview.appspot.com/5222045 Index: gcc/testsuite/ChangeLog.pph 2011-10-06 Lawrence Crowl * g++.dg/pph/c4inline.cc: Clarify failure. * g++.dg/pph/x4keyno.cc: Clarify failure. * g++.dg/pph/x4keyex.cc: Clarify failure. * g++.dg/pph/x4keyed.cc: Clarify failure. * g++.dg/pph/x0tmplclass23.h: Fix header guard variables. Index: gcc/cp/ChangeLog.pph 2011-10-06 Lawrence Crowl * pt.c (pph_in_pending_templates_list): Send pph logging to the pph log file. * pph.c (pph_tree_code_text): Correct specification of enum bound. * pph-streamer-in.c (pph_in_namespace_tree_vec): Remove. (pph_in_binding_level): Change to mutator. Mutate early so that the result is usable while reading sub-trees. (pph_in_tcc_declaration): Comment on redundancy. (pph_match_to_overload): New. (pph_match_to_function): New. (pph_match_to_link): New. (pph_search_in_chain): New. (pph_prepend_to_chain): New. (pph_merge_into_chain): New. (pph_read_namespace_tree): Rename to pph_read_any_tree. Mutate a specific chain rather than mutate a namespace. (pph_read_tree): Move within source. (pph_read_mergeable_tree): New. (pph_read_mergeable_chain): Chaining is now done by pph_in_mergeable_tree. * pph-streamer-out.c (pph_out_namespace_tree_vec): Rename to pph_out_mergeable_tree_vec. Remove unneeded namespace parameter. (pph_out_namespace_tree_vec_filtered): Remove unneeded. (pph_write_namespace_chain): Replace with pph_write_mergeable_chain. (pph_write_mergeable_links): New. (pph_out_namespace_chain_filtered): Rename to pph_out_mergeable_chain_filtered. Remove unneeded namespace parameter. (pph_out_binding_level_1): Adjust code to track the above changes. ->static_decls are already in declaration order, factor them out of mergable tests. (pph_out_tcc_declaration): Comment on redundancy. (pph_out_tcc_type): Comment on redundancy. (pph_write_namespace_tree): Rename to pph_write_any_tree. Change namespace parameter to boolean. Emit location info for merging. (pph_write_mergeable_tree): New. * pph-streamer.h: Modify function declarations to reflect the above. (pph_out_namespace_tree): Rename to pph_out_mergeable_tree. Remove unneeded namespace argument. (pph_out_namespace_tree_1): Fold into pph_out_mergeable_tree. (pph_out_namespace_chain): Rname to pph_out_mergeable_chain. Remove unneeded namespace argument. (pph_in_namespace_tree): Rname to pph_in_mergeable_tree. Change argument to chain instead of namespace. (pph_in_namespace_chain): Rname to pph_in_mergeable_chain. Change argument to chain instead of namespace. Index: gcc/testsuite/g++.dg/pph/x4keyno.cc =================================================================== --- gcc/testsuite/g++.dg/pph/x4keyno.cc (revision 179580) +++ gcc/testsuite/g++.dg/pph/x4keyno.cc (working copy) @@ -1,4 +1,4 @@ -// { dg-xfail-if "BOGUS" { "*-*-*" } { "-fpph-map=pph.map" } } +// { dg-xfail-if "BOGUS MERGE AUXVAR" { "*-*-*" } { "-fpph-map=pph.map" } } // { dg-bogus "x4keyno.cc:11:1: error: redefinition of 'const char _ZTS5keyno" "" { xfail *-*-* } 0 } #include "x0keyno1.h" Index: gcc/testsuite/g++.dg/pph/c4inline.cc =================================================================== --- gcc/testsuite/g++.dg/pph/c4inline.cc (revision 179580) +++ gcc/testsuite/g++.dg/pph/c4inline.cc (working copy) @@ -1,6 +1,8 @@ // pph asm xdiff 36250 -//Emitting a second copy of the inline function f. -//With comdat, the linker may paper over the differences. +// xfail BOGUS DUPFUN +// +// Emitting a second copy of the inline function f. +// With comdat, the linker may paper over the differences. #include "c0inline1.h" #include "c0inline2.h" Index: gcc/testsuite/g++.dg/pph/x4keyex.cc =================================================================== --- gcc/testsuite/g++.dg/pph/x4keyex.cc (revision 179580) +++ gcc/testsuite/g++.dg/pph/x4keyex.cc (working copy) @@ -1,4 +1,5 @@ // pph asm xdiff 32642 +// xfail BOGUS LABELS // // This test case fails to compare because LFB/LFE labels are different. // Index: gcc/testsuite/g++.dg/pph/x4keyed.cc =================================================================== --- gcc/testsuite/g++.dg/pph/x4keyed.cc (revision 179580) +++ gcc/testsuite/g++.dg/pph/x4keyed.cc (working copy) @@ -1,4 +1,4 @@ -// { dg-xfail-if "BOGUS" { "*-*-*" } { "-fpph-map=pph.map" } } +// { dg-xfail-if "BOGUS MERGE AUXVAR" { "*-*-*" } { "-fpph-map=pph.map" } } // { dg-bogus "x4keyed.cc:13:1: error: redefinition of 'const char _ZTS5keyed ..'" "" { xfail *-*-* } 0 } #include "x0keyed1.h" Index: gcc/testsuite/g++.dg/pph/x0tmplclass23.h =================================================================== --- gcc/testsuite/g++.dg/pph/x0tmplclass23.h (revision 179580) +++ gcc/testsuite/g++.dg/pph/x0tmplclass23.h (working copy) @@ -1,5 +1,5 @@ -#ifndef X0TMPLCLASS13_H -#define X0TMPLCLASS13_H +#ifndef X0TMPLCLASS23_H +#define X0TMPLCLASS23_H #include "a0tmplclass1_g.h" #include "a0tmplclass1_s.h" Index: gcc/cp/pph.c =================================================================== --- gcc/cp/pph.c (revision 179580) +++ gcc/cp/pph.c (working copy) @@ -47,7 +47,7 @@ FILE *pph_logfile = NULL; const char* pph_tree_code_text (enum tree_code code) { - gcc_assert (code <= TEMPLATE_INFO); + gcc_assert (code < MAX_TREE_CODES); return tree_code_name[code]; } Index: gcc/cp/pph-streamer-in.c =================================================================== --- gcc/cp/pph-streamer-in.c (revision 179580) +++ gcc/cp/pph-streamer-in.c (working copy) @@ -379,26 +379,6 @@ 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) * @@ -423,8 +403,8 @@ pph_in_qual_use_vec (pph_stream *stream) /* Forward declaration to break cyclic dependencies. */ -static cp_binding_level *pph_in_binding_level (pph_stream *, - cp_binding_level *); +static void pph_in_binding_level (cp_binding_level **, + pph_stream *, cp_binding_level *); /* Helper for pph_in_cxx_binding. Read and return a cxx_binding instance from STREAM. */ @@ -449,7 +429,7 @@ pph_in_cxx_binding_1 (pph_stream *stream type = pph_in_tree (stream); ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cxx_binding, cb, cxx_binding_make (value, type)); - cb->scope = pph_in_binding_level (stream, NULL); + pph_in_binding_level (&cb->scope, stream, NULL); bp = pph_in_bitpack (stream); cb->value_is_inherited = bp_unpack_value (&bp, 1); cb->is_local = bp_unpack_value (&bp, 1); @@ -547,8 +527,9 @@ pph_in_label_binding (pph_stream *stream level given in TO_REGISTER. This way, subsequent references to the global binding level will be done to the one set in TO_REGISTER. */ -static cp_binding_level * -pph_in_binding_level (pph_stream *stream, cp_binding_level *to_register) +static void +pph_in_binding_level (cp_binding_level **out_field, + pph_stream *stream, cp_binding_level *to_register) { unsigned i, num, image_ix, ix; cp_binding_level *bl; @@ -558,10 +539,16 @@ pph_in_binding_level (pph_stream *stream marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cp_binding_level); if (marker == PPH_RECORD_END) - return NULL; + { + *out_field = NULL; + return; + } else if (pph_is_reference_marker (marker)) - return (cp_binding_level *) pph_cache_find (stream, marker, image_ix, ix, - PPH_cp_binding_level); + { + *out_field = (cp_binding_level *) + pph_cache_find (stream, marker, image_ix, ix, PPH_cp_binding_level); + return; + } /* If TO_REGISTER is set, register that binding level instead of the newly allocated binding level into slot IX. */ @@ -573,23 +560,28 @@ pph_in_binding_level (pph_stream *stream ggc_alloc_cleared_cp_binding_level (), to_register); + /* Now activate the encompasing field in case we need to insert into a + namespace that we just read. */ + *out_field = bl; + 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); + if (flag_pph_debug >= 3) + debug_tree_chain (bl->names); + pph_in_mergeable_chain (stream, &bl->names); + pph_in_mergeable_chain (stream, &bl->namespaces); + pph_in_mergeable_chain (stream, &bl->usings); + pph_in_mergeable_chain (stream, &bl->using_directives); } 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); } + bl->static_decls = pph_in_tree_vec (stream); num = pph_in_uint (stream); bl->class_shadowed = NULL; @@ -610,7 +602,7 @@ pph_in_binding_level (pph_stream *stream } bl->blocks = pph_in_tree (stream); - bl->level_chain = pph_in_binding_level (stream, NULL); + pph_in_binding_level (&bl->level_chain, stream, NULL); bl->dead_vars_from_for = pph_in_tree_vec (stream); bl->statement_list = pph_in_chain (stream); bl->binding_depth = pph_in_uint (stream); @@ -620,8 +612,6 @@ pph_in_binding_level (pph_stream *stream 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; } @@ -673,7 +663,7 @@ pph_in_language_function (pph_stream *st /* FIXME pph. We are not reading lf->x_named_labels. */ - lf->bindings = pph_in_binding_level (stream, NULL); + pph_in_binding_level (&lf->bindings, stream, NULL); lf->x_local_names = pph_in_tree_vec (stream); /* FIXME pph. We are not reading lf->extern_decl_map. */ @@ -825,7 +815,7 @@ pph_in_struct_function (pph_stream *stre static void pph_in_ld_ns (pph_stream *stream, struct lang_decl_ns *ldns) { - ldns->level = pph_in_binding_level (stream, NULL); + pph_in_binding_level (&ldns->level, stream, NULL); } @@ -1109,11 +1099,13 @@ pph_in_scope_chain (pph_stream *stream) scope_chain->bindings. Otherwise, identifiers read from STREAM will have the wrong bindings and will fail name lookups. */ cur_bindings = scope_chain->bindings; - new_bindings = pph_in_binding_level (stream, scope_chain->bindings); + pph_in_binding_level (&new_bindings, stream, scope_chain->bindings); /* Merge the bindings from STREAM into saved_scope->bindings. */ + /* FMIXME crowl: The following should already have been done. chainon (cur_bindings->names, new_bindings->names); chainon (cur_bindings->namespaces, new_bindings->namespaces); + */ FOR_EACH_VEC_ELT (tree, new_bindings->static_decls, i, decl) VEC_safe_push (tree, gc, cur_bindings->static_decls, decl); @@ -1723,6 +1715,7 @@ pph_in_tcc_declaration (pph_stream *stre DECL_INITIAL (decl) = pph_in_tree (stream); /* The tree streamer only writes DECL_CHAIN for PARM_DECL nodes. */ + /* FIXME pph: almost redundant. */ if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL) DECL_CHAIN (decl) = pph_in_tree (stream); @@ -1774,6 +1767,7 @@ pph_in_tcc_type (pph_stream *stream, tre TYPE_NEXT_VARIANT (type) = pph_in_tree (stream); /* FIXME pph - Streaming TYPE_CANONICAL generates many type comparison failures. Why? */ + /* FIXME pph: apparently redundant. */ TREE_CHAIN (type) = pph_in_tree (stream); /* The type values cache is built as constants are instantiated, @@ -2035,7 +2029,7 @@ pph_read_tree_header (pph_stream *stream /* Allocate the tree. */ tree expr = streamer_alloc_tree (ib, data_in, tag); - /* Read the language-independent bitfields for expr. */ + /* Read the language-independent bitfields for EXPR. */ bp = streamer_read_tree_bitfields (ib, expr); /* Unpack all language-dependent bitfields. */ @@ -2047,24 +2041,149 @@ pph_read_tree_header (pph_stream *stream } -/* Callback for reading ASTs from a stream. Instantiate and return a - new tree from the PPH stream in DATA_IN. */ +/* Match a new decl EXPR at location WHERE with identifier string IDSTR + against an overload set at the LINK of a chain. + The EXPR may be added to that set. */ -tree -pph_read_tree (struct lto_input_block *ib_unused ATTRIBUTE_UNUSED, - struct data_in *root_data_in) +static tree +pph_match_to_overload (tree expr ATTRIBUTE_UNUSED, + location_t where ATTRIBUTE_UNUSED, + const char *idstr, tree *link ATTRIBUTE_UNUSED) { - /* Find data. */ - pph_stream *stream = (pph_stream *) root_data_in->sdata; - return pph_read_namespace_tree (stream, NULL); + /* FIXME crowl: Assume functions are distinct for now. */ + if (flag_pph_debug >= 2) + fprintf (pph_logfile, "PPH: function \"%s\" assumed distinct\n", idstr); + return NULL; } +/* Match a new decl EXPR at location WHERE with identifier string IDSTR + against a function at the LINK of a chain. + We may need to create an overload set if EXPR is not the same overload. */ + +static tree +pph_match_to_function (tree expr ATTRIBUTE_UNUSED, + location_t where ATTRIBUTE_UNUSED, + const char *idstr, tree *link ATTRIBUTE_UNUSED) +{ + /* FIXME crowl: Assume functions are distinct for now. */ + if (flag_pph_debug >= 2) + fprintf (pph_logfile, "PPH: function \"%s\" assumed distinct\n", idstr); + return NULL; +} + + +/* Match a new decl EXPR at location WHERE with identifier string IDSTR + against an LINK of a chain. */ + +static tree +pph_match_to_link (tree expr, location_t where, const char *idstr, tree* link) +{ + enum tree_code link_code, expr_code; + tree idtree; + const char *idptr; + + link_code = TREE_CODE (*link); + if (link_code == TREE_LIST) + return pph_match_to_overload (expr, where, idstr, link); + + expr_code = TREE_CODE (expr); + if (link_code != expr_code) + return NULL; + + idtree = DECL_NAME (*link); + if (!idtree) + return NULL; + + idptr = IDENTIFIER_POINTER (idtree); + if (!idptr) + return NULL; + + if (strcmp (idptr, idstr) != 0) + { + if (flag_pph_debug >= 4) + fprintf (pph_logfile, "PPH: link \"%s\" " + "does not match mergeable \"%s\"\n", + idptr, idstr); + return NULL; + } + + /* A name match! */ + + if (expr_code == FUNCTION_DECL) + return pph_match_to_function (expr, where, idstr, link); + + /* A non-function match. */ + return *link; +} + + +/* Possibly merge a new decl EXPR at location WHERE with identifier + string IDSTR into an the decl in the CHAIN. */ + +static tree +pph_search_in_chain (tree expr, location_t where, const char *idstr, + tree *chain) +{ + /* FIXME pph: This could resultin O(POW(n,2)) compilation. */ + tree *link = chain; + while (*link != NULL) + { + tree found = pph_match_to_link (expr, where, idstr, link); + if (found) + return found; + link = &DECL_CHAIN (*link); + } + return NULL; +} + + +/* Prepend an tree EXPR to a CHAIN. */ + +static tree +pph_prepend_to_chain (tree expr, tree *chain) +{ + DECL_CHAIN (expr) = *chain; + *chain = expr; + return expr; +} + +/* Merge the just-read header for tree EXPR onto the CHAIN, + which may require reading more from the STREAM. */ + +static tree +pph_merge_into_chain (pph_stream *stream, tree expr, tree *chain) +{ + location_t where; + const char *idstr; + tree found; + + if (!DECL_P (expr)) + return pph_prepend_to_chain (expr, chain); + + where = pph_in_location (stream); + idstr = pph_in_string (stream); + if (!idstr) + return pph_prepend_to_chain (expr, chain); + + found = pph_search_in_chain (expr, where, idstr, chain); + if (!found) + { + if (flag_pph_debug >= 3) + fprintf (pph_logfile, "PPH: %s NOT found on chain\n", idstr); + return pph_prepend_to_chain (expr, chain); + } + + if (flag_pph_debug >= 3) + fprintf (pph_logfile, "PPH: %s FOUND on chain\n", idstr); + return found; +} + /* 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) +pph_read_any_tree (pph_stream *stream, tree *chain) { struct lto_input_block *ib = stream->encoder.r.ib; struct data_in *data_in = stream->encoder.r.data_in; @@ -2105,18 +2224,8 @@ pph_read_namespace_tree (pph_stream *str /* 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; - } - } + if (chain) + expr = pph_merge_into_chain (stream, expr, chain); } gcc_assert (marker == PPH_RECORD_START @@ -2158,30 +2267,38 @@ pph_read_namespace_tree (pph_stream *str } -/* Read a chain of tree nodes from input block IB. DATA_IN contains - tables and descriptors for the file being read. */ +/* Callback for reading ASTs from a stream. Instantiate and return a + new tree from the PPH stream in DATA_IN. */ tree -pph_read_namespace_chain (pph_stream *stream, tree enclosing_namespace) +pph_read_tree (struct lto_input_block *ib_unused ATTRIBUTE_UNUSED, + struct data_in *root_data_in) +{ + /* Find data. */ + pph_stream *stream = (pph_stream *) root_data_in->sdata; + return pph_read_any_tree (stream, NULL); +} + + +/* Read a mergeable tree from STREAM into CHAIN. */ + +tree +pph_read_mergeable_tree (pph_stream *stream, tree *chain) +{ + return pph_read_any_tree (stream, chain); +} + + +/* Read a chain of tree nodes from STREAM. */ + +void +pph_read_mergeable_chain (pph_stream *stream, tree *chain) { 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; + pph_in_mergeable_tree (stream, chain); } Index: gcc/cp/pt.c =================================================================== --- gcc/cp/pt.c (revision 179580) +++ gcc/cp/pt.c (working copy) @@ -20243,7 +20243,7 @@ pph_in_pending_templates_list (pph_strea { struct pending_template *pt; if (flag_pph_debug >= 2) - fprintf (stderr, "loading %d pending templates\n", count ); + fprintf (pph_logfile, "PPH: loading %d pending templates\n", count ); pt = ggc_alloc_pending_template (); pt->next = NULL; pt->tinst = pph_in_tinst_level (stream); Index: gcc/cp/pph-streamer-out.c =================================================================== --- gcc/cp/pph-streamer-out.c (revision 179580) +++ gcc/cp/pph-streamer-out.c (working copy) @@ -584,11 +584,10 @@ pph_out_tree_vec (pph_stream *stream, VE } -/* Write all the trees (from ENCLOSING_NAMESPACE) in VEC V to STREAM. */ +/* Write all the trees in VEC V to STREAM. */ static void -pph_out_namespace_tree_vec (pph_stream *stream, VEC(tree,gc) *v, - tree enclosing_namespace) +pph_out_mergeable_tree_vec (pph_stream *stream, VEC(tree,gc) *v) { unsigned i; tree t; @@ -600,7 +599,7 @@ pph_out_namespace_tree_vec (pph_stream * 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); + pph_out_mergeable_tree (stream, t); } @@ -632,37 +631,6 @@ 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 @@ -752,33 +720,37 @@ 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. */ +/* Emit the links of a chain to the STREAM in reverse order + from the ENCLOSING_NAMESPACE starting at T. */ -void -pph_write_namespace_chain (pph_stream *stream, tree t, tree enclosing_namespace) +static void +pph_write_mergeable_links (pph_stream *stream, tree t) { - int i, count; + tree next_link; + if (!t) + return; - count = list_length (t); - streamer_write_hwi (stream->encoder.w.ob, count); - for (i = 0; i < count; i++) - { - tree saved_chain; + next_link = TREE_CHAIN (t); + pph_write_mergeable_links (stream, next_link); - /* Clear TREE_CHAIN to avoid blindly recursing into the rest - of the list. */ - saved_chain = TREE_CHAIN (t); - TREE_CHAIN (t) = NULL_TREE; + /*FIXME pph: Is this circumlocution still needed? */ + TREE_CHAIN (t) = NULL_TREE; - pph_write_namespace_tree (stream, t, enclosing_namespace); + pph_out_mergeable_tree (stream, t); - TREE_CHAIN (t) = saved_chain; - t = TREE_CHAIN (t); - } + TREE_CHAIN (t) = next_link; +} + + +/* Emit the chain of tree nodes from ENCLOSING_NAMESPACE starting at T + to STREAM. */ + +void +pph_write_mergeable_chain (pph_stream *stream, tree t) +{ + int count = list_length (t); + streamer_write_hwi (stream->encoder.w.ob, count); + pph_write_mergeable_links (stream, t); } @@ -814,8 +786,8 @@ pph_out_chain_filtered (pph_stream *stre 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) +pph_out_mergeable_chain_filtered (pph_stream *stream, tree first, + unsigned filter) { tree t; VEC(tree, heap) *to_write = NULL; @@ -824,7 +796,7 @@ pph_out_namespace_chain_filtered (pph_st faster to just call pph_out_chain directly. */ if (filter == PPHF_NONE) { - pph_out_namespace_chain (stream, first, enclosing_namespace); + pph_out_mergeable_chain (stream, first); return; } @@ -834,8 +806,7 @@ pph_out_namespace_chain_filtered (pph_st VEC_safe_push (tree, heap, to_write, t); /* Write them. */ - pph_out_namespace_tree_vec (stream, (VEC(tree,gc) *)to_write, - enclosing_namespace); + pph_out_mergeable_tree_vec (stream, (VEC(tree,gc) *)to_write); VEC_free (tree, heap, to_write); } @@ -857,25 +828,20 @@ pph_out_binding_level_1 (pph_stream *str 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); + pph_out_mergeable_chain_filtered (stream, bl->names, aux_filter); + pph_out_mergeable_chain_filtered (stream, bl->namespaces, aux_filter); + pph_out_mergeable_chain_filtered (stream, bl->usings, aux_filter); + pph_out_mergeable_chain_filtered (stream, bl->using_directives, + 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_tree_vec_filtered (stream, bl->static_decls, 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) @@ -1770,6 +1736,7 @@ pph_out_tcc_declaration (pph_stream *str pph_out_tree (stream, DECL_INITIAL (decl)); /* The tree streamer only writes DECL_CHAIN for PARM_DECL nodes. */ + /* FIXME pph: almost redundant. */ if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL) pph_out_tree (stream, DECL_CHAIN (decl)); @@ -1814,6 +1781,7 @@ pph_out_tcc_type (pph_stream *stream, tr pph_out_tree (stream, TYPE_NEXT_VARIANT (type)); /* FIXME pph - Streaming TYPE_CANONICAL generates many type comparison failures. Why? */ + /* FIXME pph: apparently redundant. */ pph_out_tree (stream, TREE_CHAIN (type)); /* The type values cache is built as constants are instantiated, @@ -2081,19 +2049,10 @@ pph_write_tree_header (pph_stream *strea } -/* Callback for writing ASTs to a stream. Write EXPR to the PPH stream - in OB. */ - -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); -} +/* Write a tree EXPR (MERGEABLE or not) to STREAM. */ void -pph_write_namespace_tree (pph_stream *stream, tree expr, - tree enclosing_namespace ) +pph_write_any_tree (pph_stream *stream, tree expr, bool mergeable) { enum pph_record_marker marker; @@ -2132,14 +2091,14 @@ pph_write_namespace_tree (pph_stream *st state of an existing tree, then we only need to write its body. */ pph_write_tree_header (stream, expr); - if (enclosing_namespace && DECL_P (expr)) + if (mergeable && DECL_P (expr)) { /* We may need to unify two declarations. */ - /* FIXME crowl: pph_out_location (stream, DECL_SOURCE_LOCATION (expr)); */ + 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)); + IDENTIFIER_LENGTH (name)); else pph_out_string (stream, NULL); } @@ -2152,6 +2111,23 @@ pph_write_namespace_tree (pph_stream *st } +/* Callback for writing ASTs to a stream. Write EXPR to the PPH stream + in OB. */ + +void +pph_write_tree (struct output_block *ob, tree expr, bool ref_p ATTRIBUTE_UNUSED) +{ + pph_stream *stream = (pph_stream *) ob->sdata; + pph_write_any_tree (stream, expr, false); +} + +void +pph_write_mergeable_tree (pph_stream *stream, tree expr) +{ + pph_write_any_tree (stream, expr, true); +} + + /* Add DECL to the symbol table for pph_out_stream. ACTION determines how DECL should be presented to the middle-end when reading this image. TOP_LEVEL and AT_END are as in rest_of_decl_compilation. */ Index: gcc/cp/pph-streamer.h =================================================================== --- gcc/cp/pph-streamer.h (revision 179580) +++ gcc/cp/pph-streamer.h (working copy) @@ -336,8 +336,8 @@ unsigned pph_get_signature (tree, size_t 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_write_mergeable_tree (pph_stream *, tree); +void pph_write_mergeable_chain (pph_stream *, 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); @@ -352,8 +352,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); +tree pph_read_mergeable_tree (pph_stream *, tree *); +void pph_read_mergeable_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); @@ -473,22 +473,13 @@ pph_out_tree (pph_stream *stream, tree t } /* 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_mergeable_tree (pph_stream *stream, tree t) { - pph_out_namespace_tree_1 (stream, t, 2, enclosing_namespace); + if (flag_pph_tracer >= 2) + pph_trace_tree (stream, t); + pph_write_mergeable_tree (stream, t); } /* Write an unsigned int VALUE to STREAM. */ @@ -574,12 +565,11 @@ pph_out_chain (pph_stream *stream, tree /* 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) +pph_out_mergeable_chain (pph_stream *stream, tree first) { if (flag_pph_tracer >= 2) pph_trace_chain (stream, first); - pph_write_namespace_chain (stream, first, enclosing_namespace); + pph_write_mergeable_chain (stream, first); } /* Write a bitpack BP to STREAM. */ @@ -676,13 +666,12 @@ pph_in_tree (pph_stream *stream) /* 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) +static inline void +pph_in_mergeable_tree (pph_stream *stream, tree *chain) { - tree t = pph_read_namespace_tree (stream, enclosing_namespace); - if (flag_pph_tracer >= 4) + tree t = pph_read_mergeable_tree (stream, chain); + if (flag_pph_tracer >= 3) pph_trace_tree (stream, t); - return t; } /* Load into an array A of cardinality C of AST from STREAM. */ @@ -731,14 +720,11 @@ 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) +/* Read and merge a chain of ASTs from STREAM into an existing CHAIN. */ +static inline void +pph_in_mergeable_chain (pph_stream *stream, tree* chain) { - tree t = pph_read_namespace_chain (stream, enclosing_namespace); - if (flag_pph_tracer >= 2) - pph_trace_chain (stream, t); - return t; + pph_read_mergeable_chain (stream, chain); } /* Read a bitpack from STREAM. */