OSDN Git Service

2009-10-15 Sebastian Pop <sebastian.pop@amd.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index 17009c6..a40c36e 100644 (file)
@@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "timevar.h"
 #include "except.h"
 #include "debug.h"
+#include "intl.h"
 
 /* Tree code classes.  */
 
@@ -152,6 +153,9 @@ static const char * const tree_node_kind_names[] = {
 static GTY(()) int next_decl_uid;
 /* Unique id for next type created.  */
 static GTY(()) int next_type_uid = 1;
+/* Unique id for next debug decl created.  Use negative numbers,
+   to catch erroneous uses.  */
+static GTY(()) int next_debug_decl_uid;
 
 /* Since we cannot rehash a type after it is in the table, we have to
    keep the hash code.  */
@@ -284,6 +288,8 @@ tree_node_structure_for_code (enum tree_code code)
            return TS_LABEL_DECL;
          case RESULT_DECL:
            return TS_RESULT_DECL;
+         case DEBUG_EXPR_DECL:
+           return TS_DECL_WRTL;
          case CONST_DECL:
            return TS_CONST_DECL;
          case TYPE_DECL:
@@ -667,6 +673,8 @@ tree_code_size (enum tree_code code)
            return sizeof (struct tree_type_decl);
          case FUNCTION_DECL:
            return sizeof (struct tree_function_decl);
+         case DEBUG_EXPR_DECL:
+           return sizeof (struct tree_decl_with_rtl);
          default:
            return sizeof (struct tree_decl_non_common);
          }
@@ -872,7 +880,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
            DECL_ALIGN (t) = 1;
        }
       DECL_SOURCE_LOCATION (t) = input_location;
-      DECL_UID (t) = next_decl_uid++;
+      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
+       DECL_UID (t) = --next_debug_decl_uid;
+      else
+       DECL_UID (t) = next_decl_uid++;
       if (TREE_CODE (t) == LABEL_DECL)
        LABEL_DECL_UID (t) = -1;
 
@@ -944,11 +955,15 @@ copy_node_stat (tree node MEM_STAT_DECL)
   TREE_CHAIN (t) = 0;
   TREE_ASM_WRITTEN (t) = 0;
   TREE_VISITED (t) = 0;
-  t->base.ann = 0;
+  if (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL)
+    *DECL_VAR_ANN_PTR (t) = 0;
 
   if (TREE_CODE_CLASS (code) == tcc_declaration)
     {
-      DECL_UID (t) = next_decl_uid++;
+      if (code == DEBUG_EXPR_DECL)
+       DECL_UID (t) = --next_debug_decl_uid;
+      else
+       DECL_UID (t) = next_decl_uid++;
       if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
          && DECL_HAS_VALUE_EXPR_P (node))
        {
@@ -1670,8 +1685,7 @@ integer_pow2p (const_tree expr)
   if (TREE_CODE (expr) != INTEGER_CST)
     return 0;
 
-  prec = (POINTER_TYPE_P (TREE_TYPE (expr))
-         ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
+  prec = int_or_pointer_precision (TREE_TYPE (expr));
   high = TREE_INT_CST_HIGH (expr);
   low = TREE_INT_CST_LOW (expr);
 
@@ -1735,9 +1749,7 @@ tree_log2 (const_tree expr)
   if (TREE_CODE (expr) == COMPLEX_CST)
     return tree_log2 (TREE_REALPART (expr));
 
-  prec = (POINTER_TYPE_P (TREE_TYPE (expr))
-         ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
-
+  prec = int_or_pointer_precision (TREE_TYPE (expr));
   high = TREE_INT_CST_HIGH (expr);
   low = TREE_INT_CST_LOW (expr);
 
@@ -1773,9 +1785,7 @@ tree_floor_log2 (const_tree expr)
   if (TREE_CODE (expr) == COMPLEX_CST)
     return tree_log2 (TREE_REALPART (expr));
 
-  prec = (POINTER_TYPE_P (TREE_TYPE (expr))
-         ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
-
+  prec = int_or_pointer_precision (TREE_TYPE (expr));
   high = TREE_INT_CST_HIGH (expr);
   low = TREE_INT_CST_LOW (expr);
 
@@ -1905,6 +1915,17 @@ purpose_member (const_tree elem, tree list)
   return NULL_TREE;
 }
 
+/* Returns element number IDX (zero-origin) of chain CHAIN, or
+   NULL_TREE.  */
+
+tree
+chain_index (int idx, tree chain)
+{
+  for (; chain && idx > 0; --idx)
+    chain = TREE_CHAIN (chain);
+  return chain;
+}
+
 /* Return nonzero if ELEM is part of the chain CHAIN.  */
 
 int
@@ -3928,9 +3949,9 @@ expanded_location
 expand_location (source_location loc)
 {
   expanded_location xloc;
-  if (loc == 0)
+  if (loc <= BUILTINS_LOCATION)
     {
-      xloc.file = NULL;
+      xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");
       xloc.line = 0;
       xloc.column = 0;
       xloc.sysp = 0;
@@ -4023,7 +4044,7 @@ iterative_hash_host_wide_int (HOST_WIDE_INT val, hashval_t val2)
 
    Record such modified types already made so we don't make duplicates.  */
 
-static tree
+tree
 build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
 {
   if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute))
@@ -4119,6 +4140,31 @@ build_type_attribute_variant (tree ttype, tree attribute)
                                            TYPE_QUALS (ttype));
 }
 
+
+/* Reset all the fields in a binfo node BINFO.  We only keep
+   BINFO_VIRTUALS, which is used by gimple_fold_obj_type_ref.  */
+
+static void
+free_lang_data_in_binfo (tree binfo)
+{
+  unsigned i;
+  tree t;
+
+  gcc_assert (TREE_CODE (binfo) == TREE_BINFO);
+
+  BINFO_OFFSET (binfo) = NULL_TREE;
+  BINFO_VTABLE (binfo) = NULL_TREE;
+  BINFO_VPTR_FIELD (binfo) = NULL_TREE;
+  BINFO_BASE_ACCESSES (binfo) = NULL;
+  BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
+  BINFO_SUBVTT_INDEX (binfo) = NULL_TREE;
+  BINFO_VPTR_FIELD (binfo) = NULL_TREE;
+
+  for (i = 0; VEC_iterate (tree, BINFO_BASE_BINFOS (binfo), i, t); i++)
+    free_lang_data_in_binfo (t);
+}
+
+
 /* Reset all language specific information still present in TYPE.  */
 
 static void
@@ -4126,11 +4172,6 @@ free_lang_data_in_type (tree type)
 {
   gcc_assert (TYPE_P (type));
 
-  /* Fill in the alias-set.  We need to at least track zeroness here
-     for correctness.  */
-  if (lang_hooks.get_alias_set (type) == 0)
-    TYPE_ALIAS_SET (type) = 0;
-
   /* Give the FE a chance to remove its own data first.  */
   lang_hooks.free_lang_data (type);
 
@@ -4168,9 +4209,7 @@ free_lang_data_in_type (tree type)
              
   /* Remove members that are not actually FIELD_DECLs from the field
      list of an aggregate.  These occur in C++.  */
-  if (TREE_CODE (type) == RECORD_TYPE
-      || TREE_CODE (type) == UNION_TYPE
-      || TREE_CODE (type) == QUAL_UNION_TYPE)
+  if (RECORD_OR_UNION_TYPE_P (type))
     {
       tree prev, member;
 
@@ -4204,30 +4243,7 @@ free_lang_data_in_type (tree type)
 
       TYPE_METHODS (type) = NULL_TREE;
       if (TYPE_BINFO (type))
-       {
-         tree binfo = TYPE_BINFO (type);
-
-         if (BINFO_VIRTUALS (binfo))
-           {
-             /* If the virtual function table for BINFO contains
-                entries, these may be useful for folding OBJ_TYPE_REF
-                expressions (see gimple_fold_obj_type_ref).  In that
-                case, we only clear the unused fields in the BINFO
-                structure.  */
-             BINFO_OFFSET (binfo) = NULL_TREE;
-             BINFO_VTABLE (binfo) = NULL_TREE;
-             BINFO_VPTR_FIELD (binfo) = NULL_TREE;
-             BINFO_BASE_ACCESSES (binfo) = NULL;
-             BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
-             BINFO_SUBVTT_INDEX (binfo) = NULL_TREE;
-             BINFO_VPTR_FIELD (binfo) = NULL_TREE;
-           }
-         else
-           {
-             /* Otherwise, get rid of the whole binfo data.  */
-             TYPE_BINFO (type) = NULL_TREE;
-           }
-       }
+       free_lang_data_in_binfo (TYPE_BINFO (type));
     }
   else
     {
@@ -4265,19 +4281,22 @@ need_assembler_name_p (tree decl)
       && !DECL_EXTERNAL (decl))
     return false;
 
-  /* Do not set assembler name on builtins.  Allow RTL expansion to
-     decide whether to expand inline or via a regular call.  */
-  if (TREE_CODE (decl) == FUNCTION_DECL
-      && DECL_BUILT_IN (decl)
-      && DECL_BUILT_IN_CLASS (decl) != BUILT_IN_FRONTEND)
-    return false;
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    {
+      /* Do not set assembler name on builtins.  Allow RTL expansion to
+        decide whether to expand inline or via a regular call.  */
+      if (DECL_BUILT_IN (decl)
+         && DECL_BUILT_IN_CLASS (decl) != BUILT_IN_FRONTEND)
+       return false;
 
-  /* For FUNCTION_DECLs, only used functions and functions
-     represented in the callgraph need an assembler name.  */
-  if (TREE_CODE (decl) == FUNCTION_DECL
-      && cgraph_node_for_decl (decl) == NULL
-      && !TREE_USED (decl))
-    return false;
+      /* Functions represented in the callgraph need an assembler name.  */
+      if (cgraph_get_node (decl) != NULL)
+       return true;
+
+      /* Unused and not public functions don't need an assembler name.  */
+      if (!TREE_USED (decl) && !TREE_PUBLIC (decl))
+       return false;
+    }
 
   return true;
 }
@@ -4329,9 +4348,6 @@ free_lang_data_in_decl (tree decl)
   if (DECL_NAME (decl))
     TREE_TYPE (DECL_NAME (decl)) = NULL_TREE;
 
-  if (TREE_CODE (decl) == CONST_DECL)
-    DECL_CONTEXT (decl) = NULL_TREE;
-
   /* Ignore any intervening types, because we are going to clear their
      TYPE_CONTEXT fields.  */
   if (TREE_CODE (decl) != FIELD_DECL)
@@ -4377,6 +4393,10 @@ free_lang_data_in_decl (tree decl)
          && DECL_FIELD_OFFSET (decl)
          && TREE_CODE (DECL_FIELD_OFFSET (decl)) != INTEGER_CST)
        DECL_FIELD_OFFSET (decl) = NULL_TREE;
+
+      /* DECL_FCONTEXT is only used for debug info generation.  */
+      if (TREE_CODE (decl) == FIELD_DECL)
+       DECL_FCONTEXT (decl) = NULL_TREE;
     }
   else if (TREE_CODE (decl) == FUNCTION_DECL)
     {
@@ -4427,7 +4447,8 @@ free_lang_data_in_decl (tree decl)
          && !TREE_STATIC (expr) && !DECL_EXTERNAL (expr))
        SET_DECL_DEBUG_EXPR (decl, NULL_TREE);
 
-      if (DECL_EXTERNAL (decl))
+      if (DECL_EXTERNAL (decl)
+         && (!TREE_STATIC (decl) || !TREE_READONLY (decl)))
        DECL_INITIAL (decl) = NULL_TREE;
     }
   else if (TREE_CODE (decl) == TYPE_DECL)
@@ -4447,6 +4468,9 @@ free_lang_data_in_decl (tree decl)
 
 struct free_lang_data_d
 {
+  /* Worklist to avoid excessive recursion.  */
+  VEC(tree,heap) *worklist;
+
   /* Set of traversed objects.  Used to avoid duplicate visits.  */
   struct pointer_set_t *pset;
 
@@ -4508,59 +4532,82 @@ add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
     gcc_unreachable ();
 }
 
+/* Push tree node T into FLD->WORKLIST.  */
+
+static inline void
+fld_worklist_push (tree t, struct free_lang_data_d *fld)
+{
+  if (t && !is_lang_specific (t) && !pointer_set_contains (fld->pset, t))
+    VEC_safe_push (tree, heap, fld->worklist, (t));
+}
+
 
 /* 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)
+find_decls_types_r (tree *tp, int *ws, void *data)
 {
   tree t = *tp;
   struct free_lang_data_d *fld = (struct free_lang_data_d *) data;
 
+  if (TREE_CODE (t) == TREE_LIST)
+    return NULL_TREE;
+
+  /* Language specific nodes will be removed, so there is no need
+     to gather anything under them.  */
+  if (is_lang_specific (t))
+    {
+      *ws = 0;
+      return NULL_TREE;
+    }
+
   if (DECL_P (t))
     {
       /* Note that walk_tree does not traverse every possible field in
         decls, so we have to do our own traversals here.  */
       add_tree_to_fld_list (t, fld);
 
-      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);
+      fld_worklist_push (DECL_NAME (t), fld);
+      fld_worklist_push (DECL_CONTEXT (t), fld);
+      fld_worklist_push (DECL_SIZE (t), fld);
+      fld_worklist_push (DECL_SIZE_UNIT (t), fld);
+
+      /* We are going to remove everything under DECL_INITIAL for
+        TYPE_DECLs.  No point walking them.  */
+      if (TREE_CODE (t) != TYPE_DECL)
+       fld_worklist_push (DECL_INITIAL (t), fld);
+
+      fld_worklist_push (DECL_ATTRIBUTES (t), fld);
+      fld_worklist_push (DECL_ABSTRACT_ORIGIN (t), fld);
 
       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);
+         fld_worklist_push (DECL_ARGUMENTS (t), fld);
+         fld_worklist_push (DECL_RESULT (t), fld);
        }
       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);
+         fld_worklist_push (DECL_ARGUMENT_FLD (t), fld);
+         fld_worklist_push (DECL_VINDEX (t), fld);
        }
       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, fld,
-                    fld->pset);
-         walk_tree (&DECL_FCONTEXT (t), find_decls_types_r, fld, fld->pset);
+         fld_worklist_push (DECL_FIELD_OFFSET (t), fld);
+         fld_worklist_push (DECL_BIT_FIELD_TYPE (t), fld);
+         fld_worklist_push (DECL_QUALIFIER (t), fld);
+         fld_worklist_push (DECL_FIELD_BIT_OFFSET (t), fld);
+         fld_worklist_push (DECL_FCONTEXT (t), fld);
        }
       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);
+         fld_worklist_push (DECL_SECTION_NAME (t), fld);
+         fld_worklist_push (DECL_COMDAT_GROUP (t), fld);
        }
+
+      if (TREE_CODE (t) != FIELD_DECL)
+       fld_worklist_push (TREE_CHAIN (t), fld);
+      *ws = 0;
     }
   else if (TYPE_P (t))
     {
@@ -4568,37 +4615,79 @@ find_decls_types_r (tree *tp, int *ws ATTRIBUTE_UNUSED, void *data)
         types, so we have to do our own traversals here.  */
       add_tree_to_fld_list (t, fld);
 
-      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 (!RECORD_OR_UNION_TYPE_P (t))
+       fld_worklist_push (TYPE_CACHED_VALUES (t), fld);
+      fld_worklist_push (TYPE_SIZE (t), fld);
+      fld_worklist_push (TYPE_SIZE_UNIT (t), fld);
+      fld_worklist_push (TYPE_ATTRIBUTES (t), fld);
+      fld_worklist_push (TYPE_POINTER_TO (t), fld);
+      fld_worklist_push (TYPE_REFERENCE_TO (t), fld);
+      fld_worklist_push (TYPE_NAME (t), fld);
+      fld_worklist_push (TYPE_MINVAL (t), fld);
+      if (!RECORD_OR_UNION_TYPE_P (t))
+       fld_worklist_push (TYPE_MAXVAL (t), fld);
+      fld_worklist_push (TYPE_MAIN_VARIANT (t), fld);
+      fld_worklist_push (TYPE_NEXT_VARIANT (t), fld);
+      fld_worklist_push (TYPE_CONTEXT (t), fld);
+      fld_worklist_push (TYPE_CANONICAL (t), fld);
+
+      if (RECORD_OR_UNION_TYPE_P (t) && TYPE_BINFO (t))
+       {
+         unsigned i;
+         tree tem;
+         for (i = 0; VEC_iterate (tree, BINFO_BASE_BINFOS (TYPE_BINFO (t)),
+                                  i, tem); ++i)
+           fld_worklist_push (TREE_TYPE (tem), fld);
+         tem = BINFO_VIRTUALS (TYPE_BINFO (t));
+         if (tem
+             /* The Java FE overloads BINFO_VIRTUALS for its own purpose.  */
+             && TREE_CODE (tem) == TREE_LIST)
+           do
+             {
+               fld_worklist_push (TREE_VALUE (tem), fld);
+               tem = TREE_CHAIN (tem);
+             }
+           while (tem);
+       }
+      if (RECORD_OR_UNION_TYPE_P (t))
+       {
+         tree tem;
+         /* Push all TYPE_FIELDS - there can be interleaving interesting
+            and non-interesting things.  */
+         tem = TYPE_FIELDS (t);
+         while (tem)
+           {
+             if (TREE_CODE (tem) == FIELD_DECL)
+               fld_worklist_push (tem, fld);
+             tem = TREE_CHAIN (tem);
+           }
+       }
 
-  /* Do not recurse into TREE_CHAIN to avoid blowing up the stack.  */
-  for (tp = &TREE_CHAIN (t); *tp; tp = &TREE_CHAIN (*tp))
-    {
-      tree saved_chain = TREE_CHAIN (*tp);
-      TREE_CHAIN (*tp) = NULL_TREE;
-      walk_tree (tp, find_decls_types_r, fld, fld->pset);
-      TREE_CHAIN (*tp) = saved_chain;
+      fld_worklist_push (TREE_CHAIN (t), fld);
+      *ws = 0;
     }
 
+  fld_worklist_push (TREE_TYPE (t), fld);
+
   return NULL_TREE;
 }
 
 
+/* Find decls and types in T.  */
+
+static void
+find_decls_types (tree t, struct free_lang_data_d *fld)
+{
+  while (1)
+    {
+      if (!pointer_set_contains (fld->pset, t))
+       walk_tree (&t, find_decls_types_r, fld, fld->pset);
+      if (VEC_empty (tree, fld->worklist))
+       break;
+      t = VEC_pop (tree, fld->worklist);
+    }
+}
+
 /* Translate all the types in LIST with the corresponding runtime
    types.  */
 
@@ -4631,23 +4720,36 @@ get_eh_types_for_runtime (tree list)
 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)
+  switch (r->type)
     {
-      tree list = r->u.allowed.type_list;
-      r->u.allowed.type_list = get_eh_types_for_runtime (list);
+    case ERT_CLEANUP:
+      break;
+
+    case ERT_TRY:
+      {
+       eh_catch c;
+
+       /* The types referenced in each catch must first be changed to the
+          EH types used at runtime.  This removes references to FE types
+          in the region.  */
+       for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
+         {
+           c->type_list = get_eh_types_for_runtime (c->type_list);
+           walk_tree (&c->type_list, find_decls_types_r, fld, fld->pset);
+         }
+      }
+      break;
+
+    case ERT_ALLOWED_EXCEPTIONS:
+      r->u.allowed.type_list
+       = get_eh_types_for_runtime (r->u.allowed.type_list);
       walk_tree (&r->u.allowed.type_list, find_decls_types_r, fld, fld->pset);
+      break;
+
+    case ERT_MUST_NOT_THROW:
+      walk_tree (&r->u.must_not_throw.failure_decl,
+                find_decls_types_r, fld, fld->pset);
+      break;
     }
 }
 
@@ -4665,7 +4767,7 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
   struct function *fn;
   tree t;
 
-  walk_tree (&n->decl, find_decls_types_r, fld, fld->pset);
+  find_decls_types (n->decl, fld);
 
   if (!gimple_has_body_p (n->decl))
     return;
@@ -4676,23 +4778,14 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
 
   /* Traverse locals. */
   for (t = fn->local_decls; t; t = TREE_CHAIN (t))
-    {
-      tree *tp = &TREE_VALUE (t);
-      tree saved_chain = TREE_CHAIN (*tp);
-      TREE_CHAIN (*tp) = NULL_TREE;
-      walk_tree (tp, find_decls_types_r, fld, fld->pset);
-      TREE_CHAIN (*tp) = saved_chain;
-    }
+    find_decls_types (TREE_VALUE (t), fld);
 
   /* 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);
-    }
+  {
+    eh_region r;
+    FOR_ALL_EH_REGION_FN (r, fn)
+      find_decls_types_in_eh_region (r, fld);
+  }
 
   /* Traverse every statement in FN.  */
   FOR_EACH_BB_FN (bb, fn)
@@ -4707,7 +4800,7 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
          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);
+             find_decls_types (*arg_p, fld);
            }
        }
 
@@ -4717,8 +4810,8 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
 
          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);
+             tree arg = gimple_op (stmt, i);
+             find_decls_types (arg, fld);
            }
        }
     }
@@ -4734,7 +4827,7 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
 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);
+  find_decls_types (v->decl, fld);
 }
 
 
@@ -4767,6 +4860,7 @@ free_lang_data_in_cgraph (void)
 
   /* Initialize sets and arrays to store referenced decls and types.  */
   fld.pset = pointer_set_create ();
+  fld.worklist = NULL;
   fld.decls = VEC_alloc (tree, heap, 100);
   fld.types = VEC_alloc (tree, heap, 100);
 
@@ -4775,7 +4869,7 @@ free_lang_data_in_cgraph (void)
     find_decls_types_in_node (n, &fld);
 
   for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
-    walk_tree (&p->decl, find_decls_types_r, &fld, fld.pset);
+    find_decls_types (p->decl, &fld);
 
   /* Find decls and types in every varpool symbol.  */
   for (v = varpool_nodes_queue; v; v = v->next_needed)
@@ -4815,6 +4909,7 @@ free_lang_data_in_cgraph (void)
     free_lang_data_in_type (t);
 
   pointer_set_destroy (fld.pset);
+  VEC_free (tree, heap, fld.worklist);
   VEC_free (tree, heap, fld.decls);
   VEC_free (tree, heap, fld.types);
 }
@@ -4825,6 +4920,23 @@ free_lang_data_in_cgraph (void)
 static unsigned
 free_lang_data (void)
 {
+  unsigned i;
+
+  /* If we are the LTO frontend we have freed lang-specific data already.  */
+  if (in_lto_p)
+    return 0;
+
+  /* Allocate and assign alias sets to the standard integer types
+     while the slots are still in the way the frontends generated them.  */
+  for (i = 0; i < itk_none; ++i)
+    if (integer_types[i])
+      TYPE_ALIAS_SET (integer_types[i]) = get_alias_set (integer_types[i]);
+
+  /* FIXME.  Remove after save_debug_info is working.  */
+  if (!(flag_generate_lto
+       || (!flag_gtoggle && debug_info_level <= DINFO_LEVEL_TERSE)))
+    return 0;
+
   /* Traverse the IL resetting language specific information for
      operands, expressions, etc.  */
   free_lang_data_in_cgraph ();
@@ -4852,9 +4964,9 @@ free_lang_data (void)
   else
     signed_char_type_node = char_type_node;
 
-  /* Reset some langhooks.  */
+  /* Reset some langhooks.  Do not reset types_compatible_p, it may
+     still be used indirectly via the get_alias_set langhook.  */
   lang_hooks.callgraph.analyze_expr = NULL;
-  lang_hooks.types_compatible_p = NULL;
   lang_hooks.dwarf_name = lhd_dwarf_name;
   lang_hooks.decl_printable_name = gimple_decl_printable_name;
   lang_hooks.set_decl_assembler_name = lhd_set_decl_assembler_name;
@@ -4865,17 +4977,14 @@ free_lang_data (void)
   diagnostic_finalizer (global_dc) = default_diagnostic_finalizer;
   diagnostic_format_decoder (global_dc) = default_tree_printer;
 
-  return 0;
-}
-
-
-/* Gate function for free_lang_data.  */
+  /* FIXME. We remove sufficient language data that the debug
+     info writer gets completely confused.  Disable debug information
+     for now.  */
+  debug_info_level = DINFO_LEVEL_NONE;
+  write_symbols = NO_DEBUG;
+  debug_hooks = &do_nothing_debug_hooks;
 
-static bool
-gate_free_lang_data (void)
-{
-  /* FIXME.  Remove after save_debug_info is working.  */
-  return !flag_gtoggle && debug_info_level <= DINFO_LEVEL_TERSE;
+  return 0;
 }
 
 
@@ -4883,8 +4992,8 @@ struct simple_ipa_opt_pass pass_ipa_free_lang_data =
 {
  {
   SIMPLE_IPA_PASS,
-  NULL,                                        /* name */
-  gate_free_lang_data,                 /* gate */
+  "*free_lang_data",                   /* name */
+  NULL,                                        /* gate */
   free_lang_data,                      /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
@@ -5311,6 +5420,7 @@ set_type_quals (tree type, int type_quals)
   TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;
   TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
   TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
+  TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
 }
 
 /* Returns true iff CAND is equivalent to BASE with TYPE_QUALS.  */
@@ -6632,7 +6742,10 @@ build_pointer_type_for_mode (tree to_type, enum machine_mode mode,
 tree
 build_pointer_type (tree to_type)
 {
-  return build_pointer_type_for_mode (to_type, ptr_mode, false);
+  addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
+                                             : TYPE_ADDR_SPACE (to_type);
+  enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
+  return build_pointer_type_for_mode (to_type, pointer_mode, false);
 }
 
 /* Same as build_pointer_type_for_mode, but for REFERENCE_TYPE.  */
@@ -6696,7 +6809,10 @@ build_reference_type_for_mode (tree to_type, enum machine_mode mode,
 tree
 build_reference_type (tree to_type)
 {
-  return build_reference_type_for_mode (to_type, ptr_mode, false);
+  addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
+                                             : TYPE_ADDR_SPACE (to_type);
+  enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
+  return build_reference_type_for_mode (to_type, pointer_mode, false);
 }
 
 /* Build a type that is compatible with t but has no cv quals anywhere
@@ -6890,6 +7006,7 @@ build_array_type (tree elt_type, tree index_type)
   t = make_node (ARRAY_TYPE);
   TREE_TYPE (t) = elt_type;
   TYPE_DOMAIN (t) = index_type;
+  TYPE_ADDR_SPACE (t) = TYPE_ADDR_SPACE (elt_type);
   layout_type (t);
 
   /* If the element type is incomplete at this point we get marked for
@@ -8853,7 +8970,7 @@ local_define_builtin (const char *name, tree type, enum built_in_function code,
 void
 build_common_builtin_nodes (void)
 {
-  tree tmp, ftype;
+  tree tmp, tmp2, ftype;
 
   if (built_in_decls[BUILT_IN_MEMCPY] == NULL
       || built_in_decls[BUILT_IN_MEMMOVE] == NULL)
@@ -8896,7 +9013,8 @@ build_common_builtin_nodes (void)
       tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
       ftype = build_function_type (ptr_type_node, tmp);
       local_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA,
-                           "alloca", ECF_NOTHROW | ECF_MALLOC);
+                           "alloca",
+                           ECF_MALLOC | (flag_stack_check ? 0 : ECF_NOTHROW));
     }
 
   tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
@@ -8958,6 +9076,47 @@ build_common_builtin_nodes (void)
   local_define_builtin ("__builtin_profile_func_exit", ftype,
                        BUILT_IN_PROFILE_FUNC_EXIT, "profile_func_exit", 0);
 
+  /* If there's a possibility that we might use the ARM EABI, build the
+    alternate __cxa_end_cleanup node used to resume from C++ and Java.  */
+  if (targetm.arm_eabi_unwinder)
+    {
+      ftype = build_function_type (void_type_node, void_list_node);
+      local_define_builtin ("__builtin_cxa_end_cleanup", ftype,
+                           BUILT_IN_CXA_END_CLEANUP,
+                           "__cxa_end_cleanup", ECF_NORETURN);
+    }
+
+  tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+  ftype = build_function_type (void_type_node, tmp);
+  local_define_builtin ("__builtin_unwind_resume", ftype,
+                       BUILT_IN_UNWIND_RESUME,
+                       (USING_SJLJ_EXCEPTIONS
+                        ? "_Unwind_SjLj_Resume" : "_Unwind_Resume"),
+                       ECF_NORETURN);
+
+  /* The exception object and filter values from the runtime.  The argument
+     must be zero before exception lowering, i.e. from the front end.  After
+     exception lowering, it will be the region number for the exception
+     landing pad.  These functions are PURE instead of CONST to prevent
+     them from being hoisted past the exception edge that will initialize
+     its value in the landing pad.  */
+  tmp = tree_cons (NULL_TREE, integer_type_node, void_list_node);
+  ftype = build_function_type (ptr_type_node, tmp);
+  local_define_builtin ("__builtin_eh_pointer", ftype, BUILT_IN_EH_POINTER,
+                       "__builtin_eh_pointer", ECF_PURE | ECF_NOTHROW);
+
+  tmp2 = lang_hooks.types.type_for_mode (targetm.eh_return_filter_mode (), 0);
+  ftype = build_function_type (tmp2, tmp);
+  local_define_builtin ("__builtin_eh_filter", ftype, BUILT_IN_EH_FILTER,
+                       "__builtin_eh_filter", ECF_PURE | ECF_NOTHROW);
+
+  tmp = tree_cons (NULL_TREE, integer_type_node, void_list_node);
+  tmp = tree_cons (NULL_TREE, integer_type_node, tmp);
+  ftype = build_function_type (void_type_node, tmp);
+  local_define_builtin ("__builtin_eh_copy_values", ftype,
+                       BUILT_IN_EH_COPY_VALUES,
+                       "__builtin_eh_copy_values", ECF_NOTHROW);
+
   /* Complex multiplication and division.  These are handled as builtins
      rather than optabs because emit_library_call_value doesn't support
      complex.  Further, we can do slightly better with folding these 
@@ -9059,7 +9218,8 @@ reconstruct_complex_type (tree type, tree bottom)
   else
     return bottom;
 
-  return build_qualified_type (outer, TYPE_QUALS (type));
+  return build_type_attribute_qual_variant (outer, TYPE_ATTRIBUTES (type),
+                                           TYPE_QUALS (type));
 }
 
 /* Returns a vector tree node given a mode (integer, vector, or BLKmode) and
@@ -9119,16 +9279,6 @@ build_opaque_vector_type (tree innertype, int nunits)
 }
 
 
-/* Build RESX_EXPR with given REGION_NUMBER.  */
-tree
-build_resx (int region_number)
-{
-  tree t;
-  t = build1 (RESX_EXPR, void_type_node,
-             build_int_cst (NULL_TREE, region_number));
-  return t;
-}
-
 /* Given an initializer INIT, return TRUE if INIT is zero or some
    aggregate of zeros.  Otherwise return FALSE.  */
 bool
@@ -9529,7 +9679,19 @@ signed_or_unsigned_type_for (int unsignedp, tree type)
 {
   tree t = type;
   if (POINTER_TYPE_P (type))
-    t = size_type_node;
+    {
+      /* If the pointer points to the normal address space, use the
+        size_type_node.  Otherwise use an appropriate size for the pointer
+        based on the named address space it points to.  */
+      if (!TYPE_ADDR_SPACE (TREE_TYPE (t)))
+       t = size_type_node;
+
+      else
+       {
+         int prec = int_or_pointer_precision (t);
+         return lang_hooks.types.type_for_size (prec, unsignedp);
+       }
+    }
 
   if (!INTEGRAL_TYPE_P (t) || TYPE_UNSIGNED (t) == unsignedp)
     return t;
@@ -10037,9 +10199,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
            return result;
 
          /* If this is a record type, also walk the fields.  */
-         if (TREE_CODE (*type_p) == RECORD_TYPE
-             || TREE_CODE (*type_p) == UNION_TYPE
-             || TREE_CODE (*type_p) == QUAL_UNION_TYPE)
+         if (RECORD_OR_UNION_TYPE_P (*type_p))
            {
              tree field;
 
@@ -10405,6 +10565,41 @@ build_target_option_node (void)
   return t;
 }
 
+/* Return the size in bits of an integer or pointer type.  TYPE_PRECISION
+   contains the bits, but in the past it was not set in some cases and there
+   was special purpose code that checked for POINTER_TYPE_P or OFFSET_TYPE, so
+   check that it is consitant when assertion checking is used.  */
+
+unsigned int
+int_or_pointer_precision (const_tree type)
+{
+#if ENABLE_ASSERT_CHECKING
+  unsigned int prec;
+
+  if (POINTER_TYPE_P (type))
+    {
+      addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (type));
+      prec = GET_MODE_BITSIZE (targetm.addr_space.pointer_mode (as));
+      gcc_assert (prec == TYPE_PRECISION (type));
+    }
+  else if (TREE_CODE (type) == OFFSET_TYPE)
+    {
+      prec = POINTER_SIZE;
+      gcc_assert (prec == TYPE_PRECISION (type));
+    }
+  else
+    {
+      prec = TYPE_PRECISION (type);
+      gcc_assert (prec != 0);
+    }
+
+  return prec;
+
+#else
+  return TYPE_PRECISION (type);
+#endif
+}
+
 /* Determine the "ultimate origin" of a block.  The block may be an inlined
    instance of an inlined instance of a block which is local to an inline
    function, so we have to trace all of the way back through the origin chain
@@ -10534,5 +10729,20 @@ tree_strip_sign_nop_conversions (tree exp)
   return exp;
 }
 
+static GTY(()) tree gcc_eh_personality_decl;
+
+/* Return the GCC personality function decl.  */
+
+tree
+lhd_gcc_personality (void)
+{
+  if (!gcc_eh_personality_decl)
+    gcc_eh_personality_decl
+      = build_personality_function (USING_SJLJ_EXCEPTIONS
+                                   ? "__gcc_personality_sj0"
+                                   : "__gcc_personality_v0");
+
+  return gcc_eh_personality_decl;
+}
 
 #include "gt-tree.h"