This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] cleanup frontend GC memory (decls and types)


Hi,

I'm not 100% sure what to make of this and if it's even worthwhile to 
continue on this path, so I'm asking for comments.  Anyway, what I wanted 
to look at is to reduce the memory overhead of the (C++) frontend, after 
it is basically done with it's work, i.e. at the end of the IPA passes.

The way to reach this is fairly trivial: basically zero out all pointers 
of everything which might hold frontend specific data, and let garbage 
collection do it's job.  As I did this for the C++ frontend my goal simply 
was to not have any tree lefts marked which have "to do with templates", 
as those surely are not necessary after parsing.

So, I first created a GC mark_hook for trees, printing out which tree got 
marked and then started to gradually zero out more stuff until the string 
"template" didn't occur anymore in the output.

My testcases were the icecream scheduler (a normal C++ program using STL) 
as small but realistic test and tramp3d as horrible test :-)  I 
concentrated on the memory use at -O0.

The results are quite promising actually, roughly saving 40% to 50% of all 
GCed memory at the end of IPA passes (i.e. before vs. after zeroing stuff 
and ggc_collect()).  The memory saving results in detail is (on x86-64):

-O0 scheduler.ii 31M -> 15M (memreport ^size)
-O0 tramp3d-v4.ii 269M -> 133M (memreport ^size)
-O1 tramp3d-v4.ii 463M -> 256M (memreport ^size)
-O1 tramp3d-v4.ii 1024559 -> 854607 (max memory use at compilation, 
                               measured via tracking mmap())

With this patch no template related type tree remains.  As you can see in 
the patch I introduced also a global uid2type hash tables (simply 
collecting all types), on top of Richards uid2decl hash table, which gives 
us a way to simply iterate over all types ever created, in addition to the 
already existing possibility to iterate over all identifiers and all 
decls.

Then I iterate over all things (identifiers, types and decls) and zero out 
several fields, fixing, adjusting or hacking up other places in the 
compiler which then fail.  There aren't that many places which really 
still need to look at language specifics after the frontend is done.  All 
these places will be a problem for LTO, so in part this investigation also 
shows where the problems for LTO will lie.  I haven't looked at the LTO 
branch to see if any of these problems are tackled already there.

In particular these are the problematic areas (for C++):
1) debug generation:
   the debug routines call back into the frontend in several places, e.g. 
   to determine if a RECORD_TYPE wasn't really a class and the like.  
   Possibly it also iterates over members of namespaces.  
   Anyway, I didn't much care for debug info, because I already knew it 
   would be a hard problem.  Like it will be for LTO.  We simply have to 
   generate debug information early, there's no real way around this.

2) mangling:
   the mangled names currenly are generated on demand while expanding from 
   tree to RTL (calling back into the frontend of course).  This can't 
   stay anyway for LTO.  Solution is simple: mangle every "interesting" 
   DECL before zeroing lang specifics.  This of course increases the 
   string pool somewhat, but in the end most of these symbols would have 
   become mangled anyway.  Some symbols are mangled although they later 
   would be found to be unused (although after IPA passes there isn't 
   _that_ much opportunity to prune the list even more)

3) thunks for virtual function:
   Again a problem for LTO.  Currently the thunks for a function are 
   emitted from the frontend, exactly when the function itself is emitted
   (as RTL).  The frontend does some analysis of thunks beforehand 
   already, but I simply deactivated emission of thunks for my experiment.
   This needs to be done before IPA, either by making thunks a middle-end
   concept, or implementing alternate entry points for real.

4) expr_size langhook:
   That's somewhat ugly.  It's called from the tree->RTL expanders when 
   one argument of a move has BLKmode.  The C++ frontend uses it to handle 
   class types specially, namely to exclude padding at the end of classes.  
   I.e. in a way there are two sizes for a class type: the full size 
   including padding (simply TYPE_SIZE(t)) and the size excluding padding,
   which is TYPE_SIZE(CLASSTYPE_AS_BASE(t)).  This size can be calculated
   before knowledge of CLASSTYPE_AS_BASE() (which is lang specific) goes 
   away, but it couldn't be stored anywhere.

   But for LTO this same problem exists.  It could be solved by either
   emitting a struct copy with types adjusted to be CLASSTYPE_AS_BASE 
   (then the RTL expander simply can use TYPE_SIZE), or by storing the 
   "real" size of the copy somewhere else.  I lean towards the former,
   as the middle end, when it sees a struct copy should have to jump 
   through hoops to find out the copy size.  There's also the 
   WITH_SIZE_EXPR, which could be used.

   For now I hacked around this by simply answering the size including 
   padding, when lang specifics aren't available anymore.

5) determining availability of varpool decls:
   when all functions are emitted (i.e. after the complete pipeline, not 
   after only IPA is done) varpool_remove_unreferenced_decls() is called, 
   which resets all decls to be unused, and then walks the whole tree to 
   determine still used decls.  This includes calling back into the 
   frontend, and can't be done with LTO.  In particular it wants to mark
   all vtables if one vtable is emitted, the vtables are not available 
   anymore when langspecifics aren't.  For now I simply deactivated 
   varpool_remove_unreferenced_decls, i.e. even unused decls are emitted
   (i.e. those still used after IPA, but found unused after the whole 
   pipeline which shouldn't occurr too often).

6) generating warnings via frontend specific walking:
   cp_write_global_declarations() likes to call cgraph_optimize() before
   emitting all warnings (for which it wants to walk all namespaces) or 
   fully generating debug info.  For now I deactivated this.  The order 
   here needs to be changed for LTO anyway.

7) debug dumping:
   well, some frontend specific functions don't expect missing 
   lang-specifics and crash.  Just making the functions in question robust 
   enough helps.

Yeah, I think that's it.  Much to my amazement even with the above hacks 
(no thunks and the expr_size hack) tramp3d still runs, just needs less 
memory for compilation :-)

Here's the patch for the curious (it applies to r132679, in particular 
needs Richis decl-uid map).  Any suggestions how to move forward with 
the above problems?  Anyone wants to tackle problem (1)? :-)


Ciao,
Michael.
Index: tree.c
===================================================================
--- tree.c	(revision 132679)
+++ tree.c	(working copy)
@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3.  
 #include "params.h"
 #include "pointer-set.h"
 #include "fixed-value.h"
+#include "cpplib.h"
 
 /* Each tree code class has an associated string representation.
    These must correspond to the tree_code_class entries.  */
@@ -113,8 +114,13 @@ static GTY(()) int next_type_uid = 1;
 /* Mapping from unique DECL_UID to the decl tree node.  */
 static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
      htab_t decl_for_uid_map;
+static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
+     htab_t uid2type_map;
 
+static int uid_type_map_eq (const void *va, const void *vb);
+static unsigned int uid_type_map_hash (const void *item);
 static void insert_decl_to_uid_decl_map (tree);
+static void insert_type_to_uid_type_map (tree);
 
 /* Since we cannot rehash a type after it is in the table, we have to
    keep the hash code.  */
@@ -239,6 +245,8 @@ init_ttree (void)
 
   decl_for_uid_map = htab_create_ggc (4093, uid_decl_map_hash,
 				      uid_decl_map_eq, NULL);
+  uid2type_map = htab_create_ggc (4093, uid_type_map_hash,
+				      uid_type_map_eq, NULL);
 
   tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON] = 1;
   tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_NON_COMMON] = 1;
@@ -627,6 +635,7 @@ make_node_stat (enum tree_code code MEM_
 
       /* We have not yet computed the alias set for this type.  */
       TYPE_ALIAS_SET (t) = -1;
+      insert_type_to_uid_type_map (t);
       break;
 
     case tcc_constant:
@@ -733,6 +742,7 @@ copy_node_stat (tree node MEM_STAT_DECL)
 	  TYPE_CACHED_VALUES_P (t) = 0;
 	  TYPE_CACHED_VALUES (t) = NULL_TREE;
 	}
+      insert_type_to_uid_type_map (t);
     }
 
   return t;
@@ -3350,6 +3360,21 @@ uid_decl_map_hash (const void *item)
   return ((const_tree)item)->decl_minimal.uid;
 }
 
+static int
+uid_type_map_eq (const void *va, const void *vb)
+{
+  const_tree a = (const_tree) va;
+  const_tree b = (const_tree) vb;
+  return (a->type.uid == b->type.uid);
+}
+
+/* Hash a tree in a uid_decl_map.  */
+
+static unsigned int
+uid_type_map_hash (const void *item)
+{
+  return ((const_tree)item)->type.uid;
+}
 /* Insert the declaration NODE into the map mapping its unique uid
    back to the tree.  */
 
@@ -3373,6 +3398,44 @@ insert_decl_to_uid_decl_map (tree node)
   *(tree *)slot = node;
 }
 
+static void
+insert_type_to_uid_type_map (tree node)
+{
+  void **slot;
+  struct tree_type key;
+
+  key.uid = TYPE_UID (node);
+  slot = htab_find_slot_with_hash (uid2type_map,
+				   &key, TYPE_UID (node), INSERT);
+
+#if 1
+  gcc_assert (!*slot);
+#endif
+
+  *(tree *)slot = node;
+}
+
+tree
+lookup_type_from_uid (int uid)
+{
+  struct tree_type key;
+
+  key.uid = uid;
+  return (tree) htab_find_with_hash (uid2type_map, &key, uid);
+}
+
+void
+remove_type_from_map (tree decl)
+{
+  struct tree_type key;
+
+  key.uid = TYPE_UID (decl);
+#if ENABLE_CHECKING
+  gcc_assert (decl == htab_find_with_hash (uid2type_map, &key, key.uid));
+#endif
+  htab_remove_elt_with_hash (uid2type_map, &key, key.uid);
+}
+
 /* Lookup the declaration tree from its unique DECL_UID UID.  Returns
    the tree node with DECL_UID UID or NULL, if this node was collected.  */
 
@@ -3385,6 +3448,149 @@ lookup_decl_from_uid (int uid)
   return (tree) htab_find_with_hash (decl_for_uid_map, &key, uid);
 }
 
+extern void reset_lang_specifics (tree t);
+
+static int
+reset_identifier (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h,
+	    const void *v ATTRIBUTE_UNUSED)
+{
+  tree id = HT_IDENT_TO_GCC_IDENT (h);
+  reset_lang_specifics (id);
+  TREE_TYPE (id) = NULL_TREE;
+  return 1;
+}
+
+static int
+reset_lang_specific (void **slot, void *unused)
+{
+  tree decl = *(tree*)slot;
+  reset_lang_specifics (decl);
+  if (1 || TREE_CODE (decl) != NAMESPACE_DECL)
+    DECL_LANG_SPECIFIC (decl) = NULL;
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      || TREE_CODE (decl) == TYPE_DECL
+      || TREE_CODE (decl) == VAR_DECL
+      || TREE_CODE (decl) == CONST_DECL)
+    TREE_CHAIN (decl) = NULL;
+  return 1;
+}
+
+static int
+reset_type_lang_specific (void **slot, void *unused)
+{
+  tree decl = *(tree*)slot;
+  reset_lang_specifics (decl);
+  switch (TREE_CODE (decl))
+    {
+      case RECORD_TYPE:
+      case UNION_TYPE:
+      case QUAL_UNION_TYPE:
+        {
+	  tree t2 = decl;
+	  while (TYPE_MAIN_VARIANT (t2) && t2 != TYPE_MAIN_VARIANT (t2))
+	    t2 = TYPE_MAIN_VARIANT (t2);
+	  TYPE_METHODS (decl) = NULL_TREE;
+	  if (decl != TREE_TYPE (va_list_type_node)
+	      && (!TYPE_STUB_DECL (t2)
+	          || TREE_CODE (DECL_NAME (TYPE_STUB_DECL (t2))) != IDENTIFIER_NODE
+	          || strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_STUB_DECL (t2))), "__ptrmemfunc_type")))
+	    TYPE_FIELDS (decl) = NULL_TREE;
+	}
+	break;
+      default:
+	TREE_CHAIN (decl) = NULL;
+        break;
+    }
+  TYPE_LANG_SPECIFIC (decl) = NULL;
+  TYPE_NEXT_VARIANT (decl) = NULL;
+  return 1;
+}
+
+static int
+set_asm_name (void **slot, void *unused)
+{
+  tree decl = *(tree*)slot;
+  if (HAS_DECL_ASSEMBLER_NAME_P (decl)
+      && (TREE_CODE (decl) == FUNCTION_DECL
+          || TREE_CODE (decl) == VAR_DECL)
+      && !DECL_ASSEMBLER_NAME_SET_P (decl)
+      && !DECL_IGNORED_P (decl)
+      && (TREE_CODE (decl) != VAR_DECL
+	  || TREE_STATIC (decl)
+	  || TREE_PUBLIC (decl)
+	  || DECL_EXTERNAL (decl)
+	  || DECL_REGISTER (decl)))
+    lang_hooks.set_decl_assembler_name (decl);
+  return 1;
+}
+
+static int
+print_leftover (void **slot, void *unused)
+{
+  tree decl = *(tree*)slot;
+  const char *s;
+  size_t length = tree_size (decl);
+  fprintf (stderr, "%d ", (int)length);
+  if (TREE_CODE (decl) == LABEL_DECL)
+    {
+      fprintf (stderr, "<L%d>:\n", (int) LABEL_DECL_UID (decl));
+    }
+  else if (0 && TREE_CODE (decl) == NAMESPACE_DECL)
+    {
+      fprintf (stderr, "namespace %s\n", IDENTIFIER_POINTER (DECL_NAME (decl)));
+    }
+  else if (DECL_P (decl))
+    {
+      s = lang_hooks.decl_printable_name (decl, 3);
+      fprintf (stderr, "%s ", s);
+      debug_generic_expr (decl);
+    }
+  else
+    {
+      s = lang_hooks.decl_printable_name (decl, 3);
+      fprintf (stderr, "%s ", s);
+      debug_generic_expr (decl);
+    }
+  return 1;
+}
+
+static int phase = 0;
+
+void
+tree_mark_hook (const void *pp)
+{
+  tree t = (tree)pp;
+  if (phase == 0 || !TYPE_P (t))
+    return;
+  const char *s = lang_hooks.decl_printable_name (t, 3);
+  fprintf (stderr, "marking %p %s ", t, s);
+  debug_generic_expr (t);
+}
+
+extern void reset_frontend (void);
+void
+free_lang_specifics (void)
+{
+  htab_traverse (decl_for_uid_map, set_asm_name, NULL);
+  fprintf (stderr, "Memory consumption before free langspecs\n");
+  ggc_force_collect = true;
+  dump_memory_report (false);
+  reset_frontend ();
+  htab_traverse (decl_for_uid_map, reset_lang_specific, NULL);
+  htab_traverse (uid2type_map, reset_type_lang_specific, NULL);
+  ht_forall (ident_hash, reset_identifier, NULL);
+  fprintf (stderr, "Memory consumption after free langspecs\n");
+  phase = 1;
+  ggc_force_collect = true;
+  dump_memory_report (false);
+  ggc_force_collect = false;
+  phase = 0;
+  fprintf (stderr, "Leftover decls:\n");
+  htab_traverse (decl_for_uid_map, print_leftover, NULL);
+  fprintf (stderr, "Leftover types:\n");
+  htab_traverse (uid2type_map, print_leftover, NULL);
+}
+
 /* Remove the declaration tree DECL from the global UID to decl map.
    This needs to be called if you ggc_free a decl tree, otherwise
    garbage collection will take care of it.  */
@@ -3410,6 +3616,10 @@ print_decl_for_uid_map_statistics (void)
 	   (long) htab_size (decl_for_uid_map),
 	   (long) htab_elements (decl_for_uid_map),
 	   htab_collisions (decl_for_uid_map));
+  fprintf (stderr, "TYPE_FOR_UID_MAP hash: size %ld, %ld elements, %f collisions\n",
+	   (long) htab_size (uid2type_map),
+	   (long) htab_elements (uid2type_map),
+	   htab_collisions (uid2type_map));
 }
 
 /* Create a DECL_... node of code CODE, name NAME and data type TYPE.
@@ -7229,6 +7439,14 @@ build_common_tree_nodes (bool signed_cha
   long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
   long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
 
+  void_type_node = make_node (VOID_TYPE);
+  layout_type (void_type_node);
+
+  /* We are not going to have real types in C with less than byte alignment,
+     so we might as well not have any types that claim to have it.  */
+  TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
+  TYPE_USER_ALIGN (void_type_node) = 0;
+
   /* Define a boolean type.  This type only represents boolean values but
      may be larger than char depending on the value of BOOL_TYPE_SIZE.
      Front ends which want to override this size (i.e. Java) can redefine
@@ -7277,14 +7495,6 @@ build_common_tree_nodes_2 (int short_dou
   boolean_false_node = TYPE_MIN_VALUE (boolean_type_node);
   boolean_true_node = TYPE_MAX_VALUE (boolean_type_node);
 
-  void_type_node = make_node (VOID_TYPE);
-  layout_type (void_type_node);
-
-  /* We are not going to have real types in C with less than byte alignment,
-     so we might as well not have any types that claim to have it.  */
-  TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
-  TYPE_USER_ALIGN (void_type_node) = 0;
-
   null_pointer_node = build_int_cst (build_pointer_type (void_type_node), 0);
   layout_type (TREE_TYPE (null_pointer_node));
 
Index: tree.h
===================================================================
--- tree.h	(revision 132679)
+++ tree.h	(working copy)
@@ -2297,6 +2297,7 @@ struct tree_block GTY(())
 
 struct die_struct;
 
+extern void tree_mark_hook (const void *);
 struct tree_type GTY(())
 {
   struct tree_common common;
Index: cgraphunit.c
===================================================================
--- cgraphunit.c	(revision 132679)
+++ cgraphunit.c	(working copy)
@@ -1389,7 +1389,11 @@ cgraph_optimize (void)
     
   /* Don't run the IPA passes if there was any error or sorry messages.  */
   if (errorcount == 0 && sorrycount == 0)
-    ipa_passes ();
+    {
+      extern void free_lang_specifics (void);
+      ipa_passes ();
+      free_lang_specifics ();
+    }
 
   /* This pass remove bodies of extern inline functions we never inlined.
      Do this later so other IPA passes see what is really going on.  */
@@ -1425,7 +1429,7 @@ cgraph_optimize (void)
       cgraph_output_pending_asms ();
 
       cgraph_expand_all_functions ();
-      varpool_remove_unreferenced_decls ();
+      /*varpool_remove_unreferenced_decls ();*/
 
       varpool_assemble_pending_decls ();
       varpool_output_debug_info ();
Index: c-decl.c
===================================================================
--- c-decl.c	(revision 132679)
+++ c-decl.c	(working copy)
@@ -8076,4 +8076,12 @@ c_write_global_declarations (void)
   ext_block = NULL;
 }
 
+void
+reset_lang_specifics (tree t)
+{
+}
+void
+reset_frontend (void)
+{
+}
 #include "gt-c-decl.h"
Index: c-pretty-print.c
===================================================================
--- c-pretty-print.c	(revision 132679)
+++ c-pretty-print.c	(working copy)
@@ -2129,16 +2129,20 @@ pp_c_tree_decl_identifier (c_pretty_prin
 {
   const char *name;
 
-  gcc_assert (DECL_P (t));
-
-  if (DECL_NAME (t))
-    name = IDENTIFIER_POINTER (DECL_NAME (t));
+  if (TREE_CODE (t) == IDENTIFIER_NODE)
+    name = IDENTIFIER_POINTER (t);
   else
     {
-      static char xname[8];
-      sprintf (xname, "<U%4x>", ((unsigned)((unsigned long)(t) & 0xffff)));
-      name = xname;
-    }
+      gcc_assert (DECL_P (t));
 
+      if (DECL_NAME (t))
+	name = IDENTIFIER_POINTER (DECL_NAME (t));
+      else
+	{
+	  static char xname[8];
+	  sprintf (xname, "<U%4x>", ((unsigned)((unsigned long)(t) & 0xffff)));
+	  name = xname;
+	}
+    }
   pp_c_identifier (pp, name);
 }
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 132679)
+++ cp/decl.c	(working copy)
@@ -2859,7 +2859,7 @@ typename_compare (const void * k1, const
 
    Returns the new TYPENAME_TYPE.  */
 
-static GTY ((param_is (union tree_node))) htab_t typename_htab;
+static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node))) htab_t typename_htab;
 
 static tree
 build_typename_type (tree context, tree name, tree fullname,
Index: cp/ptree.c
===================================================================
--- cp/ptree.c	(revision 132679)
+++ cp/ptree.c	(working copy)
@@ -100,6 +100,8 @@ cxx_print_type (FILE *file, tree node, i
     fputs ( "needs-constructor", file);
   if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (node))
     fputs (" needs-destructor", file);
+  if (!TYPE_LANG_SPECIFIC (node))
+    return;
   if (TYPE_HAS_DEFAULT_CONSTRUCTOR (node))
     fputs (" X()", file);
   if (TYPE_HAS_CONVERSION (node))
Index: cp/cp-objcp-common.c
===================================================================
--- cp/cp-objcp-common.c	(revision 132679)
+++ cp/cp-objcp-common.c	(working copy)
@@ -78,7 +78,9 @@ cp_expr_size (const_tree exp)
 {
   tree type = TREE_TYPE (exp);
 
-  if (CLASS_TYPE_P (type))
+  if (CLASS_TYPE_P (type)
+      /* XXX this is wrong.  */
+      && TYPE_LANG_SPECIFIC (type))
     {
       /* The back end should not be interested in the size of an expression
 	 of a type with both of these set; all copies of such types must go
Index: cp/error.c
===================================================================
--- cp/error.c	(revision 132679)
+++ cp/error.c	(working copy)
@@ -492,7 +492,7 @@ dump_aggr_type (tree t, int flags)
 	     the most general template, and use that name.  */
 	  tree tpl = CLASSTYPE_TI_TEMPLATE (t);
 
-	  while (DECL_TEMPLATE_INFO (tpl))
+	  while (DECL_LANG_SPECIFIC (tpl) && DECL_TEMPLATE_INFO (tpl))
 	    tpl = DECL_TI_TEMPLATE (tpl);
 	  name = tpl;
 	}
@@ -1076,11 +1076,17 @@ dump_function_decl (tree t, int flags)
   tree template_parms = NULL_TREE;
   int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS;
   int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
+  int langspec = DECL_LANG_SPECIFIC (t) != 0;
 
   flags &= ~TFF_UNQUALIFIED_NAME;
   if (TREE_CODE (t) == TEMPLATE_DECL)
     t = DECL_TEMPLATE_RESULT (t);
 
+  if (!langspec)
+    {
+      dump_function_name (t, flags);
+      return;
+    }
   /* Pretty print template instantiations only.  */
   if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t))
     {
@@ -2147,7 +2153,12 @@ const char *
 lang_decl_name (tree decl, int v)
 {
   if (v >= 2)
-    return decl_as_string (decl, TFF_DECL_SPECIFIERS);
+    {
+      if (TYPE_P (decl))
+        return type_as_string (decl, TFF_DECL_SPECIFIERS);
+      else
+        return decl_as_string (decl, TFF_DECL_SPECIFIERS);
+    }
 
   reinit_cxx_pp ();
   if (v == 1 && DECL_CLASS_SCOPE_P (decl))
Index: cp/tree.c
===================================================================
--- cp/tree.c	(revision 132679)
+++ cp/tree.c	(working copy)
@@ -949,7 +949,7 @@ copy_binfo (tree binfo, tree type, tree 
    While all these live in the same table, they are completely independent,
    and the hash code is computed differently for each of these.  */
 
-static GTY ((param_is (union tree_node))) htab_t list_hash_table;
+static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node))) htab_t list_hash_table;
 
 struct list_proxy
 {
@@ -2742,6 +2742,49 @@ cast_valid_in_integral_constant_expressi
 	  || type == error_mark_node);
 }
 
+extern void reset_lang_specifics (tree t);
+extern void reset_frontend (void);
+void
+reset_lang_specifics (tree t)
+{
+  if (TREE_CODE (t) == IDENTIFIER_NODE)
+    {
+      IDENTIFIER_NAMESPACE_BINDINGS (t) = 0;
+      IDENTIFIER_BINDING (t) = 0;
+      IDENTIFIER_TEMPLATE (t) = 0;
+      IDENTIFIER_LABEL_VALUE (t) = 0;
+    }
+  if (TREE_CODE (t) == TYPE_DECL)
+    {
+      DECL_FRIENDLIST (t) = 0;
+    }
+  if (TREE_CODE (t) == METHOD_TYPE
+      || TREE_CODE (t) == FUNCTION_TYPE)
+    {
+      /* Default args are not interesting anymore.  */
+      tree argtypes = TYPE_ARG_TYPES (t);
+      while (argtypes)
+        {
+	  TREE_PURPOSE (argtypes) = 0;
+	  argtypes = TREE_CHAIN (argtypes);
+	}
+    }
+  if (TREE_CODE (t) == ENUMERAL_TYPE)
+    ENUM_TEMPLATE_INFO (t) = 0;
+}
+
+void
+reset_frontend (void)
+{
+  scope_chain = NULL;
+  canonical_template_parms = NULL;
+  cplus_array_htab = NULL;
+  local_classes = NULL;
+  extern void reset_abstract_pending_vars (void);
+  reset_abstract_pending_vars ();
+  extern void reset_conv_type_names (void);
+  reset_conv_type_names ();
+}
 
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 /* Complain that some language-specific thing hanging off a tree
Index: cp/mangle.c
===================================================================
--- cp/mangle.c	(revision 132679)
+++ cp/mangle.c	(working copy)
@@ -319,9 +319,13 @@ decl_is_template_id (const tree decl, tr
     }
   else
     {
+      tree tit;
       /* Check if this is a primary template.  */
       if (DECL_LANG_SPECIFIC (decl) != NULL
 	  && DECL_USE_TEMPLATE (decl)
+	  && (tit = DECL_TI_TEMPLATE (decl))
+	  && TREE_CODE (tit) != OVERLOAD
+	  && TREE_CODE (tit) != IDENTIFIER_NODE
 	  && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))
 	  && TREE_CODE (decl) != TEMPLATE_DECL)
 	{
@@ -1226,6 +1230,11 @@ write_number (unsigned HOST_WIDE_INT num
 static inline void
 write_integer_cst (const tree cst)
 {
+  if (TREE_CODE (cst) != INTEGER_CST)
+    {
+      write_unsigned_number (4242424242);
+      return;
+    }
   int sign = tree_int_cst_sgn (cst);
 
   if (TREE_INT_CST_HIGH (cst) + (sign < 0))
@@ -1558,7 +1567,7 @@ write_type (tree type)
 
   MANGLE_TRACE_TREE ("type", type);
 
-  if (type == error_mark_node)
+  if (type == error_mark_node || type == unknown_type_node || type == global_type_node)
     return;
 
   if (find_substitution (type))
@@ -2851,6 +2860,13 @@ mangle_thunk (tree fn_decl, const int th
 
 static GTY ((param_is (union tree_node))) htab_t conv_type_names;
 
+extern void reset_conv_type_names (void);
+void
+reset_conv_type_names (void)
+{
+  conv_type_names = NULL;
+}
+
 /* Hash a node (VAL1) in the table.  */
 
 static hashval_t
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 132679)
+++ cp/cp-tree.h	(working copy)
@@ -533,7 +533,8 @@ enum cp_tree_node_structure_enum {
 
 /* The resulting tree type.  */
 union lang_tree_node GTY((desc ("cp_tree_node_structure (&%h)"),
-       chain_next ("(union lang_tree_node *)GENERIC_NEXT (&%h.generic)")))
+       chain_next ("(union lang_tree_node *)GENERIC_NEXT (&%h.generic)"),
+       mark_hook ("tree_mark_hook")))
 {
   union tree_node GTY ((tag ("TS_CP_GENERIC"),
 			desc ("tree_node_structure (&%h)"))) generic;
@@ -806,6 +807,8 @@ struct saved_scope GTY(())
 /* A list of private types mentioned, for deferred access checking.  */
 
 extern GTY(()) struct saved_scope *scope_chain;
+extern GTY(()) VEC(tree,gc) *canonical_template_parms;
+
 
 struct cxx_int_tree_map GTY(())
 {
Index: cp/cxx-pretty-print.c
===================================================================
--- cp/cxx-pretty-print.c	(revision 132679)
+++ cp/cxx-pretty-print.c	(working copy)
@@ -2121,6 +2121,13 @@ pp_cxx_declaration (cxx_pretty_printer *
       pp_cxx_expression (pp, STATIC_ASSERT_MESSAGE (t));
       pp_cxx_right_paren (pp);
     }
+  else if (TREE_CODE (t) == NAMESPACE_DECL)
+    {
+      if (DECL_NAMESPACE_ALIAS (t))
+	pp_cxx_namespace_alias_definition (pp, t);
+      else
+	pp_cxx_original_namespace_definition (pp, t);
+    }
   else if (!DECL_LANG_SPECIFIC (t))
     pp_cxx_simple_declaration (pp, t);
   else if (DECL_USE_TEMPLATE (t))
@@ -2155,13 +2162,6 @@ pp_cxx_declaration (cxx_pretty_printer *
 	pp_cxx_simple_declaration (pp, t);
       break;
 
-    case NAMESPACE_DECL:
-      if (DECL_NAMESPACE_ALIAS (t))
-	pp_cxx_namespace_alias_definition (pp, t);
-      else
-	pp_cxx_original_namespace_definition (pp, t);
-      break;
-
     default:
       pp_unsupported_tree (pp, t);
       break;
Index: cp/typeck2.c
===================================================================
--- cp/typeck2.c	(revision 132679)
+++ cp/typeck2.c	(working copy)
@@ -161,6 +161,12 @@ pat_compare (const void* val1, const voi
 static GTY ((param_is (struct pending_abstract_type)))
 htab_t abstract_pending_vars = NULL;
 
+void reset_abstract_pending_vars (void);
+void
+reset_abstract_pending_vars (void)
+{
+  abstract_pending_vars = NULL;
+}
 
 /* This function is called after TYPE is completed, and will check if there
    are pending declarations for which we still need to verify the abstractness
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 132679)
+++ cp/pt.c	(working copy)
@@ -85,7 +85,7 @@ static htab_t local_specializations;
    the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
    TREE_LIST, whose TREE_VALUEs contain the canonical template
    parameters of various types and levels.  */
-static GTY(()) VEC(tree,gc) *canonical_template_parms;
+VEC(tree,gc) *canonical_template_parms;
 
 #define UNIFY_ALLOW_NONE 0
 #define UNIFY_ALLOW_MORE_CV_QUAL 1
@@ -8070,6 +8070,7 @@ tsubst_decl (tree t, tree args, tsubst_f
 	DECL_PENDING_INLINE_INFO (r) = 0;
 	DECL_PENDING_INLINE_P (r) = 0;
 	DECL_SAVED_TREE (r) = NULL_TREE;
+	DECL_STRUCT_FUNCTION (r) = 0;
 	TREE_USED (r) = 0;
 	if (DECL_CLONED_FUNCTION (r))
 	  {
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 132679)
+++ cp/semantics.c	(working copy)
@@ -3138,6 +3138,8 @@ emit_associated_thunks (tree fn)
     {
       tree thunk;
 
+      if (!DECL_LANG_SPECIFIC (fn))
+        return;
       for (thunk = DECL_THUNKS (fn); thunk; thunk = TREE_CHAIN (thunk))
 	{
 	  if (!THUNK_ALIAS (thunk))
Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c	(revision 132679)
+++ cp/name-lookup.c	(working copy)
@@ -807,6 +807,7 @@ pushdecl_maybe_friend (tree x, bool is_f
 		TYPE_NAME (type) = x;
 	    }
 	  else if (type != error_mark_node && TYPE_NAME (type) != x
+	  	   && 1
 		   /* We don't want to copy the type when all we're
 		      doing is making a TYPE_DECL for the purposes of
 		      inlining.  */
Index: cp/decl2.c
===================================================================
--- cp/decl2.c	(revision 132679)
+++ cp/decl2.c	(working copy)
@@ -3083,7 +3083,9 @@ cxx_callgraph_analyze_expr (tree *tp, in
 	cgraph_mark_needed_node (cgraph_node (BASELINK_FUNCTIONS (t)));
       break;
     case VAR_DECL:
-      if (DECL_VTABLE_OR_VTT_P (t))
+      if (DECL_VTABLE_OR_VTT_P (t)
+	  /* XXX */
+          /*&& TYPE_LANG_SPECIFIC (DECL_CONTEXT (t))*/)
 	{
 	  /* The ABI requires that all virtual tables be emitted
 	     whenever one of them is.  */
@@ -3462,7 +3464,10 @@ cp_write_global_declarations (void)
 
   /* Now, issue warnings about static, but not defined, functions,
      etc., and emit debugging information.  */
+  /* XXX */
+#if 0
   walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider);
+#endif
   if (VEC_length (tree, pending_statics) != 0)
     {
       check_global_declarations (VEC_address (tree, pending_statics),


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]