OSDN Git Service

* tree.c (type_contains_placeholder_1): Always return false
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index 009888a..572b880 100644 (file)
@@ -48,7 +48,24 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree-iterator.h"
 #include "basic-block.h"
 #include "tree-flow.h"
-#include "opts.h"
+#include "params.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);
@@ -95,9 +112,6 @@ struct type_hash GTY(())
   tree type;
 };
 
-/* Additional language-dependent binfo slots.  */
-unsigned binfo_lang_slots;
-
 /* Initial size of the hash table (rounded to next prime).  */
 #define TYPE_HASH_INITIAL_SIZE 1000
 
@@ -111,11 +125,18 @@ unsigned binfo_lang_slots;
 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);
@@ -131,6 +152,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
@@ -145,57 +169,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);
 
@@ -208,13 +227,38 @@ 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_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.  */
 
@@ -222,70 +266,75 @@ 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 == TREE_BINFO)
-       kind = binfo_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]++;
@@ -300,26 +349,23 @@ 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;
       DECL_IN_SYSTEM_HEADER (t) = in_system_header;
       DECL_SOURCE_LOCATION (t) = input_location;
-      if (code == TRANSLATION_UNIT_DECL)
-       DECL_UID (t) = cur_in_fname;
-      else
-       DECL_UID (t) = next_decl_uid++;
+      DECL_UID (t) = next_decl_uid++;
 
       /* We have not yet computed the alias set for this declaration.  */
       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;
@@ -333,12 +379,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:
@@ -357,6 +403,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
          break;
        }
       break;
+
+    default:
+      /* Other classes need no special treatment.  */
+      break;
     }
 
   return t;
@@ -372,10 +422,7 @@ 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);
@@ -386,9 +433,9 @@ copy_node_stat (tree node MEM_STAT_DECL)
   TREE_VISITED (t) = 0;
   t->common.ann = 0;
 
-  if (TREE_CODE_CLASS (code) == 'd' && code != TRANSLATION_UNIT_DECL)
+  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
@@ -398,6 +445,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;
@@ -427,23 +481,246 @@ 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 zero or sign extended depending
+   on the type.  */
+
+tree
+build_int_cst_type (tree type, HOST_WIDE_INT low)
+{
+  unsigned HOST_WIDE_INT val = (unsigned HOST_WIDE_INT) low;
+  unsigned bits;
+  bool signed_p;
+  bool negative;
+  tree ret;
+
+  if (!type)
+    type = integer_type_node;
+
+  bits = TYPE_PRECISION (type);
+  signed_p = !TYPE_UNSIGNED (type);
+  negative = ((val >> (bits - 1)) & 1) != 0;
+
+  if (signed_p && negative)
+    {
+      if (bits < HOST_BITS_PER_WIDE_INT)
+       val = val | ((~(unsigned HOST_WIDE_INT) 0) << bits);
+      ret = build_int_cst_wide (type, val, ~(unsigned HOST_WIDE_INT) 0);
+    }
+  else
+    {
+      if (bits < HOST_BITS_PER_WIDE_INT)
+       val = val & ~((~(unsigned HOST_WIDE_INT) 0) << bits);
+      ret = build_int_cst_wide (type, val, 0);
+    }
+
+  return ret;
+}
 
-   This function should be used via the `build_int_2' macro.  */
+/* 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));
+}
+
+/* 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.  */
 
@@ -556,10 +833,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;
 }
@@ -586,21 +876,12 @@ build_complex (tree type, tree real, tree imag)
 /* Build a BINFO with LEN language slots.  */
 
 tree
-make_tree_binfo_stat (unsigned lang_slots MEM_STAT_DECL)
+make_tree_binfo_stat (unsigned base_binfos MEM_STAT_DECL)
 {
   tree t;
-  static unsigned length;
-  
-  if (!length)
-    {
-      length = (offsetof (struct tree_binfo, lang_slots)
-               + (sizeof (((struct tree_binfo *)0)->lang_slots[0])
-                  * lang_slots));
-      binfo_lang_slots = lang_slots;
-    }
-  else if (binfo_lang_slots != lang_slots)
-    abort ();
-  
+  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;
@@ -608,10 +889,12 @@ make_tree_binfo_stat (unsigned lang_slots MEM_STAT_DECL)
 
   t = ggc_alloc_zone_stat (length, tree_zone PASS_MEM_STAT);
 
-  memset (t, 0, length);
+  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;
 }
 
@@ -708,10 +991,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;
@@ -967,21 +1249,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
@@ -1016,8 +1283,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++;
     }
@@ -1062,8 +1328,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
 
@@ -1161,7 +1426,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;
 }
@@ -1248,7 +1513,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));
 
@@ -1298,34 +1563,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);
@@ -1333,20 +1604,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:
@@ -1354,14 +1622,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
@@ -1424,7 +1692,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;
 }
@@ -1449,9 +1716,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);
@@ -1467,37 +1734,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)
-    {
-    default:
-      return TREE_CODE_LENGTH (code);
-    }
-}
-
 /* Return which tree structure is used by T.  */
 
 enum tree_node_structure_enum
@@ -1507,22 +1743,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;
@@ -1536,132 +1779,7 @@ tree_node_structure (tree t)
     case VALUE_HANDLE:         return TS_VALUE_HANDLE;
 
     default:
-      abort ();
-    }
-}
-
-/* Perform any modifications to EXPR required when it is unsaved.  Does
-   not recurse into EXPR's subtrees.  */
-
-void
-unsave_expr_1 (tree expr)
-{
-  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.
-
-   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.
-
-   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;
+      gcc_unreachable ();
     }
 }
 \f
@@ -1682,22 +1800,23 @@ contains_placeholder_p (tree exp)
 
   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:
@@ -1713,7 +1832,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));
@@ -1730,12 +1849,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.  */
@@ -1743,7 +1862,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.  */
@@ -1760,7 +1879,8 @@ type_contains_placeholder_p (tree type)
     case METHOD_TYPE:
     case FILE_TYPE:
     case FUNCTION_TYPE:
-      return 0;
+    case VECTOR_TYPE:
+      return false;
 
     case INTEGER_TYPE:
     case REAL_TYPE:
@@ -1769,8 +1889,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));
@@ -1779,33 +1897,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
@@ -1813,84 +1905,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 WITH_CLEANUP_EXPR:
-      return 1;
-
-    case CLEANUP_POINT_EXPR:
-      return 0;
+  bool result;
 
-    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;
+  /* 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;
 
-    case DECL_EXPR:
-      return (DECL_INITIAL (DECL_EXPR_DECL (exp))
-             && has_cleanups (DECL_INITIAL (DECL_EXPR_DECL (exp))));
+  /* 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;
 
-    default:
-      break;
-    }
-
-  /* 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,
@@ -1922,15 +1967,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;
 
@@ -1938,23 +1982,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;
@@ -1990,12 +2034,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);
@@ -2022,10 +2066,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;
@@ -2034,10 +2078,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)))
@@ -2063,18 +2107,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;
@@ -2120,12 +2164,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
@@ -2245,13 +2289,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
@@ -2260,12 +2304,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.  */
@@ -2279,13 +2323,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);
@@ -2333,36 +2377,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 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.  */
+     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))
        ;
-      else if (decl_function_context (node) == current_function_decl)
+      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
     {
@@ -2381,7 +2433,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.  */
 
@@ -2390,10 +2442,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;
@@ -2413,10 +2462,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:
@@ -2428,10 +2477,7 @@ 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);
 
@@ -2448,13 +2494,13 @@ 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)
     {
@@ -2471,6 +2517,8 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
       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.  */
@@ -2483,12 +2531,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;
     }
@@ -2499,7 +2550,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;             \
@@ -2517,12 +2568,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;
@@ -2531,12 +2578,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;
@@ -2547,9 +2593,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;
 }
@@ -2560,18 +2607,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);
@@ -2598,9 +2639,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;
 }
@@ -2611,18 +2653,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);
@@ -2630,9 +2666,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;
 }
@@ -2675,7 +2712,7 @@ tree
       t = build4 (code, tt, arg0, arg1, arg2, arg3);
       break;
     default:
-      abort ();
+      gcc_unreachable ();
     }
   va_end (p);
 
@@ -2733,6 +2770,11 @@ 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;
 }
 \f
@@ -2764,12 +2806,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;
 }
@@ -2830,6 +2873,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.
 
@@ -2893,6 +3004,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.
 
@@ -2901,29 +3013,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;
@@ -2940,6 +3052,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
@@ -2950,12 +3073,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;
     }
 
@@ -3031,7 +3154,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.
 
@@ -3084,6 +3207,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 ("%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
@@ -3146,29 +3344,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;
 }
@@ -3216,11 +3430,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)
@@ -3256,9 +3472,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:
@@ -3347,8 +3562,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;
@@ -3599,10 +3813,8 @@ host_integerp (tree t, int pos)
 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.  */
@@ -3709,7 +3921,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:
@@ -3774,12 +3986,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++)
        {
@@ -3836,7 +4048,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)
@@ -3881,97 +4093,92 @@ 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)
-       {
-         val = iterative_hash_object (TREE_INT_CST_LOW (t), val);
-         val = iterative_hash_object (TREE_INT_CST_HIGH (t), val);
-       }
-      else if (code == REAL_CST)
-       {
-         unsigned int val2 = real_hash (TREE_REAL_CST_PTR (t));
+    /* 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));
 
-         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)
+       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;
+    default:
+      class = TREE_CODE_CLASS (code);
+
+      if (class == tcc_declaration)
        {
-         val = iterative_hash_expr (TREE_REALPART (t), val);
-         val = iterative_hash_expr (TREE_IMAGPART (t), val);
+         /* Decls we can just compare 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);
-    }
-  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);
+      return val;
+      break;
     }
-  else
-    abort ();
-
-  return val;
 }
 \f
 /* Constructors for pointer, array and function types.
@@ -4120,7 +4327,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);
@@ -4133,6 +4340,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.
@@ -4193,9 +4422,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);
@@ -4326,10 +4558,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));
 }
@@ -4685,7 +4916,8 @@ int_fits_type_p (tree c, tree type)
     {
       c = copy_node (c);
       TREE_TYPE (c) = type;
-      return !force_fit_type (c, 0);
+      c = force_fit_type (c, -1, false, false);
+      return !TREE_OVERFLOW (c);
     }
 }
 
@@ -4702,7 +4934,8 @@ find_var_from_fn (tree *tp, int *walk_subtrees, void *data)
   if (TYPE_P (*tp))
     *walk_subtrees = 0;
 
-  else if (DECL_P (*tp) && lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn))
+  else if (DECL_P (*tp)
+          && lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn))
     return *tp;
 
   return NULL_TREE;
@@ -4749,7 +4982,6 @@ variably_modified_type_p (tree type, tree fn)
     case POINTER_TYPE:
     case REFERENCE_TYPE:
     case ARRAY_TYPE:
-    case SET_TYPE:
     case VECTOR_TYPE:
       if (variably_modified_type_p (TREE_TYPE (type), fn))
        return true;
@@ -4874,18 +5106,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;
@@ -4902,8 +5134,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.  */
@@ -4922,7 +5153,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);
@@ -4974,11 +5205,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;
@@ -5103,9 +5334,10 @@ get_set_constructor_bits (tree init, char *buffer, int bit_size)
          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 ();
+         gcc_assert (lo_index >= 0);
+         gcc_assert (lo_index < bit_size);
+         gcc_assert (hi_index >= 0);
+         gcc_assert (hi_index < bit_size);
          for (; lo_index <= hi_index; lo_index++)
            buffer[lo_index] = 1;
        }
@@ -5163,8 +5395,9 @@ get_set_constructor_bytes (tree init, unsigned char *buffer, int wd_size)
 #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,
@@ -5179,22 +5412,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);
 }
@@ -5230,7 +5468,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);
@@ -5240,12 +5478,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);
 }
 
@@ -5287,18 +5526,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);
@@ -5311,6 +5558,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
@@ -5339,20 +5598,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)
 {
-  /* This function is called after command line parsing is complete,
-     but before any DECL nodes should have been created.  Therefore,
-     now is the appropriate time to adjust next_decl_uid so that the
-     range 0 .. num_in_fnames-1 is reserved for TRANSLATION_UNIT_DECLs.  */
-  if (next_decl_uid)
-    abort ();
-  next_decl_uid = num_in_fnames;
-
   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);
@@ -5380,8 +5631,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
@@ -5397,7 +5647,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");
@@ -5410,9 +5660,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);
@@ -5431,8 +5681,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);
@@ -5485,7 +5734,7 @@ 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;
   }
@@ -5523,10 +5772,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;
@@ -5537,36 +5791,43 @@ 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 NULL_TREE;
+  return make_vector_type (innertype, nunits, VOIDmode);
 }
 
 /* Given an initializer INIT, return TRUE if INIT is zero or some
@@ -5607,10 +5868,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;
@@ -5640,19 +5897,258 @@ 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);
 }
 
 #include "gt-tree.h"