Re-adding gcc-patches (forgot to send plain text last time...sigh!)

On Tue, Jul 12, 2011 at 10:56 AM, Gabriel Charette <gch...@google.com> wrote:
> I like this implementation!
> Only one thing, if we ACTUALLY want "to_register" NULL instead of the read
> value we can't as in your current implementation NULL means don't do the
> alternate registration.
> Could that be a problem or do we expect the structures we pass to this to
> always be non-null? (i.e. for scope_chain->bindings this is definitely ok,
> but what about other potential uses?), if we keep it this way we should at
> least make it clear in the function's comment that NULL means don't do
> alternate registration I think.
> Gab
>
> On Mon, Jul 11, 2011 at 2:42 PM, Diego Novillo <dnovi...@google.com> wrote:
>>
>> This patch adapts an idea from Gab that allow us to register alternate
>> addresses in the cache.  The problem here is making sure that symbols
>> read from a PPH file reference the right bindings.
>>
>> If a symbol is in the global namespace when compiling a header file,
>> its bindings will point to NAMESPACE_LEVEL(global_namespace)->bindings,
>> but that global_namespace is the global_namespace instantiated for the
>> header file.  When reading that PPH image from a translation unit, we
>> need to refer to the bindings of the *current* global_namespace.
>>
>> In general we solve this by inserting the pointer in the streamer
>> cache.  For instance, to avoid instantiating a second global_namespace
>> decl, the initialization code of both the writer and the reader store
>> global_namespace into the streaming cache.  This way, all the
>> references to global_namespace point to the current global_namespace
>> as known by the writer and the reader.
>>
>> However, we cannot use the same trick on the bindings for
>> global_namespace.  If we simply inserted it into the cache then
>> writing out NAMESPACE_LEVEL(global_namespace)->bindings would simply
>> write a reference to the current one and on the reader side, it would
>> simply restore a pointer to the current translation unit's bindings.
>> Without ever actually writing or reading anything (since it was
>> satisified from the cache).
>>
>> Therefore, we want a mechanism that allows the reader to: (a) read all
>> the symbols in the global bindings, and (b) references to the
>> global binding made by the symbols should point to the global bindings
>> of the current translation unit (instead of the one in the PPH image).
>>
>> That's where ALLOC_AND_REGISTER_ALTERNATE comes in.  When called, it
>> allocates the data structure but registers another pointer in the
>> cache.  We use this trick when calling pph_in_binding_level from the
>> toplevel:
>>
>> +  new_bindings = pph_in_binding_level (stream, scope_chain->bindings);
>>
>> This way, when pph_in_binding_level tries to allocate the binding
>> structure read from STREAM, it registers scope_chain->bindings in the
>> cache.  This way, references to the original file's global binding are
>> automatically redirected to the current translation unit's global
>> bindings.
>>
>> Gab, I modified your original implementation to move all the logic to
>> the place where we need to make this decision.  This way, it is easier
>> to tell which functions need this alternate registration, instead of
>> relying on some status flag squirreled away in the STREAM data
>> structure.
>>
>>
>> Tested on x86_64.  Applied to branch.
>>
>> 2011-07-11   Diego Novillo  <dnovi...@google.com>
>>             Gabriel Charette  <gch...@google.com>
>>
>>        * pph-streamer-in.c (ALLOC_AND_REGISTER_ALTERNATE): Define.
>>        (pph_in_binding_level): Add argument TO_REGISTER.  Call
>>        ALLOC_AND_REGISTER_ALTERNATE if set.
>>        Update all users.
>>        (pph_register_decls_in_symtab): Call varpool_finalize_decl
>>        on all file-local symbols.
>>        (pph_in_scope_chain): Call pph_in_binding_level with
>>        scope_chain->bindings as the alternate pointer to
>>        register in the streaming cache.
>>
>> diff --git a/gcc/cp/ChangeLog.pph b/gcc/cp/ChangeLog.pph
>> index 1011902..f18c2f4 100644
>> --- a/gcc/cp/ChangeLog.pph
>> +++ b/gcc/cp/ChangeLog.pph
>> @@ -1,3 +1,16 @@
>> +2011-07-11   Diego Novillo  <dnovi...@google.com>
>> +            Gabriel Charette  <gch...@google.com>
>> +
>> +       * pph-streamer-in.c (ALLOC_AND_REGISTER_ALTERNATE): Define.
>> +       (pph_in_binding_level): Add argument TO_REGISTER.  Call
>> +       ALLOC_AND_REGISTER_ALTERNATE if set.
>> +       Update all users.
>> +       (pph_register_decls_in_symtab): Call varpool_finalize_decl
>> +       on all file-local symbols.
>> +       (pph_in_scope_chain): Call pph_in_binding_level with
>> +       scope_chain->bindings as the alternate pointer to
>> +       register in the streaming cache.
>> +
>>  2011-07-07   Diego Novillo  <dnovi...@google.com>
>>
>>        * pph-streamer-in.c (pph_register_decls_in_symtab): Rename
>> diff --git a/gcc/cp/pph-streamer-in.c b/gcc/cp/pph-streamer-in.c
>> index 571ebf5..903cd94 100644
>> --- a/gcc/cp/pph-streamer-in.c
>> +++ b/gcc/cp/pph-streamer-in.c
>> @@ -42,6 +42,18 @@ along with GCC; see the file COPYING3.  If not see
>>       pph_register_shared_data (STREAM, DATA, IX);             \
>>     } while (0)
>>
>> +/* Same as ALLOC_AND_REGISTER, but instead of registering DATA into the
>> +   cache at slot IX, it registers ALT_DATA.  Used to support mapping
>> +   pointers to global data in the original STREAM that need to point
>> +   to a different instance when aggregating individual PPH files into
>> +   the current translation unit (see pph_in_binding_level for an
>> +   example).  */
>> +#define ALLOC_AND_REGISTER_ALTERNATE(STREAM, IX, DATA, ALLOC_EXPR,
>> ALT_DATA)\
>> +    do {                                                               \
>> +      (DATA) = (ALLOC_EXPR);                                           \
>> +      pph_register_shared_data (STREAM, ALT_DATA, IX);                 \
>> +    } while (0)
>> +
>>  /* Callback for unpacking value fields in ASTs.  BP is the bitpack
>>    we are unpacking from.  EXPR is the tree to unpack.  */
>>
>> @@ -482,7 +494,8 @@ pph_in_qual_use_vec (pph_stream *stream)
>>
>>
>>  /* Forward declaration to break cyclic dependencies.  */
>> -static struct cp_binding_level *pph_in_binding_level (pph_stream *);
>> +static struct cp_binding_level *pph_in_binding_level (pph_stream *,
>> +                                                   struct
>> cp_binding_level *);
>>
>>  /* Helper for pph_in_cxx_binding.  Read and return a cxx_binding
>>    instance from STREAM.  */
>> @@ -505,7 +518,7 @@ pph_in_cxx_binding_1 (pph_stream *stream)
>>   value = pph_in_tree (stream);
>>   type = pph_in_tree (stream);
>>   ALLOC_AND_REGISTER (stream, ix, cb, cxx_binding_make (value, type));
>> -  cb->scope = pph_in_binding_level (stream);
>> +  cb->scope = pph_in_binding_level (stream, NULL);
>>   bp = pph_in_bitpack (stream);
>>   cb->value_is_inherited = bp_unpack_value (&bp, 1);
>>   cb->is_local = bp_unpack_value (&bp, 1);
>> @@ -581,10 +594,26 @@ pph_in_label_binding (pph_stream *stream)
>>  }
>>
>>
>> -/* Read and return an instance of cp_binding_level from STREAM.  */
>> +/* Read and return an instance of cp_binding_level from STREAM.
>> +   TO_REGISTER is used when the caller wants to read a binding level,
>> +   but register a different binding level in the streaming cache.
>> +   This is needed when reading the binding for global_namespace.
>> +
>> +   When the file was created global_namespace was localized to that
>> +   particular file.  However, when instantiating a PPH file into
>> +   memory, we are now using the global_namespace for the current
>> +   translation unit.  Therefore, every reference to the
>> +   global_namespace and its bindings should be pointing to the
>> +   CURRENT global namespace, not the one in STREAM.
>> +
>> +   Therefore, if TO_REGISTER is set, and we read a binding level from
>> +   STREAM for the first time, instead of registering the newly
>> +   instantiated binding level into the cache, we register the binding
>> +   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 struct cp_binding_level *
>> -pph_in_binding_level (pph_stream *stream)
>> +pph_in_binding_level (pph_stream *stream, struct cp_binding_level
>> *to_register)
>>  {
>>   unsigned i, num, ix;
>>   struct cp_binding_level *bl;
>> @@ -597,7 +626,14 @@ pph_in_binding_level (pph_stream *stream)
>>   else if (marker == PPH_RECORD_SHARED)
>>     return (struct cp_binding_level *) pph_in_shared_data (stream, ix);
>>
>> -  ALLOC_AND_REGISTER (stream, ix, bl, ggc_alloc_cleared_cp_binding_level
>> ());
>> +  /* If TO_REGISTER is set, register that binding level instead of the
>> newly
>> +     allocated binding level into slot IX.  */
>> +  if (to_register == NULL)
>> +    ALLOC_AND_REGISTER (stream, ix, bl,
>> ggc_alloc_cleared_cp_binding_level ());
>> +  else
>> +    ALLOC_AND_REGISTER_ALTERNATE (stream, ix, bl,
>> +                                 ggc_alloc_cleared_cp_binding_level (),
>> +                                 to_register);
>>
>>   bl->names = pph_in_chain (stream);
>>   bl->namespaces = pph_in_chain (stream);
>> @@ -627,7 +663,7 @@ pph_in_binding_level (pph_stream *stream)
>>
>>   bl->blocks = pph_in_chain (stream);
>>   bl->this_entity = pph_in_tree (stream);
>> -  bl->level_chain = pph_in_binding_level (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);
>>   bl->binding_depth = pph_in_uint (stream);
>> @@ -713,7 +749,7 @@ pph_in_language_function (pph_stream *stream)
>>
>>   /* FIXME pph.  We are not reading lf->x_named_labels.  */
>>
>> -  lf->bindings = pph_in_binding_level (stream);
>> +  lf->bindings = pph_in_binding_level (stream, NULL);
>>   lf->x_local_names = pph_in_tree_vec (stream);
>>
>>   /* FIXME pph.  We are not reading lf->extern_decl_map.  */
>> @@ -854,7 +890,7 @@ pph_in_struct_function (pph_stream *stream, tree decl)
>>  static void
>>  pph_in_ld_ns (pph_stream *stream, struct lang_decl_ns *ldns)
>>  {
>> -  ldns->level = pph_in_binding_level (stream);
>> +  ldns->level = pph_in_binding_level (stream, NULL);
>>  }
>>
>>
>> @@ -1140,10 +1176,10 @@ pph_in_lang_type (pph_stream *stream)
>>
>>
>>  /* Register all the symbols in binding level BL in the callgraph symbol
>> -   table.  NS is the namespace where all the symbols in BL live.  */
>> +   table.  */
>>
>>  static void
>> -pph_register_decls_in_symtab (struct cp_binding_level *bl, tree ns)
>> +pph_register_decls_in_symtab (struct cp_binding_level *bl)
>>  {
>>   tree t;
>>
>> @@ -1153,18 +1189,16 @@ pph_register_decls_in_symtab (struct
>> cp_binding_level *bl, tree ns)
>>   bl->namespaces = nreverse (bl->namespaces);
>>
>>   for (t = bl->names; t; t = DECL_CHAIN (t))
>> -    if (DECL_NAME (t) && IDENTIFIER_NAMESPACE_BINDINGS (DECL_NAME (t)))
>> -      {
>> -       cxx_binding *b = IDENTIFIER_NAMESPACE_BINDINGS (DECL_NAME (t));
>> -       b->scope = NAMESPACE_LEVEL (ns);
>> -
>> -       if (TREE_CODE (t) == VAR_DECL && TREE_STATIC (t) && !DECL_EXTERNAL
>> (t))
>> -         varpool_finalize_decl (t);
>> -      }
>> +    {
>> +      /* Add file-local symbols to the varpool.  */
>> +      if (TREE_CODE (t) == VAR_DECL && TREE_STATIC (t) && !DECL_EXTERNAL
>> (t))
>> +       varpool_finalize_decl (t);
>> +    }
>>
>> +  /* Recurse into the namespaces contained in BL.  */
>>   for (t = bl->namespaces; t; t = DECL_CHAIN (t))
>>     if (NAMESPACE_LEVEL (t))
>> -      pph_register_decls_in_symtab (NAMESPACE_LEVEL (t), t);
>> +      pph_register_decls_in_symtab (NAMESPACE_LEVEL (t));
>>  }
>>
>>
>> @@ -1173,18 +1207,21 @@ pph_register_decls_in_symtab (struct
>> cp_binding_level *bl, tree ns)
>>  static void
>>  pph_in_scope_chain (pph_stream *stream)
>>  {
>> -  struct saved_scope *file_scope_chain;
>>   unsigned i;
>>   tree decl;
>>   cp_class_binding *cb;
>>   cp_label_binding *lb;
>>   struct cp_binding_level *cur_bindings, *new_bindings;
>>
>> -  file_scope_chain = ggc_alloc_cleared_saved_scope ();
>> -  file_scope_chain->bindings = new_bindings = pph_in_binding_level
>> (stream);
>> +  /* When reading the symbols in STREAM's global binding level, make
>> +     sure that references to the global binding level point to
>> +     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_register_decls_in_symtab (new_bindings, global_namespace);
>> +  /* Register all the symbols in STREAM with the call graph.  */
>> +  pph_register_decls_in_symtab (new_bindings);
>>
>>   /* Merge the bindings from STREAM into saved_scope->bindings.  */
>>   chainon (cur_bindings->names, new_bindings->names);
>>
>>
>> --
>> This patch is available for review at
>> http://codereview.appspot.com/4685054
>
>

Reply via email to