Jason,

We are having several issues re-instantiating symbols and
namespaces from a pph image.  We are not handling all the cases
and the contortions we are going through are getting increasingly
bizarre.  Perhaps you could give us a few pointers?

When we write the contents of a header file into an image, we do
the following in pph_write_file_contents
(http://gcc.gnu.org/viewcvs/branches/pph/gcc/cp/pph-streamer-out.c?view=markup):


static void
pph_write_file_contents (pph_stream *stream, cpp_idents_used *idents_used)
{ 
  pph_out_identifiers (stream, idents_used);
  pph_out_scope_chain (stream, scope_chain, false);
  if (flag_pph_dump_tree)
    pph_dump_namespace (pph_logfile, global_namespace);
  pph_out_tree (stream, keyed_classes, false);
  pph_out_tree_vec (stream, unemitted_tinfo_decls, false);
  pph_out_tree (stream, static_aggregates, false);
}

In pph_out_scope_chain, we simply pickle out the contents of
scope_chain->bindings.

When compiling the translation unit, we read and merge a pph
image in pph_read_file_contents
(http://gcc.gnu.org/viewcvs/branches/pph/gcc/cp/pph-streamer-in.c?view=markup). 

When re-building scope_chain->bindings, we call pph_add_bindings,
which will add everything under the file's scope_chain->bindings
into the current translation unit global_namespace.

This is currently pretty hacky, we are calling some symbol
registration functions that I'm not sure are completely right.
So we have various assembly miscomparisons, strange duplicate
declaration errors and outright ICEs.  The code currently does:

static void
pph_add_bindings_to_namespace (struct cp_binding_level *bl, tree ns)
{
  tree t, chain;

  /* The chains are built backwards (ref: add_decl_to_level),
     reverse them before putting them back in.  */
  bl->names = nreverse (bl->names);
  bl->namespaces = nreverse (bl->namespaces);

  for (t = bl->names; t; t = chain)
    {
      /* Pushing a decl into a scope clobbers its DECL_CHAIN.
         Preserve it.  */
      chain = DECL_CHAIN (t);
      pushdecl_into_namespace (t, ns);

      if (TREE_CODE (t) == VAR_DECL && TREE_STATIC (t) && !DECL_EXTERNAL (t))
        varpool_finalize_decl (t);
    }

  for (t = bl->namespaces; t; t = chain)
    {
      /* Pushing a decl into a scope clobbers its DECL_CHAIN.
         Preserve it.  */
      chain = DECL_CHAIN (t);
      pushdecl_into_namespace (t, ns);
      if (NAMESPACE_LEVEL (t))
        pph_add_bindings_to_namespace (NAMESPACE_LEVEL (t), t);
    }
}

and we call it with global_namespace the first time.  The call to
pushdecl_into_namespace is mostly a wrapper around
pushdecl_with_scope:

tree
pushdecl_into_namespace (tree dcl, tree nsp)
{
  tree ret;
  /* FIXME pph: There might be a better way to do this...  */
  struct cp_binding_level *level = NAMESPACE_LEVEL (nsp);
  tree saved = current_namespace;
  current_namespace = nsp;
#if 0
  ret = pushdecl_maybe_friend (dcl, /*is_friend=*/false);
#else
  ret = pushdecl_with_scope (dcl, level, /*is_friend=*/false);
#endif
  current_namespace = saved;
  return ret;
}

I've been looking around in the parser, and it seems to use a
variety of different symbol registration routines.  I think all
this reconstruction we are doing needs to be re-written, it is
quite hacky and incomplete.

Is there a canonical way that we should use to rebuild the
elements from scope_chain->bindings?  Could we not simply add
them to the current translation unit's scope_chain->bindings
as-is, instead of doing all these pushdecl calls?

When we read the PPH file back in we do need to create varpool
entries for some symbols so they get processed by the callgraph,
but I'm not sure what's the best way to go about that.


Thanks.  Diego.

Reply via email to