[lto] Re-implement pass_ipa_free_lang_specifics [1/3]

Diego Novillo dnovillo@google.com
Tue Jan 20 16:17:00 GMT 2009


This set of 3 patches overhauls the way we remove front end data
from the IL.  We used to have two hash tables collecting every
type and symbol instantiated.  The cleanup process would traverse
those.

However, some planned cleanups may require context of where the
symbol/type is found and we may also need to process other nodes
(like constants).  Additionally, this was processing too many
nodes, we only need to process those present in the IL.

The main change is then to change the hash table traversal with
a cgraph and varpool traversal.  The cleanup proceeds in three
stages:

1- Every callgraph node and varpool node is traversed looking for
   decls and types embedded in them.  This is a more exhaustive
   search than that done by find_referenced_vars, because it will
   also collect individual fields, decls embedded in types, etc.

2- All the decls found are cleaned up.

3- All the types found are cleaned up.

The ordering between decls and types is important because
cleaning up decls means setting assembler names, which needs to
do name mangling.  So types cannot be freed up until assembler
names have been set up.

The first patch implements the new IL traversal.  This required
some changes in the streamer:

1- Replacing char_type_node with unsigned_char_type_node is still
   problematic.  It causes no regresions in the testsuite, but it
   does break several internal applications.  I am still tracking
   it down, but in the meantime I have worked around the issue by
   just writing out unsigned_char_type_node whenever
   char_type_node is requested (output_type_ref_1).

   This workaround fixes some outstanding problems when using
   -funsigned-char.  I think it can fix all of them, but a full
   build is still ongoing.  The patch adds one testcase and
   another is being reduced.  I will add it as soon as I get a
   manageable test.

2- Runtime types for EH need to be exposed earlier.  Since we are
   only cleaning up types present in the IL, we need to call
   lookup_type_for_runtime during the cleanup.  We were doing
   this too late, which meant that these types were not cleaned
   up.

The patch also renames pass_ipa_free_lang_specifics to
pass_ipa_free_lang_data and adds a timer for the pass.

All three patches have been tested on x86_64 and i686.  I will
commit after all tests are done.


2009-01-20  Diego Novillo  <dnovillo@google.com>

	* tree.h (TYPE_MAXVAL): Define.
	(TYPE_MINVAL): Define.
	* tree.c: Include cgraph.h, timevar.h and except.h.
	(free_lang_data_in_type): Rename from reset_type_lang_specific.
	Change argument to be the type to process.
	Change return type to void.
	Update all users.
	If TYPE has char_type_node as its TREE_TYPE, change it to
	signed_char_type_node or unsigned_char_type_node
	according to flag_signed_char.
	If TYPE is char_type_node, reset its cached values.
	(set_asm_name): Remove.  Update all users.
	(free_lang_data_in_decl): Rename from
	reset_decl_lang_specific.
	Change argument to be the decl to process.
	Change return type to void.
	Update all users.
	If DECL has char_type_node as its TREE_TYPE, change it to
	signed_char_type_node or unsigned_char_type_node
	according to flag_signed_char.
	(struct free_lang_data_d): Declare.
	(find_decls_types_r): New.
	(get_eh_types_for_runtime): Move from lto-function-out.c.
	(find_decls_types_in_eh_region): New.
	(find_decls_types_in_node): New.
	(find_decls_types_in_var): New.
	(free_lang_data_in_cgraph): New.
	(free_lang_data): Rename from free_lang_specifics
	Call free_lang_data_in_cgraph.
	Set char_type_node to unsigned_char_type_node if -funsigned-char
	was given.
	(gate_free_lang_data): Rename from gate_free_lang_specifics.
	Update all users.
	(pass_ipa_free_lang_data): Rename from free_lang_specifics.
	Update all users.
	Add timer TV_IPA_FREE_LANG_DATA.
	* Makefile.in (tree.o): Add dependency on CGRAPH_H,
	TIMEVAR_H and except.h.
	* lto-function-out.c (output_tree): Do not handle char_type_node.
	(get_eh_types_for_runtime): Move to tree.c.
	(output_eh_region): Do not call get_eh_types_for_runtime.
	(output_tree): Move check for flag_signed_char ... 
	(output_type_ref_1): ... here.
	* timevar.def (TV_IPA_FREE_LANG_DATA): Define.
	* langhooks.h (struct lang_hooks): Rename
	free_lang_specifics to free_lang_data.
	Update all users.
	* langhooks-def.h (LANG_HOOKS_FREE_LANG_DATA): Rename
	from LANG_HOOKS_RESET_LANG_SPECIFICS.  Update all users.
	* except.c (output_ttype): Only call lookup_type_for_runtime
	if TYPE is actually a type.

lto/ChangeLog:

	* lto-lang.c (LANG_HOOKS_TYPES_COMPATIBLE_P): Update.

cp/ChangeLog.lto:

	* tree.c (cp_free_lang_data): Rename from cp_reset_lang_specifics.
	Update all users.

testsuite/ChangeLog.lto:

	* gcc.dg/lto/20090113_0.c: New.


Index: tree.h
===================================================================
--- tree.h	(revision 143495)
+++ tree.h	(working copy)
@@ -2098,6 +2098,8 @@ struct tree_block GTY(())
 #define TYPE_NEXT_VARIANT(NODE) (TYPE_CHECK (NODE)->type.next_variant)
 #define TYPE_MAIN_VARIANT(NODE) (TYPE_CHECK (NODE)->type.main_variant)
 #define TYPE_CONTEXT(NODE) (TYPE_CHECK (NODE)->type.context)
+#define TYPE_MAXVAL(NODE) (TYPE_CHECK (NODE)->type.maxval)
+#define TYPE_MINVAL(NODE) (TYPE_CHECK (NODE)->type.minval)
 
 /* Vector types need to check target flags to determine type.  */
 extern enum machine_mode vector_type_mode (const_tree);
Index: tree.c
===================================================================
--- tree.c	(revision 143495)
+++ tree.c	(working copy)
@@ -53,6 +53,9 @@ along with GCC; see the file COPYING3.  
 #include "fixed-value.h"
 #include "tree-pass.h"
 #include "langhooks-def.h"
+#include "cgraph.h"
+#include "timevar.h"
+#include "except.h"
 
 /* Tree code classes.  */
 
@@ -3883,13 +3792,15 @@ build_type_attribute_variant (tree ttype
 					    TYPE_QUALS (ttype));
 }
 
-/* Helper function of free_lang_specifics. */
+/* Reset all language specific information still present in TYPE.  */
 
-static int
-reset_type_lang_specific (void **slot, void *unused ATTRIBUTE_UNUSED)
+static void
+free_lang_data_in_type (tree type)
 {
-  tree type = *(tree *) slot;
-  lang_hooks.reset_lang_specifics (type);
+  gcc_assert (TYPE_P (type));
+
+  /* Give the FE a chance to remove its own data first.  */
+  lang_hooks.free_lang_data (type);
 
   TREE_LANG_FLAG_0 (type) = 0;
   TREE_LANG_FLAG_1 (type) = 0;
@@ -3981,28 +3892,15 @@ reset_type_lang_specific (void **slot, v
      FIXME lto: This will break debug info generation.  */
   TYPE_CONTEXT (type) = NULL_TREE;
 
-  /* If -funsigned-char is used, force all the expressions using
-     char_type_node to use unsigned_char_type_node.  */
-  if (flag_signed_char == 0)
-    {
-      if (type == char_type_node)
-	memcpy (type, unsigned_char_type_node, tree_size (type));
-      else if (TYPE_MAIN_VARIANT (type) == char_type_node)
-	TYPE_MAIN_VARIANT (type) = unsigned_char_type_node;
-
-      /* Clear the cached values for TYPE.  */
-      if (TYPE_CACHED_VALUES_P (type))
-	{
-	  TYPE_CACHED_VALUES_P (type) = 0;
-	  TYPE_CACHED_VALUES (type) = NULL;
-	}
-    }
-
-  return 1;
 }
 
 
-
 /* Return true if DECL may need an assembler name to be set.  */
 
 static inline bool
@@ -4037,29 +3935,16 @@ need_assembler_name_p (tree decl)
 }
 
 
-/* Helper function of free_lang_specifics.
-   Set the assembler name for nodes that may need one.  */
-
-static int
-set_asm_name (void **slot, void *unused ATTRIBUTE_UNUSED)
-{
-  tree decl = *((tree *) slot);
-
-  if (need_assembler_name_p (decl))
-    lang_hooks.set_decl_assembler_name (decl);
-
-  return 1;
-}
-
-
-/* Helper function of free_lang_specifics. */
+/* Reset all language specific information still present in symbol
+   DECL.  */
 
-static int
-reset_decl_lang_specific (void **slot, void *unused ATTRIBUTE_UNUSED)
+static void
+free_lang_data_in_decl (tree decl)
 {
-  tree decl = *(tree *) slot;
+  gcc_assert (DECL_P (decl));
 
-  lang_hooks.reset_lang_specifics (decl);
+  /* Give the FE a chance to remove its own data first.  */
+  lang_hooks.free_lang_data (decl);
 
   TREE_LANG_FLAG_0 (decl) = 0;
   TREE_LANG_FLAG_1 (decl) = 0;
@@ -4069,9 +3954,9 @@ reset_decl_lang_specific (void **slot, v
   TREE_LANG_FLAG_5 (decl) = 0;
   TREE_LANG_FLAG_6 (decl) = 0;
 
+  /* Ignore any intervening types, because we are going to clear their
+     TYPE_CONTEXT fields.  */
   if (TREE_CODE (decl) != FIELD_DECL)
-    /* Ignore any intervening types, because we
-       are going to clear their TYPE_CONTEXT fields.  */
     DECL_CONTEXT (decl) = decl_function_context (decl);
 
   if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
@@ -4137,29 +4022,333 @@ reset_decl_lang_specific (void **slot, v
       DECL_CONTEXT (decl) = NULL_TREE;
     }
 
-  return 1;
 }
 
-/* Free resources that are used by FE but are not needed once they are done. */
+/* Data used when collecting DECLs and TYPEs for language data removal.  */
 
-static unsigned
-free_lang_specifics (void)
+struct free_lang_data_d
 {
-  struct cgraph_node *node;
+  /* Set of traversed objects.  Used to avoid duplicate visits.  */
+  struct pointer_set_t *pset;
 
-  /* Set assembler names now, as callbacks from the back-end
-     will fail after we strip DECL_CONTEXT from declaration nodes.  */
-  htab_traverse (decl_for_uid_map, set_asm_name, NULL);
+  /* Array of symbols to process with free_lang_data_in_decl.  */
+  VEC(tree,heap) *decls;
 
-  for (node = cgraph_nodes; node; node = node->next)
+  /* Array of types to process with free_lang_data_in_type.  */
+  VEC(tree,heap) *types;
+};
+
+
+/* Operand callback helper for free_lang_data_in_node.  *TP is the
+   subtree operand being considered.  */
+
+static tree
+find_decls_types_r (tree *tp, int *ws ATTRIBUTE_UNUSED, void *data)
+{
+  tree t = *tp;
+  struct free_lang_data_d *fld = (struct free_lang_data_d *) data;
+  struct pointer_set_t *pset = fld->pset;
+
+  /* Note that walk_tree does not traverse every possible field in
+     types nor decls, so we have to do our own traversals here.  */
+  if (DECL_P (t))
     {
-      tree decl = node->decl;
-      if (!DECL_ASSEMBLER_NAME_SET_P (decl))
-	lang_hooks.set_decl_assembler_name (decl);
+      VEC_safe_push (tree, heap, fld->decls, t);
+
+      walk_tree (&DECL_NAME (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&DECL_CONTEXT (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&DECL_SIZE (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&DECL_SIZE_UNIT (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&DECL_INITIAL (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&DECL_ATTRIBUTES (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&DECL_ABSTRACT_ORIGIN (t), find_decls_types_r, fld, fld->pset);
+
+      if (TREE_CODE (t) == FUNCTION_DECL)
+	{
+	  walk_tree (&DECL_ARGUMENTS (t), find_decls_types_r, fld, fld->pset);
+	  walk_tree (&DECL_RESULT (t), find_decls_types_r, fld, fld->pset);
+	}
+      else if (TREE_CODE (t) == TYPE_DECL)
+	{
+	  walk_tree (&DECL_ARGUMENT_FLD (t), find_decls_types_r, fld,
+		     fld->pset);
+	  walk_tree (&DECL_VINDEX (t), find_decls_types_r, fld, fld->pset);
+	}
+      else if (TREE_CODE (t) == FIELD_DECL)
+	{
+	  walk_tree (&DECL_FIELD_OFFSET (t), find_decls_types_r, fld,
+		     fld->pset);
+	  walk_tree (&DECL_BIT_FIELD_TYPE (t), find_decls_types_r, fld,
+		     fld->pset);
+	  walk_tree (&DECL_QUALIFIER (t), find_decls_types_r, fld, fld->pset);
+	  walk_tree (&DECL_FIELD_BIT_OFFSET (t), find_decls_types_r, pset,
+		     pset);
+	  walk_tree (&DECL_FCONTEXT (t), find_decls_types_r, fld, fld->pset);
+	}
+      else if (TREE_CODE (t) == VAR_DECL)
+	{
+	  walk_tree (&DECL_SECTION_NAME (t), find_decls_types_r, fld,
+		     fld->pset);
+	  walk_tree (&DECL_COMDAT_GROUP (t), find_decls_types_r, fld,
+		     fld->pset);
+	}
     }
+  else if (TYPE_P (t))
+    {
+      VEC_safe_push (tree, heap, fld->types, t);
 
-  htab_traverse (decl_for_uid_map, reset_decl_lang_specific, NULL);
-  htab_traverse (uid2type_map, reset_type_lang_specific, NULL);
+      walk_tree (&TYPE_CACHED_VALUES (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_SIZE (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_SIZE_UNIT (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_ATTRIBUTES (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_POINTER_TO (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_REFERENCE_TO (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_NAME (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_MINVAL (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_MAXVAL (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_NEXT_VARIANT (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_MAIN_VARIANT (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_CONTEXT (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_CANONICAL (t), find_decls_types_r, fld, fld->pset);
+    }
+
+  if (TREE_TYPE (t))
+    walk_tree (&TREE_TYPE (t), find_decls_types_r, fld, fld->pset);
+
+  if (TREE_CHAIN (t))
+    walk_tree (&TREE_CHAIN (t), find_decls_types_r, fld, fld->pset);
+
+  return NULL_TREE;
+}
+
+
+/* Translate all the types in LIST with the corresponding runtime
+   types.  */
+
+static tree
+get_eh_types_for_runtime (tree list)
+{
+  tree head, prev;
+
+  if (list == NULL_TREE)
+    return NULL_TREE;
+
+  head = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list)));
+  prev = head;
+  list = TREE_CHAIN (list);
+  while (list)
+    {
+      tree n = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list)));
+      TREE_CHAIN (prev) = n;
+      prev = TREE_CHAIN (prev);
+      list = TREE_CHAIN (list);
+    }
+
+  return head;
+}
+
+
+/* Find decls and types referenced in EH region R and store them in
+   FLD->DECLS and FLD->TYPES.  */
+
+static void
+find_decls_types_in_eh_region (eh_region r, struct free_lang_data_d *fld)
+{
+  if (r == NULL)
+    return;
+
+  /* The types referenced in R must first be changed to the EH types
+     used at runtime.  This removes references to FE types in the
+     region.  */
+  if (r->type == ERT_CATCH)
+    {
+      tree list = r->u.eh_catch.type_list;
+      r->u.eh_catch.type_list = get_eh_types_for_runtime (list);
+      walk_tree (&r->u.eh_catch.type_list, find_decls_types_r, fld, fld->pset);
+    }
+  else if (r->type == ERT_ALLOWED_EXCEPTIONS)
+    {
+      tree list = r->u.allowed.type_list;
+      r->u.allowed.type_list = get_eh_types_for_runtime (list);
+      walk_tree (&r->u.allowed.type_list, find_decls_types_r, fld, fld->pset);
+    }
+}
+
+
+/* Find decls and types referenced in cgraph node N and store them in
+   FLD->DECLS and FLD->TYPES.  Unlike pass_referenced_vars, this will
+   look for *every* kind of DECL and TYPE node reachable from N,
+   including those embedded inside types and decls (i.e,, TYPE_DECLs,
+   NAMESPACE_DECLs, etc).  */
+
+static void
+find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
+{
+  basic_block bb;
+  struct function *fn;
+
+  /* Although free_lang_data_in_cgraph will set the assembler name on
+     most DECLs, it refuses to do it on unused ones.  For cgraph
+     nodes, we need to set it even if it's seemingly unused.  */
+  if (!DECL_ASSEMBLER_NAME_SET_P (n->decl))
+    lang_hooks.set_decl_assembler_name (n->decl);
+
+  walk_tree (&n->decl, find_decls_types_r, fld, fld->pset);
+
+  if (!gimple_has_body_p (n->decl))
+    return;
+
+  gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
+
+  fn = DECL_STRUCT_FUNCTION (n->decl);
+
+  /* Traverse EH regions in FN.  */
+  if (fn->eh->region_array)
+    {
+      unsigned i;
+      eh_region r;
+
+      for (i = 0; VEC_iterate (eh_region, fn->eh->region_array, i, r); i++)
+	find_decls_types_in_eh_region (r, fld);
+    }
+
+  /* Traverse every statement in FN.  */
+  FOR_EACH_BB_FN (bb, fn)
+    {
+      gimple_stmt_iterator si;
+      unsigned i;
+
+      for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
+	{
+	  gimple phi = gsi_stmt (si);
+
+	  for (i = 0; i < gimple_phi_num_args (phi); i++)
+	    {
+	      tree *arg_p = gimple_phi_arg_def_ptr (phi, i);
+	      walk_tree (arg_p, find_decls_types_r, fld, fld->pset);
+	    }
+	}
+
+      for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+	{
+	  gimple stmt = gsi_stmt (si);
+
+	  for (i = 0; i < gimple_num_ops (stmt); i++)
+	    {
+	      tree *arg_p = gimple_op_ptr (stmt, i);
+	      walk_tree (arg_p, find_decls_types_r, fld, fld->pset);
+	    }
+	}
+    }
+}
+
+
+/* Find decls and types referenced in varpool node N and store them in
+   FLD->DECLS and FLD->TYPES.  Unlike pass_referenced_vars, this will
+   look for *every* kind of DECL and TYPE node reachable from N,
+   including those embedded inside types and decls (i.e,, TYPE_DECLs,
+   NAMESPACE_DECLs, etc).  */
+
+
+static void
+find_decls_types_in_var (struct varpool_node *v, struct free_lang_data_d *fld)
+{
+  walk_tree (&v->decl, find_decls_types_r, fld, fld->pset);
+}
+
+
+/* Free language specific information for every operand and expression
+   in every node of the call graph.  This process operates in three stages:
+
+   1- Every callgraph node and varpool node is traversed looking for
+      decls and types embedded in them.  This is a more exhaustive
+      search than that done by find_referenced_vars, because it will
+      also collect individual fields, decls embedded in types, etc.
+
+   2- All the decls found are sent to free_lang_data_in_decl.
+
+   3- All the types found are sent to free_lang_data_in_type.
+
+   The ordering between decls and types is important because
+   free_lang_data_in_decl sets assembler names, which includes
+   mangling.  So types cannot be freed up until assembler names have
+   been set up.  */
+
+static void
+free_lang_data_in_cgraph (void)
+{
+  struct cgraph_node *n;
+  struct varpool_node *v;
+  struct free_lang_data_d fld;
+  tree t;
+  unsigned i;
+
+  /* Initialize sets and arrays to store referenced decls and types.  */
+  fld.pset = pointer_set_create ();
+  fld.decls = VEC_alloc (tree, heap, 100);
+  fld.types = VEC_alloc (tree, heap, 100);
+
+  /* Find decls and types in the body of every function in the callgraph.  */
+  for (n = cgraph_nodes; n; n = n->next)
+    find_decls_types_in_node (n, &fld);
+
+  /* Find decls and types in every varpool symbol.  */
+  for (v = varpool_nodes_queue; v; v = v->next_needed)
+    find_decls_types_in_var (v, &fld);
+
+  /* Set the assembler name on every decl found.  We need to do this
+     now because free_lang_data_in_decl will invalidate data needed
+     for mangling.  This breaks mangling on interdependent decls.  */
+  for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++)
+    if (need_assembler_name_p (t))
+      lang_hooks.set_decl_assembler_name (t);
+
+  /* Traverse every decl found freeing its language data.  */
+  for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++)
+    free_lang_data_in_decl (t);
+
+  /* Traverse every type found freeing its language data.  */
+  for (i = 0; VEC_iterate (tree, fld.types, i, t); i++)
+    free_lang_data_in_type (t);
+
+  pointer_set_destroy (fld.pset);
+  VEC_free (tree, heap, fld.decls);
+  VEC_free (tree, heap, fld.types);
+}
+
+
+/* Free resources that are used by FE but are not needed once they are done. */
+
+static unsigned
+free_lang_data (void)
+{
+  /* Traverse the IL resetting language specific information for
+     operands, expressions, etc.  */
+  free_lang_data_in_cgraph ();
 
   /* FIXME lto.  This is a hack.  ptrdiff_type_node is only created
      by the C/C++ FE.  This should be converted to some similar
@@ -4186,29 +4376,29 @@ free_lang_specifics (void)
 }
 
 
-/* Gate function for free_lang_specifics.  FIXME lto.  This should be
+/* Gate function for free_lang_data.  FIXME lto.  This should be
    unconditional and not depend on whether we're producing LTO
    information and it should be done very early on.  This currently
    breaks libstdc++ builds, though.  */
 
 static bool
-gate_free_lang_specifics (void)
+gate_free_lang_data (void)
 {
   return flag_generate_lto;
 }
 
 
-struct simple_ipa_opt_pass pass_ipa_free_lang_specifics = 
+struct simple_ipa_opt_pass pass_ipa_free_lang_data = 
 {
  {
   SIMPLE_IPA_PASS,
   NULL,					/* name */
-  gate_free_lang_specifics,		/* gate */
-  free_lang_specifics,			/* execute */
+  gate_free_lang_data,			/* gate */
+  free_lang_data,			/* execute */
   NULL,					/* sub */
   NULL,					/* next */
   0,					/* static_pass_number */
-  0,					/* tv_id */
+  TV_IPA_FREE_LANG_DATA,		/* tv_id */
   0,	                                /* properties_required */
   0,					/* properties_provided */
   0,					/* properties_destroyed */
Index: tree-pass.h
===================================================================
--- tree-pass.h	(revision 143495)
+++ tree-pass.h	(working copy)
@@ -391,7 +391,7 @@ extern struct gimple_opt_pass pass_build
 extern struct gimple_opt_pass pass_reset_cc_flags;
 
 /* IPA Passes */
-extern struct simple_ipa_opt_pass pass_ipa_free_lang_specifics;
+extern struct simple_ipa_opt_pass pass_ipa_free_lang_data;
 extern struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility;
 extern struct simple_ipa_opt_pass pass_ipa_early_inline;
 
Index: lto-function-out.c
===================================================================
--- lto-function-out.c	(revision 143519)
+++ lto-function-out.c	(working copy)
@@ -571,6 +571,12 @@ type_decl_is_local (tree decl ATTRIBUTE_
 static void
 output_type_ref_1 (struct output_block *ob, tree node)
 {
+  /* FIXME lto.  This is a hack, the use of -funsigned-char should be
+     reflected in the IL by changing every reference to char_type_node
+     into unsigned_char_type_node in pass_ipa_free_lang_data.  */
+  if (flag_signed_char == 0 && node == char_type_node)
+    node = unsigned_char_type_node;
+
   output_record_start (ob, NULL, NULL, LTO_global_type_ref);
   lto_output_type_ref_index (ob->decl_state, ob->main_stream, node);
 
@@ -669,32 +675,6 @@ output_record_start (struct output_block
 }
 
 
-/* Translate all the types in LIST with the corresponding runtime
-   types.  */
-
-static tree
-get_eh_types_for_runtime (tree list)
-{
-  tree head, prev;
-
-  if (list == NULL_TREE)
-    return NULL_TREE;
-
-  head = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list)));
-  prev = head;
-  list = TREE_CHAIN (list);
-  while (list)
-    {
-      tree n = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list)));
-      TREE_CHAIN (prev) = n;
-      prev = TREE_CHAIN (prev);
-      list = TREE_CHAIN (list);
-    }
-
-  return head;
-}
-
-
 /* Output EH region R to OB.  */
 
 static void
@@ -784,10 +764,7 @@ output_eh_region (struct output_block *o
 	 by calling output_zero.  */
       list = r->u.eh_catch.type_list;
       if (list)
-	{
-	  list = get_eh_types_for_runtime (list);
-	  output_expr_operand (ob, list);
-	}
+	output_expr_operand (ob, list);
       else
 	output_zero (ob);
 
@@ -799,7 +776,7 @@ output_eh_region (struct output_block *o
     }
   else if (r->type == ERT_ALLOWED_EXCEPTIONS)
     {
-      tree list = get_eh_types_for_runtime (r->u.allowed.type_list);
+      tree list = r->u.allowed.type_list;
       if (list)
 	output_expr_operand (ob, list);
       else
@@ -2747,7 +2724,7 @@ output_type_decl (struct output_block *o
   /* Must output name before type.  */
   output_tree (ob, decl->decl_minimal.name);
 
-  /* Should be cleared by pass_ipa_free_lang_specifics.  */
+  /* Should be cleared by pass_ipa_free_lang_data.  */
   gcc_assert (decl->decl_minimal.context == NULL_TREE);
 
   output_tree (ob, decl->decl_with_vis.assembler_name);
@@ -2764,7 +2741,7 @@ output_type_decl (struct output_block *o
   output_tree (ob, decl->decl_common.size);
   output_tree (ob, decl->decl_common.size_unit);
 
-  /* We expect pass_ipa_free_lang_specifics to clear the INITIAL field.  */
+  /* We expect pass_ipa_free_lang_data to clear the INITIAL field.  */
   gcc_assert (decl->decl_common.initial == NULL_TREE);
 
   /* lang_specific */
@@ -2990,7 +2967,7 @@ output_type (struct output_block *ob, tr
   LTO_DEBUG_TOKEN ("binfo");
   output_tree (ob, type->type.binfo);
 
-  /* Should be cleared by pass_ipa_free_lang_specifics.  */
+  /* Should be cleared by pass_ipa_free_lang_data.  */
   gcc_assert (type->type.context == NULL_TREE);
 
   LTO_DEBUG_TOKEN ("canonical");
@@ -3097,9 +3074,6 @@ output_tree (struct output_block *ob, tr
   void **slot;
   struct lto_decl_slot d_slot;
 
-  if (flag_signed_char == 0 && expr == char_type_node)
-    expr = unsigned_char_type_node;
-
   if (expr == NULL_TREE)
     {
       output_zero (ob);
Index: testsuite/gcc.dg/lto/20090113_0.c
===================================================================
--- testsuite/gcc.dg/lto/20090113_0.c	(revision 0)
+++ testsuite/gcc.dg/lto/20090113_0.c	(revision 0)
@@ -0,0 +1,14 @@
+/* { dg-options "{-flto -funsigned-char}" } */
+
+extern void abort ();
+
+char c = 0xff;
+
+int
+main ()
+{
+ int i = (unsigned) c;
+ if (i < 0)
+   abort ();
+ return 0;
+}
Index: cp/cp-objcp-common.h
===================================================================
--- cp/cp-objcp-common.h	(revision 143495)
+++ cp/cp-objcp-common.h	(working copy)
@@ -30,8 +30,8 @@ extern tree objcp_tsubst_copy_and_build 
    specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c,
    respectively.  */
 
-#undef LANG_HOOKS_RESET_LANG_SPECIFICS
-#define LANG_HOOKS_RESET_LANG_SPECIFICS cp_reset_lang_specifics
+#undef LANG_HOOKS_FREE_LANG_DATA
+#define LANG_HOOKS_FREE_LANG_DATA cp_free_lang_data
 #undef LANG_HOOKS_TREE_SIZE
 #define LANG_HOOKS_TREE_SIZE cp_tree_size
 #undef LANG_HOOKS_FINISH
Index: cp/tree.c
===================================================================
--- cp/tree.c	(revision 143495)
+++ cp/tree.c	(working copy)
@@ -2829,7 +2829,7 @@ cp_fix_function_decl_p (tree decl)
 /* Clean the C++ specific parts of the tree T. */
 
 void
-cp_reset_lang_specifics (tree t)
+cp_free_lang_data (tree t)
 {
   if (TREE_CODE (t) == METHOD_TYPE
       || TREE_CODE (t) == FUNCTION_TYPE)
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 143495)
+++ cp/cp-tree.h	(working copy)
@@ -4819,7 +4819,7 @@ extern tree finish_decltype_type        
 extern tree finish_trait_expr			(enum cp_trait_kind, tree, tree);
 
 /* in tree.c */
-void cp_reset_lang_specifics (tree t);
+void cp_free_lang_data 				(tree t);
 extern void lang_check_failed			(const char *, int,
 						 const char *) ATTRIBUTE_NORETURN;
 extern tree stabilize_expr			(tree, tree *);
Index: timevar.def
===================================================================
--- timevar.def	(revision 143495)
+++ timevar.def	(working copy)
@@ -53,6 +53,7 @@ DEFTIMEVAR (TV_IPA_REFERENCE         , "
 DEFTIMEVAR (TV_IPA_PURE_CONST        , "ipa pure const")
 DEFTIMEVAR (TV_IPA_TYPE_ESCAPE       , "ipa type escape")
 DEFTIMEVAR (TV_IPA_PTA               , "ipa points-to")
+DEFTIMEVAR (TV_IPA_FREE_LANG_DATA    , "ipa free lang data")
 /* Time spent by constructing CFG.  */
 DEFTIMEVAR (TV_CFG                   , "cfg construction")
 /* Time spent by cleaning up CFG.  */
Index: langhooks.h
===================================================================
--- langhooks.h	(revision 143495)
+++ langhooks.h	(working copy)
@@ -240,7 +240,7 @@ struct lang_hooks
   size_t identifier_size;
 
   /* Remove any parts of the tree that are used only by the FE. */
-  void (*reset_lang_specifics) (tree);
+  void (*free_lang_data) (tree);
 
   /* Determines the size of any language-specific tcc_constant or
      tcc_exceptional nodes.  Since it is called from make_node, the
Index: except.c
===================================================================
--- except.c	(revision 143495)
+++ except.c	(working copy)
@@ -3481,7 +3481,14 @@ output_ttype (tree type, int tt_format, 
     {
       struct varpool_node *node;
 
-      type = lookup_type_for_runtime (type);
+      /* FIXME lto.  During LTO compiles, pass_ipa_free_lang_data
+	 changes all types to runtime types so TYPE should already be
+	 a runtime type reference.  When pass_ipa_free_lang data is
+	 made a default pass, we can then remove the call to
+	 lookup_type_for_runtime below.  */
+      if (TYPE_P (type))
+	type = lookup_type_for_runtime (type);
+
       value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
 
       /* Let cgraph know that the rtti decl is used.  Not all of the
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 143495)
+++ Makefile.in	(working copy)
@@ -2134,7 +2134,8 @@ tree.o : tree.c $(CONFIG_H) $(SYSTEM_H) 
    all-tree.def $(FLAGS_H) $(FUNCTION_H) $(PARAMS_H) \
    $(TOPLEV_H) $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H) langhooks.h \
    $(REAL_H) gt-tree.h tree-iterator.h $(BASIC_BLOCK_H) $(TREE_FLOW_H) \
-   $(OBSTACK_H) pointer-set.h fixed-value.h tree-pass.h langhooks-def.h
+   $(OBSTACK_H) pointer-set.h fixed-value.h tree-pass.h langhooks-def.h \
+   $(CGRAPH_H) $(TIMEVAR_H) except.h
 tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TREE_H) langhooks.h $(TOPLEV_H) $(SPLAY_TREE_H) $(TREE_DUMP_H) \
    tree-iterator.h tree-pass.h $(DIAGNOSTIC_H) $(REAL_H) fixed-value.h
Index: passes.c
===================================================================
--- passes.c	(revision 143495)
+++ passes.c	(working copy)
@@ -536,7 +536,7 @@ init_optimization_passes (void)
       NEXT_PASS (pass_inline_parameters);
       NEXT_PASS (pass_rebuild_cgraph_edges);
     }
-  NEXT_PASS (pass_ipa_free_lang_specifics);
+  NEXT_PASS (pass_ipa_free_lang_data);
   NEXT_PASS (pass_early_local_passes);
     {
       struct opt_pass **p = &pass_early_local_passes.pass.sub;
Index: lto-section-out.c
===================================================================
--- lto-section-out.c	(revision 143495)
+++ lto-section-out.c	(working copy)
@@ -867,8 +867,7 @@ lto_get_common_nodes (void)
      distinction should only be relevant to the front-end, so we always
      use the C definition here in lto1.
 
-     These should be assured in pass_ipa_free_lang_specifics.  */
-
+     These should be assured in pass_ipa_free_lang_data.  */
   gcc_assert (fileptr_type_node == ptr_type_node);
   gcc_assert (TYPE_MAIN_VARIANT (fileptr_type_node) == ptr_type_node);
   
Index: langhooks-def.h
===================================================================
--- langhooks-def.h	(revision 143495)
+++ langhooks-def.h	(working copy)
@@ -103,7 +103,7 @@ extern void lhd_omp_firstprivatize_type_
 #define LANG_HOOKS_DECL_PRINTABLE_NAME	lhd_decl_printable_name
 #define LANG_HOOKS_DWARF_NAME		lhd_dwarf_name
 #define LANG_HOOKS_EXPR_SIZE		lhd_expr_size
-#define LANG_HOOKS_RESET_LANG_SPECIFICS	lhd_do_nothing_t
+#define LANG_HOOKS_FREE_LANG_DATA	lhd_do_nothing_t
 #define LANG_HOOKS_TREE_SIZE		lhd_tree_size
 #define LANG_HOOKS_TYPES_COMPATIBLE_P	lhd_types_compatible_p
 #define LANG_HOOKS_BUILTIN_FUNCTION	lhd_builtin_function
@@ -239,7 +239,7 @@ extern void lhd_end_section (void);
 #define LANG_HOOKS_INITIALIZER { \
   LANG_HOOKS_NAME, \
   LANG_HOOKS_IDENTIFIER_SIZE, \
-  LANG_HOOKS_RESET_LANG_SPECIFICS, \
+  LANG_HOOKS_FREE_LANG_DATA, \
   LANG_HOOKS_TREE_SIZE, \
   LANG_HOOKS_INIT_OPTIONS, \
   LANG_HOOKS_INITIALIZE_DIAGNOSTICS, \



More information about the Gcc-patches mailing list