OSDN Git Service

2003-06-10 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index 2c56b95..ad4f51c 100644 (file)
@@ -1,6 +1,6 @@
 /* Language-independent node constructors for parse phase of GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -31,6 +31,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "flags.h"
 #include "tree.h"
 #include "real.h"
@@ -90,9 +92,9 @@ static const char * const tree_node_kind_names[] = {
 #endif /* GATHER_STATISTICS */
 
 /* Unique id for next decl created.  */
-static int next_decl_uid;
+static GTY(()) int next_decl_uid;
 /* Unique id for next type created.  */
-static int next_type_uid = 1;
+static GTY(()) int next_type_uid = 1;
 
 /* Since we cannot rehash a type after it is in the table, we have to
    keep the hash code.  */
@@ -119,7 +121,7 @@ static GTY ((if_marked ("type_hash_marked_p"), param_is (struct type_hash)))
 static void set_type_quals PARAMS ((tree, int));
 static void append_random_chars PARAMS ((char *));
 static int type_hash_eq PARAMS ((const void *, const void *));
-static unsigned int type_hash_hash PARAMS ((const void *));
+static hashval_t type_hash_hash PARAMS ((const void *));
 static void print_type_hash_statistics PARAMS((void));
 static void finish_vector_type PARAMS((tree));
 static tree make_vector PARAMS ((enum machine_mode, tree, int));
@@ -134,8 +136,8 @@ void
 init_ttree ()
 {
   /* Initialize the hash table of types.  */
-  type_hash_table = htab_create (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
-                                type_hash_eq, 0);
+  type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
+                                    type_hash_eq, 0);
 }
 
 \f
@@ -177,31 +179,35 @@ tree_size (node)
     case '1':  /* a unary arithmetic expression */
     case '2':  /* a binary arithmetic expression */
       return (sizeof (struct tree_exp)
-             + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *));
+             + TREE_CODE_LENGTH (code) * sizeof (char *) - sizeof (char *));
 
     case 'c':  /* a constant */
-      /* We can't use TREE_CODE_LENGTH for INTEGER_CST, since the number of
-        words is machine-dependent due to varying length of HOST_WIDE_INT,
-        which might be wider than a pointer (e.g., long long).  Similarly
-        for REAL_CST, since the number of words is machine-dependent due
-        to varying size and alignment of `double'.  */
-      if (code == INTEGER_CST)
-       return sizeof (struct tree_int_cst);
-      else if (code == REAL_CST)
-       return sizeof (struct tree_real_cst);
-      else
-       return (sizeof (struct tree_common)
-               + TREE_CODE_LENGTH (code) * sizeof (char *));
+      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);
+       default:
+         return (*lang_hooks.tree_size) (code);
+       }
 
     case 'x':  /* something random, like an identifier.  */
-      {
-       size_t length;
-       length = (sizeof (struct tree_common)
-                 + TREE_CODE_LENGTH (code) * sizeof (char *));
-       if (code == TREE_VEC)
-         length += (TREE_VEC_LENGTH (node) - 1) * sizeof (char *);
-       return length;
-      }
+      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);
+
+       default:
+         return (*lang_hooks.tree_size) (code);
+       }
 
     default:
       abort ();
@@ -295,7 +301,6 @@ make_node (code)
     {
     case 's':
       TREE_SIDE_EFFECTS (t) = 1;
-      TREE_TYPE (t) = void_type_node;
       break;
 
     case 'd':
@@ -303,7 +308,7 @@ make_node (code)
        DECL_ALIGN (t) = 1;
       DECL_USER_ALIGN (t) = 0;
       DECL_IN_SYSTEM_HEADER (t) = in_system_header;
-      DECL_SOURCE_LINE (t) = lineno;
+      DECL_SOURCE_LINE (t) = input_line;
       DECL_SOURCE_FILE (t) =
        (input_filename) ? input_filename : "<built-in>";
       DECL_UID (t) = next_decl_uid++;
@@ -463,6 +468,29 @@ build_vector (type, vals)
   return v;
 }
 
+/* Return a new CONSTRUCTOR node whose type is TYPE and whose values
+   are in a list pointed to by VALS.  */
+tree
+build_constructor (type, vals)
+     tree type, vals;
+{
+  tree c = make_node (CONSTRUCTOR);
+  TREE_TYPE (c) = type;
+  CONSTRUCTOR_ELTS (c) = vals;
+
+  /* ??? May not be necessary.  Mirrors what build does.  */
+  if (vals)
+    {
+      TREE_SIDE_EFFECTS (c) = TREE_SIDE_EFFECTS (vals);
+      TREE_READONLY (c) = TREE_READONLY (vals);
+      TREE_CONSTANT (c) = TREE_CONSTANT (vals);
+    }
+  else
+    TREE_CONSTANT (c) = 0;  /* safe side */
+
+  return c;
+}
+
 /* Return a new REAL_CST node whose type is TYPE and value is D.  */
 
 tree
@@ -474,11 +502,8 @@ build_real (type, d)
   REAL_VALUE_TYPE *dp;
   int overflow = 0;
 
-  /* Check for valid float value for this type on this target machine;
-     if not, can print error message and store a valid value in D.  */
-#ifdef CHECK_FLOAT_VALUE
-  CHECK_FLOAT_VALUE (TYPE_MODE (type), d, overflow);
-#endif
+  /* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
+     Consider doing it via real_convert now.  */
 
   v = make_node (REAL_CST);
   dp = ggc_alloc (sizeof (REAL_VALUE_TYPE));
@@ -726,6 +751,24 @@ integer_pow2p (expr)
          || (low == 0 && (high & (high - 1)) == 0));
 }
 
+/* Return 1 if EXPR is an integer constant other than zero or a
+   complex constant other than zero.  */
+
+int
+integer_nonzerop (expr)
+     tree expr;
+{
+  STRIP_NOPS (expr);
+
+  return ((TREE_CODE (expr) == INTEGER_CST
+          && ! TREE_CONSTANT_OVERFLOW (expr)
+          && (TREE_INT_CST_LOW (expr) != 0
+              || TREE_INT_CST_HIGH (expr) != 0))
+         || (TREE_CODE (expr) == COMPLEX_CST
+             && (integer_nonzerop (TREE_REALPART (expr))
+                 || integer_nonzerop (TREE_IMAGPART (expr)))));
+}
+
 /* Return the power of two represented by a tree node known to be a
    power of two.  */
 
@@ -947,41 +990,6 @@ chain_member (elem, chain)
   return 0;
 }
 
-/* Return nonzero if ELEM is equal to TREE_VALUE (CHAIN) for any piece of
-   chain CHAIN.  This and the next function are currently unused, but
-   are retained for completeness.  */
-
-int
-chain_member_value (elem, chain)
-     tree elem, chain;
-{
-  while (chain)
-    {
-      if (elem == TREE_VALUE (chain))
-       return 1;
-      chain = TREE_CHAIN (chain);
-    }
-
-  return 0;
-}
-
-/* Return nonzero if ELEM is equal to TREE_PURPOSE (CHAIN)
-   for any piece of chain CHAIN.  */
-
-int
-chain_member_purpose (elem, chain)
-     tree elem, chain;
-{
-  while (chain)
-    {
-      if (elem == TREE_PURPOSE (chain))
-       return 1;
-      chain = TREE_CHAIN (chain);
-    }
-
-  return 0;
-}
-
 /* Return the length of a chain of nodes chained through TREE_CHAIN.
    We expect a null pointer to mark the end of the chain.
    This is the Lisp primitive `length'.  */
@@ -1023,26 +1031,27 @@ tree
 chainon (op1, op2)
      tree op1, op2;
 {
+  tree t1;
 
-  if (op1)
-    {
-      tree t1;
-#ifdef ENABLE_TREE_CHECKING
-      tree t2;
-#endif
+  if (!op1)
+    return op2;
+  if (!op2)
+    return op1;
+
+  for (t1 = op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1))
+    continue;
+  TREE_CHAIN (t1) = op2;
 
-      for (t1 = op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1))
-       ;
-      TREE_CHAIN (t1) = op2;
 #ifdef ENABLE_TREE_CHECKING
-      for (t2 = op2; t2; t2 = TREE_CHAIN (t2))
-       if (t2 == t1)
-         abort ();  /* Circularity created.  */
+  {
+    tree t2;
+    for (t2 = op2; t2; t2 = TREE_CHAIN (t2))
+      if (t2 == t1)
+       abort ();  /* Circularity created.  */
+  }
 #endif
-      return op1;
-    }
-  else
-    return op2;
+
+  return op1;
 }
 
 /* Return the last node in a chain of nodes (chained through TREE_CHAIN).  */
@@ -1074,31 +1083,6 @@ nreverse (t)
     }
   return prev;
 }
-
-/* Given a chain CHAIN of tree nodes,
-   construct and return a list of those nodes.  */
-
-tree
-listify (chain)
-     tree chain;
-{
-  tree result = NULL_TREE;
-  tree in_tail = chain;
-  tree out_tail = NULL_TREE;
-
-  while (in_tail)
-    {
-      tree next = tree_cons (NULL_TREE, in_tail, NULL_TREE);
-      if (out_tail)
-       TREE_CHAIN (out_tail) = next;
-      else
-       result = next;
-      out_tail = next;
-      in_tail = TREE_CHAIN (in_tail);
-    }
-
-  return result;
-}
 \f
 /* Return a newly created TREE_LIST node whose
    purpose and value fields are PARM and VALUE.  */
@@ -1114,7 +1098,7 @@ build_tree_list (parm, value)
 }
 
 /* Return a newly created TREE_LIST node whose
-   purpose and value fields are PARM and VALUE
+   purpose and value fields are PURPOSE and VALUE
    and whose TREE_CHAIN is CHAIN.  */
 
 tree
@@ -1139,6 +1123,44 @@ tree_cons (purpose, value, chain)
   return node;
 }
 
+/* Return the first expression in a sequence of COMPOUND_EXPRs.  */
+
+tree
+expr_first (tree expr)
+{
+  if (expr == NULL_TREE)
+    return expr;
+  while (TREE_CODE (expr) == COMPOUND_EXPR)
+    expr = TREE_OPERAND (expr, 0);
+  return expr;
+}
+
+/* Return the last expression in a sequence of COMPOUND_EXPRs.  */
+
+tree
+expr_last (tree expr)
+{
+  if (expr == NULL_TREE)
+    return expr;
+  while (TREE_CODE (expr) == COMPOUND_EXPR)
+    expr = TREE_OPERAND (expr, 1);
+  return expr;
+}
+
+/* Return the number of subexpressions in a sequence of COMPOUND_EXPRs.  */
+
+int
+expr_length (tree expr)
+{
+  int len = 0;
+  
+  if (expr == NULL_TREE)
+    return 0;
+  for (; TREE_CODE (expr) == COMPOUND_EXPR; expr = TREE_OPERAND (expr, 1))
+    len += expr_length (TREE_OPERAND (expr, 0));
+  ++len;
+  return len;
+}
 \f
 /* Return the size nominally occupied by an object of type TYPE
    when it resides in memory.  The value is measured in units of bytes,
@@ -1202,7 +1224,6 @@ tree
 bit_position (field)
      tree field;
 {
-
   return bit_from_pos (DECL_FIELD_OFFSET (field),
                       DECL_FIELD_BIT_OFFSET (field));
 }
@@ -1398,33 +1419,19 @@ save_expr (expr)
   tree t = fold (expr);
   tree inner;
 
-  /* We don't care about whether this can be used as an lvalue in this
-     context.  */
-  while (TREE_CODE (t) == NON_LVALUE_EXPR)
-    t = TREE_OPERAND (t, 0);
-
-  /* If we have simple operations applied to a SAVE_EXPR or to a SAVE_EXPR and
-     a constant, it will be more efficient to not make another SAVE_EXPR since
-     it will allow better simplification and GCSE will be able to merge the
-     computations if they actualy occur.  */
-  for (inner = t;
-       (TREE_CODE_CLASS (TREE_CODE (inner)) == '1'
-       || (TREE_CODE_CLASS (TREE_CODE (inner)) == '2'
-           && TREE_CONSTANT (TREE_OPERAND (inner, 1))));
-       inner = TREE_OPERAND (inner, 0))
-    ;
-
   /* If the tree evaluates to a constant, then we don't want to hide that
      fact (i.e. this allows further folding, and direct checks for constants).
      However, a read-only object that has side effects cannot be bypassed.
      Since it is no problem to reevaluate literals, we just return the
      literal node.  */
+  inner = skip_simple_arithmetic (t);
   if (TREE_CONSTANT (inner)
       || (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner))
-      || TREE_CODE (inner) == SAVE_EXPR || TREE_CODE (inner) == ERROR_MARK)
+      || TREE_CODE (inner) == SAVE_EXPR
+      || TREE_CODE (inner) == ERROR_MARK)
     return t;
 
-  /* If T contains a PLACEHOLDER_EXPR, we must evaluate it each time, since
+  /* If INNER contains a PLACEHOLDER_EXPR, we must evaluate it each time, since
      it means that the size or offset of some field of an object depends on
      the value within another field.
 
@@ -1433,7 +1440,7 @@ save_expr (expr)
      evaluated more than once.  Front-ends must assure this case cannot
      happen by surrounding any such subexpressions in their own SAVE_EXPR
      and forcing evaluation at the proper time.  */
-  if (contains_placeholder_p (t))
+  if (contains_placeholder_p (inner))
     return t;
 
   t = build (SAVE_EXPR, TREE_TYPE (expr), t, current_function_decl, NULL_TREE);
@@ -1446,6 +1453,55 @@ save_expr (expr)
   return t;
 }
 
+/* Look inside EXPR and into any simple arithmetic operations.  Return
+   the innermost non-arithmetic node.  */
+
+tree
+skip_simple_arithmetic (expr)
+     tree expr;
+{
+  tree inner;
+  
+  /* We don't care about whether this can be used as an lvalue in this
+     context.  */
+  while (TREE_CODE (expr) == NON_LVALUE_EXPR)
+    expr = TREE_OPERAND (expr, 0);
+
+  /* If we have simple operations applied to a SAVE_EXPR or to a SAVE_EXPR and
+     a constant, it will be more efficient to not make another SAVE_EXPR since
+     it will allow better simplification and GCSE will be able to merge the
+     computations if they actually occur.  */
+  inner = expr;
+  while (1)
+    {
+      if (TREE_CODE_CLASS (TREE_CODE (inner)) == '1')
+       inner = TREE_OPERAND (inner, 0);
+      else if (TREE_CODE_CLASS (TREE_CODE (inner)) == '2')
+       {
+         if (TREE_CONSTANT (TREE_OPERAND (inner, 1)))
+           inner = TREE_OPERAND (inner, 0);
+         else if (TREE_CONSTANT (TREE_OPERAND (inner, 0)))
+           inner = TREE_OPERAND (inner, 1);
+         else
+           break;
+       }
+      else
+       break;
+    }
+
+  return inner;
+}
+
+/* Return TRUE if EXPR is a SAVE_EXPR or wraps simple arithmetic around a
+   SAVE_EXPR.  Return FALSE otherwise.  */
+
+bool
+saved_expr_p (expr)
+     tree expr;
+{
+  return TREE_CODE (skip_simple_arithmetic (expr)) == SAVE_EXPR;
+}
+
 /* 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.  */
@@ -1637,7 +1693,7 @@ unsafe_for_reeval (expr)
 {
   int unsafeness = 0;
   enum tree_code code;
-  int i, tmp;
+  int i, tmp, tmp2;
   tree exp;
   int first_rtl;
 
@@ -1663,8 +1719,9 @@ unsafe_for_reeval (expr)
       return unsafeness;
 
     case CALL_EXPR:
+      tmp2 = unsafe_for_reeval (TREE_OPERAND (expr, 0));
       tmp = unsafe_for_reeval (TREE_OPERAND (expr, 1));
-      return MAX (tmp, 1);
+      return MAX (MAX (tmp, 1), tmp2);
 
     case TARGET_EXPR:
       unsafeness = 1;
@@ -1708,7 +1765,7 @@ unsafe_for_reeval (expr)
 /* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size
    or offset that depends on a field within a record.  */
 
-int
+bool
 contains_placeholder_p (exp)
      tree exp;
 {
@@ -1733,13 +1790,12 @@ contains_placeholder_p (exp)
         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));
+      return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
 
     case 'x':
       if (code == TREE_LIST)
-       return (contains_placeholder_p (TREE_VALUE (exp))
-               || (TREE_CHAIN (exp) != 0
-                   && contains_placeholder_p (TREE_CHAIN (exp))));
+       return (CONTAINS_PLACEHOLDER_P (TREE_VALUE (exp))
+               || CONTAINS_PLACEHOLDER_P (TREE_CHAIN (exp)));
       break;
 
     case '1':
@@ -1749,16 +1805,16 @@ contains_placeholder_p (exp)
        {
        case COMPOUND_EXPR:
          /* Ignoring the first operand isn't quite right, but works best.  */
-         return contains_placeholder_p (TREE_OPERAND (exp, 1));
+         return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1));
 
        case RTL_EXPR:
        case CONSTRUCTOR:
          return 0;
 
        case COND_EXPR:
-         return (contains_placeholder_p (TREE_OPERAND (exp, 0))
-                 || contains_placeholder_p (TREE_OPERAND (exp, 1))
-                 || contains_placeholder_p (TREE_OPERAND (exp, 2)));
+         return (CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0))
+                 || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1))
+                 || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2)));
 
        case SAVE_EXPR:
          /* If we already know this doesn't have a placeholder, don't
@@ -1767,15 +1823,14 @@ contains_placeholder_p (exp)
            return 0;
 
          SAVE_EXPR_NOPLACEHOLDER (exp) = 1;
-         result = contains_placeholder_p (TREE_OPERAND (exp, 0));
+         result = CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
          if (result)
            SAVE_EXPR_NOPLACEHOLDER (exp) = 0;
 
          return result;
 
        case CALL_EXPR:
-         return (TREE_OPERAND (exp, 1) != 0
-                 && contains_placeholder_p (TREE_OPERAND (exp, 1)));
+         return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1));
 
        default:
          break;
@@ -1784,10 +1839,10 @@ contains_placeholder_p (exp)
       switch (TREE_CODE_LENGTH (code))
        {
        case 1:
-         return contains_placeholder_p (TREE_OPERAND (exp, 0));
+         return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
        case 2:
-         return (contains_placeholder_p (TREE_OPERAND (exp, 0))
-                 || contains_placeholder_p (TREE_OPERAND (exp, 1)));
+         return (CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0))
+                 || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)));
        default:
          return 0;
        }
@@ -1798,6 +1853,109 @@ contains_placeholder_p (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.  */
+
+bool
+type_contains_placeholder_p (type)
+     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.  */
+  if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (type))
+      || CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (type))
+      || (TREE_TYPE (type) != 0
+         && type_contains_placeholder_p (TREE_TYPE (type))))
+    return 1;
+
+  /* Now do type-specific checks.  Note that the last part of the check above
+     greatly limits what we have to do below.  */
+  switch (TREE_CODE (type))
+    {
+    case VOID_TYPE:
+    case COMPLEX_TYPE:
+    case VECTOR_TYPE:
+    case ENUMERAL_TYPE:
+    case BOOLEAN_TYPE:
+    case CHAR_TYPE:
+    case POINTER_TYPE:
+    case OFFSET_TYPE:
+    case REFERENCE_TYPE:
+    case METHOD_TYPE:
+    case FILE_TYPE:
+    case FUNCTION_TYPE:
+      return 0;
+
+    case INTEGER_TYPE:
+    case REAL_TYPE:
+      /* Here we just check the bounds.  */
+      return (CONTAINS_PLACEHOLDER_P (TYPE_MIN_VALUE (type))
+             || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type)));
+
+    case ARRAY_TYPE:
+    case SET_TYPE:
+      /* We're already checked the component type (TREE_TYPE), so just check
+        the index type.  */
+      return type_contains_placeholder_p (TYPE_DOMAIN (type));
+
+    case RECORD_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
+             && (CONTAINS_PLACEHOLDER_P (DECL_FIELD_OFFSET (field))
+                 || (TREE_CODE (type) == QUAL_UNION_TYPE
+                     && CONTAINS_PLACEHOLDER_P (DECL_QUALIFIER (field)))
+                 || type_contains_placeholder_p (TREE_TYPE (field))))
+           {
+             ret = true;
+             break;
+           }
+
+       /* 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;
+      }
+
+    default:
+      abort ();
+    }
+}
+
 /* Return 1 if EXP contains any expressions that produce cleanups for an
    outer scope to deal with.  Used by fold.  */
 
@@ -1921,8 +2079,13 @@ substitute_in_expr (exp, f, r)
          else if (code == CONSTRUCTOR)
            abort ();
 
-         op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
-         op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r);
+         op0 = TREE_OPERAND (exp, 0);
+         op1 = TREE_OPERAND (exp, 1);
+         if (CONTAINS_PLACEHOLDER_P (op0))
+           op0 = substitute_in_expr (op0, f, r);
+         if (CONTAINS_PLACEHOLDER_P (op1))
+           op1 = substitute_in_expr (op1, f, r);
+
          if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
            return exp;
 
@@ -1948,9 +2111,17 @@ substitute_in_expr (exp, f, r)
          else if (code != COND_EXPR)
            abort ();
 
-         op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
-         op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r);
-         op2 = substitute_in_expr (TREE_OPERAND (exp, 2), f, r);
+         op0 = TREE_OPERAND (exp, 0);
+         op1 = TREE_OPERAND (exp, 1);
+         op2 = TREE_OPERAND (exp, 2);
+
+         if (CONTAINS_PLACEHOLDER_P (op0))
+           op0 = substitute_in_expr (op0, f, r);
+         if (CONTAINS_PLACEHOLDER_P (op1))
+           op1 = substitute_in_expr (op1, f, r);
+         if (CONTAINS_PLACEHOLDER_P (op2))
+           op2 = substitute_in_expr (op2, f, r);
+
          if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
              && op2 == TREE_OPERAND (exp, 2))
            return exp;
@@ -2208,17 +2379,16 @@ stabilize_reference_1 (e)
    Constants, decls, types and misc nodes cannot be.  */
 
 tree
-build VPARAMS ((enum tree_code code, tree tt, ...))
+build (enum tree_code code, tree tt, ...)
 {
   tree t;
   int length;
   int i;
   int fro;
   int constant;
+  va_list p;
 
-  VA_OPEN (p, tt);
-  VA_FIXEDARG (p, enum tree_code, code);
-  VA_FIXEDARG (p, tree, tt);
+  va_start (p, tt);
 
   t = make_node (code);
   length = TREE_CODE_LENGTH (code);
@@ -2295,7 +2465,7 @@ build VPARAMS ((enum tree_code code, tree tt, ...))
            }
        }
     }
-  VA_CLOSE (p);
+  va_end (p);
 
   TREE_CONSTANT (t) = constant;
   return t;
@@ -2311,17 +2481,28 @@ build1 (code, type, node)
      tree type;
      tree node;
 {
-  int length;
+  int length = sizeof (struct tree_exp);
 #ifdef GATHER_STATISTICS
   tree_node_kind kind;
 #endif
   tree t;
 
 #ifdef GATHER_STATISTICS
-  if (TREE_CODE_CLASS (code) == 'r')
-    kind = r_kind;
-  else
-    kind = e_kind;
+  switch (TREE_CODE_CLASS (code))
+    {
+    case 's':  /* an expression with side effects */
+      kind = s_kind;
+      break;
+    case 'r':  /* a reference */
+      kind = r_kind;
+      break;
+    default:
+      kind = e_kind;
+      break;
+    }
+
+  tree_node_counts[(int) kind]++;
+  tree_node_sizes[(int) kind] += length;
 #endif
 
 #ifdef ENABLE_CHECKING
@@ -2331,17 +2512,10 @@ build1 (code, type, node)
     abort ();
 #endif /* ENABLE_CHECKING */
 
-  length = sizeof (struct tree_exp);
-
   t = ggc_alloc_tree (length);
 
   memset ((PTR) t, 0, sizeof (struct tree_common));
 
-#ifdef GATHER_STATISTICS
-  tree_node_counts[(int) kind]++;
-  tree_node_sizes[(int) kind] += length;
-#endif
-
   TREE_SET_CODE (t, code);
 
   TREE_TYPE (t) = type;
@@ -2353,7 +2527,9 @@ build1 (code, type, node)
       TREE_READONLY (t) = TREE_READONLY (node);
     }
 
-  switch (code)
+  if (TREE_CODE_CLASS (code) == 's')
+    TREE_SIDE_EFFECTS (t) = 1;
+  else switch (code)
     {
     case INIT_EXPR:
     case MODIFY_EXPR:
@@ -2390,14 +2566,14 @@ build1 (code, type, node)
    or even garbage if their values do not matter.  */
 
 tree
-build_nt VPARAMS ((enum tree_code code, ...))
+build_nt (enum tree_code code, ...)
 {
   tree t;
   int length;
   int i;
+  va_list p;
 
-  VA_OPEN (p, code);
-  VA_FIXEDARG (p, enum tree_code, code);
+  va_start (p, code);
 
   t = make_node (code);
   length = TREE_CODE_LENGTH (code);
@@ -2405,7 +2581,7 @@ build_nt VPARAMS ((enum tree_code code, ...))
   for (i = 0; i < length; i++)
     TREE_OPERAND (t, i) = va_arg (p, tree);
 
-  VA_CLOSE (p);
+  va_end (p);
   return t;
 }
 \f
@@ -2555,54 +2731,7 @@ build_type_attribute_variant (ttype, attribute)
   return ttype;
 }
 
-/* Default value of targetm.comp_type_attributes that always returns 1.  */
-
-int
-default_comp_type_attributes (type1, type2)
-     tree type1 ATTRIBUTE_UNUSED;
-     tree type2 ATTRIBUTE_UNUSED;
-{
-  return 1;
-}
-
-/* Default version of targetm.set_default_type_attributes that always does
-   nothing.  */
-
-void
-default_set_default_type_attributes (type)
-     tree type ATTRIBUTE_UNUSED;
-{
-}
-
-/* Default version of targetm.insert_attributes that always does nothing.  */
-void
-default_insert_attributes (decl, attr_ptr)
-     tree decl ATTRIBUTE_UNUSED;
-     tree *attr_ptr ATTRIBUTE_UNUSED;
-{
-}
-
-/* Default value of targetm.function_attribute_inlinable_p that always
-   returns false.  */
-bool
-default_function_attribute_inlinable_p (fndecl)
-     tree fndecl ATTRIBUTE_UNUSED;
-{
-  /* By default, functions with machine attributes cannot be inlined.  */
-  return false;
-}
-
-/* Default value of targetm.ms_bitfield_layout_p that always returns
-   false.  */
-bool
-default_ms_bitfield_layout_p (record)
-     tree record ATTRIBUTE_UNUSED;
-{
-  /* By default, GCC does not use the MS VC++ bitfield layout rules.  */
-  return false;
-}
-
-/* Return non-zero if IDENT is a valid name for attribute ATTR,
+/* 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.  */
@@ -2939,7 +3068,7 @@ type_hash_eq (va, vb)
 
 /* Return the cached hash value.  */
 
-static unsigned int
+static hashval_t
 type_hash_hash (item)
      const void *item;
 {
@@ -3493,31 +3622,125 @@ compare_tree_int (t, u)
   else
     return 1;
 }
+
+/* Generate a hash value for an expression.  This can be used iteratively
+   by passing a previous result as the "val" argument.
+
+   This function is intended to produce the same hash for expressions which
+   would compare equal using operand_equal_p.  */
+
+hashval_t
+iterative_hash_expr (tree t, hashval_t val)
+{
+  int i;
+  enum tree_code code;
+  char class;
+
+  if (t == NULL_TREE)
+    return iterative_hash_object (t, val);
+
+  code = TREE_CODE (t);
+  class = TREE_CODE_CLASS (code);
+
+  if (class == 'd')
+    {
+      /* Decls we can just compare by pointer.  */
+      val = iterative_hash_object (t, val);
+    }
+  else if (class == 'c')
+    {
+      /* 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)
+       val = iterative_hash (TREE_REAL_CST_PTR (t),
+                             sizeof (REAL_VALUE_TYPE), val);
+      else if (code == STRING_CST)
+       val = iterative_hash (TREE_STRING_POINTER (t),
+                             TREE_STRING_LENGTH (t), val);
+      else if (code == COMPLEX_CST)
+       {
+         val = iterative_hash_expr (TREE_REALPART (t), val);
+         val = iterative_hash_expr (TREE_IMAGPART (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) || class == 'r')
+    {
+      val = iterative_hash_object (code, val);
+
+      if (code == NOP_EXPR || code == CONVERT_EXPR
+         || code == NON_LVALUE_EXPR)
+       val = iterative_hash_object (TREE_TYPE (t), val);
+
+      if (code == PLUS_EXPR || code == MULT_EXPR || code == MIN_EXPR
+         || code == MAX_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR
+         || code == BIT_AND_EXPR || code == NE_EXPR || code == EQ_EXPR)
+       {
+         /* 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
+       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
+    abort ();
+
+  return val;
+}
 \f
 /* Constructors for pointer, array and function types.
    (RECORD_TYPE, UNION_TYPE and ENUMERAL_TYPE nodes are
    constructed by language-dependent code, not here.)  */
 
-/* Construct, lay out and return the type of pointers to TO_TYPE.
-   If such a type has already been constructed, reuse it.  */
+/* Construct, lay out and return the type of pointers to TO_TYPE
+   with mode MODE. If such a type has already been constructed,
+   reuse it.  */
 
 tree
-build_pointer_type (to_type)
+build_pointer_type_for_mode (to_type, mode)
      tree to_type;
+     enum machine_mode mode;
 {
   tree t = TYPE_POINTER_TO (to_type);
 
   /* First, if we already have a type for pointers to TO_TYPE, use it.  */
-
-  if (t != 0)
+  if (t != 0 && mode == ptr_mode)
     return t;
 
-  /* We need a new one.  */
   t = make_node (POINTER_TYPE);
 
   TREE_TYPE (t) = to_type;
+  TYPE_MODE (t) = mode;
 
   /* Record this type as the pointer to TO_TYPE.  */
+  if (mode == ptr_mode)
   TYPE_POINTER_TO (to_type) = t;
 
   /* Lay out the type.  This function has many callers that are concerned
@@ -3528,25 +3751,37 @@ build_pointer_type (to_type)
   return t;
 }
 
-/* Build the node for the type of references-to-TO_TYPE.  */
+/* By default build pointers in ptr_mode.  */
 
 tree
-build_reference_type (to_type)
+build_pointer_type (to_type)
+     tree to_type;
+{
+  return build_pointer_type_for_mode (to_type, ptr_mode);
+}
+
+/* Construct, lay out and return the type of references to TO_TYPE
+   with mode MODE. If such a type has already been constructed,
+   reuse it.  */
+
+tree
+build_reference_type_for_mode (to_type, mode)
      tree to_type;
+     enum machine_mode mode;
 {
   tree t = TYPE_REFERENCE_TO (to_type);
 
   /* First, if we already have a type for pointers to TO_TYPE, use it.  */
-
-  if (t)
+  if (t != 0 && mode == ptr_mode)
     return t;
 
-  /* We need a new one.  */
   t = make_node (REFERENCE_TYPE);
 
   TREE_TYPE (t) = to_type;
+  TYPE_MODE (t) = mode;
 
   /* Record this type as the pointer to TO_TYPE.  */
+  if (mode == ptr_mode)
   TYPE_REFERENCE_TO (to_type) = t;
 
   layout_type (t);
@@ -3554,6 +3789,17 @@ build_reference_type (to_type)
   return t;
 }
 
+
+/* Build the node for the type of references-to-TO_TYPE by default
+   in ptr_mode.  */
+
+tree
+build_reference_type (to_type)
+     tree to_type;
+{
+  return build_reference_type_for_mode (to_type, ptr_mode);
+}
+
 /* Build a type that is compatible with t but has no cv quals anywhere
    in its type, thus
 
@@ -3648,36 +3894,6 @@ build_index_2_type (lowval, highval)
   return build_range_type (sizetype, lowval, highval);
 }
 
-/* Return nonzero iff ITYPE1 and ITYPE2 are equal (in the LISP sense).
-   Needed because when index types are not hashed, equal index types
-   built at different times appear distinct, even though structurally,
-   they are not.  */
-
-int
-index_type_equal (itype1, itype2)
-     tree itype1, itype2;
-{
-  if (TREE_CODE (itype1) != TREE_CODE (itype2))
-    return 0;
-
-  if (TREE_CODE (itype1) == INTEGER_TYPE)
-    {
-      if (TYPE_PRECISION (itype1) != TYPE_PRECISION (itype2)
-         || TYPE_MODE (itype1) != TYPE_MODE (itype2)
-         || simple_cst_equal (TYPE_SIZE (itype1), TYPE_SIZE (itype2)) != 1
-         || TYPE_ALIGN (itype1) != TYPE_ALIGN (itype2))
-       return 0;
-
-      if (1 == simple_cst_equal (TYPE_MIN_VALUE (itype1),
-                                TYPE_MIN_VALUE (itype2))
-         && 1 == simple_cst_equal (TYPE_MAX_VALUE (itype1),
-                                   TYPE_MAX_VALUE (itype2)))
-       return 1;
-    }
-
-  return 0;
-}
-
 /* Construct, lay out and return the type of arrays of elements with ELT_TYPE
    and number of elements specified by the range of values of INDEX_TYPE.
    If such a type has already been constructed, reuse it.  */
@@ -3772,12 +3988,12 @@ build_function_type (value_type, arg_types)
    be terminated by NULL_TREE.  */
 
 tree
-build_function_type_list VPARAMS ((tree return_type, ...))
+build_function_type_list (tree return_type, ...)
 {
   tree t, args, last;
+  va_list p;
 
-  VA_OPEN (p, return_type);
-  VA_FIXEDARG (p, tree, return_type);
+  va_start (p, return_type);
 
   t = va_arg (p, tree);
   for (args = NULL_TREE; t != NULL_TREE; t = va_arg (p, tree))
@@ -3788,7 +4004,7 @@ build_function_type_list VPARAMS ((tree return_type, ...))
   TREE_CHAIN (last) = void_list_node;
   args = build_function_type (return_type, args);
 
-  VA_CLOSE (p);
+  va_end (p);
   return args;
 }
 
@@ -4053,10 +4269,10 @@ get_narrower (op, unsignedp_ptr)
 
       /* See what's inside this conversion.  If we decide to strip it,
         we will set WIN.  */
-      op = TREE_OPERAND (op, 0);
 
       if (bitschange > 0)
        {
+         op = TREE_OPERAND (op, 0);
          /* An extension: the outermost one can be stripped,
             but remember whether it is zero or sign extension.  */
          if (first)
@@ -4075,6 +4291,7 @@ get_narrower (op, unsignedp_ptr)
          if (first)
            uns = TREE_UNSIGNED (TREE_TYPE (op));
          first = 0;
+         op = TREE_OPERAND (op, 0);
        }
 
       win = op;
@@ -4123,29 +4340,58 @@ int
 int_fits_type_p (c, type)
      tree c, type;
 {
-  /* If the bounds of the type are integers, we can check ourselves.
-     If not, but this type is a subtype, try checking against that.
-     Otherwise, use force_fit_type, which checks against the precision.  */
-  if (TYPE_MAX_VALUE (type) != NULL_TREE
-      && TYPE_MIN_VALUE (type) != NULL_TREE
-      && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
-      && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST)
+  tree type_low_bound = TYPE_MIN_VALUE (type);
+  tree type_high_bound = TYPE_MAX_VALUE (type);
+  int ok_for_low_bound, ok_for_high_bound;
+    
+  /* Perform some generic filtering first, which may allow making a decision
+     even if the bounds are not constant.  First, negative integers never fit
+     in unsigned types, */
+  if ((TREE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0)
+      /* Also, unsigned integers with top bit set never fit signed types.  */
+      || (! TREE_UNSIGNED (type) 
+         && TREE_UNSIGNED (TREE_TYPE (c)) && tree_int_cst_msb (c)))
+    return 0;
+
+  /* If at least one bound of the type is a constant integer, we can check
+     ourselves and maybe make a decision. If no such decision is possible, but
+     this type is a subtype, try checking against that.  Otherwise, use
+     force_fit_type, which checks against the precision.
+
+     Compute the status for each possibly constant bound, and return if we see
+     one does not match. Use ok_for_xxx_bound for this purpose, assigning -1
+     for "unknown if constant fits", 0 for "constant known *not* to fit" and 1
+     for "constant known to fit".  */
+
+  ok_for_low_bound = -1;
+  ok_for_high_bound = -1;
+    
+  /* Check if C >= type_low_bound.  */
+  if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST)
     {
-      if (TREE_UNSIGNED (type))
-       return (! INT_CST_LT_UNSIGNED (TYPE_MAX_VALUE (type), c)
-               && ! INT_CST_LT_UNSIGNED (c, TYPE_MIN_VALUE (type))
-               /* Negative ints never fit unsigned types.  */
-               && ! (TREE_INT_CST_HIGH (c) < 0
-                     && ! TREE_UNSIGNED (TREE_TYPE (c))));
-      else
-       return (! INT_CST_LT (TYPE_MAX_VALUE (type), c)
-               && ! INT_CST_LT (c, TYPE_MIN_VALUE (type))
-               /* Unsigned ints with top bit set never fit signed types.  */
-               && ! (TREE_INT_CST_HIGH (c) < 0
-                     && TREE_UNSIGNED (TREE_TYPE (c))));
+      ok_for_low_bound = ! tree_int_cst_lt (c, type_low_bound);
+      if (! ok_for_low_bound)
+       return 0;
+    }
+
+  /* Check if c <= type_high_bound.  */
+  if (type_high_bound && TREE_CODE (type_high_bound) == INTEGER_CST)
+    {
+      ok_for_high_bound = ! tree_int_cst_lt (type_high_bound, c);
+      if (! ok_for_high_bound)
+       return 0;
     }
+
+  /* If the constant fits both bounds, the result is known.  */
+  if (ok_for_low_bound == 1 && ok_for_high_bound == 1)
+    return 1;
+
+  /* If we haven't been able to decide at this point, there nothing more we
+     can check ourselves here. Look at the base type if we have one.  */
   else if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != 0)
     return int_fits_type_p (c, TREE_TYPE (type));
+  
+  /* Or to force_fit_type, if nothing else.  */
   else
     {
       c = copy_node (c);
@@ -4154,6 +4400,68 @@ int_fits_type_p (c, type)
     }
 }
 
+/* Returns true if T is, contains, or refers to a type with variable
+   size.  This concept is more general than that of C99 'variably
+   modified types': in C99, a struct type is never variably modified
+   because a VLA may not appear as a structure member.  However, in
+   GNU C code like:
+    
+     struct S { int i[f()]; };
+
+   is valid, and other languages may define similar constructs.  */
+
+bool
+variably_modified_type_p (type)
+     tree type;
+{
+  if (type == error_mark_node)
+    return false;
+
+  /* If TYPE itself has variable size, it is variably modified.  
+
+     We do not yet have a representation of the C99 '[*]' syntax.
+     When a representation is chosen, this function should be modified
+     to test for that case as well.  */
+  if (TYPE_SIZE (type) 
+      && TYPE_SIZE (type) != error_mark_node
+      && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+    return true;
+
+  /* If TYPE is a pointer or reference, it is variably modified if 
+     the type pointed to is variably modified.  */
+  if ((TREE_CODE (type) == POINTER_TYPE
+       || TREE_CODE (type) == REFERENCE_TYPE)
+      && variably_modified_type_p (TREE_TYPE (type)))
+    return true;
+  
+  /* If TYPE is an array, it is variably modified if the array
+     elements are.  (Note that the VLA case has already been checked
+     above.)  */
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && variably_modified_type_p (TREE_TYPE (type)))
+    return true;
+
+  /* If TYPE is a function type, it is variably modified if any of the
+     parameters or the return type are variably modified.  */
+  if (TREE_CODE (type) == FUNCTION_TYPE
+      || TREE_CODE (type) == METHOD_TYPE)
+    {
+      tree parm;
+
+      if (variably_modified_type_p (TREE_TYPE (type)))
+       return true;
+      for (parm = TYPE_ARG_TYPES (type); 
+          parm && parm != void_list_node; 
+          parm = TREE_CHAIN (parm))
+       if (variably_modified_type_p (TREE_VALUE (parm)))
+         return true;
+    }
+
+  /* The current language may have other cases to check, but in general,
+     all other types are not variably modified.  */
+  return (*lang_hooks.tree_inlining.var_mod_type_p) (type);
+}
+
 /* Given a DECL or TYPE, return the scope in which it was declared, or
    NULL_TREE if there is no containing scope.  */
 
@@ -4274,29 +4582,6 @@ get_callee_fndecl (call)
   return NULL_TREE;
 }
 
-/* Print debugging information about the obstack O, named STR.  */
-
-void
-print_obstack_statistics (str, o)
-     const char *str;
-     struct obstack *o;
-{
-  struct _obstack_chunk *chunk = o->chunk;
-  int n_chunks = 1;
-  int n_alloc = 0;
-
-  n_alloc += o->next_free - chunk->contents;
-  chunk = chunk->prev;
-  while (chunk)
-    {
-      n_chunks += 1;
-      n_alloc += chunk->limit - &chunk->contents[0];
-      chunk = chunk->prev;
-    }
-  fprintf (stderr, "obstack %s: %u bytes, %d chunks\n",
-          str, n_alloc, n_chunks);
-}
-
 /* Print debugging information about tree nodes generated during the compile,
    and any language-specific information.  */
 
@@ -4332,6 +4617,38 @@ dump_tree_statistics ()
 \f
 #define FILE_FUNCTION_FORMAT "_GLOBAL__%s_%s"
 
+const char *flag_random_seed;
+
+/* Set up a default flag_random_seed value, if there wasn't one already.  */
+
+void
+default_flag_random_seed (void)
+{
+  unsigned HOST_WIDE_INT value;
+  char *new_random_seed;
+  
+  if (flag_random_seed != NULL)
+    return;
+
+  /* Get some more or less random data.  */
+#ifdef HAVE_GETTIMEOFDAY
+ {
+   struct timeval tv;
+   
+   gettimeofday (&tv, NULL);
+   value = (((unsigned HOST_WIDE_INT) tv.tv_usec << 16) 
+           ^ tv.tv_sec ^ getpid ());
+ }
+#else
+  value = getpid ();
+#endif
+
+  /* This slightly overestimates the space required.  */
+  new_random_seed = xmalloc (HOST_BITS_PER_WIDE_INT / 3 + 2);
+  sprintf (new_random_seed, HOST_WIDE_INT_PRINT_UNSIGNED, value);
+  flag_random_seed = new_random_seed;
+}
+
 /* Appends 6 random characters to TEMPLATE to (hopefully) avoid name
    clashes in cases where we can't reliably choose a unique name.
 
@@ -4343,40 +4660,20 @@ append_random_chars (template)
 {
   static const char letters[]
     = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-  static unsigned HOST_WIDE_INT value;
   unsigned HOST_WIDE_INT v;
+  size_t i;
 
-  if (! value)
-    {
-      struct stat st;
-
-      /* VALUE should be unique for each file and must not change between
-        compiles since this can cause bootstrap comparison errors.  */
+  default_flag_random_seed ();
 
-      if (stat (main_input_filename, &st) < 0)
-       {
-         /* This can happen when preprocessed text is shipped between
-            machines, e.g. with bug reports.  Assume that uniqueness
-            isn't actually an issue.  */
-         value = 1;
-       }
-      else
-       {
-         /* In VMS, ino is an array, so we have to use both values.  We
-            conditionalize that.  */
-#ifdef VMS
-#define INO_TO_INT(INO) ((int) (INO)[1] << 16 ^ (int) (INO)[2])
-#else
-#define INO_TO_INT(INO) INO
-#endif
-         value = st.st_dev ^ INO_TO_INT (st.st_ino) ^ st.st_mtime;
-       }
-    }
+  /* This isn't a very good hash, but it does guarantee no collisions 
+     when the random string is generated by the code above and the time
+     delta is small.  */
+  v = 0;
+  for (i = 0; i < strlen (flag_random_seed); i++)
+    v = (v << 4) ^ (v >> (HOST_BITS_PER_WIDE_INT - 4)) ^ flag_random_seed[i];
 
   template += strlen (template);
 
-  v = value;
-
   /* Fill in the random bits.  */
   template[0] = letters[v % 62];
   v /= 62;
@@ -4609,10 +4906,42 @@ tree_class_check_failed (node, cl, file, line, function)
      tree_code_name[TREE_CODE (node)], function, trim_filename (file), line);
 }
 
+/* Similar to above, except that the check is for the bounds of a TREE_VEC's
+   (dynamically sized) vector.  */
+
+void
+tree_vec_elt_check_failed (idx, len, file, line, function)
+     int idx;
+     int len;
+     const char *file;
+     int line;
+     const char *function;
+{
+  internal_error
+    ("tree check: accessed elt %d of tree_vec with %d elts in %s, at %s:%d",
+     idx + 1, len, function, trim_filename (file), line);
+}
+
+/* Similar to above, except that the check is for the bounds of the operand
+   vector of an expression node.  */
+
+void
+tree_operand_check_failed (idx, code, file, line, function)
+     int idx;
+     enum tree_code code;
+     const char *file;
+     int line;
+     const char *function;
+{
+  internal_error
+    ("tree check: accessed operand %d of %s with %d operands in %s, at %s:%d",
+     idx + 1, tree_code_name[code], TREE_CODE_LENGTH (code),
+     function, trim_filename (file), line);
+}
 #endif /* ENABLE_TREE_CHECKING */
 \f
 /* For a new vector type node T, build the information necessary for
-   debuggint output.  */
+   debugging output.  */
 
 static void
 finish_vector_type (t)
@@ -4766,6 +5095,8 @@ build_common_tree_nodes_2 (short_double)
 
   unsigned_V4SI_type_node
     = make_vector (V4SImode, unsigned_intSI_type_node, 1);
+  unsigned_V2HI_type_node
+    = make_vector (V2HImode, unsigned_intHI_type_node, 1);
   unsigned_V2SI_type_node
     = make_vector (V2SImode, unsigned_intSI_type_node, 1);
   unsigned_V2DI_type_node
@@ -4778,10 +5109,13 @@ build_common_tree_nodes_2 (short_double)
     = make_vector (V8HImode, unsigned_intHI_type_node, 1);
   unsigned_V16QI_type_node
     = make_vector (V16QImode, unsigned_intQI_type_node, 1);
+  unsigned_V1DI_type_node
+    = make_vector (V1DImode, unsigned_intDI_type_node, 1);
 
   V16SF_type_node = make_vector (V16SFmode, float_type_node, 0);
   V4SF_type_node = make_vector (V4SFmode, float_type_node, 0);
   V4SI_type_node = make_vector (V4SImode, intSI_type_node, 0);
+  V2HI_type_node = make_vector (V2HImode, intHI_type_node, 0);
   V2SI_type_node = make_vector (V2SImode, intSI_type_node, 0);
   V2DI_type_node = make_vector (V2DImode, intDI_type_node, 0);
   V4HI_type_node = make_vector (V4HImode, intHI_type_node, 0);
@@ -4790,6 +5124,7 @@ build_common_tree_nodes_2 (short_double)
   V2SF_type_node = make_vector (V2SFmode, float_type_node, 0);
   V2DF_type_node = make_vector (V2DFmode, double_type_node, 0);
   V16QI_type_node = make_vector (V16QImode, intQI_type_node, 0);
+  V1DI_type_node = make_vector (V1DImode, intDI_type_node, 0);
 }
 
 /* Returns a vector tree node given a vector mode, the inner type, and
@@ -4837,7 +5172,7 @@ initializer_zerop (init)
       {
        if (AGGREGATE_TYPE_P (TREE_TYPE (init)))
          {
-           tree aggr_init = TREE_OPERAND (init, 1);
+           tree aggr_init = CONSTRUCTOR_ELTS (init);
 
            while (aggr_init)
              {