OSDN Git Service

Give credit, where credit is due.
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index 64d2dd5..de74fe9 100644 (file)
@@ -1,6 +1,6 @@
 /* Language-independent node constructors for parse phase of GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -48,6 +48,25 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree-iterator.h"
 #include "basic-block.h"
 #include "tree-flow.h"
+#include "params.h"
+#include "pointer-set.h"
+
+/* Each tree code class has an associated string representation.
+   These must correspond to the tree_code_class entries.  */
+
+const char *const tree_code_class_strings[] =
+{
+  "exceptional",
+  "constant",
+  "type",
+  "declaration",
+  "reference",
+  "comparison",
+  "unary",
+  "binary",
+  "statement",
+  "expression",
+};
 
 /* obstack.[ch] explicitly declined to prototype this.  */
 extern int _obstack_allocated_p (struct obstack *h, void *obj);
@@ -71,6 +90,7 @@ static const char * const tree_node_kind_names[] = {
   "perm_tree_lists",
   "temp_tree_lists",
   "vecs",
+  "binfos",
   "phi_nodes",
   "ssa names",
   "random kinds",
@@ -106,11 +126,18 @@ struct type_hash GTY(())
 static GTY ((if_marked ("type_hash_marked_p"), param_is (struct type_hash)))
      htab_t type_hash_table;
 
+/* Hash table and temporary node for larger integer const values.  */
+static GTY (()) tree int_cst_node;
+static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
+     htab_t int_cst_hash_table;
+
 static void set_type_quals (tree, int);
 static int type_hash_eq (const void *, const void *);
 static hashval_t type_hash_hash (const void *);
+static hashval_t int_cst_hash_hash (const void *);
+static int int_cst_hash_eq (const void *, const void *);
 static void print_type_hash_statistics (void);
-static void finish_vector_type (tree);
+static tree make_vector_type (tree, int, enum machine_mode);
 static int type_hash_marked_p (const void *);
 static unsigned int type_hash_list (tree, hashval_t);
 static unsigned int attribute_hash_list (tree, hashval_t);
@@ -126,6 +153,9 @@ init_ttree (void)
   /* Initialize the hash table of types.  */
   type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
                                     type_hash_eq, 0);
+  int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
+                                       int_cst_hash_eq, NULL);
+  int_cst_node = make_node (INTEGER_CST);
 }
 
 \f
@@ -140,57 +170,52 @@ decl_assembler_name (tree decl)
   return DECL_CHECK (decl)->decl.assembler_name;
 }
 
-/* Compute the number of bytes occupied by 'node'.  This routine only
-   looks at TREE_CODE and, if the code is TREE_VEC, TREE_VEC_LENGTH.  */
+/* Compute the number of bytes occupied by a tree with code CODE.
+   This function cannot be used for TREE_VEC, PHI_NODE, or STRING_CST
+   codes, which are of variable length.  */
 size_t
-tree_size (tree node)
+tree_code_size (enum tree_code code)
 {
-  enum tree_code code = TREE_CODE (node);
-
   switch (TREE_CODE_CLASS (code))
     {
-    case 'd':  /* A decl node */
+    case tcc_declaration:  /* A decl node */
       return sizeof (struct tree_decl);
 
-    case 't':  /* a type node */
+    case tcc_type:  /* a type node */
       return sizeof (struct tree_type);
 
-    case 'r':  /* a reference */
-    case 'e':  /* an expression */
-    case 's':  /* an expression with side effects */
-    case '<':  /* a comparison expression */
-    case '1':  /* a unary arithmetic expression */
-    case '2':  /* a binary arithmetic expression */
+    case tcc_reference:   /* a reference */
+    case tcc_expression:  /* an expression */
+    case tcc_statement:   /* an expression with side effects */
+    case tcc_comparison:  /* a comparison expression */
+    case tcc_unary:       /* a unary arithmetic expression */
+    case tcc_binary:      /* a binary arithmetic expression */
       return (sizeof (struct tree_exp)
-             + TREE_CODE_LENGTH (code) * sizeof (char *) - sizeof (char *));
+             + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *));
 
-    case 'c':  /* a constant */
+    case tcc_constant:  /* a constant */
       switch (code)
        {
        case INTEGER_CST:       return sizeof (struct tree_int_cst);
        case REAL_CST:          return sizeof (struct tree_real_cst);
        case COMPLEX_CST:       return sizeof (struct tree_complex);
        case VECTOR_CST:        return sizeof (struct tree_vector);
-       case STRING_CST:        return sizeof (struct tree_string);
+       case STRING_CST:        gcc_unreachable ();
        default:
          return lang_hooks.tree_size (code);
        }
 
-    case 'x':  /* something random, like an identifier.  */
+    case tcc_exceptional:  /* something random, like an identifier.  */
       switch (code)
        {
        case IDENTIFIER_NODE:   return lang_hooks.identifier_size;
        case TREE_LIST:         return sizeof (struct tree_list);
-       case TREE_VEC:          return (sizeof (struct tree_vec)
-                                       + TREE_VEC_LENGTH(node) * sizeof(char *)
-                                       - sizeof (char *));
 
        case ERROR_MARK:
        case PLACEHOLDER_EXPR:  return sizeof (struct tree_common);
 
-       case PHI_NODE:          return (sizeof (struct tree_phi_node)
-                                       + (PHI_ARG_CAPACITY (node) - 1) *
-                                       sizeof (struct phi_arg_d));
+       case TREE_VEC:
+       case PHI_NODE:          gcc_unreachable ();
 
        case SSA_NAME:          return sizeof (struct tree_ssa_name);
 
@@ -203,13 +228,42 @@ tree_size (tree node)
        }
 
     default:
-      abort ();
+      gcc_unreachable ();
+    }
+}
+
+/* Compute the number of bytes occupied by NODE.  This routine only
+   looks at TREE_CODE, except for PHI_NODE and TREE_VEC nodes.  */
+size_t
+tree_size (tree node)
+{
+  enum tree_code code = TREE_CODE (node);
+  switch (code)
+    {
+    case PHI_NODE:
+      return (sizeof (struct tree_phi_node)
+             + (PHI_ARG_CAPACITY (node) - 1) * sizeof (struct phi_arg_d));
+
+    case TREE_BINFO:
+      return (offsetof (struct tree_binfo, base_binfos)
+             + VEC_embedded_size (tree, BINFO_N_BASE_BINFOS (node)));
+
+    case TREE_VEC:
+      return (sizeof (struct tree_vec)
+             + (TREE_VEC_LENGTH (node) - 1) * sizeof(char *));
+
+    case STRING_CST:
+      return sizeof (struct tree_string) + TREE_STRING_LENGTH (node) - 1;
+
+    default:
+      return tree_code_size (code);
     }
 }
 
-/* Return a newly allocated node of code CODE.
-   For decl and type nodes, some other fields are initialized.
-   The rest of the node is initialized to zero.
+/* Return a newly allocated node of code CODE.  For decl and type
+   nodes, some other fields are initialized.  The rest of the node is
+   initialized to zero.  This function cannot be used for PHI_NODE or
+   TREE_VEC nodes, which is enforced by asserts in tree_code_size.
 
    Achoo!  I got a code in the node.  */
 
@@ -217,75 +271,85 @@ tree
 make_node_stat (enum tree_code code MEM_STAT_DECL)
 {
   tree t;
-  int type = TREE_CODE_CLASS (code);
-  size_t length;
+  enum tree_code_class type = TREE_CODE_CLASS (code);
+  size_t length = tree_code_size (code);
 #ifdef GATHER_STATISTICS
   tree_node_kind kind;
-#endif
-  struct tree_common ttmp;
-
-  /* We can't allocate a TREE_VEC, PHI_NODE, or STRING_CST
-     without knowing how many elements it will have.  */
-  if (code == TREE_VEC || code == PHI_NODE)
-    abort ();
-
-  TREE_SET_CODE ((tree)&ttmp, code);
-  length = tree_size ((tree)&ttmp);
 
-#ifdef GATHER_STATISTICS
   switch (type)
     {
-    case 'd':  /* A decl node */
+    case tcc_declaration:  /* A decl node */
       kind = d_kind;
       break;
 
-    case 't':  /* a type node */
+    case tcc_type:  /* a type node */
       kind = t_kind;
       break;
 
-    case 's':  /* an expression with side effects */
+    case tcc_statement:  /* an expression with side effects */
       kind = s_kind;
       break;
 
-    case 'r':  /* a reference */
+    case tcc_reference:  /* a reference */
       kind = r_kind;
       break;
 
-    case 'e':  /* an expression */
-    case '<':  /* a comparison expression */
-    case '1':  /* a unary arithmetic expression */
-    case '2':  /* a binary arithmetic expression */
+    case tcc_expression:  /* an expression */
+    case tcc_comparison:  /* a comparison expression */
+    case tcc_unary:  /* a unary arithmetic expression */
+    case tcc_binary:  /* a binary arithmetic expression */
       kind = e_kind;
       break;
 
-    case 'c':  /* a constant */
+    case tcc_constant:  /* a constant */
       kind = c_kind;
       break;
 
-    case 'x':  /* something random, like an identifier.  */
-      if (code == IDENTIFIER_NODE)
-       kind = id_kind;
-      else if (code == TREE_VEC)
-       kind = vec_kind;
-      else if (code == PHI_NODE)
-       kind = phi_kind;
-      else if (code == SSA_NAME)
-       kind = ssa_name_kind;
-      else if (code == BLOCK)
-       kind = b_kind;
-      else
-       kind = x_kind;
-      break;
+    case tcc_exceptional:  /* something random, like an identifier.  */
+      switch (code)
+       {
+       case IDENTIFIER_NODE:
+         kind = id_kind;
+         break;
+
+       case TREE_VEC:;
+         kind = vec_kind;
+         break;
 
+       case TREE_BINFO:
+         kind = binfo_kind;
+         break;
+
+       case PHI_NODE:
+         kind = phi_kind;
+         break;
+
+       case SSA_NAME:
+         kind = ssa_name_kind;
+         break;
+
+       case BLOCK:
+         kind = b_kind;
+         break;
+
+       default:
+         kind = x_kind;
+         break;
+       }
+      break;
+      
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   tree_node_counts[(int) kind]++;
   tree_node_sizes[(int) kind] += length;
 #endif
 
-  t = ggc_alloc_zone_stat (length, tree_zone PASS_MEM_STAT);
+  if (code == IDENTIFIER_NODE)
+    t = ggc_alloc_zone_pass_stat (length, &tree_id_zone);
+  else
+    t = ggc_alloc_zone_pass_stat (length, &tree_zone);
 
   memset (t, 0, length);
 
@@ -293,11 +357,11 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
 
   switch (type)
     {
-    case 's':
+    case tcc_statement:
       TREE_SIDE_EFFECTS (t) = 1;
       break;
 
-    case 'd':
+    case tcc_declaration:
       if (code != FUNCTION_DECL)
        DECL_ALIGN (t) = 1;
       DECL_USER_ALIGN (t) = 0;
@@ -309,7 +373,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
       DECL_POINTER_ALIAS_SET (t) = -1;
       break;
 
-    case 't':
+    case tcc_type:
       TYPE_UID (t) = next_type_uid++;
       TYPE_ALIGN (t) = char_type_node ? TYPE_ALIGN (char_type_node) : 0;
       TYPE_USER_ALIGN (t) = 0;
@@ -323,12 +387,12 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
       TYPE_ALIAS_SET (t) = -1;
       break;
 
-    case 'c':
+    case tcc_constant:
       TREE_CONSTANT (t) = 1;
       TREE_INVARIANT (t) = 1;
       break;
 
-    case 'e':
+    case tcc_expression:
       switch (code)
        {
        case INIT_EXPR:
@@ -347,6 +411,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
          break;
        }
       break;
+
+    default:
+      /* Other classes need no special treatment.  */
+      break;
     }
 
   return t;
@@ -362,13 +430,10 @@ copy_node_stat (tree node MEM_STAT_DECL)
   enum tree_code code = TREE_CODE (node);
   size_t length;
 
-#ifdef ENABLE_CHECKING
-  if (code == STATEMENT_LIST)
-    abort ();
-#endif
+  gcc_assert (code != STATEMENT_LIST);
 
   length = tree_size (node);
-  t = ggc_alloc_zone_stat (length, tree_zone PASS_MEM_STAT);
+  t = ggc_alloc_zone_pass_stat (length, &tree_zone);
   memcpy (t, node, length);
 
   TREE_CHAIN (t) = 0;
@@ -376,9 +441,9 @@ copy_node_stat (tree node MEM_STAT_DECL)
   TREE_VISITED (t) = 0;
   t->common.ann = 0;
 
-  if (TREE_CODE_CLASS (code) == 'd')
+  if (TREE_CODE_CLASS (code) == tcc_declaration)
     DECL_UID (t) = next_decl_uid++;
-  else if (TREE_CODE_CLASS (code) == 't')
+  else if (TREE_CODE_CLASS (code) == tcc_type)
     {
       TYPE_UID (t) = next_type_uid++;
       /* The following is so that the debug code for
@@ -388,6 +453,13 @@ copy_node_stat (tree node MEM_STAT_DECL)
         but the optimizer should catch that.  */
       TYPE_SYMTAB_POINTER (t) = 0;
       TYPE_SYMTAB_ADDRESS (t) = 0;
+      
+      /* Do not copy the values cache.  */
+      if (TYPE_CACHED_VALUES_P(t))
+       {
+         TYPE_CACHED_VALUES_P (t) = 0;
+         TYPE_CACHED_VALUES (t) = NULL_TREE;
+       }
     }
 
   return t;
@@ -417,23 +489,272 @@ copy_list (tree list)
 }
 
 \f
-/* Return a newly constructed INTEGER_CST node whose constant value
-   is specified by the two ints LOW and HI.
-   The TREE_TYPE is set to `int'.
+/* Create an INT_CST node with a LOW value sign extended.  */
+
+tree
+build_int_cst (tree type, HOST_WIDE_INT low)
+{
+  return build_int_cst_wide (type, low, low < 0 ? -1 : 0);
+}
+
+/* Create an INT_CST node with a LOW value zero extended.  */
+
+tree
+build_int_cstu (tree type, unsigned HOST_WIDE_INT low)
+{
+  return build_int_cst_wide (type, low, 0);
+}
+
+/* Create an INT_CST node with a LOW value in TYPE.  The value is sign extended
+   if it is negative.  This function is similar to build_int_cst, but
+   the extra bits outside of the type precision are cleared.  Constants
+   with these extra bits may confuse the fold so that it detects overflows
+   even in cases when they do not occur, and in general should be avoided.
+   We cannot however make this a default behavior of build_int_cst without
+   more intrusive changes, since there are parts of gcc that rely on the extra
+   precision of the integer constants.  */
+
+tree
+build_int_cst_type (tree type, HOST_WIDE_INT low)
+{
+  unsigned HOST_WIDE_INT val = (unsigned HOST_WIDE_INT) low;
+  unsigned HOST_WIDE_INT hi, mask;
+  unsigned bits;
+  bool signed_p;
+  bool negative;
+
+  if (!type)
+    type = integer_type_node;
+
+  bits = TYPE_PRECISION (type);
+  signed_p = !TYPE_UNSIGNED (type);
+
+  if (bits >= HOST_BITS_PER_WIDE_INT)
+    negative = (low < 0);
+  else
+    {
+      /* If the sign bit is inside precision of LOW, use it to determine
+        the sign of the constant.  */
+      negative = ((val >> (bits - 1)) & 1) != 0;
+
+      /* Mask out the bits outside of the precision of the constant.  */
+      mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1;
+
+      if (signed_p && negative)
+       val |= ~mask;
+      else
+       val &= mask;
+    }
+
+  /* Determine the high bits.  */
+  hi = (negative ? ~(unsigned HOST_WIDE_INT) 0 : 0);
+
+  /* For unsigned type we need to mask out the bits outside of the type
+     precision.  */
+  if (!signed_p)
+    {
+      if (bits <= HOST_BITS_PER_WIDE_INT)
+       hi = 0;
+      else
+       {
+         bits -= HOST_BITS_PER_WIDE_INT;
+         mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1;
+         hi &= mask;
+       }
+    }
+
+  return build_int_cst_wide (type, val, hi);
+}
+
+/* These are the hash table functions for the hash table of INTEGER_CST
+   nodes of a sizetype.  */
+
+/* Return the hash code code X, an INTEGER_CST.  */
+
+static hashval_t
+int_cst_hash_hash (const void *x)
+{
+  tree t = (tree) x;
+
+  return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t)
+         ^ htab_hash_pointer (TREE_TYPE (t)));
+}
+
+/* Return nonzero if the value represented by *X (an INTEGER_CST tree node)
+   is the same as that given by *Y, which is the same.  */
+
+static int
+int_cst_hash_eq (const void *x, const void *y)
+{
+  tree xt = (tree) x;
+  tree yt = (tree) y;
+
+  return (TREE_TYPE (xt) == TREE_TYPE (yt)
+         && TREE_INT_CST_HIGH (xt) == TREE_INT_CST_HIGH (yt)
+         && TREE_INT_CST_LOW (xt) == TREE_INT_CST_LOW (yt));
+}
 
-   This function should be used via the `build_int_2' macro.  */
+/* Create an INT_CST node of TYPE and value HI:LOW.  If TYPE is NULL,
+   integer_type_node is used.  The returned node is always shared.
+   For small integers we use a per-type vector cache, for larger ones
+   we use a single hash table.  */
 
 tree
-build_int_2_wide (unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
+build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
 {
-  tree t = make_node (INTEGER_CST);
+  tree t;
+  int ix = -1;
+  int limit = 0;
+
+  if (!type)
+    type = integer_type_node;
+
+  switch (TREE_CODE (type))
+    {
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      /* Cache NULL pointer.  */
+      if (!hi && !low)
+       {
+         limit = 1;
+         ix = 0;
+       }
+      break;
+
+    case BOOLEAN_TYPE:
+      /* Cache false or true.  */
+      limit = 2;
+      if (!hi && low < 2)
+       ix = low;
+      break;
+
+    case INTEGER_TYPE:
+    case CHAR_TYPE:
+    case OFFSET_TYPE:
+      if (TYPE_UNSIGNED (type))
+       {
+         /* Cache 0..N */
+         limit = INTEGER_SHARE_LIMIT;
+         if (!hi && low < (unsigned HOST_WIDE_INT)INTEGER_SHARE_LIMIT)
+           ix = low;
+       }
+      else
+       {
+         /* Cache -1..N */
+         limit = INTEGER_SHARE_LIMIT + 1;
+         if (!hi && low < (unsigned HOST_WIDE_INT)INTEGER_SHARE_LIMIT)
+           ix = low + 1;
+         else if (hi == -1 && low == -(unsigned HOST_WIDE_INT)1)
+           ix = 0;
+       }
+      break;
+    default:
+      break;
+    }
+
+  if (ix >= 0)
+    {
+      /* Look for it in the type's vector of small shared ints.  */
+      if (!TYPE_CACHED_VALUES_P (type))
+       {
+         TYPE_CACHED_VALUES_P (type) = 1;
+         TYPE_CACHED_VALUES (type) = make_tree_vec (limit);
+       }
+
+      t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix);
+      if (t)
+       {
+         /* Make sure no one is clobbering the shared constant.  */
+         gcc_assert (TREE_TYPE (t) == type);
+         gcc_assert (TREE_INT_CST_LOW (t) == low);
+         gcc_assert (TREE_INT_CST_HIGH (t) == hi);
+       }
+      else
+       {
+         /* Create a new shared int.  */
+         t = make_node (INTEGER_CST);
+
+         TREE_INT_CST_LOW (t) = low;
+         TREE_INT_CST_HIGH (t) = hi;
+         TREE_TYPE (t) = type;
+         
+         TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
+       }
+    }
+  else
+    {
+      /* Use the cache of larger shared ints.  */
+      void **slot;
+
+      TREE_INT_CST_LOW (int_cst_node) = low;
+      TREE_INT_CST_HIGH (int_cst_node) = hi;
+      TREE_TYPE (int_cst_node) = type;
+
+      slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT);
+      t = *slot;
+      if (!t)
+       {
+         /* Insert this one into the hash table.  */
+         t = int_cst_node;
+         *slot = t;
+         /* Make a new node for next time round.  */
+         int_cst_node = make_node (INTEGER_CST);
+       }
+    }
 
-  TREE_INT_CST_LOW (t) = low;
-  TREE_INT_CST_HIGH (t) = hi;
-  TREE_TYPE (t) = integer_type_node;
   return t;
 }
 
+/* Builds an integer constant in TYPE such that lowest BITS bits are ones
+   and the rest are zeros.  */
+
+tree
+build_low_bits_mask (tree type, unsigned bits)
+{
+  unsigned HOST_WIDE_INT low;
+  HOST_WIDE_INT high;
+  unsigned HOST_WIDE_INT all_ones = ~(unsigned HOST_WIDE_INT) 0;
+
+  gcc_assert (bits <= TYPE_PRECISION (type));
+
+  if (bits == TYPE_PRECISION (type)
+      && !TYPE_UNSIGNED (type))
+    {
+      /* Sign extended all-ones mask.  */
+      low = all_ones;
+      high = -1;
+    }
+  else if (bits <= HOST_BITS_PER_WIDE_INT)
+    {
+      low = all_ones >> (HOST_BITS_PER_WIDE_INT - bits);
+      high = 0;
+    }
+  else
+    {
+      bits -= HOST_BITS_PER_WIDE_INT;
+      low = all_ones;
+      high = all_ones >> (HOST_BITS_PER_WIDE_INT - bits);
+    }
+
+  return build_int_cst_wide (type, low, high);
+}
+
+/* Checks that X is integer constant that can be expressed in (unsigned)
+   HOST_WIDE_INT without loss of precision.  */
+
+bool
+cst_and_fits_in_hwi (tree x)
+{
+  if (TREE_CODE (x) != INTEGER_CST)
+    return false;
+
+  if (TYPE_PRECISION (TREE_TYPE (x)) > HOST_BITS_PER_WIDE_INT)
+    return false;
+
+  return (TREE_INT_CST_HIGH (x) == 0
+         || TREE_INT_CST_HIGH (x) == -1);
+}
+
 /* Return a new VECTOR_CST node whose type is TYPE and whose values
    are in a list pointed by VALS.  */
 
@@ -546,10 +867,23 @@ build_real_from_int_cst (tree type, tree i)
 tree
 build_string (int len, const char *str)
 {
-  tree s = make_node (STRING_CST);
+  tree s;
+  size_t length;
+  
+  length = len + sizeof (struct tree_string);
 
+#ifdef GATHER_STATISTICS
+  tree_node_counts[(int) c_kind]++;
+  tree_node_sizes[(int) c_kind] += length;
+#endif  
+
+  s = ggc_alloc_tree (length);
+
+  memset (s, 0, sizeof (struct tree_common));
+  TREE_SET_CODE (s, STRING_CST);
   TREE_STRING_LENGTH (s) = len;
-  TREE_STRING_POINTER (s) = ggc_alloc_string (str, len);
+  memcpy ((char *) TREE_STRING_POINTER (s), str, len);
+  ((char *) TREE_STRING_POINTER (s))[len] = '\0';
 
   return s;
 }
@@ -573,6 +907,32 @@ build_complex (tree type, tree real, tree imag)
   return t;
 }
 
+/* Build a BINFO with LEN language slots.  */
+
+tree
+make_tree_binfo_stat (unsigned base_binfos MEM_STAT_DECL)
+{
+  tree t;
+  size_t length = (offsetof (struct tree_binfo, base_binfos)
+                  + VEC_embedded_size (tree, base_binfos));
+
+#ifdef GATHER_STATISTICS
+  tree_node_counts[(int) binfo_kind]++;
+  tree_node_sizes[(int) binfo_kind] += length;
+#endif
+
+  t = ggc_alloc_zone_pass_stat (length, &tree_zone);
+
+  memset (t, 0, offsetof (struct tree_binfo, base_binfos));
+
+  TREE_SET_CODE (t, TREE_BINFO);
+
+  VEC_embedded_init (tree, BINFO_BASE_BINFOS (t), base_binfos);
+
+  return t;
+}
+
+
 /* Build a newly constructed TREE_VEC node of length LEN.  */
 
 tree
@@ -586,7 +946,7 @@ make_tree_vec_stat (int len MEM_STAT_DECL)
   tree_node_sizes[(int) vec_kind] += length;
 #endif
 
-  t = ggc_alloc_zone_stat (length, tree_zone PASS_MEM_STAT);
+  t = ggc_alloc_zone_pass_stat (length, &tree_zone);
 
   memset (t, 0, length);
 
@@ -665,10 +1025,9 @@ integer_all_onesp (tree expr)
 
       shift_amount = prec - HOST_BITS_PER_WIDE_INT;
 
-      if (shift_amount > HOST_BITS_PER_WIDE_INT)
-       /* Can not handle precisions greater than twice the host int size.  */
-       abort ();
-      else if (shift_amount == HOST_BITS_PER_WIDE_INT)
+      /* Can not handle precisions greater than twice the host int size.  */
+      gcc_assert (shift_amount <= HOST_BITS_PER_WIDE_INT);
+      if (shift_amount == HOST_BITS_PER_WIDE_INT)
        /* Shifting by the host word size is undefined according to the ANSI
           standard, so we must handle this as a special case.  */
        high_value = -1;
@@ -924,21 +1283,6 @@ purpose_member (tree elem, tree list)
   return NULL_TREE;
 }
 
-/* Return first list element whose BINFO_TYPE is ELEM.
-   Return 0 if ELEM is not in LIST.  */
-
-tree
-binfo_member (tree elem, tree list)
-{
-  while (list)
-    {
-      if (elem == BINFO_TYPE (list))
-       return list;
-      list = TREE_CHAIN (list);
-    }
-  return NULL_TREE;
-}
-
 /* Return nonzero if ELEM is part of the chain CHAIN.  */
 
 int
@@ -973,8 +1317,7 @@ list_length (tree t)
 #ifdef ENABLE_TREE_CHECKING
       if (len % 2)
        q = TREE_CHAIN (q);
-      if (p == q)
-       abort ();
+      gcc_assert (p != q);
 #endif
       len++;
     }
@@ -1019,8 +1362,7 @@ chainon (tree op1, tree op2)
   {
     tree t2;
     for (t2 = op2; t2; t2 = TREE_CHAIN (t2))
-      if (t2 == t1)
-       abort ();  /* Circularity created.  */
+      gcc_assert (t2 != t1);
   }
 #endif
 
@@ -1076,8 +1418,7 @@ tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL)
 {
   tree node;
 
-  node = ggc_alloc_zone_stat (sizeof (struct tree_list),
-                             tree_zone PASS_MEM_STAT);
+  node = ggc_alloc_zone_pass_stat (sizeof (struct tree_list), &tree_zone);
 
   memset (node, 0, sizeof (struct tree_common));
 
@@ -1118,7 +1459,7 @@ size_in_bytes (tree type)
     }
 
   if (TREE_CODE (t) == INTEGER_CST)
-    force_fit_type (t, 0);
+    t = force_fit_type (t, 0, false, false);
 
   return t;
 }
@@ -1157,9 +1498,9 @@ bit_position (tree field)
                       DECL_FIELD_BIT_OFFSET (field));
 }
 
-/* Likewise, but return as an integer.  Abort if it cannot be represented
-   in that way (since it could be a signed value, we don't have the option
-   of returning -1 like int_size_in_byte can.  */
+/* Likewise, but return as an integer.  It must be representable in
+   that way (since it could be a signed value, we don't have the
+   option of returning -1 like int_size_in_byte can.  */
 
 HOST_WIDE_INT
 int_bit_position (tree field)
@@ -1177,9 +1518,9 @@ byte_position (tree field)
                        DECL_FIELD_BIT_OFFSET (field));
 }
 
-/* Likewise, but return as an integer.  Abort if it cannot be represented
-   in that way (since it could be a signed value, we don't have the option
-   of returning -1 like int_size_in_byte can.  */
+/* Likewise, but return as an integer.  It must be representable in
+   that way (since it could be a signed value, we don't have the
+   option of returning -1 like int_size_in_byte can.  */
 
 HOST_WIDE_INT
 int_byte_position (tree field)
@@ -1205,7 +1546,7 @@ expr_align (tree t)
 
     case SAVE_EXPR:         case COMPOUND_EXPR:       case MODIFY_EXPR:
     case INIT_EXPR:         case TARGET_EXPR:         case WITH_CLEANUP_EXPR:
-    case CLEANUP_POINT_EXPR:  case UNSAVE_EXPR:
+    case CLEANUP_POINT_EXPR:
       /* These don't change the alignment of an object.  */
       return expr_align (TREE_OPERAND (t, 0));
 
@@ -1255,34 +1596,40 @@ array_type_nelts (tree type)
          : fold (build2 (MINUS_EXPR, TREE_TYPE (max), max, min)));
 }
 \f
-/* Return nonzero if arg is static -- a reference to an object in
-   static storage.  This is not the same as the C meaning of `static'.  */
+/* If arg is static -- a reference to an object in static storage -- then
+   return the object.  This is not the same as the C meaning of `static'.
+   If arg isn't static, return NULL.  */
 
-int
+tree
 staticp (tree arg)
 {
   switch (TREE_CODE (arg))
     {
     case FUNCTION_DECL:
-      /* Nested functions aren't static, since taking their address
-        involves a trampoline.  */
-      return ((decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg))
-             && ! DECL_NON_ADDR_CONST_P (arg));
+      /* Nested functions are static, even though taking their address will
+        involve a trampoline as we unnest the nested function and create
+        the trampoline on the tree level.  */
+      return arg;
 
     case VAR_DECL:
       return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
              && ! DECL_THREAD_LOCAL (arg)
-             && ! DECL_NON_ADDR_CONST_P (arg));
+             && ! DECL_NON_ADDR_CONST_P (arg)
+             ? arg : NULL);
+
+    case CONST_DECL:
+      return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
+             ? arg : NULL);
 
     case CONSTRUCTOR:
-      return TREE_STATIC (arg);
+      return TREE_STATIC (arg) ? arg : NULL;
 
     case LABEL_DECL:
     case STRING_CST:
-      return 1;
+      return arg;
 
     case COMPONENT_REF:
-      /* If the thing being referenced is not a field, then it is 
+      /* If the thing being referenced is not a field, then it is
         something language specific.  */
       if (TREE_CODE (TREE_OPERAND (arg, 1)) != FIELD_DECL)
        return (*lang_hooks.staticp) (arg);
@@ -1290,20 +1637,17 @@ staticp (tree arg)
       /* If we are referencing a bitfield, we can't evaluate an
         ADDR_EXPR at compile time and so it isn't a constant.  */
       if (DECL_BIT_FIELD (TREE_OPERAND (arg, 1)))
-       return 0;
+       return NULL;
 
       return staticp (TREE_OPERAND (arg, 0));
 
     case BIT_FIELD_REF:
-      return 0;
+      return NULL;
 
-#if 0
-       /* This case is technically correct, but results in setting
-         TREE_CONSTANT on ADDR_EXPRs that cannot be evaluated at
-         compile time.  */
+    case MISALIGNED_INDIRECT_REF:
+    case ALIGN_INDIRECT_REF:
     case INDIRECT_REF:
-      return TREE_CONSTANT (TREE_OPERAND (arg, 0));
-#endif
+      return TREE_CONSTANT (TREE_OPERAND (arg, 0)) ? arg : NULL;
 
     case ARRAY_REF:
     case ARRAY_RANGE_REF:
@@ -1311,14 +1655,14 @@ staticp (tree arg)
          && TREE_CODE (TREE_OPERAND (arg, 1)) == INTEGER_CST)
        return staticp (TREE_OPERAND (arg, 0));
       else
-       return 0;
+       return false;
 
     default:
       if ((unsigned int) TREE_CODE (arg)
          >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
        return lang_hooks.staticp (arg);
       else
-       return 0;
+       return NULL;
     }
 }
 \f
@@ -1381,7 +1725,6 @@ save_expr (tree expr)
      value was computed on both sides of the jump.  So make sure it isn't
      eliminated as dead.  */
   TREE_SIDE_EFFECTS (t) = 1;
-  TREE_READONLY (t) = 1;
   TREE_INVARIANT (t) = 1;
   return t;
 }
@@ -1406,9 +1749,9 @@ skip_simple_arithmetic (tree expr)
   inner = expr;
   while (1)
     {
-      if (TREE_CODE_CLASS (TREE_CODE (inner)) == '1')
+      if (UNARY_CLASS_P (inner))
        inner = TREE_OPERAND (inner, 0);
-      else if (TREE_CODE_CLASS (TREE_CODE (inner)) == '2')
+      else if (BINARY_CLASS_P (inner))
        {
          if (TREE_INVARIANT (TREE_OPERAND (inner, 1)))
            inner = TREE_OPERAND (inner, 0);
@@ -1424,41 +1767,6 @@ skip_simple_arithmetic (tree expr)
   return inner;
 }
 
-/* Arrange for an expression to be expanded multiple independent
-   times.  This is useful for cleanup actions, as the backend can
-   expand them multiple times in different places.  */
-
-tree
-unsave_expr (tree expr)
-{
-  tree t;
-
-  /* If this is already protected, no sense in protecting it again.  */
-  if (TREE_CODE (expr) == UNSAVE_EXPR)
-    return expr;
-
-  t = build1 (UNSAVE_EXPR, TREE_TYPE (expr), expr);
-  TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr);
-  return t;
-}
-
-/* Returns the index of the first non-tree operand for CODE, or the number
-   of operands if all are trees.  */
-
-int
-first_rtl_op (enum tree_code code)
-{
-  switch (code)
-    {
-    case GOTO_SUBROUTINE_EXPR:
-      return 0;
-    case WITH_CLEANUP_EXPR:
-      return 2;
-    default:
-      return TREE_CODE_LENGTH (code);
-    }
-}
-
 /* Return which tree structure is used by T.  */
 
 enum tree_node_structure_enum
@@ -1468,22 +1776,29 @@ tree_node_structure (tree t)
 
   switch (TREE_CODE_CLASS (code))
     {
-    case 'd':  return TS_DECL;
-    case 't':  return TS_TYPE;
-    case 'r': case '<': case '1': case '2': case 'e': case 's':
+    case tcc_declaration:
+      return TS_DECL;
+    case tcc_type:
+      return TS_TYPE;
+    case tcc_reference:
+    case tcc_comparison:
+    case tcc_unary:
+    case tcc_binary:
+    case tcc_expression:
+    case tcc_statement:
       return TS_EXP;
-    default:  /* 'c' and 'x' */
+    default:  /* tcc_constant and tcc_exceptional */
       break;
     }
   switch (code)
     {
-      /* 'c' cases.  */
+      /* tcc_constant cases.  */
     case INTEGER_CST:          return TS_INT_CST;
     case REAL_CST:             return TS_REAL_CST;
     case COMPLEX_CST:          return TS_COMPLEX;
     case VECTOR_CST:           return TS_VECTOR;
     case STRING_CST:           return TS_STRING;
-      /* 'x' cases.  */
+      /* tcc_exceptional cases.  */
     case ERROR_MARK:           return TS_COMMON;
     case IDENTIFIER_NODE:      return TS_IDENTIFIER;
     case TREE_LIST:            return TS_LIST;
@@ -1493,171 +1808,48 @@ tree_node_structure (tree t)
     case PLACEHOLDER_EXPR:     return TS_COMMON;
     case STATEMENT_LIST:       return TS_STATEMENT_LIST;
     case BLOCK:                        return TS_BLOCK;
+    case TREE_BINFO:           return TS_BINFO;
     case VALUE_HANDLE:         return TS_VALUE_HANDLE;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
+\f
+/* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size
+   or offset that depends on a field within a record.  */
 
-/* Perform any modifications to EXPR required when it is unsaved.  Does
-   not recurse into EXPR's subtrees.  */
-
-void
-unsave_expr_1 (tree expr)
+bool
+contains_placeholder_p (tree exp)
 {
-  switch (TREE_CODE (expr))
-    {
-    case TARGET_EXPR:
-      /* Don't mess with a TARGET_EXPR that hasn't been expanded.
-         It's OK for this to happen if it was part of a subtree that
-         isn't immediately expanded, such as operand 2 of another
-         TARGET_EXPR.  */
-      if (TREE_OPERAND (expr, 1))
-       break;
-
-      TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 3);
-      TREE_OPERAND (expr, 3) = NULL_TREE;
-      break;
-
-    default:
-      break;
-    }
-}
-
-/* Return 0 if it is safe to evaluate EXPR multiple times,
-   return 1 if it is safe if EXPR is unsaved afterward, or
-   return 2 if it is completely unsafe.
+  enum tree_code code;
 
-   This assumes that CALL_EXPRs and TARGET_EXPRs are never replicated in
-   an expression tree, so that it safe to unsave them and the surrounding
-   context will be correct.
+  if (!exp)
+    return 0;
 
-   SAVE_EXPRs basically *only* appear replicated in an expression tree,
-   occasionally across the whole of a function.  It is therefore only
-   safe to unsave a SAVE_EXPR if you know that all occurrences appear
-   below the UNSAVE_EXPR.  */
-
-int
-unsafe_for_reeval (tree expr)
-{
-  int unsafeness = 0;
-  enum tree_code code;
-  int i, tmp, tmp2;
-  tree exp;
-  int first_rtl;
-
-  if (expr == NULL_TREE)
-    return 1;
-
-  code = TREE_CODE (expr);
-  first_rtl = first_rtl_op (code);
-
-  switch (code)
-    {
-    case SAVE_EXPR:
-      return 2;
-
-      /* A label can only be emitted once.  */
-    case LABEL_EXPR:
-      return 1;
-
-    case BIND_EXPR:
-      unsafeness = 1;
-      break;
-
-    case TREE_LIST:
-      for (exp = expr; exp != 0; exp = TREE_CHAIN (exp))
-       {
-         tmp = unsafe_for_reeval (TREE_VALUE (exp));
-         unsafeness = MAX (tmp, unsafeness);
-       }
-
-      return unsafeness;
-
-    case CALL_EXPR:
-      tmp2 = unsafe_for_reeval (TREE_OPERAND (expr, 0));
-      tmp = unsafe_for_reeval (TREE_OPERAND (expr, 1));
-      return MAX (MAX (tmp, 1), tmp2);
-
-    case TARGET_EXPR:
-      unsafeness = 1;
-      break;
-
-    case EXIT_BLOCK_EXPR:
-      /* EXIT_BLOCK_LABELED_BLOCK, a.k.a. TREE_OPERAND (expr, 0), holds
-        a reference to an ancestor LABELED_BLOCK, so we need to avoid
-        unbounded recursion in the 'e' traversal code below.  */
-      exp = EXIT_BLOCK_RETURN (expr);
-      return exp ? unsafe_for_reeval (exp) : 0;
-
-    default:
-      tmp = lang_hooks.unsafe_for_reeval (expr);
-      if (tmp >= 0)
-       return tmp;
-      break;
-    }
-
-  switch (TREE_CODE_CLASS (code))
-    {
-    case 'c':  /* a constant */
-    case 't':  /* a type node */
-    case 'x':  /* something random, like an identifier or an ERROR_MARK.  */
-    case 'd':  /* A decl node */
-      return 0;
-
-    case 'e':  /* an expression */
-    case 'r':  /* a reference */
-    case 's':  /* an expression with side effects */
-    case '<':  /* a comparison expression */
-    case '2':  /* a binary arithmetic expression */
-    case '1':  /* a unary arithmetic expression */
-      for (i = first_rtl - 1; i >= 0; i--)
-       {
-         tmp = unsafe_for_reeval (TREE_OPERAND (expr, i));
-         unsafeness = MAX (tmp, unsafeness);
-       }
-
-      return unsafeness;
-
-    default:
-      return 2;
-    }
-}
-\f
-/* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size
-   or offset that depends on a field within a record.  */
-
-bool
-contains_placeholder_p (tree exp)
-{
-  enum tree_code code;
-
-  if (!exp)
-    return 0;
-
-  code = TREE_CODE (exp);
-  if (code == PLACEHOLDER_EXPR)
-    return 1;
+  code = TREE_CODE (exp);
+  if (code == PLACEHOLDER_EXPR)
+    return 1;
 
   switch (TREE_CODE_CLASS (code))
     {
-    case 'r':
+    case tcc_reference:
       /* Don't look at any PLACEHOLDER_EXPRs that might be in index or bit
         position computations since they will be converted into a
         WITH_RECORD_EXPR involving the reference, which will assume
         here will be valid.  */
       return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
 
-    case 'x':
+    case tcc_exceptional:
       if (code == TREE_LIST)
        return (CONTAINS_PLACEHOLDER_P (TREE_VALUE (exp))
                || CONTAINS_PLACEHOLDER_P (TREE_CHAIN (exp)));
       break;
 
-    case '1':
-    case '2':  case '<':
-    case 'e':
+    case tcc_unary:
+    case tcc_binary:
+    case tcc_comparison:
+    case tcc_expression:
       switch (code)
        {
        case COMPOUND_EXPR:
@@ -1673,7 +1865,7 @@ contains_placeholder_p (tree exp)
          break;
        }
 
-      switch (first_rtl_op (code))
+      switch (TREE_CODE_LENGTH (code))
        {
        case 1:
          return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
@@ -1690,12 +1882,12 @@ contains_placeholder_p (tree exp)
   return 0;
 }
 
-/* Return 1 if any part of the computation of TYPE involves a PLACEHOLDER_EXPR.
-   This includes size, bounds, qualifiers (for QUAL_UNION_TYPE) and field
-   positions.  */
+/* Return true if any part of the computation of TYPE involves a
+   PLACEHOLDER_EXPR.  This includes size, bounds, qualifiers
+   (for QUAL_UNION_TYPE) and field positions.  */
 
-bool
-type_contains_placeholder_p (tree type)
+static bool
+type_contains_placeholder_1 (tree type)
 {
   /* If the size contains a placeholder or the parent type (component type in
      the case of arrays) type involves a placeholder, this type does.  */
@@ -1703,7 +1895,7 @@ type_contains_placeholder_p (tree type)
       || CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (type))
       || (TREE_TYPE (type) != 0
          && type_contains_placeholder_p (TREE_TYPE (type))))
-    return 1;
+    return true;
 
   /* Now do type-specific checks.  Note that the last part of the check above
      greatly limits what we have to do below.  */
@@ -1718,9 +1910,9 @@ type_contains_placeholder_p (tree type)
     case OFFSET_TYPE:
     case REFERENCE_TYPE:
     case METHOD_TYPE:
-    case FILE_TYPE:
     case FUNCTION_TYPE:
-      return 0;
+    case VECTOR_TYPE:
+      return false;
 
     case INTEGER_TYPE:
     case REAL_TYPE:
@@ -1729,8 +1921,6 @@ type_contains_placeholder_p (tree type)
              || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type)));
 
     case ARRAY_TYPE:
-    case SET_TYPE:
-    case VECTOR_TYPE:
       /* We're already checked the component type (TREE_TYPE), so just check
         the index type.  */
       return type_contains_placeholder_p (TYPE_DOMAIN (type));
@@ -1739,33 +1929,7 @@ type_contains_placeholder_p (tree type)
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
       {
-       static tree seen_types = 0;
        tree field;
-       bool ret = 0;
-
-       /* We have to be careful here that we don't end up in infinite
-          recursions due to a field of a type being a pointer to that type
-          or to a mutually-recursive type.  So we store a list of record
-          types that we've seen and see if this type is in them.  To save
-          memory, we don't use a list for just one type.  Here we check
-          whether we've seen this type before and store it if not.  */
-       if (seen_types == 0)
-         seen_types = type;
-       else if (TREE_CODE (seen_types) != TREE_LIST)
-         {
-           if (seen_types == type)
-             return 0;
-
-           seen_types = tree_cons (NULL_TREE, type,
-                                   build_tree_list (NULL_TREE, seen_types));
-         }
-       else
-         {
-           if (value_member (type, seen_types) != 0)
-             return 0;
-
-           seen_types = tree_cons (NULL_TREE, type, seen_types);
-         }
 
        for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
          if (TREE_CODE (field) == FIELD_DECL
@@ -1773,85 +1937,37 @@ type_contains_placeholder_p (tree type)
                  || (TREE_CODE (type) == QUAL_UNION_TYPE
                      && CONTAINS_PLACEHOLDER_P (DECL_QUALIFIER (field)))
                  || type_contains_placeholder_p (TREE_TYPE (field))))
-           {
-             ret = true;
-             break;
-           }
+           return true;
 
-       /* Now remove us from seen_types and return the result.  */
-       if (seen_types == type)
-         seen_types = 0;
-       else
-         seen_types = TREE_CHAIN (seen_types);
-
-       return ret;
+       return false;
       }
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
-/* Return 1 if EXP contains any expressions that produce cleanups for an
-   outer scope to deal with.  Used by fold.  */
-
-int
-has_cleanups (tree exp)
+bool
+type_contains_placeholder_p (tree type)
 {
-  int i, nops, cmp;
-
-  if (! TREE_SIDE_EFFECTS (exp))
-    return 0;
-
-  switch (TREE_CODE (exp))
-    {
-    case TARGET_EXPR:
-    case GOTO_SUBROUTINE_EXPR:
-    case WITH_CLEANUP_EXPR:
-      return 1;
-
-    case CLEANUP_POINT_EXPR:
-      return 0;
-
-    case CALL_EXPR:
-      for (exp = TREE_OPERAND (exp, 1); exp; exp = TREE_CHAIN (exp))
-       {
-         cmp = has_cleanups (TREE_VALUE (exp));
-         if (cmp)
-           return cmp;
-       }
-      return 0;
+  bool result;
 
-    case DECL_EXPR:
-      return (DECL_INITIAL (DECL_EXPR_DECL (exp))
-             && has_cleanups (DECL_INITIAL (DECL_EXPR_DECL (exp))));
+  /* If the contains_placeholder_bits field has been initialized,
+     then we know the answer.  */
+  if (TYPE_CONTAINS_PLACEHOLDER_INTERNAL (type) > 0)
+    return TYPE_CONTAINS_PLACEHOLDER_INTERNAL (type) - 1;
 
-    default:
-      break;
-    }
+  /* Indicate that we've seen this type node, and the answer is false.
+     This is what we want to return if we run into recursion via fields.  */
+  TYPE_CONTAINS_PLACEHOLDER_INTERNAL (type) = 1;
 
-  /* This general rule works for most tree codes.  All exceptions should be
-     handled above.  If this is a language-specific tree code, we can't
-     trust what might be in the operand, so say we don't know
-     the situation.  */
-  if ((int) TREE_CODE (exp) >= (int) LAST_AND_UNUSED_TREE_CODE)
-    return -1;
+  /* Compute the real value.  */
+  result = type_contains_placeholder_1 (type);
 
-  nops = first_rtl_op (TREE_CODE (exp));
-  for (i = 0; i < nops; i++)
-    if (TREE_OPERAND (exp, i) != 0)
-      {
-       int type = TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, i)));
-       if (type == 'e' || type == '<' || type == '1' || type == '2'
-           || type == 'r' || type == 's')
-         {
-           cmp = has_cleanups (TREE_OPERAND (exp, i));
-           if (cmp)
-             return cmp;
-         }
-      }
+  /* Store the real value.  */
+  TYPE_CONTAINS_PLACEHOLDER_INTERNAL (type) = result + 1;
 
-  return 0;
+  return result;
 }
 \f
 /* Given a tree EXP, a FIELD_DECL F, and a replacement value R,
@@ -1883,15 +1999,14 @@ substitute_in_expr (tree exp, tree f, tree r)
      /* If this expression is getting a value from a PLACEHOLDER_EXPR
        and it is the right field, replace it with R.  */
      for (inner = TREE_OPERAND (exp, 0);
-         TREE_CODE_CLASS (TREE_CODE (inner)) == 'r';
+         REFERENCE_CLASS_P (inner);
          inner = TREE_OPERAND (inner, 0))
        ;
      if (TREE_CODE (inner) == PLACEHOLDER_EXPR
         && TREE_OPERAND (exp, 1) == f)
        return r;
 
-     /* If this expression hasn't been completed let, leave it
-       alone.  */
+     /* If this expression hasn't been completed let, leave it alone.  */
      if (TREE_CODE (inner) == PLACEHOLDER_EXPR && TREE_TYPE (inner) == 0)
        return exp;
 
@@ -1899,23 +2014,23 @@ substitute_in_expr (tree exp, tree f, tree r)
      if (op0 == TREE_OPERAND (exp, 0))
        return exp;
 
-     new = fold (build (code, TREE_TYPE (exp), op0, TREE_OPERAND (exp, 1),
-                       NULL_TREE));
+     new = fold (build3 (COMPONENT_REF, TREE_TYPE (exp),
+                        op0, TREE_OPERAND (exp, 1), NULL_TREE));
    }
   else
     switch (TREE_CODE_CLASS (code))
       {
-      case 'c':
-      case 'd':
+      case tcc_constant:
+      case tcc_declaration:
        return exp;
 
-      case 'x':
-      case '1':
-      case '2':
-      case '<':
-      case 'e':
-      case 'r':
-       switch (first_rtl_op (code))
+      case tcc_exceptional:
+      case tcc_unary:
+      case tcc_binary:
+      case tcc_comparison:
+      case tcc_expression:
+      case tcc_reference:
+       switch (TREE_CODE_LENGTH (code))
          {
          case 0:
            return exp;
@@ -1951,12 +2066,12 @@ substitute_in_expr (tree exp, tree f, tree r)
            break;
 
          default:
-           abort ();
+           gcc_unreachable ();
          }
        break;
 
       default:
-       abort ();
+       gcc_unreachable ();
       }
 
   TREE_READONLY (new) = TREE_READONLY (exp);
@@ -1983,10 +2098,10 @@ substitute_placeholder_in_expr (tree exp, tree obj)
           elt = ((TREE_CODE (elt) == COMPOUND_EXPR
                   || TREE_CODE (elt) == COND_EXPR)
                  ? TREE_OPERAND (elt, 1)
-                 : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
-                    || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
-                    || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
-                    || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
+                 : (REFERENCE_CLASS_P (elt)
+                    || UNARY_CLASS_P (elt)
+                    || BINARY_CLASS_P (elt)
+                    || EXPRESSION_CLASS_P (elt))
                  ? TREE_OPERAND (elt, 0) : 0))
        if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
          return elt;
@@ -1995,10 +2110,10 @@ substitute_placeholder_in_expr (tree exp, tree obj)
           elt = ((TREE_CODE (elt) == COMPOUND_EXPR
                   || TREE_CODE (elt) == COND_EXPR)
                  ? TREE_OPERAND (elt, 1)
-                 : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
-                    || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
-                    || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
-                    || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
+                 : (REFERENCE_CLASS_P (elt)
+                    || UNARY_CLASS_P (elt)
+                    || BINARY_CLASS_P (elt)
+                    || EXPRESSION_CLASS_P (elt))
                  ? TREE_OPERAND (elt, 0) : 0))
        if (POINTER_TYPE_P (TREE_TYPE (elt))
            && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
@@ -2024,18 +2139,18 @@ substitute_placeholder_in_expr (tree exp, tree obj)
   else
     switch (TREE_CODE_CLASS (code))
       {
-      case 'c':
-      case 'd':
+      case tcc_constant:
+      case tcc_declaration:
        return exp;
 
-      case 'x':
-      case '1':
-      case '2':
-      case '<':
-      case 'e':
-      case 'r':
-      case 's':
-       switch (first_rtl_op (code))
+      case tcc_exceptional:
+      case tcc_unary:
+      case tcc_binary:
+      case tcc_comparison:
+      case tcc_expression:
+      case tcc_reference:
+      case tcc_statement:
+       switch (TREE_CODE_LENGTH (code))
          {
          case 0:
            return exp;
@@ -2081,12 +2196,12 @@ substitute_placeholder_in_expr (tree exp, tree obj)
              return fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3));
 
          default:
-           abort ();
+           gcc_unreachable ();
          }
        break;
 
       default:
-       abort ();
+       gcc_unreachable ();
       }
 }
 \f
@@ -2206,13 +2321,13 @@ stabilize_reference_1 (tree e)
 
   switch (TREE_CODE_CLASS (code))
     {
-    case 'x':
-    case 't':
-    case 'd':
-    case '<':
-    case 's':
-    case 'e':
-    case 'r':
+    case tcc_exceptional:
+    case tcc_type:
+    case tcc_declaration:
+    case tcc_comparison:
+    case tcc_statement:
+    case tcc_expression:
+    case tcc_reference:
       /* If the expression has side-effects, then encase it in a SAVE_EXPR
         so that it will only be evaluated once.  */
       /* The reference (r) and comparison (<) classes could be handled as
@@ -2221,12 +2336,12 @@ stabilize_reference_1 (tree e)
        return save_expr (e);
       return e;
 
-    case 'c':
+    case tcc_constant:
       /* Constants need no processing.  In fact, we should never reach
         here.  */
       return e;
 
-    case '2':
+    case tcc_binary:
       /* Division is slow and tends to be compiled with jumps,
         especially the division by powers of 2 that is often
         found inside of an array reference.  So do it just once.  */
@@ -2240,13 +2355,13 @@ stabilize_reference_1 (tree e)
                         stabilize_reference_1 (TREE_OPERAND (e, 1)));
       break;
 
-    case '1':
+    case tcc_unary:
       /* Recursively stabilize each operand.  */
       result = build_nt (code, stabilize_reference_1 (TREE_OPERAND (e, 0)));
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   TREE_TYPE (result) = TREE_TYPE (e);
@@ -2294,32 +2409,44 @@ do { tree _node = (NODE); \
          && TREE_CODE (TREE_TYPE (TREE_OPERAND (node, 0))) == ARRAY_TYPE)
        {
          UPDATE_TITCSE (TREE_OPERAND (node, 1));
-         UPDATE_TITCSE (array_ref_low_bound (node));
-         UPDATE_TITCSE (array_ref_element_size (node));
+         if (TREE_OPERAND (node, 2))
+           UPDATE_TITCSE (TREE_OPERAND (node, 2));
+         if (TREE_OPERAND (node, 3))
+           UPDATE_TITCSE (TREE_OPERAND (node, 3));
        }
       /* Likewise, just because this is a COMPONENT_REF doesn't mean we have a
         FIELD_DECL, apparently.  The G++ front end can put something else
         there, at least temporarily.  */
       else if (TREE_CODE (node) == COMPONENT_REF
               && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL)
-       UPDATE_TITCSE (component_ref_field_offset (node));
+       {
+         if (TREE_OPERAND (node, 2))
+           UPDATE_TITCSE (TREE_OPERAND (node, 2));
+       }
       else if (TREE_CODE (node) == BIT_FIELD_REF)
        UPDATE_TITCSE (TREE_OPERAND (node, 2));
     }
-             
+
   /* Now see what's inside.  If it's an INDIRECT_REF, copy our properties from
-     it.  If it's a decl, it's definitely invariant and it's constant if the
-     decl is static.  (Taking the address of a volatile variable is not
-     volatile.)  If it's a constant, the address is both invariant and
+     the address, since &(*a)->b is a form of addition.  If it's a decl, it's
+     invariant and constant if the decl is static.  It's also invariant if it's
+     a decl in the current function.  Taking the address of a volatile variable
+     is not volatile.  If it's a constant, the address is both invariant and
      constant.  Otherwise it's neither.  */
   if (TREE_CODE (node) == INDIRECT_REF)
-    UPDATE_TITCSE (node);
+    UPDATE_TITCSE (TREE_OPERAND (node, 0));
   else if (DECL_P (node))
     {
-      if (!staticp (node))
+      if (staticp (node))
+       ;
+      else if (decl_function_context (node) == current_function_decl
+              /* Addresses of thread-local variables are invariant.  */
+              || (TREE_CODE (node) == VAR_DECL && DECL_THREAD_LOCAL (node)))
        tc = false;
+      else
+       ti = tc = false;
     }
-  else if (TREE_CODE_CLASS (TREE_CODE (node)) == 'c')
+  else if (CONSTANT_CLASS_P (node))
     ;
   else
     {
@@ -2338,7 +2465,7 @@ do { tree _node = (NODE); \
    Constants, decls, types and misc nodes cannot be.
 
    We define 5 non-variadic functions, from 0 to 4 arguments.  This is
-   enough for all extant tree codes.  These functions can be called 
+   enough for all extant tree codes.  These functions can be called
    directly (preferably!), but can also be obtained via GCC preprocessor
    magic within the build macro.  */
 
@@ -2347,10 +2474,7 @@ build0_stat (enum tree_code code, tree tt MEM_STAT_DECL)
 {
   tree t;
 
-#ifdef ENABLE_CHECKING
-  if (TREE_CODE_LENGTH (code) != 0)
-    abort ();
-#endif
+  gcc_assert (TREE_CODE_LENGTH (code) == 0);
 
   t = make_node_stat (code PASS_MEM_STAT);
   TREE_TYPE (t) = tt;
@@ -2370,10 +2494,10 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
 #ifdef GATHER_STATISTICS
   switch (TREE_CODE_CLASS (code))
     {
-    case 's':  /* an expression with side effects */
+    case tcc_statement:  /* an expression with side effects */
       kind = s_kind;
       break;
-    case 'r':  /* a reference */
+    case tcc_reference:  /* a reference */
       kind = r_kind;
       break;
     default:
@@ -2385,12 +2509,9 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
   tree_node_sizes[(int) kind] += length;
 #endif
 
-#ifdef ENABLE_CHECKING
-  if (TREE_CODE_LENGTH (code) != 1)
-    abort ();
-#endif /* ENABLE_CHECKING */
+  gcc_assert (TREE_CODE_LENGTH (code) == 1);
 
-  t = ggc_alloc_zone_stat (length, tree_zone PASS_MEM_STAT);
+  t = ggc_alloc_zone_pass_stat (length, &tree_zone);
 
   memset (t, 0, sizeof (struct tree_common));
 
@@ -2405,29 +2526,25 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
   TREE_COMPLEXITY (t) = 0;
   TREE_OPERAND (t, 0) = node;
   TREE_BLOCK (t) = NULL_TREE;
-  if (node && !TYPE_P (node) && first_rtl_op (code) != 0)
+  if (node && !TYPE_P (node))
     {
       TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (node);
       TREE_READONLY (t) = TREE_READONLY (node);
     }
 
-  if (TREE_CODE_CLASS (code) == 's')
+  if (TREE_CODE_CLASS (code) == tcc_statement)
     TREE_SIDE_EFFECTS (t) = 1;
   else switch (code)
     {
-    case INIT_EXPR:
-    case MODIFY_EXPR:
     case VA_ARG_EXPR:
-    case PREDECREMENT_EXPR:
-    case PREINCREMENT_EXPR:
-    case POSTDECREMENT_EXPR:
-    case POSTINCREMENT_EXPR:
       /* All of these have side-effects, no matter what their
         operands are.  */
       TREE_SIDE_EFFECTS (t) = 1;
       TREE_READONLY (t) = 0;
       break;
 
+    case MISALIGNED_INDIRECT_REF:
+    case ALIGN_INDIRECT_REF:
     case INDIRECT_REF:
       /* Whether a dereference is readonly has nothing to do with whether
         its operand is readonly.  */
@@ -2440,12 +2557,15 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
       break;
 
     default:
-      if (TREE_CODE_CLASS (code) == '1' && node && !TYPE_P (node)
+      if (TREE_CODE_CLASS (code) == tcc_unary
+         && node && !TYPE_P (node)
          && TREE_CONSTANT (node))
        TREE_CONSTANT (t) = 1;
-      if (TREE_CODE_CLASS (code) == '1' && node && TREE_INVARIANT (node))
+      if (TREE_CODE_CLASS (code) == tcc_unary
+         && node && TREE_INVARIANT (node))
        TREE_INVARIANT (t) = 1;
-      if (TREE_CODE_CLASS (code) == 'r' && node && TREE_THIS_VOLATILE (node))
+      if (TREE_CODE_CLASS (code) == tcc_reference
+         && node && TREE_THIS_VOLATILE (node))
        TREE_THIS_VOLATILE (t) = 1;
       break;
     }
@@ -2456,7 +2576,7 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
 #define PROCESS_ARG(N)                 \
   do {                                 \
     TREE_OPERAND (t, N) = arg##N;      \
-    if (arg##N &&!TYPE_P (arg##N) && fro > N) \
+    if (arg##N &&!TYPE_P (arg##N))     \
       {                                        \
         if (TREE_SIDE_EFFECTS (arg##N))        \
          side_effects = 1;             \
@@ -2474,12 +2594,8 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
 {
   bool constant, read_only, side_effects, invariant;
   tree t;
-  int fro;
 
-#ifdef ENABLE_CHECKING
-  if (TREE_CODE_LENGTH (code) != 2)
-    abort ();
-#endif
+  gcc_assert (TREE_CODE_LENGTH (code) == 2);
 
   t = make_node_stat (code PASS_MEM_STAT);
   TREE_TYPE (t) = tt;
@@ -2488,12 +2604,11 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
      result based on those same flags for the arguments.  But if the
      arguments aren't really even `tree' expressions, we shouldn't be trying
      to do this.  */
-  fro = first_rtl_op (code);
 
   /* Expressions without side effects may be constant if their
      arguments are as well.  */
-  constant = (TREE_CODE_CLASS (code) == '<'
-             || TREE_CODE_CLASS (code) == '2');
+  constant = (TREE_CODE_CLASS (code) == tcc_comparison
+             || TREE_CODE_CLASS (code) == tcc_binary);
   read_only = 1;
   side_effects = TREE_SIDE_EFFECTS (t);
   invariant = constant;
@@ -2504,9 +2619,10 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
   TREE_READONLY (t) = read_only;
   TREE_CONSTANT (t) = constant;
   TREE_INVARIANT (t) = invariant;
-  TREE_SIDE_EFFECTS (t) = side_effects;  
+  TREE_SIDE_EFFECTS (t) = side_effects;
   TREE_THIS_VOLATILE (t)
-    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
+    = (TREE_CODE_CLASS (code) == tcc_reference
+       && arg0 && TREE_THIS_VOLATILE (arg0));
 
   return t;
 }
@@ -2517,18 +2633,12 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
 {
   bool constant, read_only, side_effects, invariant;
   tree t;
-  int fro;
 
-#ifdef ENABLE_CHECKING
-  if (TREE_CODE_LENGTH (code) != 3)
-    abort ();
-#endif
+  gcc_assert (TREE_CODE_LENGTH (code) == 3);
 
   t = make_node_stat (code PASS_MEM_STAT);
   TREE_TYPE (t) = tt;
 
-  fro = first_rtl_op (code);
-
   side_effects = TREE_SIDE_EFFECTS (t);
 
   PROCESS_ARG(0);
@@ -2555,9 +2665,10 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
          }
     }
 
-  TREE_SIDE_EFFECTS (t) = side_effects;  
+  TREE_SIDE_EFFECTS (t) = side_effects;
   TREE_THIS_VOLATILE (t)
-    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
+    = (TREE_CODE_CLASS (code) == tcc_reference
+       && arg0 && TREE_THIS_VOLATILE (arg0));
 
   return t;
 }
@@ -2568,18 +2679,12 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
 {
   bool constant, read_only, side_effects, invariant;
   tree t;
-  int fro;
 
-#ifdef ENABLE_CHECKING
-  if (TREE_CODE_LENGTH (code) != 4)
-    abort ();
-#endif
+  gcc_assert (TREE_CODE_LENGTH (code) == 4);
 
   t = make_node_stat (code PASS_MEM_STAT);
   TREE_TYPE (t) = tt;
 
-  fro = first_rtl_op (code);
-
   side_effects = TREE_SIDE_EFFECTS (t);
 
   PROCESS_ARG(0);
@@ -2587,9 +2692,10 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
   PROCESS_ARG(2);
   PROCESS_ARG(3);
 
-  TREE_SIDE_EFFECTS (t) = side_effects;  
+  TREE_SIDE_EFFECTS (t) = side_effects;
   TREE_THIS_VOLATILE (t)
-    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
+    = (TREE_CODE_CLASS (code) == tcc_reference
+       && arg0 && TREE_THIS_VOLATILE (arg0));
 
   return t;
 }
@@ -2632,7 +2738,7 @@ tree
       t = build4 (code, tt, arg0, arg1, arg2, arg3);
       break;
     default:
-      abort ();
+      gcc_unreachable ();
     }
   va_end (p);
 
@@ -2690,16 +2796,37 @@ build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL)
   else if (code == FUNCTION_DECL)
     DECL_MODE (t) = FUNCTION_MODE;
 
+  /* Set default visibility to whatever the user supplied with
+     visibility_specified depending on #pragma GCC visibility.  */
+  DECL_VISIBILITY (t) = default_visibility;
+  DECL_VISIBILITY_SPECIFIED (t) = visibility_options.inpragma;
+
   return t;
 }
+
+/* Builds and returns function declaration with NAME and TYPE.  */
+
+tree
+build_fn_decl (const char *name, tree type)
+{
+  tree id = get_identifier (name);
+  tree decl = build_decl (FUNCTION_DECL, id, type);
+
+  DECL_EXTERNAL (decl) = 1;
+  TREE_PUBLIC (decl) = 1;
+  DECL_ARTIFICIAL (decl) = 1;
+  TREE_NOTHROW (decl) = 1;
+
+  return decl;
+}
+
 \f
 /* BLOCK nodes are used to represent the structure of binding contours
    and declarations, once those contours have been exited and their contents
    compiled.  This information is used for outputting debugging info.  */
 
 tree
-build_block (tree vars, tree tags ATTRIBUTE_UNUSED, tree subblocks,
-            tree supercontext, tree chain)
+build_block (tree vars, tree subblocks, tree supercontext, tree chain)
 {
   tree block = make_node (BLOCK);
 
@@ -2721,12 +2848,13 @@ expanded_location
 expand_location (source_location loc)
 {
   expanded_location xloc;
-  if (loc == 0) { xloc.file = NULL; xloc.line = 0; }
+  if (loc == 0) { xloc.file = NULL; xloc.line = 0;  xloc.column = 0; }
   else
     {
       const struct line_map *map = linemap_lookup (&line_table, loc);
       xloc.file = map->to_file;
       xloc.line = SOURCE_LINE (map, loc);
+      xloc.column = SOURCE_COLUMN (map, loc);
     };
   return xloc;
 }
@@ -2787,6 +2915,74 @@ build_decl_attribute_variant (tree ddecl, tree attribute)
   return ddecl;
 }
 
+/* Borrowed from hashtab.c iterative_hash implementation.  */
+#define mix(a,b,c) \
+{ \
+  a -= b; a -= c; a ^= (c>>13); \
+  b -= c; b -= a; b ^= (a<< 8); \
+  c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \
+  a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
+  b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
+  c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
+  a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
+  b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
+  c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
+}
+
+
+/* Produce good hash value combining VAL and VAL2.  */
+static inline hashval_t
+iterative_hash_hashval_t (hashval_t val, hashval_t val2)
+{
+  /* the golden ratio; an arbitrary value.  */
+  hashval_t a = 0x9e3779b9;
+
+  mix (a, val, val2);
+  return val2;
+}
+
+/* Produce good hash value combining PTR and VAL2.  */
+static inline hashval_t
+iterative_hash_pointer (void *ptr, hashval_t val2)
+{
+  if (sizeof (ptr) == sizeof (hashval_t))
+    return iterative_hash_hashval_t ((size_t) ptr, val2);
+  else
+    {
+      hashval_t a = (hashval_t) (size_t) ptr;
+      /* Avoid warnings about shifting of more than the width of the type on
+         hosts that won't execute this path.  */
+      int zero = 0;
+      hashval_t b = (hashval_t) ((size_t) ptr >> (sizeof (hashval_t) * 8 + zero));
+      mix (a, b, val2);
+      return val2;
+    }
+}
+
+/* Produce good hash value combining VAL and VAL2.  */
+static inline hashval_t
+iterative_hash_host_wide_int (HOST_WIDE_INT val, hashval_t val2)
+{
+  if (sizeof (HOST_WIDE_INT) == sizeof (hashval_t))
+    return iterative_hash_hashval_t (val, val2);
+  else
+    {
+      hashval_t a = (hashval_t) val;
+      /* Avoid warnings about shifting of more than the width of the type on
+         hosts that won't execute this path.  */
+      int zero = 0;
+      hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 8 + zero));
+      mix (a, b, val2);
+      if (sizeof (HOST_WIDE_INT) > 2 * sizeof (hashval_t))
+       {
+         hashval_t a = (hashval_t) (val >> (sizeof (hashval_t) * 16 + zero));
+         hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 24 + zero));
+         mix (a, b, val2);
+       }
+      return val2;
+    }
+}
+
 /* Return a type like TTYPE except that its TYPE_ATTRIBUTE
    is ATTRIBUTE.
 
@@ -2850,6 +3046,7 @@ build_type_attribute_variant (tree ttype, tree attribute)
   return ttype;
 }
 
+
 /* Return nonzero if IDENT is a valid name for attribute ATTR,
    or zero if not.
 
@@ -2858,29 +3055,29 @@ build_type_attribute_variant (tree ttype, tree attribute)
    `text'.  One might then also require attribute lists to be stored in
    their canonicalized form.  */
 
-int
-is_attribute_p (const char *attr, tree ident)
+static int
+is_attribute_with_length_p (const char *attr, int attr_len, tree ident)
 {
-  int ident_len, attr_len;
+  int ident_len;
   const char *p;
 
   if (TREE_CODE (ident) != IDENTIFIER_NODE)
     return 0;
-
-  if (strcmp (attr, IDENTIFIER_POINTER (ident)) == 0)
-    return 1;
-
+  
   p = IDENTIFIER_POINTER (ident);
-  ident_len = strlen (p);
-  attr_len = strlen (attr);
+  ident_len = IDENTIFIER_LENGTH (ident);
+  
+  if (ident_len == attr_len
+      && strcmp (attr, p) == 0)
+    return 1;
 
   /* If ATTR is `__text__', IDENT must be `text'; and vice versa.  */
   if (attr[0] == '_')
     {
-      if (attr[1] != '_'
-         || attr[attr_len - 2] != '_'
-         || attr[attr_len - 1] != '_')
-       abort ();
+      gcc_assert (attr[1] == '_');
+      gcc_assert (attr[attr_len - 2] == '_');
+      gcc_assert (attr[attr_len - 1] == '_');
+      gcc_assert (attr[1] == '_');
       if (ident_len == attr_len - 4
          && strncmp (attr + 2, p, attr_len - 4) == 0)
        return 1;
@@ -2897,6 +3094,17 @@ is_attribute_p (const char *attr, tree ident)
   return 0;
 }
 
+/* Return nonzero if IDENT is a valid name for attribute ATTR,
+   or zero if not.
+
+   We try both `text' and `__text__', ATTR may be either one.  */
+
+int
+is_attribute_p (const char *attr, tree ident)
+{
+  return is_attribute_with_length_p (attr, strlen (attr), ident);
+}
+
 /* Given an attribute name and a list of attributes, return a pointer to the
    attribute's list element if the attribute is part of the list, or NULL_TREE
    if not found.  If the attribute appears more than once, this only
@@ -2907,12 +3115,12 @@ tree
 lookup_attribute (const char *attr_name, tree list)
 {
   tree l;
+  size_t attr_len = strlen (attr_name);
 
   for (l = list; l; l = TREE_CHAIN (l))
     {
-      if (TREE_CODE (TREE_PURPOSE (l)) != IDENTIFIER_NODE)
-       abort ();
-      if (is_attribute_p (attr_name, TREE_PURPOSE (l)))
+      gcc_assert (TREE_CODE (TREE_PURPOSE (l)) == IDENTIFIER_NODE);
+      if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l)))
        return l;
     }
 
@@ -2988,7 +3196,7 @@ merge_decl_attributes (tree olddecl, tree newdecl)
                           DECL_ATTRIBUTES (newdecl));
 }
 
-#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
+#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
 
 /* Specialization of merge_decl_attributes for various Windows targets.
 
@@ -3041,6 +3249,81 @@ merge_dllimport_decl_attributes (tree old, tree new)
   return a;
 }
 
+/* Handle a "dllimport" or "dllexport" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+tree
+handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
+                     bool *no_add_attrs)
+{
+  tree node = *pnode;
+
+  /* These attributes may apply to structure and union types being created,
+     but otherwise should pass to the declaration involved.  */
+  if (!DECL_P (node))
+    {
+      if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
+                  | (int) ATTR_FLAG_ARRAY_NEXT))
+       {
+         *no_add_attrs = true;
+         return tree_cons (name, args, NULL_TREE);
+       }
+      if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
+       {
+         warning (0, "%qs attribute ignored", IDENTIFIER_POINTER (name));
+         *no_add_attrs = true;
+       }
+
+      return NULL_TREE;
+    }
+
+  /* Report error on dllimport ambiguities seen now before they cause
+     any damage.  */
+  if (is_attribute_p ("dllimport", name))
+    {
+      /* Like MS, treat definition of dllimported variables and
+        non-inlined functions on declaration as syntax errors.  We
+        allow the attribute for function definitions if declared
+        inline.  */
+      if (TREE_CODE (node) == FUNCTION_DECL  && DECL_INITIAL (node)
+          && !DECL_DECLARED_INLINE_P (node))
+       {
+         error ("%Jfunction %qD definition is marked dllimport.", node, node);
+         *no_add_attrs = true;
+       }
+
+      else if (TREE_CODE (node) == VAR_DECL)
+       {
+         if (DECL_INITIAL (node))
+           {
+             error ("%Jvariable %qD definition is marked dllimport.",
+                    node, node);
+             *no_add_attrs = true;
+           }
+
+         /* `extern' needn't be specified with dllimport.
+            Specify `extern' now and hope for the best.  Sigh.  */
+         DECL_EXTERNAL (node) = 1;
+         /* Also, implicitly give dllimport'd variables declared within
+            a function global scope, unless declared static.  */
+         if (current_function_decl != NULL_TREE && !TREE_STATIC (node))
+           TREE_PUBLIC (node) = 1;
+       }
+    }
+
+  /*  Report error if symbol is not accessible at global scope.  */
+  if (!TREE_PUBLIC (node)
+      && (TREE_CODE (node) == VAR_DECL
+         || TREE_CODE (node) == FUNCTION_DECL))
+    {
+      error ("%Jexternal linkage required for symbol %qD because of "
+            "%qs attribute.", node, node, IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 #endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES  */
 \f
 /* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask
@@ -3103,29 +3386,45 @@ build_qualified_type (tree type, int type_quals)
   /* If not, build it.  */
   if (!t)
     {
-      t = build_type_copy (type);
+      t = build_variant_type_copy (type);
       set_type_quals (t, type_quals);
     }
 
   return t;
 }
 
+/* Create a new distinct copy of TYPE.  The new type is made its own
+   MAIN_VARIANT.  */
+
+tree
+build_distinct_type_copy (tree type)
+{
+  tree t = copy_node (type);
+  
+  TYPE_POINTER_TO (t) = 0;
+  TYPE_REFERENCE_TO (t) = 0;
+
+  /* Make it its own variant.  */
+  TYPE_MAIN_VARIANT (t) = t;
+  TYPE_NEXT_VARIANT (t) = 0;
+  
+  return t;
+}
+
 /* Create a new variant of TYPE, equivalent but distinct.
    This is so the caller can modify it.  */
 
 tree
-build_type_copy (tree type)
+build_variant_type_copy (tree type)
 {
   tree t, m = TYPE_MAIN_VARIANT (type);
 
-  t = copy_node (type);
-
-  TYPE_POINTER_TO (t) = 0;
-  TYPE_REFERENCE_TO (t) = 0;
-
-  /* Add this type to the chain of variants of TYPE.  */
+  t = build_distinct_type_copy (type);
+  
+  /* Add the new type to the chain of variants of TYPE.  */
   TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
   TYPE_NEXT_VARIANT (m) = t;
+  TYPE_MAIN_VARIANT (t) = m;
 
   return t;
 }
@@ -3173,11 +3472,13 @@ type_hash_eq (const void *va, const void *vb)
     {
     case VOID_TYPE:
     case COMPLEX_TYPE:
-    case VECTOR_TYPE:
     case POINTER_TYPE:
     case REFERENCE_TYPE:
       return 1;
 
+    case VECTOR_TYPE:
+      return TYPE_VECTOR_SUBPARTS (a->type) == TYPE_VECTOR_SUBPARTS (b->type);
+
     case ENUMERAL_TYPE:
       if (TYPE_VALUES (a->type) != TYPE_VALUES (b->type)
          && !(TYPE_VALUES (a->type)
@@ -3213,9 +3514,8 @@ type_hash_eq (const void *va, const void *vb)
                      && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST
                      && type_list_equal (TYPE_ARG_TYPES (a->type),
                                          TYPE_ARG_TYPES (b->type)))));
-                                                                     
+
     case ARRAY_TYPE:
-    case SET_TYPE:
       return TYPE_DOMAIN (a->type) == TYPE_DOMAIN (b->type);
 
     case RECORD_TYPE:
@@ -3304,8 +3604,7 @@ type_hash_canon (unsigned int hashcode, tree type)
 
   /* The hash table only contains main variants, so ensure that's what we're
      being passed.  */
-  if (TYPE_MAIN_VARIANT (type) != type)
-    abort ();
+  gcc_assert (TYPE_MAIN_VARIANT (type) == type);
 
   if (!lang_hooks.types.hash_types)
     return type;
@@ -3551,15 +3850,13 @@ host_integerp (tree t, int pos)
 
 /* Return the HOST_WIDE_INT least significant bits of T if it is an
    INTEGER_CST and there is no overflow.  POS is nonzero if the result must
-   be positive.  Abort if we cannot satisfy the above conditions.  */
+   be positive.  We must be able to satisfy the above conditions.  */
 
 HOST_WIDE_INT
 tree_low_cst (tree t, int pos)
 {
-  if (host_integerp (t, pos))
-    return TREE_INT_CST_LOW (t);
-  else
-    abort ();
+  gcc_assert (host_integerp (t, pos));
+  return TREE_INT_CST_LOW (t);
 }
 
 /* Return the most significant bit of the integer constant T.  */
@@ -3666,7 +3963,7 @@ simple_cst_equal (tree t1, tree t2)
                         TREE_STRING_LENGTH (t1)));
 
     case CONSTRUCTOR:
-      return simple_cst_list_equal (CONSTRUCTOR_ELTS (t1), 
+      return simple_cst_list_equal (CONSTRUCTOR_ELTS (t1),
                                    CONSTRUCTOR_ELTS (t2));
 
     case SAVE_EXPR:
@@ -3731,12 +4028,12 @@ simple_cst_equal (tree t1, tree t2)
 
   switch (TREE_CODE_CLASS (code1))
     {
-    case '1':
-    case '2':
-    case '<':
-    case 'e':
-    case 'r':
-    case 's':
+    case tcc_unary:
+    case tcc_binary:
+    case tcc_comparison:
+    case tcc_expression:
+    case tcc_reference:
+    case tcc_statement:
       cmp = 1;
       for (i = 0; i < TREE_CODE_LENGTH (code1); i++)
        {
@@ -3793,7 +4090,7 @@ associative_tree_code (enum tree_code code)
   return false;
 }
 
-/* Return true if CODE represents an commutative tree code.  Otherwise
+/* Return true if CODE represents a commutative tree code.  Otherwise
    return false.  */
 bool
 commutative_tree_code (enum tree_code code)
@@ -3838,97 +4135,104 @@ iterative_hash_expr (tree t, hashval_t val)
   char class;
 
   if (t == NULL_TREE)
-    return iterative_hash_object (t, val);
+    return iterative_hash_pointer (t, val);
 
   code = TREE_CODE (t);
-  class = TREE_CODE_CLASS (code);
 
-  if (class == 'd'
-      || TREE_CODE (t) == VALUE_HANDLE)
-    {
-      /* Decls we can just compare by pointer.  */
-      val = iterative_hash_object (t, val);
-    }
-  else if (class == 'c')
+  switch (code)
     {
-      /* Alas, constants aren't shared, so we can't rely on pointer
-        identity.  */
-      if (code == INTEGER_CST)
+    /* Alas, constants aren't shared, so we can't rely on pointer
+       identity.  */
+    case INTEGER_CST:
+      val = iterative_hash_host_wide_int (TREE_INT_CST_LOW (t), val);
+      return iterative_hash_host_wide_int (TREE_INT_CST_HIGH (t), val);
+    case REAL_CST:
+      {
+       unsigned int val2 = real_hash (TREE_REAL_CST_PTR (t));
+
+       return iterative_hash_hashval_t (val2, val);
+      }
+    case STRING_CST:
+      return iterative_hash (TREE_STRING_POINTER (t),
+                            TREE_STRING_LENGTH (t), val);
+    case COMPLEX_CST:
+      val = iterative_hash_expr (TREE_REALPART (t), val);
+      return iterative_hash_expr (TREE_IMAGPART (t), val);
+    case VECTOR_CST:
+      return iterative_hash_expr (TREE_VECTOR_CST_ELTS (t), val);
+
+    case SSA_NAME:
+    case VALUE_HANDLE:
+      /* we can just compare by pointer.  */
+      return iterative_hash_pointer (t, val);
+
+    case TREE_LIST:
+      /* A list of expressions, for a CALL_EXPR or as the elements of a
+        VECTOR_CST.  */
+      for (; t; t = TREE_CHAIN (t))
+       val = iterative_hash_expr (TREE_VALUE (t), val);
+      return val;
+    case FUNCTION_DECL:
+      /* When referring to a built-in FUNCTION_DECL, use the
+        __builtin__ form.  Otherwise nodes that compare equal
+        according to operand_equal_p might get different
+        hash codes.  */
+      if (DECL_BUILT_IN (t))
        {
-         val = iterative_hash_object (TREE_INT_CST_LOW (t), val);
-         val = iterative_hash_object (TREE_INT_CST_HIGH (t), val);
+         val = iterative_hash_pointer (built_in_decls[DECL_FUNCTION_CODE (t)], 
+                                     val);
+         return val;
        }
-      else if (code == REAL_CST)
-       {
-         unsigned int val2 = real_hash (TREE_REAL_CST_PTR (t));
+      /* else FALL THROUGH */
+    default:
+      class = TREE_CODE_CLASS (code);
 
-         val = iterative_hash (&val2, sizeof (unsigned int), val);
-       }
-      else if (code == STRING_CST)
-       val = iterative_hash (TREE_STRING_POINTER (t),
-                             TREE_STRING_LENGTH (t), val);
-      else if (code == COMPLEX_CST)
+      if (class == tcc_declaration)
        {
-         val = iterative_hash_expr (TREE_REALPART (t), val);
-         val = iterative_hash_expr (TREE_IMAGPART (t), val);
+         /* Otherwise, we can just compare decls by pointer.  */
+         val = iterative_hash_pointer (t, val);
        }
-      else if (code == VECTOR_CST)
-       val = iterative_hash_expr (TREE_VECTOR_CST_ELTS (t), val);
       else
-       abort ();
-    }
-  else if (IS_EXPR_CODE_CLASS (class))
-    {
-      val = iterative_hash_object (code, val);
-
-      /* Don't hash the type, that can lead to having nodes which
-        compare equal according to operand_equal_p, but which
-        have different hash codes.  */
-      if (code == NOP_EXPR
-         || code == CONVERT_EXPR
-         || code == NON_LVALUE_EXPR)
        {
-         /* Make sure to include signness in the hash computation.  */
-         val += TYPE_UNSIGNED (TREE_TYPE (t));
-         val = iterative_hash_expr (TREE_OPERAND (t, 0), val);
-       }
+         gcc_assert (IS_EXPR_CODE_CLASS (class));
+         
+         val = iterative_hash_object (code, val);
+
+         /* Don't hash the type, that can lead to having nodes which
+            compare equal according to operand_equal_p, but which
+            have different hash codes.  */
+         if (code == NOP_EXPR
+             || code == CONVERT_EXPR
+             || code == NON_LVALUE_EXPR)
+           {
+             /* Make sure to include signness in the hash computation.  */
+             val += TYPE_UNSIGNED (TREE_TYPE (t));
+             val = iterative_hash_expr (TREE_OPERAND (t, 0), val);
+           }
 
-      if (commutative_tree_code (code))
-       {
-         /* It's a commutative expression.  We want to hash it the same
-            however it appears.  We do this by first hashing both operands
-            and then rehashing based on the order of their independent
-            hashes.  */
-         hashval_t one = iterative_hash_expr (TREE_OPERAND (t, 0), 0);
-         hashval_t two = iterative_hash_expr (TREE_OPERAND (t, 1), 0);
-         hashval_t t;
-
-         if (one > two)
-           t = one, one = two, two = t;
-
-         val = iterative_hash_object (one, val);
-         val = iterative_hash_object (two, val);
+         else if (commutative_tree_code (code))
+           {
+             /* It's a commutative expression.  We want to hash it the same
+                however it appears.  We do this by first hashing both operands
+                and then rehashing based on the order of their independent
+                hashes.  */
+             hashval_t one = iterative_hash_expr (TREE_OPERAND (t, 0), 0);
+             hashval_t two = iterative_hash_expr (TREE_OPERAND (t, 1), 0);
+             hashval_t t;
+
+             if (one > two)
+               t = one, one = two, two = t;
+
+             val = iterative_hash_hashval_t (one, val);
+             val = iterative_hash_hashval_t (two, val);
+           }
+         else
+           for (i = TREE_CODE_LENGTH (code) - 1; i >= 0; --i)
+             val = iterative_hash_expr (TREE_OPERAND (t, i), val);
        }
-      else
-       for (i = first_rtl_op (code) - 1; i >= 0; --i)
-         val = iterative_hash_expr (TREE_OPERAND (t, i), val);
+      return val;
+      break;
     }
-  else if (code == TREE_LIST)
-    {
-      /* A list of expressions, for a CALL_EXPR or as the elements of a
-        VECTOR_CST.  */
-      for (; t; t = TREE_CHAIN (t))
-       val = iterative_hash_expr (TREE_VALUE (t), val);
-    }
-  else if (code == SSA_NAME)
-    {
-      val = iterative_hash_object (SSA_NAME_VERSION (t), val);
-      val = iterative_hash_expr (SSA_NAME_VAR (t), val);
-    }
-  else
-    abort ();
-
-  return val;
 }
 \f
 /* Constructors for pointer, array and function types.
@@ -4077,7 +4381,7 @@ build_index_type (tree maxval)
   TREE_TYPE (itype) = sizetype;
   TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype);
   TYPE_MIN_VALUE (itype) = size_zero_node;
-  TYPE_MAX_VALUE (itype) = convert (sizetype, maxval);
+  TYPE_MAX_VALUE (itype) = fold_convert (sizetype, maxval);
   TYPE_MODE (itype) = TYPE_MODE (sizetype);
   TYPE_SIZE (itype) = TYPE_SIZE (sizetype);
   TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (sizetype);
@@ -4090,6 +4394,28 @@ build_index_type (tree maxval)
     return itype;
 }
 
+/* Builds a signed or unsigned integer type of precision PRECISION.
+   Used for C bitfields whose precision does not match that of
+   built-in target types.  */
+tree
+build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision,
+                               int unsignedp)
+{
+  tree itype = make_node (INTEGER_TYPE);
+
+  TYPE_PRECISION (itype) = precision;
+
+  if (unsignedp)
+    fixup_unsigned_type (itype);
+  else
+    fixup_signed_type (itype);
+
+  if (host_integerp (TYPE_MAX_VALUE (itype), 1))
+    return type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype);
+
+  return itype;
+}
+
 /* Create a range of some discrete type TYPE (an INTEGER_TYPE,
    ENUMERAL_TYPE, BOOLEAN_TYPE, or CHAR_TYPE), with
    low bound LOWVAL and high bound HIGHVAL.
@@ -4150,9 +4476,12 @@ build_array_type (tree elt_type, tree index_type)
   t = make_node (ARRAY_TYPE);
   TREE_TYPE (t) = elt_type;
   TYPE_DOMAIN (t) = index_type;
-
+  
   if (index_type == 0)
-    return t;
+    {
+      layout_type (t);
+      return t;
+    }
 
   hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode);
   hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode);
@@ -4228,9 +4557,14 @@ build_function_type_list (tree return_type, ...)
   for (args = NULL_TREE; t != NULL_TREE; t = va_arg (p, tree))
     args = tree_cons (NULL_TREE, t, args);
 
-  last = args;
-  args = nreverse (args);
-  TREE_CHAIN (last) = void_list_node;
+  if (args == NULL_TREE)
+    args = void_list_node;
+  else
+    {
+      last = args;
+      args = nreverse (args);
+      TREE_CHAIN (last) = void_list_node;
+    }
   args = build_function_type (return_type, args);
 
   va_end (p);
@@ -4283,10 +4617,9 @@ build_method_type_directly (tree basetype,
 tree
 build_method_type (tree basetype, tree type)
 {
-  if (TREE_CODE (type) != FUNCTION_TYPE)
-    abort ();
+  gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
 
-  return build_method_type_directly (basetype, 
+  return build_method_type_directly (basetype,
                                     TREE_TYPE (type),
                                     TYPE_ARG_TYPES (type));
 }
@@ -4412,7 +4745,8 @@ get_unwidened (tree op, tree for_type)
        && TYPE_UNSIGNED (type));
   tree win = op;
 
-  while (TREE_CODE (op) == NOP_EXPR)
+  while (TREE_CODE (op) == NOP_EXPR
+        || TREE_CODE (op) == CONVERT_EXPR)
     {
       int bitschange
        = TYPE_PRECISION (TREE_TYPE (op))
@@ -4442,7 +4776,9 @@ get_unwidened (tree op, tree for_type)
          /* TYPE_UNSIGNED says whether this is a zero-extension.
             Let's avoid computing it if it does not affect WIN
             and if UNS will not be needed again.  */
-         if ((uns || TREE_CODE (op) == NOP_EXPR)
+         if ((uns
+              || TREE_CODE (op) == NOP_EXPR
+              || TREE_CODE (op) == CONVERT_EXPR)
              && TYPE_UNSIGNED (TREE_TYPE (op)))
            {
              uns = 1;
@@ -4496,6 +4832,7 @@ get_narrower (tree op, int *unsignedp_ptr)
   int uns = 0;
   int first = 1;
   tree win = op;
+  bool integral_p = INTEGRAL_TYPE_P (TREE_TYPE (op));
 
   while (TREE_CODE (op) == NOP_EXPR)
     {
@@ -4532,6 +4869,10 @@ get_narrower (tree op, int *unsignedp_ptr)
            uns = TYPE_UNSIGNED (TREE_TYPE (op));
          first = 0;
          op = TREE_OPERAND (op, 0);
+         /* Keep trying to narrow, but don't assign op to win if it
+            would turn an integral type into something else.  */
+         if (INTEGRAL_TYPE_P (TREE_TYPE (op)) != integral_p)
+           continue;
        }
 
       win = op;
@@ -4583,16 +4924,8 @@ int_fits_type_p (tree c, tree type)
 {
   tree type_low_bound = TYPE_MIN_VALUE (type);
   tree type_high_bound = TYPE_MAX_VALUE (type);
-  int ok_for_low_bound, ok_for_high_bound;
-
-  /* Perform some generic filtering first, which may allow making a decision
-     even if the bounds are not constant.  First, negative integers never fit
-     in unsigned types, */
-  if ((TYPE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0)
-      /* Also, unsigned integers with top bit set never fit signed types.  */
-      || (! TYPE_UNSIGNED (type)
-         && TYPE_UNSIGNED (TREE_TYPE (c)) && tree_int_cst_msb (c)))
-    return 0;
+  bool ok_for_low_bound, ok_for_high_bound;
+  tree tmp;
 
   /* If at least one bound of the type is a constant integer, we can check
      ourselves and maybe make a decision. If no such decision is possible, but
@@ -4604,58 +4937,104 @@ int_fits_type_p (tree c, tree type)
      for "unknown if constant fits", 0 for "constant known *not* to fit" and 1
      for "constant known to fit".  */
 
-  ok_for_low_bound = -1;
-  ok_for_high_bound = -1;
-
   /* Check if C >= type_low_bound.  */
   if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST)
     {
-      ok_for_low_bound = ! tree_int_cst_lt (c, type_low_bound);
-      if (! ok_for_low_bound)
+      if (tree_int_cst_lt (c, type_low_bound))
        return 0;
+      ok_for_low_bound = true;
     }
+  else
+    ok_for_low_bound = false;
 
   /* Check if c <= type_high_bound.  */
   if (type_high_bound && TREE_CODE (type_high_bound) == INTEGER_CST)
     {
-      ok_for_high_bound = ! tree_int_cst_lt (type_high_bound, c);
-      if (! ok_for_high_bound)
+      if (tree_int_cst_lt (type_high_bound, c))
        return 0;
+      ok_for_high_bound = true;
     }
+  else
+    ok_for_high_bound = false;
 
   /* If the constant fits both bounds, the result is known.  */
-  if (ok_for_low_bound == 1 && ok_for_high_bound == 1)
+  if (ok_for_low_bound && ok_for_high_bound)
     return 1;
 
+  /* Perform some generic filtering which may allow making a decision
+     even if the bounds are not constant.  First, negative integers
+     never fit in unsigned types, */
+  if (TYPE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0)
+    return 0;
+
+  /* Second, narrower types always fit in wider ones.  */
+  if (TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (c)))
+    return 1;
+
+  /* Third, unsigned integers with top bit set never fit signed types.  */
+  if (! TYPE_UNSIGNED (type)
+      && TYPE_UNSIGNED (TREE_TYPE (c))
+      && tree_int_cst_msb (c))
+    return 0;
+
   /* If we haven't been able to decide at this point, there nothing more we
      can check ourselves here. Look at the base type if we have one.  */
-  else if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != 0)
+  if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != 0)
     return int_fits_type_p (c, TREE_TYPE (type));
 
   /* Or to force_fit_type, if nothing else.  */
-  else
-    {
-      c = copy_node (c);
-      TREE_TYPE (c) = type;
-      return !force_fit_type (c, 0);
-    }
+  tmp = copy_node (c);
+  TREE_TYPE (tmp) = type;
+  tmp = force_fit_type (tmp, -1, false, false);
+  return TREE_INT_CST_HIGH (tmp) == TREE_INT_CST_HIGH (c)
+         && TREE_INT_CST_LOW (tmp) == TREE_INT_CST_LOW (c);
+}
+
+/* Subprogram of following function.  Called by walk_tree.
+
+   Return *TP if it is an automatic variable or parameter of the
+   function passed in as DATA.  */
+
+static tree
+find_var_from_fn (tree *tp, int *walk_subtrees, void *data)
+{
+  tree fn = (tree) data;
+
+  if (TYPE_P (*tp))
+    *walk_subtrees = 0;
+
+  else if (DECL_P (*tp)
+          && lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn))
+    return *tp;
+
+  return NULL_TREE;
 }
 
 /* Returns true if T is, contains, or refers to a type with variable
-   size.  This concept is more general than that of C99 'variably
-   modified types': in C99, a struct type is never variably modified
-   because a VLA may not appear as a structure member.  However, in
-   GNU C code like:
+   size.  If FN is nonzero, only return true if a modifier of the type
+   or position of FN is a variable or parameter inside FN.
+
+   This concept is more general than that of C99 'variably modified types':
+   in C99, a struct type is never variably modified because a VLA may not
+   appear as a structure member.  However, in GNU C code like:
 
      struct S { int i[f()]; };
 
    is valid, and other languages may define similar constructs.  */
 
 bool
-variably_modified_type_p (tree type)
+variably_modified_type_p (tree type, tree fn)
 {
   tree t;
 
+/* Test if T is either variable (if FN is zero) or an expression containing
+   a variable in FN.  */
+#define RETURN_TRUE_IF_VAR(T)                                          \
+  do { tree _t = (T);                                                  \
+    if (_t && _t != error_mark_node && TREE_CODE (_t) != INTEGER_CST   \
+        && (!fn || walk_tree (&_t, find_var_from_fn, fn, NULL)))       \
+      return true;  } while (0)
+
   if (type == error_mark_node)
     return false;
 
@@ -4664,18 +5043,16 @@ variably_modified_type_p (tree type)
      We do not yet have a representation of the C99 '[*]' syntax.
      When a representation is chosen, this function should be modified
      to test for that case as well.  */
-  t = TYPE_SIZE (type);
-  if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
-    return true;
+  RETURN_TRUE_IF_VAR (TYPE_SIZE (type));
+  RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT(type));
 
   switch (TREE_CODE (type))
     {
     case POINTER_TYPE:
     case REFERENCE_TYPE:
     case ARRAY_TYPE:
-    case SET_TYPE:
     case VECTOR_TYPE:
-      if (variably_modified_type_p (TREE_TYPE (type)))
+      if (variably_modified_type_p (TREE_TYPE (type), fn))
        return true;
       break;
 
@@ -4683,13 +5060,13 @@ variably_modified_type_p (tree type)
     case METHOD_TYPE:
       /* If TYPE is a function type, it is variably modified if any of the
          parameters or the return type are variably modified.  */
-      if (variably_modified_type_p (TREE_TYPE (type)))
+      if (variably_modified_type_p (TREE_TYPE (type), fn))
          return true;
 
       for (t = TYPE_ARG_TYPES (type);
           t && t != void_list_node;
           t = TREE_CHAIN (t))
-       if (variably_modified_type_p (TREE_VALUE (t)))
+       if (variably_modified_type_p (TREE_VALUE (t), fn))
          return true;
       break;
 
@@ -4700,13 +5077,8 @@ variably_modified_type_p (tree type)
     case CHAR_TYPE:
       /* Scalar types are variably modified if their end points
         aren't constant.  */
-      t = TYPE_MIN_VALUE (type);
-      if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
-       return true;
-
-      t = TYPE_MAX_VALUE (type);
-      if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
-       return true;
+      RETURN_TRUE_IF_VAR (TYPE_MIN_VALUE (type));
+      RETURN_TRUE_IF_VAR (TYPE_MAX_VALUE (type));
       break;
 
     case RECORD_TYPE:
@@ -4719,14 +5091,12 @@ variably_modified_type_p (tree type)
       for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
        if (TREE_CODE (t) == FIELD_DECL)
          {
-           tree t1 = DECL_FIELD_OFFSET (t);
+           RETURN_TRUE_IF_VAR (DECL_FIELD_OFFSET (t));
+           RETURN_TRUE_IF_VAR (DECL_SIZE (t));
+           RETURN_TRUE_IF_VAR (DECL_SIZE_UNIT (t));
 
-           if (t1 && t1 != error_mark_node && TREE_CODE (t1) != INTEGER_CST)
-             return true;
-
-           t1 = DECL_SIZE (t);
-           if (t1 && t1 != error_mark_node && TREE_CODE (t1) != INTEGER_CST)
-             return true;
+           if (TREE_CODE (type) == QUAL_UNION_TYPE)
+             RETURN_TRUE_IF_VAR (DECL_QUALIFIER (t));
          }
        break;
 
@@ -4736,7 +5106,9 @@ variably_modified_type_p (tree type)
 
   /* The current language may have other cases to check, but in general,
      all other types are not variably modified.  */
-  return lang_hooks.tree_inlining.var_mod_type_p (type);
+  return lang_hooks.tree_inlining.var_mod_type_p (type, fn);
+
+#undef RETURN_TRUE_IF_VAR
 }
 
 /* Given a DECL or TYPE, return the scope in which it was declared, or
@@ -4803,18 +5175,18 @@ decl_type_context (tree decl)
       case UNION_TYPE:
       case QUAL_UNION_TYPE:
        return context;
-       
+
       case TYPE_DECL:
       case FUNCTION_DECL:
        context = DECL_CONTEXT (context);
        break;
-       
+
       case BLOCK:
        context = BLOCK_SUPERCONTEXT (context);
        break;
-       
+
       default:
-       abort ();
+       gcc_unreachable ();
       }
 
   return NULL_TREE;
@@ -4831,8 +5203,7 @@ get_callee_fndecl (tree call)
 
   /* It's invalid to call this function with anything but a
      CALL_EXPR.  */
-  if (TREE_CODE (call) != CALL_EXPR)
-    abort ();
+  gcc_assert (TREE_CODE (call) == CALL_EXPR);
 
   /* The first operand to the CALL is the address of the function
      called.  */
@@ -4851,7 +5222,7 @@ get_callee_fndecl (tree call)
   if (TREE_CODE (addr) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (addr, 0)) == FUNCTION_DECL)
     return TREE_OPERAND (addr, 0);
-  
+
   /* We couldn't figure out what was being called.  Maybe the front
      end has some idea.  */
   return lang_hooks.lang_get_callee_fndecl (call);
@@ -4903,11 +5274,11 @@ crc32_string (unsigned chksum, const char *string)
     {
       unsigned value = *string << 24;
       unsigned ix;
-      
+
       for (ix = 8; ix--; value <<= 1)
        {
          unsigned feedback;
-         
+
          feedback = (value ^ chksum) & 0x80000000 ? 0x04c11db7 : 0;
          chksum <<= 1;
          chksum ^= feedback;
@@ -4997,103 +5368,12 @@ get_file_function_name (int kind)
   return get_file_function_name_long (p);
 }
 \f
-/* Expand (the constant part of) a SET_TYPE CONSTRUCTOR node.
-   The result is placed in BUFFER (which has length BIT_SIZE),
-   with one bit in each char ('\000' or '\001').
-
-   If the constructor is constant, NULL_TREE is returned.
-   Otherwise, a TREE_LIST of the non-constant elements is emitted.  */
-
-tree
-get_set_constructor_bits (tree init, char *buffer, int bit_size)
-{
-  int i;
-  tree vals;
-  HOST_WIDE_INT domain_min
-    = tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (init))), 0);
-  tree non_const_bits = NULL_TREE;
-
-  for (i = 0; i < bit_size; i++)
-    buffer[i] = 0;
-
-  for (vals = TREE_OPERAND (init, 1);
-       vals != NULL_TREE; vals = TREE_CHAIN (vals))
-    {
-      if (!host_integerp (TREE_VALUE (vals), 0)
-         || (TREE_PURPOSE (vals) != NULL_TREE
-             && !host_integerp (TREE_PURPOSE (vals), 0)))
-       non_const_bits
-         = tree_cons (TREE_PURPOSE (vals), TREE_VALUE (vals), non_const_bits);
-      else if (TREE_PURPOSE (vals) != NULL_TREE)
-       {
-         /* Set a range of bits to ones.  */
-         HOST_WIDE_INT lo_index
-           = tree_low_cst (TREE_PURPOSE (vals), 0) - domain_min;
-         HOST_WIDE_INT hi_index
-           = tree_low_cst (TREE_VALUE (vals), 0) - domain_min;
-
-         if (lo_index < 0 || lo_index >= bit_size
-             || hi_index < 0 || hi_index >= bit_size)
-           abort ();
-         for (; lo_index <= hi_index; lo_index++)
-           buffer[lo_index] = 1;
-       }
-      else
-       {
-         /* Set a single bit to one.  */
-         HOST_WIDE_INT index
-           = tree_low_cst (TREE_VALUE (vals), 0) - domain_min;
-         if (index < 0 || index >= bit_size)
-           {
-             error ("invalid initializer for bit string");
-             return NULL_TREE;
-           }
-         buffer[index] = 1;
-       }
-    }
-  return non_const_bits;
-}
-
-/* Expand (the constant part of) a SET_TYPE CONSTRUCTOR node.
-   The result is placed in BUFFER (which is an array of bytes).
-   If the constructor is constant, NULL_TREE is returned.
-   Otherwise, a TREE_LIST of the non-constant elements is emitted.  */
-
-tree
-get_set_constructor_bytes (tree init, unsigned char *buffer, int wd_size)
-{
-  int i;
-  int set_word_size = BITS_PER_UNIT;
-  int bit_size = wd_size * set_word_size;
-  int bit_pos = 0;
-  unsigned char *bytep = buffer;
-  char *bit_buffer = alloca (bit_size);
-  tree non_const_bits = get_set_constructor_bits (init, bit_buffer, bit_size);
-
-  for (i = 0; i < wd_size; i++)
-    buffer[i] = 0;
-
-  for (i = 0; i < bit_size; i++)
-    {
-      if (bit_buffer[i])
-       {
-         if (BYTES_BIG_ENDIAN)
-           *bytep |= (1 << (set_word_size - 1 - bit_pos));
-         else
-           *bytep |= 1 << bit_pos;
-       }
-      bit_pos++;
-      if (bit_pos >= set_word_size)
-       bit_pos = 0, bytep++;
-    }
-  return non_const_bits;
-}
-\f
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 
 /* Complain that the tree code of NODE does not match the expected 0
-   terminated list of trailing codes. FILE, LINE, and FUNCTION are of
-   the caller.  */
+   terminated list of trailing codes. The trailing code list can be
+   empty, for a more vague error message.  FILE, LINE, and FUNCTION
+   are of the caller.  */
 
 void
 tree_check_failed (const tree node, const char *file,
@@ -5108,22 +5388,27 @@ tree_check_failed (const tree node, const char *file,
   while ((code = va_arg (args, int)))
     length += 4 + strlen (tree_code_name[code]);
   va_end (args);
-  va_start (args, function);
-  buffer = alloca (length);
-  length = 0;
-  while ((code = va_arg (args, int)))
+  if (length)
     {
-      if (length)
+      va_start (args, function);
+      length += strlen ("expected ");
+      buffer = alloca (length);
+      length = 0;
+      while ((code = va_arg (args, int)))
        {
-         strcpy (buffer + length, " or ");
-         length += 4;
+         const char *prefix = length ? " or " : "expected ";
+         
+         strcpy (buffer + length, prefix);
+         length += strlen (prefix);
+         strcpy (buffer + length, tree_code_name[code]);
+         length += strlen (tree_code_name[code]);
        }
-      strcpy (buffer + length, tree_code_name[code]);
-      length += strlen (tree_code_name[code]);
+      va_end (args);
     }
-  va_end (args);
-  
-  internal_error ("tree check: expected %s, have %s in %s, at %s:%d",
+  else
+    buffer = (char *)"unexpected node";
+
+  internal_error ("tree check: %s, have %s in %s, at %s:%d",
                  buffer, tree_code_name[TREE_CODE (node)],
                  function, trim_filename (file), line);
 }
@@ -5159,7 +5444,7 @@ tree_not_check_failed (const tree node, const char *file,
       length += strlen (tree_code_name[code]);
     }
   va_end (args);
-  
+
   internal_error ("tree check: expected none of %s, have %s in %s, at %s:%d",
                  buffer, tree_code_name[TREE_CODE (node)],
                  function, trim_filename (file), line);
@@ -5169,12 +5454,13 @@ tree_not_check_failed (const tree node, const char *file,
    code, given in CL.  */
 
 void
-tree_class_check_failed (const tree node, int cl, const char *file,
-                        int line, const char *function)
+tree_class_check_failed (const tree node, const enum tree_code_class cl,
+                        const char *file, int line, const char *function)
 {
   internal_error
-    ("tree check: expected class '%c', have '%c' (%s) in %s, at %s:%d",
-     cl, TREE_CODE_CLASS (TREE_CODE (node)),
+    ("tree check: expected class %qs, have %qs (%s) in %s, at %s:%d",
+     TREE_CODE_CLASS_STRING (cl),
+     TREE_CODE_CLASS_STRING (TREE_CODE_CLASS (TREE_CODE (node))),
      tree_code_name[TREE_CODE (node)], function, trim_filename (file), line);
 }
 
@@ -5216,18 +5502,26 @@ tree_operand_check_failed (int idx, enum tree_code code, const char *file,
 }
 #endif /* ENABLE_TREE_CHECKING */
 \f
-/* For a new vector type node T, build the information necessary for
-   debugging output.  */
+/* Create a new vector type node holding SUBPARTS units of type INNERTYPE,
+   and mapped to the machine mode MODE.  Initialize its fields and build
+   the information necessary for debugging output.  */
 
-static void
-finish_vector_type (tree t)
+static tree
+make_vector_type (tree innertype, int nunits, enum machine_mode mode)
 {
+  tree t = make_node (VECTOR_TYPE);
+
+  TREE_TYPE (t) = TYPE_MAIN_VARIANT (innertype);
+  TYPE_VECTOR_SUBPARTS (t) = nunits;
+  TYPE_MODE (t) = mode;
+  TYPE_READONLY (t) = TYPE_READONLY (innertype);
+  TYPE_VOLATILE (t) = TYPE_VOLATILE (innertype);
+
   layout_type (t);
 
   {
-    tree index = build_int_2 (TYPE_VECTOR_SUBPARTS (t) - 1, 0);
-    tree array = build_array_type (TREE_TYPE (t),
-                                  build_index_type (index));
+    tree index = build_int_cst (NULL_TREE, nunits - 1);
+    tree array = build_array_type (innertype, build_index_type (index));
     tree rt = make_node (RECORD_TYPE);
 
     TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);
@@ -5240,6 +5534,18 @@ finish_vector_type (tree t)
        numbers equal.  */
     TYPE_UID (rt) = TYPE_UID (t);
   }
+
+  /* Build our main variant, based on the main variant of the inner type.  */
+  if (TYPE_MAIN_VARIANT (innertype) != innertype)
+    {
+      tree innertype_main_variant = TYPE_MAIN_VARIANT (innertype);
+      unsigned int hash = TYPE_HASH (innertype_main_variant);
+      TYPE_MAIN_VARIANT (t)
+        = type_hash_canon (hash, make_vector_type (innertype_main_variant,
+                                                  nunits, mode));
+    }
+
+  return t;
 }
 
 static tree
@@ -5268,12 +5574,12 @@ make_or_reuse_type (unsigned size, int unsignedp)
    this function to select one of the types as sizetype.  */
 
 void
-build_common_tree_nodes (int signed_char)
+build_common_tree_nodes (bool signed_char, bool signed_sizetype)
 {
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
 
-  initialize_sizetypes ();
+  initialize_sizetypes (signed_sizetype);
 
   /* Define both `signed char' and `unsigned char'.  */
   signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
@@ -5301,8 +5607,7 @@ build_common_tree_nodes (int signed_char)
      boolean_type_node before calling build_common_tree_nodes_2.  */
   boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
   TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
-  TYPE_MAX_VALUE (boolean_type_node) = build_int_2 (1, 0);
-  TREE_TYPE (TYPE_MAX_VALUE (boolean_type_node)) = boolean_type_node;
+  TYPE_MAX_VALUE (boolean_type_node) = build_int_cst (boolean_type_node, 1);
   TYPE_PRECISION (boolean_type_node) = 1;
 
   /* Fill in the rest of the sized types.  Reuse existing type nodes
@@ -5318,7 +5623,7 @@ build_common_tree_nodes (int signed_char)
   unsigned_intSI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (SImode), 1);
   unsigned_intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 1);
   unsigned_intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 1);
-  
+
   access_public_node = get_identifier ("public");
   access_protected_node = get_identifier ("protected");
   access_private_node = get_identifier ("private");
@@ -5331,9 +5636,9 @@ void
 build_common_tree_nodes_2 (int short_double)
 {
   /* Define these next since types below may used them.  */
-  integer_zero_node = build_int_2 (0, 0);
-  integer_one_node = build_int_2 (1, 0);
-  integer_minus_one_node = build_int_2 (-1, -1);
+  integer_zero_node = build_int_cst (NULL_TREE, 0);
+  integer_one_node = build_int_cst (NULL_TREE, 1);
+  integer_minus_one_node = build_int_cst (NULL_TREE, -1);
 
   size_zero_node = size_int (0);
   size_one_node = size_int (1);
@@ -5352,8 +5657,7 @@ build_common_tree_nodes_2 (int short_double)
   TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
   TYPE_USER_ALIGN (void_type_node) = 0;
 
-  null_pointer_node = build_int_2 (0, 0);
-  TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
+  null_pointer_node = build_int_cst (build_pointer_type (void_type_node), 0);
   layout_type (TREE_TYPE (null_pointer_node));
 
   ptr_type_node = build_pointer_type (void_type_node);
@@ -5406,12 +5710,172 @@ build_common_tree_nodes_2 (int short_double)
        don't copy record types and let c_common_nodes_and_builtins()
        declare the type to be __builtin_va_list.  */
     if (TREE_CODE (t) != RECORD_TYPE)
-      t = build_type_copy (t);
+      t = build_variant_type_copy (t);
 
     va_list_type_node = t;
   }
 }
 
+/* A subroutine of build_common_builtin_nodes.  Define a builtin function.  */
+
+static void
+local_define_builtin (const char *name, tree type, enum built_in_function code,
+                      const char *library_name, int ecf_flags)
+{
+  tree decl;
+
+  decl = lang_hooks.builtin_function (name, type, code, BUILT_IN_NORMAL,
+                                     library_name, NULL_TREE);
+  if (ecf_flags & ECF_CONST)
+    TREE_READONLY (decl) = 1;
+  if (ecf_flags & ECF_PURE)
+    DECL_IS_PURE (decl) = 1;
+  if (ecf_flags & ECF_NORETURN)
+    TREE_THIS_VOLATILE (decl) = 1;
+  if (ecf_flags & ECF_NOTHROW)
+    TREE_NOTHROW (decl) = 1;
+  if (ecf_flags & ECF_MALLOC)
+    DECL_IS_MALLOC (decl) = 1;
+
+  built_in_decls[code] = decl;
+  implicit_built_in_decls[code] = decl;
+}
+
+/* Call this function after instantiating all builtins that the language
+   front end cares about.  This will build the rest of the builtins that
+   are relied upon by the tree optimizers and the middle-end.  */
+
+void
+build_common_builtin_nodes (void)
+{
+  tree tmp, ftype;
+
+  if (built_in_decls[BUILT_IN_MEMCPY] == NULL
+      || built_in_decls[BUILT_IN_MEMMOVE] == NULL)
+    {
+      tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
+      tmp = tree_cons (NULL_TREE, const_ptr_type_node, tmp);
+      tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
+      ftype = build_function_type (ptr_type_node, tmp);
+
+      if (built_in_decls[BUILT_IN_MEMCPY] == NULL)
+       local_define_builtin ("__builtin_memcpy", ftype, BUILT_IN_MEMCPY,
+                             "memcpy", ECF_NOTHROW);
+      if (built_in_decls[BUILT_IN_MEMMOVE] == NULL)
+       local_define_builtin ("__builtin_memmove", ftype, BUILT_IN_MEMMOVE,
+                             "memmove", ECF_NOTHROW);
+    }
+
+  if (built_in_decls[BUILT_IN_MEMCMP] == NULL)
+    {
+      tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
+      tmp = tree_cons (NULL_TREE, const_ptr_type_node, tmp);
+      tmp = tree_cons (NULL_TREE, const_ptr_type_node, tmp);
+      ftype = build_function_type (ptr_type_node, tmp);
+      local_define_builtin ("__builtin_memcmp", ftype, BUILT_IN_MEMCMP,
+                           "memcmp", ECF_PURE | ECF_NOTHROW);
+    }
+
+  if (built_in_decls[BUILT_IN_MEMSET] == NULL)
+    {
+      tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
+      tmp = tree_cons (NULL_TREE, integer_type_node, tmp);
+      tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
+      ftype = build_function_type (ptr_type_node, tmp);
+      local_define_builtin ("__builtin_memset", ftype, BUILT_IN_MEMSET,
+                           "memset", ECF_NOTHROW);
+    }
+
+  if (built_in_decls[BUILT_IN_ALLOCA] == NULL)
+    {
+      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);
+    }
+
+  tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+  tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
+  tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
+  ftype = build_function_type (void_type_node, tmp);
+  local_define_builtin ("__builtin_init_trampoline", ftype,
+                       BUILT_IN_INIT_TRAMPOLINE,
+                       "__builtin_init_trampoline", ECF_NOTHROW);
+
+  tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+  ftype = build_function_type (ptr_type_node, tmp);
+  local_define_builtin ("__builtin_adjust_trampoline", ftype,
+                       BUILT_IN_ADJUST_TRAMPOLINE,
+                       "__builtin_adjust_trampoline",
+                       ECF_CONST | ECF_NOTHROW);
+
+  tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+  tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
+  ftype = build_function_type (void_type_node, tmp);
+  local_define_builtin ("__builtin_nonlocal_goto", ftype,
+                       BUILT_IN_NONLOCAL_GOTO,
+                       "__builtin_nonlocal_goto",
+                       ECF_NORETURN | ECF_NOTHROW);
+
+  ftype = build_function_type (ptr_type_node, void_list_node);
+  local_define_builtin ("__builtin_stack_save", ftype, BUILT_IN_STACK_SAVE,
+                       "__builtin_stack_save", ECF_NOTHROW);
+
+  tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+  ftype = build_function_type (void_type_node, tmp);
+  local_define_builtin ("__builtin_stack_restore", ftype,
+                       BUILT_IN_STACK_RESTORE,
+                       "__builtin_stack_restore", ECF_NOTHROW);
+
+  ftype = build_function_type (void_type_node, void_list_node);
+  local_define_builtin ("__builtin_profile_func_enter", ftype,
+                       BUILT_IN_PROFILE_FUNC_ENTER, "profile_func_enter", 0);
+  local_define_builtin ("__builtin_profile_func_exit", ftype,
+                       BUILT_IN_PROFILE_FUNC_EXIT, "profile_func_exit", 0);
+
+  /* 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 
+     beasties if the real and complex parts of the arguments are separate.  */
+  {
+    enum machine_mode mode;
+
+    for (mode = MIN_MODE_COMPLEX_FLOAT; mode <= MAX_MODE_COMPLEX_FLOAT; ++mode)
+      {
+       char mode_name_buf[4], *q;
+       const char *p;
+       enum built_in_function mcode, dcode;
+       tree type, inner_type;
+
+       type = lang_hooks.types.type_for_mode (mode, 0);
+       if (type == NULL)
+         continue;
+       inner_type = TREE_TYPE (type);
+
+       tmp = tree_cons (NULL_TREE, inner_type, void_list_node);
+       tmp = tree_cons (NULL_TREE, inner_type, tmp);
+       tmp = tree_cons (NULL_TREE, inner_type, tmp);
+       tmp = tree_cons (NULL_TREE, inner_type, tmp);
+       ftype = build_function_type (type, tmp);
+
+        mcode = BUILT_IN_COMPLEX_MUL_MIN + mode - MIN_MODE_COMPLEX_FLOAT;
+        dcode = BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT;
+
+        for (p = GET_MODE_NAME (mode), q = mode_name_buf; *p; p++, q++)
+         *q = TOLOWER (*p);
+       *q = '\0';
+
+       built_in_names[mcode] = concat ("__mul", mode_name_buf, "3", NULL);
+        local_define_builtin (built_in_names[mcode], ftype, mcode,
+                             built_in_names[mcode], ECF_CONST | ECF_NOTHROW);
+
+       built_in_names[dcode] = concat ("__div", mode_name_buf, "3", NULL);
+        local_define_builtin (built_in_names[dcode], ftype, dcode,
+                             built_in_names[dcode], ECF_CONST | ECF_NOTHROW);
+      }
+  }
+}
+
 /* HACK.  GROSS.  This is absolutely disgusting.  I wish there was a
    better way.
 
@@ -5444,10 +5908,15 @@ reconstruct_complex_type (tree type, tree bottom)
     }
   else if (TREE_CODE (type) == METHOD_TYPE)
     {
+      tree argtypes;
       inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
+      /* The build_method_type_directly() routine prepends 'this' to argument list,
+         so we must compensate by getting rid of it.  */
+      argtypes = TYPE_ARG_TYPES (type);
       outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type),
-                                         inner, 
+                                         inner,
                                          TYPE_ARG_TYPES (type));
+      TYPE_ARG_TYPES (outer) = argtypes;
     }
   else
     return bottom;
@@ -5458,36 +5927,53 @@ reconstruct_complex_type (tree type, tree bottom)
   return outer;
 }
 
-/* Returns a vector tree node given a vector mode and inner type.  */
+/* Returns a vector tree node given a mode (integer, vector, or BLKmode) and
+   the inner type.  */
 tree
 build_vector_type_for_mode (tree innertype, enum machine_mode mode)
 {
-  tree t;
-  t = make_node (VECTOR_TYPE);
-  TREE_TYPE (t) = innertype;
-  TYPE_MODE (t) = mode;
-  finish_vector_type (t);
-  return t;
+  int nunits;
+
+  switch (GET_MODE_CLASS (mode))
+    {
+    case MODE_VECTOR_INT:
+    case MODE_VECTOR_FLOAT:
+      nunits = GET_MODE_NUNITS (mode);
+      break;
+
+    case MODE_INT:
+      /* Check that there are no leftover bits.  */
+      gcc_assert (GET_MODE_BITSIZE (mode)
+                 % TREE_INT_CST_LOW (TYPE_SIZE (innertype)) == 0);
+
+      nunits = GET_MODE_BITSIZE (mode)
+              / TREE_INT_CST_LOW (TYPE_SIZE (innertype));
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  return make_vector_type (innertype, nunits, mode);
 }
 
-/* Similarly, but takes inner type and units.  */
+/* Similarly, but takes the inner type and number of units, which must be
+   a power of two.  */
 
 tree
 build_vector_type (tree innertype, int nunits)
 {
-  enum machine_mode innermode = TYPE_MODE (innertype);
-  enum machine_mode mode;
-
-  if (GET_MODE_CLASS (innermode) == MODE_FLOAT)
-    mode = MIN_MODE_VECTOR_FLOAT;
-  else
-    mode = MIN_MODE_VECTOR_INT;
-
-  for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
-    if (GET_MODE_NUNITS (mode) == nunits && GET_MODE_INNER (mode) == innermode)
-      return build_vector_type_for_mode (innertype, mode);
+  return make_vector_type (innertype, nunits, VOIDmode);
+}
 
-  return NULL_TREE;
+/* 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
@@ -5528,10 +6014,6 @@ initializer_zerop (tree init)
       if (elt == NULL_TREE)
        return true;
 
-      /* A set is empty only if it has no elements.  */
-      if (TREE_CODE (TREE_TYPE (init)) == SET_TYPE)
-       return false;
-
       for (; elt ; elt = TREE_CHAIN (elt))
        if (! initializer_zerop (TREE_VALUE (elt)))
          return false;
@@ -5561,19 +6043,647 @@ build_empty_stmt (void)
 }
 
 
+/* Returns true if it is possible to prove that the index of
+   an array access REF (an ARRAY_REF expression) falls into the
+   array bounds.  */
+
+bool
+in_array_bounds_p (tree ref)
+{
+  tree idx = TREE_OPERAND (ref, 1);
+  tree min, max;
+
+  if (TREE_CODE (idx) != INTEGER_CST)
+    return false;
+
+  min = array_ref_low_bound (ref);
+  max = array_ref_up_bound (ref);
+  if (!min
+      || !max
+      || TREE_CODE (min) != INTEGER_CST
+      || TREE_CODE (max) != INTEGER_CST)
+    return false;
+
+  if (tree_int_cst_lt (idx, min)
+      || tree_int_cst_lt (max, idx))
+    return false;
+
+  return true;
+}
+
+/* Return true if T (assumed to be a DECL) is a global variable.  */
+
+bool
+is_global_var (tree t)
+{
+  return (TREE_STATIC (t) || DECL_EXTERNAL (t));
+}
+
 /* Return true if T (assumed to be a DECL) must be assigned a memory
    location.  */
 
 bool
 needs_to_live_in_memory (tree t)
 {
-  return (DECL_NEEDS_TO_LIVE_IN_MEMORY_INTERNAL (t)
-         || TREE_STATIC (t)
-          || DECL_EXTERNAL (t)
-         || DECL_NONLOCAL (t)
+  return (TREE_ADDRESSABLE (t)
+         || is_global_var (t)
          || (TREE_CODE (t) == RESULT_DECL
-             && aggregate_value_p (t, current_function_decl))
-         || decl_function_context (t) != current_function_decl);
+             && aggregate_value_p (t, current_function_decl)));
+}
+
+/* There are situations in which a language considers record types
+   compatible which have different field lists.  Decide if two fields
+   are compatible.  It is assumed that the parent records are compatible.  */
+
+bool
+fields_compatible_p (tree f1, tree f2)
+{
+  if (!operand_equal_p (DECL_FIELD_BIT_OFFSET (f1),
+                       DECL_FIELD_BIT_OFFSET (f2), OEP_ONLY_CONST))
+    return false;
+
+  if (!operand_equal_p (DECL_FIELD_OFFSET (f1),
+                        DECL_FIELD_OFFSET (f2), OEP_ONLY_CONST))
+    return false;
+
+  if (!lang_hooks.types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2)))
+    return false;
+
+  return true;
+}
+
+/* Locate within RECORD a field that is compatible with ORIG_FIELD.  */
+
+tree
+find_compatible_field (tree record, tree orig_field)
+{
+  tree f;
+
+  for (f = TYPE_FIELDS (record); f ; f = TREE_CHAIN (f))
+    if (TREE_CODE (f) == FIELD_DECL
+       && fields_compatible_p (f, orig_field))
+      return f;
+
+  /* ??? Why isn't this on the main fields list?  */
+  f = TYPE_VFIELD (record);
+  if (f && TREE_CODE (f) == FIELD_DECL
+      && fields_compatible_p (f, orig_field))
+    return f;
+
+  /* ??? We should abort here, but Java appears to do Bad Things
+     with inherited fields.  */
+  return orig_field;
+}
+
+/* Return value of a constant X.  */
+
+HOST_WIDE_INT
+int_cst_value (tree x)
+{
+  unsigned bits = TYPE_PRECISION (TREE_TYPE (x));
+  unsigned HOST_WIDE_INT val = TREE_INT_CST_LOW (x);
+  bool negative = ((val >> (bits - 1)) & 1) != 0;
+
+  gcc_assert (bits <= HOST_BITS_PER_WIDE_INT);
+
+  if (negative)
+    val |= (~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1;
+  else
+    val &= ~((~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1);
+
+  return val;
+}
+
+/* Returns the greatest common divisor of A and B, which must be
+   INTEGER_CSTs.  */
+
+tree
+tree_fold_gcd (tree a, tree b)
+{
+  tree a_mod_b;
+  tree type = TREE_TYPE (a);
+
+  gcc_assert (TREE_CODE (a) == INTEGER_CST);
+  gcc_assert (TREE_CODE (b) == INTEGER_CST);
+
+  if (integer_zerop (a))
+    return b;
+
+  if (integer_zerop (b))
+    return a;
+
+  if (tree_int_cst_sgn (a) == -1)
+    a = fold (build2 (MULT_EXPR, type, a,
+                     convert (type, integer_minus_one_node)));
+
+  if (tree_int_cst_sgn (b) == -1)
+    b = fold (build2 (MULT_EXPR, type, b,
+                     convert (type, integer_minus_one_node)));
+
+  while (1)
+    {
+      a_mod_b = fold (build2 (FLOOR_MOD_EXPR, type, a, b));
+
+      if (!TREE_INT_CST_LOW (a_mod_b)
+         && !TREE_INT_CST_HIGH (a_mod_b))
+       return b;
+
+      a = b;
+      b = a_mod_b;
+    }
+}
+
+/* Returns unsigned variant of TYPE.  */
+
+tree
+unsigned_type_for (tree type)
+{
+  return lang_hooks.types.unsigned_type (type);
+}
+
+/* Returns signed variant of TYPE.  */
+
+tree
+signed_type_for (tree type)
+{
+  return lang_hooks.types.signed_type (type);
+}
+
+/* Returns the largest value obtainable by casting something in INNER type to
+   OUTER type.  */
+
+tree
+upper_bound_in_type (tree outer, tree inner)
+{
+  unsigned HOST_WIDE_INT lo, hi;
+  unsigned bits = TYPE_PRECISION (inner);
+
+  if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner))
+    {
+      /* Zero extending in these cases.  */
+      if (bits <= HOST_BITS_PER_WIDE_INT)
+       {
+         hi = 0;
+         lo = (~(unsigned HOST_WIDE_INT) 0)
+                 >> (HOST_BITS_PER_WIDE_INT - bits);
+       }
+      else
+       {
+         hi = (~(unsigned HOST_WIDE_INT) 0)
+                 >> (2 * HOST_BITS_PER_WIDE_INT - bits);
+         lo = ~(unsigned HOST_WIDE_INT) 0;
+       }
+    }
+  else
+    {
+      /* Sign extending in these cases.  */
+      if (bits <= HOST_BITS_PER_WIDE_INT)
+       {
+         hi = 0;
+         lo = (~(unsigned HOST_WIDE_INT) 0)
+                 >> (HOST_BITS_PER_WIDE_INT - bits) >> 1;
+       }
+      else
+       {
+         hi = (~(unsigned HOST_WIDE_INT) 0)
+                 >> (2 * HOST_BITS_PER_WIDE_INT - bits) >> 1;
+         lo = ~(unsigned HOST_WIDE_INT) 0;
+       }
+    }
+
+  return fold_convert (outer,
+                      build_int_cst_wide (inner, lo, hi));
+}
+
+/* Returns the smallest value obtainable by casting something in INNER type to
+   OUTER type.  */
+
+tree
+lower_bound_in_type (tree outer, tree inner)
+{
+  unsigned HOST_WIDE_INT lo, hi;
+  unsigned bits = TYPE_PRECISION (inner);
+
+  if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner))
+    lo = hi = 0;
+  else if (bits <= HOST_BITS_PER_WIDE_INT)
+    {
+      hi = ~(unsigned HOST_WIDE_INT) 0;
+      lo = (~(unsigned HOST_WIDE_INT) 0) << (bits - 1);
+    }
+  else
+    {
+      hi = (~(unsigned HOST_WIDE_INT) 0) << (bits - HOST_BITS_PER_WIDE_INT - 1);
+      lo = 0;
+    }
+
+  return fold_convert (outer,
+                      build_int_cst_wide (inner, lo, hi));
+}
+
+/* Return nonzero if two operands that are suitable for PHI nodes are
+   necessarily equal.  Specifically, both ARG0 and ARG1 must be either
+   SSA_NAME or invariant.  Note that this is strictly an optimization.
+   That is, callers of this function can directly call operand_equal_p
+   and get the same result, only slower.  */
+
+int
+operand_equal_for_phi_arg_p (tree arg0, tree arg1)
+{
+  if (arg0 == arg1)
+    return 1;
+  if (TREE_CODE (arg0) == SSA_NAME || TREE_CODE (arg1) == SSA_NAME)
+    return 0;
+  return operand_equal_p (arg0, arg1, 0);
+}
+
+/* Returns number of zeros at the end of binary representation of X.
+   
+   ??? Use ffs if available?  */
+
+tree
+num_ending_zeros (tree x)
+{
+  unsigned HOST_WIDE_INT fr, nfr;
+  unsigned num, abits;
+  tree type = TREE_TYPE (x);
+
+  if (TREE_INT_CST_LOW (x) == 0)
+    {
+      num = HOST_BITS_PER_WIDE_INT;
+      fr = TREE_INT_CST_HIGH (x);
+    }
+  else
+    {
+      num = 0;
+      fr = TREE_INT_CST_LOW (x);
+    }
+
+  for (abits = HOST_BITS_PER_WIDE_INT / 2; abits; abits /= 2)
+    {
+      nfr = fr >> abits;
+      if (nfr << abits == fr)
+       {
+         num += abits;
+         fr = nfr;
+       }
+    }
+
+  if (num > TYPE_PRECISION (type))
+    num = TYPE_PRECISION (type);
+
+  return build_int_cst_type (type, num);
+}
+
+
+#define WALK_SUBTREE(NODE)                             \
+  do                                                   \
+    {                                                  \
+      result = walk_tree (&(NODE), func, data, pset);  \
+      if (result)                                      \
+       return result;                                  \
+    }                                                  \
+  while (0)
+
+/* This is a subroutine of walk_tree that walks field of TYPE that are to
+   be walked whenever a type is seen in the tree.  Rest of operands and return
+   value are as for walk_tree.  */
+
+static tree
+walk_type_fields (tree type, walk_tree_fn func, void *data,
+                 struct pointer_set_t *pset)
+{
+  tree result = NULL_TREE;
+
+  switch (TREE_CODE (type))
+    {
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      /* We have to worry about mutually recursive pointers.  These can't
+        be written in C.  They can in Ada.  It's pathological, but
+        there's an ACATS test (c38102a) that checks it.  Deal with this
+        by checking if we're pointing to another pointer, that one
+        points to another pointer, that one does too, and we have no htab.
+        If so, get a hash table.  We check three levels deep to avoid
+        the cost of the hash table if we don't need one.  */
+      if (POINTER_TYPE_P (TREE_TYPE (type))
+         && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (type)))
+         && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (TREE_TYPE (type))))
+         && !pset)
+       {
+         result = walk_tree_without_duplicates (&TREE_TYPE (type),
+                                                func, data);
+         if (result)
+           return result;
+
+         break;
+       }
+
+      /* ... fall through ... */
+
+    case COMPLEX_TYPE:
+      WALK_SUBTREE (TREE_TYPE (type));
+      break;
+
+    case METHOD_TYPE:
+      WALK_SUBTREE (TYPE_METHOD_BASETYPE (type));
+
+      /* Fall through.  */
+
+    case FUNCTION_TYPE:
+      WALK_SUBTREE (TREE_TYPE (type));
+      {
+       tree arg;
+
+       /* We never want to walk into default arguments.  */
+       for (arg = TYPE_ARG_TYPES (type); arg; arg = TREE_CHAIN (arg))
+         WALK_SUBTREE (TREE_VALUE (arg));
+      }
+      break;
+
+    case ARRAY_TYPE:
+      /* Don't follow this nodes's type if a pointer for fear that we'll
+        have infinite recursion.  Those types are uninteresting anyway.  */
+      if (!POINTER_TYPE_P (TREE_TYPE (type))
+         && TREE_CODE (TREE_TYPE (type)) != OFFSET_TYPE)
+       WALK_SUBTREE (TREE_TYPE (type));
+      WALK_SUBTREE (TYPE_DOMAIN (type));
+      break;
+
+    case BOOLEAN_TYPE:
+    case ENUMERAL_TYPE:
+    case INTEGER_TYPE:
+    case CHAR_TYPE:
+    case REAL_TYPE:
+      WALK_SUBTREE (TYPE_MIN_VALUE (type));
+      WALK_SUBTREE (TYPE_MAX_VALUE (type));
+      break;
+
+    case OFFSET_TYPE:
+      WALK_SUBTREE (TREE_TYPE (type));
+      WALK_SUBTREE (TYPE_OFFSET_BASETYPE (type));
+      break;
+
+    default:
+      break;
+    }
+
+  return NULL_TREE;
+}
+
+/* Apply FUNC to all the sub-trees of TP in a pre-order traversal.  FUNC is
+   called with the DATA and the address of each sub-tree.  If FUNC returns a
+   non-NULL value, the traversal is stopped, and the value returned by FUNC
+   is returned.  If PSET is non-NULL it is used to record the nodes visited,
+   and to avoid visiting a node more than once.  */
+
+tree
+walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
+{
+  enum tree_code code;
+  int walk_subtrees;
+  tree result;
+
+#define WALK_SUBTREE_TAIL(NODE)                                \
+  do                                                   \
+    {                                                  \
+       tp = & (NODE);                                  \
+       goto tail_recurse;                              \
+    }                                                  \
+  while (0)
+
+ tail_recurse:
+  /* Skip empty subtrees.  */
+  if (!*tp)
+    return NULL_TREE;
+
+  /* Don't walk the same tree twice, if the user has requested
+     that we avoid doing so.  */
+  if (pset && pointer_set_insert (pset, *tp))
+    return NULL_TREE;
+
+  /* Call the function.  */
+  walk_subtrees = 1;
+  result = (*func) (tp, &walk_subtrees, data);
+
+  /* If we found something, return it.  */
+  if (result)
+    return result;
+
+  code = TREE_CODE (*tp);
+
+  /* Even if we didn't, FUNC may have decided that there was nothing
+     interesting below this point in the tree.  */
+  if (!walk_subtrees)
+    {
+      if (code == TREE_LIST)
+       /* But we still need to check our siblings.  */
+       WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
+      else
+       return NULL_TREE;
+    }
+
+  result = lang_hooks.tree_inlining.walk_subtrees (tp, &walk_subtrees, func,
+                                                  data, pset);
+  if (result || ! walk_subtrees)
+    return result;
+
+  /* If this is a DECL_EXPR, walk into various fields of the type that it's
+     defining.  We only want to walk into these fields of a type in this
+     case.  Note that decls get walked as part of the processing of a
+     BIND_EXPR.
+
+     ??? Precisely which fields of types that we are supposed to walk in
+     this case vs. the normal case aren't well defined.  */
+  if (code == DECL_EXPR
+      && TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL
+      && TREE_CODE (TREE_TYPE (DECL_EXPR_DECL (*tp))) != ERROR_MARK)
+    {
+      tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp));
+
+      /* Call the function for the type.  See if it returns anything or
+        doesn't want us to continue.  If we are to continue, walk both
+        the normal fields and those for the declaration case.  */
+      result = (*func) (type_p, &walk_subtrees, data);
+      if (result || !walk_subtrees)
+       return NULL_TREE;
+
+      result = walk_type_fields (*type_p, func, data, pset);
+      if (result)
+       return result;
+
+      WALK_SUBTREE (TYPE_SIZE (*type_p));
+      WALK_SUBTREE (TYPE_SIZE_UNIT (*type_p));
+
+      /* 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)
+       {
+         tree field;
+
+         for (field = TYPE_FIELDS (*type_p); field;
+              field = TREE_CHAIN (field))
+           {
+             /* We'd like to look at the type of the field, but we can easily
+                get infinite recursion.  So assume it's pointed to elsewhere
+                in the tree.  Also, ignore things that aren't fields.  */
+             if (TREE_CODE (field) != FIELD_DECL)
+               continue;
+
+             WALK_SUBTREE (DECL_FIELD_OFFSET (field));
+             WALK_SUBTREE (DECL_SIZE (field));
+             WALK_SUBTREE (DECL_SIZE_UNIT (field));
+             if (TREE_CODE (*type_p) == QUAL_UNION_TYPE)
+               WALK_SUBTREE (DECL_QUALIFIER (field));
+           }
+       }
+    }
+
+  else if (code != SAVE_EXPR
+          && code != BIND_EXPR
+          && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
+    {
+      int i, len;
+
+      /* Walk over all the sub-trees of this operand.  */
+      len = TREE_CODE_LENGTH (code);
+      /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same.
+        But, we only want to walk once.  */
+      if (code == TARGET_EXPR
+         && TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1))
+       --len;
+
+      /* Go through the subtrees.  We need to do this in forward order so
+         that the scope of a FOR_EXPR is handled properly.  */
+#ifdef DEBUG_WALK_TREE
+      for (i = 0; i < len; ++i)
+       WALK_SUBTREE (TREE_OPERAND (*tp, i));
+#else
+      for (i = 0; i < len - 1; ++i)
+       WALK_SUBTREE (TREE_OPERAND (*tp, i));
+
+      if (len)
+       {
+         /* The common case is that we may tail recurse here.  */
+         if (code != BIND_EXPR
+             && !TREE_CHAIN (*tp))
+           WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1));
+         else
+           WALK_SUBTREE (TREE_OPERAND (*tp, len - 1));
+       }
+#endif
+    }
+
+  /* If this is a type, walk the needed fields in the type.  */
+  else if (TYPE_P (*tp))
+    {
+      result = walk_type_fields (*tp, func, data, pset);
+      if (result)
+       return result;
+    }
+  else
+    {
+      /* Not one of the easy cases.  We must explicitly go through the
+        children.  */
+      switch (code)
+       {
+       case ERROR_MARK:
+       case IDENTIFIER_NODE:
+       case INTEGER_CST:
+       case REAL_CST:
+       case VECTOR_CST:
+       case STRING_CST:
+       case BLOCK:
+       case PLACEHOLDER_EXPR:
+       case SSA_NAME:
+       case FIELD_DECL:
+       case RESULT_DECL:
+         /* None of thse have subtrees other than those already walked
+            above.  */
+         break;
+
+       case TREE_LIST:
+         WALK_SUBTREE (TREE_VALUE (*tp));
+         WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
+         break;
+
+       case TREE_VEC:
+         {
+           int len = TREE_VEC_LENGTH (*tp);
+
+           if (len == 0)
+             break;
+
+           /* Walk all elements but the first.  */
+           while (--len)
+             WALK_SUBTREE (TREE_VEC_ELT (*tp, len));
+
+           /* Now walk the first one as a tail call.  */
+           WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0));
+         }
+
+       case COMPLEX_CST:
+         WALK_SUBTREE (TREE_REALPART (*tp));
+         WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp));
+
+       case CONSTRUCTOR:
+         WALK_SUBTREE_TAIL (CONSTRUCTOR_ELTS (*tp));
+
+       case SAVE_EXPR:
+         WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));
+
+       case BIND_EXPR:
+         {
+           tree decl;
+           for (decl = BIND_EXPR_VARS (*tp); decl; decl = TREE_CHAIN (decl))
+             {
+               /* Walk the DECL_INITIAL and DECL_SIZE.  We don't want to walk
+                  into declarations that are just mentioned, rather than
+                  declared; they don't really belong to this part of the tree.
+                  And, we can see cycles: the initializer for a declaration
+                  can refer to the declaration itself.  */
+               WALK_SUBTREE (DECL_INITIAL (decl));
+               WALK_SUBTREE (DECL_SIZE (decl));
+               WALK_SUBTREE (DECL_SIZE_UNIT (decl));
+             }
+           WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp));
+         }
+
+       case STATEMENT_LIST:
+         {
+           tree_stmt_iterator i;
+           for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i))
+             WALK_SUBTREE (*tsi_stmt_ptr (i));
+         }
+         break;
+
+       default:
+         /* ??? This could be a language-defined node.  We really should make
+            a hook for it, but right now just ignore it.  */
+         break;
+       }
+    }
+
+  /* We didn't find what we were looking for.  */
+  return NULL_TREE;
+
+#undef WALK_SUBTREE_TAIL
+}
+#undef WALK_SUBTREE
+
+/* Like walk_tree, but does not walk duplicate nodes more than once.  */
+
+tree
+walk_tree_without_duplicates (tree *tp, walk_tree_fn func, void *data)
+{
+  tree result;
+  struct pointer_set_t *pset;
+
+  pset = pointer_set_create ();
+  result = walk_tree (tp, func, data, pset);
+  pointer_set_destroy (pset);
+  return result;
 }
 
 #include "gt-tree.h"