OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index 8f70747..e2ffc4b 100644 (file)
@@ -1,5 +1,6 @@
 /* Language-independent node constructors for parse phase of GNU compiler.
-   Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -42,11 +43,15 @@ Boston, MA 02111-1307, USA.  */
 #include "obstack.h"
 #include "toplev.h"
 #include "ggc.h"
+#include "hashtab.h"
+#include "output.h"
 
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 /* obstack.[ch] explicitly declined to prototype this. */
-extern int _obstack_allocated_p PROTO ((struct obstack *h, PTR obj));
+extern int _obstack_allocated_p PARAMS ((struct obstack *h, PTR obj));
+
+static void unsave_expr_now_r PARAMS ((tree));
 
 /* Tree nodes of permanent duration are allocated in this obstack.
    They are the identifier nodes, and everything outside of
@@ -241,43 +246,48 @@ static int next_decl_uid;
 /* Unique id for next type created.  */
 static int next_type_uid = 1;
 
-/* The language-specific function for alias analysis.  If NULL, the
-   language does not do any special alias analysis.  */
-int (*lang_get_alias_set) PROTO((tree));
-
 /* Here is how primitive or already-canonicalized types' hash
    codes are made.  */
 #define TYPE_HASH(TYPE) ((unsigned long) (TYPE) & 0777777)
 
-/* Each hash table slot is a bucket containing a chain
-   of these structures.  */
+/* Since we cannot rehash a type after it is in the table, we have to
+   keep the hash code.  */
 
 struct type_hash
 {
-  struct type_hash *next;      /* Next structure in the bucket.  */
-  int hashcode;                        /* Hash code of this type.  */
-  tree type;                   /* The type recorded here.  */
+  unsigned long hash;
+  tree type;
 };
 
-/* Now here is the hash table.  When recording a type, it is added
-   to the slot whose index is the hash code mod the table size.
-   Note that the hash table is used for several kinds of types
-   (function types, array types and array index range types, for now).
-   While all these live in the same table, they are completely independent,
-   and the hash code is computed differently for each of these.  */
-
-#define TYPE_HASH_SIZE 59
-struct type_hash *type_hash_table[TYPE_HASH_SIZE];
-
-static void set_type_quals PROTO((tree, int));
-static void append_random_chars PROTO((char *));
-static void build_real_from_int_cst_1 PROTO((PTR));
-static void mark_type_hash PROTO ((void *));
-static void fix_sizetype PROTO ((tree));
-
-/* If non-null, a language specific helper for unsave_expr_now. */
-
-void (*lang_unsave_expr_now) PROTO((tree));
+/* Initial size of the hash table (rounded to next prime). */
+#define TYPE_HASH_INITIAL_SIZE 1000
+
+/* Now here is the hash table.  When recording a type, it is added to
+   the slot whose index is the hash code.  Note that the hash table is
+   used for several kinds of types (function types, array types and
+   array index range types, for now).  While all these live in the
+   same table, they are completely independent, and the hash code is
+   computed differently for each of these.  */
+
+htab_t type_hash_table;
+
+static void build_real_from_int_cst_1 PARAMS ((PTR));
+static void set_type_quals PARAMS ((tree, int));
+static void append_random_chars PARAMS ((char *));
+static void mark_type_hash PARAMS ((void *));
+static int type_hash_eq PARAMS ((const void*, const void*));
+static unsigned int type_hash_hash PARAMS ((const void*));
+static void print_type_hash_statistics PARAMS((void));
+static int mark_hash_entry PARAMS((void **, void *));
+static void finish_vector_type PARAMS((tree));
+
+/* If non-null, these are language-specific helper functions for
+   unsave_expr_now.  If present, LANG_UNSAVE is called before its
+   argument (an UNSAVE_EXPR) is to be unsaved, and all other
+   processing in unsave_expr_now is aborted.  LANG_UNSAVE_EXPR_NOW is
+   called from unsave_expr_1 for language-specific tree codes.  */
+void (*lang_unsave) PARAMS ((tree *));
+void (*lang_unsave_expr_now) PARAMS ((tree));
 
 /* The string used as a placeholder instead of a source file name for
    built-in tree nodes.  The variable, which is dynamically allocated,
@@ -287,6 +297,7 @@ static char *built_in_filename;
 #define BUILT_IN_FILENAME ("<built-in>")
 \f
 tree global_trees[TI_MAX];
+tree integer_types[itk_none];
 \f
 /* Init the principal obstacks.  */
 
@@ -315,12 +326,14 @@ init_obstacks ()
 
   /* Init the hash table of identifiers.  */
   bzero ((char *) hash_table, sizeof hash_table);
+  ggc_add_tree_root (hash_table, sizeof hash_table / sizeof (tree));
 
-  ggc_add_tree_root (hash_table, MAX_HASH_TABLE);
-  ggc_add_root (type_hash_table, TYPE_HASH_SIZE
-               sizeof(struct type_hash *),
-               mark_type_hash);
+  /* Initialize the hash table of types.  */
+  type_hash_table = htab_create (TYPE_HASH_INITIAL_SIZE, type_hash_hash
+                                type_hash_eq, 0);
+  ggc_add_root (&type_hash_table, 1, sizeof type_hash_table, mark_type_hash);
   ggc_add_tree_root (global_trees, TI_MAX);
+  ggc_add_tree_root (integer_types, itk_none);
 }
 
 void
@@ -339,8 +352,8 @@ gcc_obstack_init (obstack)
 #define OBSTACK_CHUNK_FREE free
 #endif
   _obstack_begin (obstack, OBSTACK_CHUNK_SIZE, 0,
-                 (void *(*) PROTO ((long))) OBSTACK_CHUNK_ALLOC,
-                 (void (*) PROTO ((void *))) OBSTACK_CHUNK_FREE);
+                 (void *(*) PARAMS ((long))) OBSTACK_CHUNK_ALLOC,
+                 (void (*) PARAMS ((void *))) OBSTACK_CHUNK_FREE);
 }
 
 /* Save all variables describing the current status into the structure
@@ -568,6 +581,7 @@ permanent_allocation (function_end)
     }
   else
     obstack_free (&momentary_obstack, momentary_firstobj);
+
   obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj);
   obstack_free (&temp_decl_obstack, temp_decl_firstobj);
 
@@ -874,13 +888,15 @@ resume_momentary (yes)
 void
 init_tree_codes ()
 {
-  built_in_filename = 
-    ggc_alloc_string (BUILT_IN_FILENAME, sizeof (BUILT_IN_FILENAME));
+  built_in_filename
+    ggc_alloc_string (BUILT_IN_FILENAME, sizeof (BUILT_IN_FILENAME));
   ggc_add_string_root (&built_in_filename, 1);
 }
 
 /* Return a newly allocated node of code CODE.
    Initialize the node's unique id and its TREE_PERMANENT flag.
+   Note that if garbage collection is in use, TREE_PERMANENT will
+   always be zero - we want to eliminate use of TREE_PERMANENT.
    For decl and type nodes, some other fields are initialized.
    The rest of the node is initialized to zero.
 
@@ -977,7 +993,7 @@ make_node (code)
       if (code == BIND_EXPR && obstack != &permanent_obstack)
        obstack = saveable_obstack;
       length = sizeof (struct tree_exp)
-       + (tree_code_length[(int) code] - 1) * sizeof (char *);
+       + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *);
       break;
 
     case 'c':  /* a constant */
@@ -986,7 +1002,7 @@ make_node (code)
 #endif
       obstack = expression_obstack;
 
-      /* We can't use tree_code_length for INTEGER_CST, since the number of
+      /* 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
@@ -998,7 +1014,7 @@ make_node (code)
        length = sizeof (struct tree_real_cst);
       else
        length = sizeof (struct tree_common)
-         + tree_code_length[(int) code] * sizeof (char *);
+         + TREE_CODE_LENGTH (code) * sizeof (char *);
       break;
 
     case 'x':  /* something random, like an identifier.  */
@@ -1013,7 +1029,7 @@ make_node (code)
        kind = x_kind;
 #endif
       length = sizeof (struct tree_common)
-       + tree_code_length[(int) code] * sizeof (char *);
+       + TREE_CODE_LENGTH (code) * sizeof (char *);
       /* Identifier nodes are always permanent since they are
         unique in a compiler run.  */
       if (code == IDENTIFIER_NODE) obstack = &permanent_obstack;
@@ -1026,10 +1042,9 @@ make_node (code)
   if (ggc_p)
     t = ggc_alloc_tree (length);
   else
-    {
-      t = (tree) obstack_alloc (obstack, length);
-      memset ((PTR) t, 0, length);
-    }
+    t = (tree) obstack_alloc (obstack, length);
+
+  memset ((PTR) t, 0, length);
 
 #ifdef GATHER_STATISTICS
   tree_node_counts[(int)kind]++;
@@ -1037,8 +1052,7 @@ make_node (code)
 #endif
 
   TREE_SET_CODE (t, code);
-  if (obstack == &permanent_obstack)
-    TREE_PERMANENT (t) = 1;
+  TREE_SET_PERMANENT (t);
 
   switch (type)
     {
@@ -1050,8 +1064,8 @@ make_node (code)
     case 'd':
       if (code != FUNCTION_DECL)
        DECL_ALIGN (t) = 1;
-      DECL_IN_SYSTEM_HEADER (t)
-       = in_system_header && (obstack == &permanent_obstack);
+      DECL_USER_ALIGN (t) = 0;
+      DECL_IN_SYSTEM_HEADER (t) = in_system_header;
       DECL_SOURCE_LINE (t) = lineno;
       DECL_SOURCE_FILE (t) = 
        (input_filename) ? input_filename : built_in_filename;
@@ -1064,6 +1078,7 @@ make_node (code)
     case 't':
       TYPE_UID (t) = next_type_uid++;
       TYPE_ALIGN (t) = 1;
+      TYPE_USER_ALIGN (t) = 0;
       TYPE_MAIN_VARIANT (t) = t;
       TYPE_OBSTACK (t) = obstack;
       TYPE_ATTRIBUTES (t) = NULL_TREE;
@@ -1103,6 +1118,21 @@ make_node (code)
 
   return t;
 }
+
+/* A front-end can reset this to an appropriate function if types need
+   special handling.  */
+
+tree (*make_lang_type_fn) PARAMS ((enum tree_code)) = make_node;
+
+/* Return a new type (with the indicated CODE), doing whatever
+   language-specific processing is required.  */
+
+tree 
+make_lang_type (code)
+     enum tree_code code;
+{
+  return (*make_lang_type_fn) (code);
+}
 \f
 /* Return a new node with the same contents as NODE except that its
    TREE_CHAIN is zero and it has a fresh uid.  Unlike make_node, this
@@ -1139,11 +1169,11 @@ copy_node (node)
     case '1':  /* a unary arithmetic expression */
     case '2':  /* a binary arithmetic expression */
       length = sizeof (struct tree_exp)
-       + (tree_code_length[(int) code] - 1) * sizeof (char *);
+       + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *);
       break;
 
     case 'c':  /* a constant */
-      /* We can't use tree_code_length for INTEGER_CST, since the number of
+      /* 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
@@ -1154,12 +1184,12 @@ copy_node (node)
        length = sizeof (struct tree_real_cst);
       else
        length = (sizeof (struct tree_common)
-                 + tree_code_length[(int) code] * sizeof (char *));
+                 + TREE_CODE_LENGTH (code) * sizeof (char *));
       break;
 
     case 'x':  /* something random, like an identifier.  */
       length = sizeof (struct tree_common)
-       + tree_code_length[(int) code] * sizeof (char *);
+       + TREE_CODE_LENGTH (code) * sizeof (char *);
       if (code == TREE_VEC)
        length += (TREE_VEC_LENGTH (node) - 1) * sizeof (char *);
     }
@@ -1170,9 +1200,7 @@ copy_node (node)
     t = (tree) obstack_alloc (current_obstack, length);
   memcpy (t, node, length);
 
-  /* EXPR_WITH_FILE_LOCATION must keep filename info stored in TREE_CHAIN */
-  if (TREE_CODE (node) != EXPR_WITH_FILE_LOCATION)
-    TREE_CHAIN (t) = 0;
+  TREE_CHAIN (t) = 0;
   TREE_ASM_WRITTEN (t) = 0;
 
   if (TREE_CODE_CLASS (code) == 'd')
@@ -1191,7 +1219,7 @@ copy_node (node)
       TYPE_SYMTAB_ADDRESS (t) = 0;
     }
 
-  TREE_PERMANENT (t) = (current_obstack == &permanent_obstack);
+  TREE_SET_PERMANENT (t);
 
   return t;
 }
@@ -1240,7 +1268,7 @@ get_identifier (text)
 
   /* Decide how much of that length to hash on */
   hash_len = len;
-  if (warn_id_clash && (unsigned)len > id_clash_len)
+  if (warn_id_clash && len > id_clash_len)
     hash_len = id_clash_len;
 
   /* Compute hash code */
@@ -1259,7 +1287,7 @@ get_identifier (text)
       return idp;              /* <-- return if found */
 
   /* Not found; optionally warn about a similar identifier */
-  if (warn_id_clash && do_identifier_warnings && (unsigned)len >= id_clash_len)
+  if (warn_id_clash && do_identifier_warnings && len >= id_clash_len)
     for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
       if (!strncmp (IDENTIFIER_POINTER (idp), text, id_clash_len))
        {
@@ -1268,7 +1296,7 @@ get_identifier (text)
          break;
        }
 
-  if (tree_code_length[(int) IDENTIFIER_NODE] < 0)
+  if (TREE_CODE_LENGTH (IDENTIFIER_NODE) < 0)
     abort ();                  /* set_identifier_size hasn't been called.  */
 
   /* Not found, create one, add to chain */
@@ -1306,7 +1334,7 @@ maybe_get_identifier (text)
 
   /* Decide how much of that length to hash on */
   hash_len = len;
-  if (warn_id_clash && (unsigned)len > id_clash_len)
+  if (warn_id_clash && len > id_clash_len)
     hash_len = id_clash_len;
 
   /* Compute hash code */
@@ -1357,9 +1385,11 @@ set_identifier_size (size)
 
 tree
 build_int_2_wide (low, hi)
-     HOST_WIDE_INT low, hi;
+     unsigned HOST_WIDE_INT low;
+     HOST_WIDE_INT hi;
 {
   register tree t = make_node (INTEGER_CST);
+
   TREE_INT_CST_LOW (t) = low;
   TREE_INT_CST_HIGH (t) = hi;
   TREE_TYPE (t) = integer_type_node;
@@ -1396,11 +1426,15 @@ build_real (type, d)
 
 REAL_VALUE_TYPE
 real_value_from_int_cst (type, i)
-     tree type, i;
+     tree type ATTRIBUTE_UNUSED, i;
 {
   REAL_VALUE_TYPE d;
 
 #ifdef REAL_ARITHMETIC
+  /* Clear all bits of the real value type so that we can later do
+     bitwise comparisons to see if two values are the same.  */
+  bzero ((char *) &d, sizeof d);
+
   if (! TREE_UNSIGNED (TREE_TYPE (i)))
     REAL_VALUE_FROM_INT (d, TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i),
                         TYPE_MODE (type));
@@ -1418,7 +1452,7 @@ real_value_from_int_cst (type, i)
       e = ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))
            * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)));
       d *= e;
-      e = (double) (unsigned HOST_WIDE_INT) (~ TREE_INT_CST_LOW (i));
+      e = (double) (~ TREE_INT_CST_LOW (i));
       d += e;
       d = (- d - 1.0);
     }
@@ -1430,38 +1464,44 @@ real_value_from_int_cst (type, i)
       e = ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))
            * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)));
       d *= e;
-      e = (double) (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (i);
+      e = (double) TREE_INT_CST_LOW (i);
       d += e;
     }
 #endif /* not REAL_ARITHMETIC */
   return d;
 }
 
+/* Args to pass to and from build_real_from_int_cst_1.  */
+
 struct brfic_args
 {
-  /* Input */
-  tree type, i;
-  /* Output */
-  REAL_VALUE_TYPE d;
+  tree type;                   /* Input: type to conver to. */
+  tree i;                      /* Input: operand to convert */
+  REAL_VALUE_TYPE d;           /* Output: floating point value. */
 };
 
+/* Convert an integer to a floating point value while protected by a floating
+   point exception handler.  */
+
 static void
 build_real_from_int_cst_1 (data)
   PTR data;
 {
-  struct brfic_args * args = (struct brfic_args *) data;
+  struct brfic_args *args = (struct brfic_args *) data;
   
 #ifdef REAL_ARITHMETIC
   args->d = real_value_from_int_cst (args->type, args->i);
 #else
-  args->d =
-    REAL_VALUE_TRUNCATE (TYPE_MODE (args->type),
-                        real_value_from_int_cst (args->type, args->i));
+  args->d
+    REAL_VALUE_TRUNCATE (TYPE_MODE (args->type),
+                          real_value_from_int_cst (args->type, args->i));
 #endif
 }
 
-/* This function can't be implemented if we can't do arithmetic
-   on the float representation.  */
+/* Given a tree representing an integer constant I, return a tree
+   representing the same value as a floating-point constant of type TYPE.
+   We cannot perform this operation if there is no way of doing arithmetic
+   on floating-point values.  */
 
 tree
 build_real_from_int_cst (type, i)
@@ -1481,10 +1521,8 @@ build_real_from_int_cst (type, i)
   args.i = i;
 
   if (do_float_handler (build_real_from_int_cst_1, (PTR) &args))
-    {
-      /* Receive output from build_real_from_int_cst_1() */
-      d = args.d;
-    }
+    /* Receive output from build_real_from_int_cst_1() */
+    d = args.d;
   else
     {
       /* We got an exception from build_real_from_int_cst_1() */
@@ -1519,11 +1557,13 @@ build_string (len, str)
      deferring constant output in varasm.c.  */
 
   register tree s = make_node (STRING_CST);
+
   TREE_STRING_LENGTH (s) = len;
   if (ggc_p)
     TREE_STRING_POINTER (s) = ggc_alloc_string (str, len);
   else
     TREE_STRING_POINTER (s) = obstack_copy0 (saveable_obstack, str, len);
+
   return s;
 }
 
@@ -1566,15 +1606,12 @@ make_tree_vec (len)
   if (ggc_p)
     t = ggc_alloc_tree (length);
   else
-    {
-      t = (tree) obstack_alloc (obstack, length);
-      bzero ((PTR) t, length);
-    }
+    t = (tree) obstack_alloc (obstack, length);
 
+  memset ((PTR) t, 0, length);
   TREE_SET_CODE (t, TREE_VEC);
   TREE_VEC_LENGTH (t) = len;
-  if (obstack == &permanent_obstack)
-    TREE_PERMANENT (t) = 1;
+  TREE_SET_PERMANENT (t);
 
   return t;
 }
@@ -1638,14 +1675,16 @@ integer_all_onesp (expr)
 
   uns = TREE_UNSIGNED (TREE_TYPE (expr));
   if (!uns)
-    return TREE_INT_CST_LOW (expr) == -1 && TREE_INT_CST_HIGH (expr) == -1;
+    return (TREE_INT_CST_LOW (expr) == ~ (unsigned HOST_WIDE_INT) 0
+           && TREE_INT_CST_HIGH (expr) == -1);
 
   /* Note that using TYPE_PRECISION here is wrong.  We care about the
      actual bits, not the (arbitrary) range of the type.  */
   prec = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (expr)));
   if (prec >= HOST_BITS_PER_WIDE_INT)
     {
-      int high_value, shift_amount;
+      HOST_WIDE_INT high_value;
+      int shift_amount;
 
       shift_amount = prec - HOST_BITS_PER_WIDE_INT;
 
@@ -1659,11 +1698,11 @@ integer_all_onesp (expr)
       else
        high_value = ((HOST_WIDE_INT) 1 << shift_amount) - 1;
 
-      return TREE_INT_CST_LOW (expr) == -1
-       && TREE_INT_CST_HIGH (expr) == high_value;
+      return (TREE_INT_CST_LOW (expr) == ~ (unsigned HOST_WIDE_INT) 0
+             && TREE_INT_CST_HIGH (expr) == high_value);
     }
   else
-    return TREE_INT_CST_LOW (expr) == ((HOST_WIDE_INT) 1 << prec) - 1;
+    return TREE_INT_CST_LOW (expr) == ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
 }
 
 /* Return 1 if EXPR is an integer constant that is a power of 2 (i.e., has only
@@ -1751,6 +1790,46 @@ tree_log2 (expr)
          :  exact_log2 (low));
 }
 
+/* Similar, but return the largest integer Y such that 2 ** Y is less
+   than or equal to EXPR.  */
+
+int
+tree_floor_log2 (expr)
+     tree expr;
+{
+  int prec;
+  HOST_WIDE_INT high, low;
+
+  STRIP_NOPS (expr);
+
+  if (TREE_CODE (expr) == COMPLEX_CST)
+    return tree_log2 (TREE_REALPART (expr));
+
+  prec = (POINTER_TYPE_P (TREE_TYPE (expr))
+         ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
+
+  high = TREE_INT_CST_HIGH (expr);
+  low = TREE_INT_CST_LOW (expr);
+
+  /* First clear all bits that are beyond the type's precision in case
+     we've been sign extended.  Ignore if type's precision hasn't been set
+     since what we are doing is setting it.  */
+
+  if (prec == 2 * HOST_BITS_PER_WIDE_INT || prec == 0)
+    ;
+  else if (prec > HOST_BITS_PER_WIDE_INT)
+    high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+  else
+    {
+      high = 0;
+      if (prec < HOST_BITS_PER_WIDE_INT)
+       low &= ~((HOST_WIDE_INT) (-1) << prec);
+    }
+
+  return (high != 0 ? HOST_BITS_PER_WIDE_INT + floor_log2 (high)
+         : floor_log2 (low));
+}
+
 /* Return 1 if EXPR is the real constant zero.  */
 
 int
@@ -1878,10 +1957,8 @@ chain_member (elem, chain)
 }
 
 /* Return nonzero if ELEM is equal to TREE_VALUE (CHAIN) for any piece of
-   chain CHAIN.  */
-/* ??? This function was added for machine specific attributes but is no
-   longer used.  It could be deleted if we could confirm all front ends
-   don't use it.  */
+   chain CHAIN.  This and the next function are currently unused, but
+   are retained for completeness.  */
 
 int
 chain_member_value (elem, chain)
@@ -1899,9 +1976,6 @@ chain_member_value (elem, chain)
 
 /* Return nonzero if ELEM is equal to TREE_PURPOSE (CHAIN)
    for any piece of chain CHAIN.  */
-/* ??? This function was added for machine specific attributes but is no
-   longer used.  It could be deleted if we could confirm all front ends
-   don't use it.  */
 
 int
 chain_member_purpose (elem, chain)
@@ -1934,6 +2008,22 @@ list_length (t)
   return len;
 }
 
+/* Returns the number of FIELD_DECLs in TYPE.  */
+
+int
+fields_length (type)
+     tree type;
+{
+  tree t = TYPE_FIELDS (type);
+  int count = 0;
+
+  for (; t; t = TREE_CHAIN (t))
+    if (TREE_CODE (t) == FIELD_DECL)
+      ++count;
+
+  return count;
+}
+
 /* Concatenate two chains of nodes (chained through TREE_CHAIN)
    by modifying the last node in chain 1 to point to chain 2.
    This is the Lisp primitive `nconc'.  */
@@ -1946,14 +2036,14 @@ chainon (op1, op2)
   if (op1)
     {
       register tree t1;
-#ifdef ENABLE_CHECKING
+#ifdef ENABLE_TREE_CHECKING
       register tree t2;
 #endif
 
       for (t1 = op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1))
        ;
       TREE_CHAIN (t1) = op2;
-#ifdef ENABLE_CHECKING
+#ifdef ENABLE_TREE_CHECKING
       for (t2 = op2; t2; t2 = TREE_CHAIN (t2))
         if (t2 == t1)
           abort ();  /* Circularity created.  */
@@ -2039,6 +2129,7 @@ build_decl_list (parm, value)
 {
   register tree node;
   register struct obstack *ambient_obstack = current_obstack;
+
   current_obstack = &temp_decl_obstack;
   node = build_tree_list (parm, value);
   current_obstack = ambient_obstack;
@@ -2053,6 +2144,7 @@ build_expr_list (parm, value)
 {
   register tree node;
   register struct obstack *ambient_obstack = current_obstack;
+
   current_obstack = expression_obstack;
   node = build_tree_list (parm, value);
   current_obstack = ambient_obstack;
@@ -2067,29 +2159,22 @@ tree
 tree_cons (purpose, value, chain)
      tree purpose, value, chain;
 {
-#if 0
-  register tree node = make_node (TREE_LIST);
-#else
   register tree node;
 
   if (ggc_p)
     node = ggc_alloc_tree (sizeof (struct tree_list));
   else
-    {
-      node = (tree) obstack_alloc (current_obstack, sizeof (struct tree_list));
-      memset (node, 0, sizeof (struct tree_common));
-    }
+    node = (tree) obstack_alloc (current_obstack, sizeof (struct tree_list));
+
+  memset (node, 0, sizeof (struct tree_common));
 
 #ifdef GATHER_STATISTICS
-  tree_node_counts[(int)x_kind]++;
-  tree_node_sizes[(int)x_kind] += sizeof (struct tree_list);
+  tree_node_counts[(int) x_kind]++;
+  tree_node_sizes[(int) x_kind] += sizeof (struct tree_list);
 #endif
 
-
   TREE_SET_CODE (node, TREE_LIST);
-  if (current_obstack == &permanent_obstack)
-    TREE_PERMANENT (node) = 1;
-#endif
+  TREE_SET_PERMANENT (node);
 
   TREE_CHAIN (node) = chain;
   TREE_PURPOSE (node) = purpose;
@@ -2105,6 +2190,7 @@ decl_tree_cons (purpose, value, chain)
 {
   register tree node;
   register struct obstack *ambient_obstack = current_obstack;
+
   current_obstack = &temp_decl_obstack;
   node = tree_cons (purpose, value, chain);
   current_obstack = ambient_obstack;
@@ -2119,6 +2205,7 @@ expr_tree_cons (purpose, value, chain)
 {
   register tree node;
   register struct obstack *ambient_obstack = current_obstack;
+
   current_obstack = expression_obstack;
   node = tree_cons (purpose, value, chain);
   current_obstack = ambient_obstack;
@@ -2133,8 +2220,8 @@ perm_tree_cons (purpose, value, chain)
 {
   register tree node;
   register struct obstack *ambient_obstack = current_obstack;
-  current_obstack = &permanent_obstack;
 
+  current_obstack = &permanent_obstack;
   node = tree_cons (purpose, value, chain);
   current_obstack = ambient_obstack;
   return node;
@@ -2148,8 +2235,8 @@ temp_tree_cons (purpose, value, chain)
 {
   register tree node;
   register struct obstack *ambient_obstack = current_obstack;
-  current_obstack = &temporary_obstack;
 
+  current_obstack = &temporary_obstack;
   node = tree_cons (purpose, value, chain);
   current_obstack = ambient_obstack;
   return node;
@@ -2163,8 +2250,8 @@ saveable_tree_cons (purpose, value, chain)
 {
   register tree node;
   register struct obstack *ambient_obstack = current_obstack;
-  current_obstack = saveable_obstack;
 
+  current_obstack = saveable_obstack;
   node = tree_cons (purpose, value, chain);
   current_obstack = ambient_obstack;
   return node;
@@ -2187,11 +2274,13 @@ size_in_bytes (type)
 
   type = TYPE_MAIN_VARIANT (type);
   t = TYPE_SIZE_UNIT (type);
+
   if (t == 0)
     {
       incomplete_type_error (NULL_TREE, type);
-      return integer_zero_node;
+      return size_zero_node;
     }
+
   if (TREE_CODE (t) == INTEGER_CST)
     force_fit_type (t, 0);
 
@@ -2214,17 +2303,109 @@ int_size_in_bytes (type)
   t = TYPE_SIZE_UNIT (type);
   if (t == 0
       || TREE_CODE (t) != INTEGER_CST
-      || TREE_INT_CST_HIGH (t) != 0)
+      || TREE_OVERFLOW (t)
+      || TREE_INT_CST_HIGH (t) != 0
+      /* If the result would appear negative, it's too big to represent.  */
+      || (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0)
     return -1;
 
   return TREE_INT_CST_LOW (t);
 }
 \f
-/* Return, as a tree node, the number of elements for TYPE (which is an
-   ARRAY_TYPE) minus one. This counts only elements of the top array.
+/* Return the bit position of FIELD, in bits from the start of the record.
+   This is a tree of type bitsizetype.  */
+
+tree
+bit_position (field)
+     tree field;
+{
+
+  return bit_from_pos (DECL_FIELD_OFFSET (field),
+                      DECL_FIELD_BIT_OFFSET (field));
+}
+
+/* Likewise, but return as an integer.  Abort if it cannot be represented
+   in that way (since it could be a signed value, we don't have the option
+   of returning -1 like int_size_in_byte can.  */
 
-   Don't let any SAVE_EXPRs escape; if we are called as part of a cleanup
-   action, they would get unsaved.  */
+HOST_WIDE_INT
+int_bit_position (field)
+     tree field;
+{
+  return tree_low_cst (bit_position (field), 0);
+}
+\f
+/* Return the byte position of FIELD, in bytes from the start of the record.
+   This is a tree of type sizetype.  */
+
+tree
+byte_position (field)
+     tree field;
+{
+  return byte_from_pos (DECL_FIELD_OFFSET (field),
+                       DECL_FIELD_BIT_OFFSET (field));
+}
+
+/* Likewise, but return as an integer.  Abort if it cannot be represented
+   in that way (since it could be a signed value, we don't have the option
+   of returning -1 like int_size_in_byte can.  */
+
+HOST_WIDE_INT
+int_byte_position (field)
+     tree field;
+{
+  return tree_low_cst (byte_position (field), 0);
+}
+\f
+/* Return the strictest alignment, in bits, that T is known to have.  */
+
+unsigned int
+expr_align (t)
+     tree t;
+{
+  unsigned int align0, align1;
+
+  switch (TREE_CODE (t))
+    {
+    case NOP_EXPR:  case CONVERT_EXPR:  case NON_LVALUE_EXPR:
+      /* If we have conversions, we know that the alignment of the
+        object must meet each of the alignments of the types.  */
+      align0 = expr_align (TREE_OPERAND (t, 0));
+      align1 = TYPE_ALIGN (TREE_TYPE (t));
+      return MAX (align0, align1);
+
+    case SAVE_EXPR:         case COMPOUND_EXPR:       case MODIFY_EXPR:
+    case INIT_EXPR:         case TARGET_EXPR:         case WITH_CLEANUP_EXPR:
+    case WITH_RECORD_EXPR:  case CLEANUP_POINT_EXPR:  case UNSAVE_EXPR:
+      /* These don't change the alignment of an object.  */
+      return expr_align (TREE_OPERAND (t, 0));
+
+    case COND_EXPR:
+      /* The best we can do is say that the alignment is the least aligned
+        of the two arms.  */
+      align0 = expr_align (TREE_OPERAND (t, 1));
+      align1 = expr_align (TREE_OPERAND (t, 2));
+      return MIN (align0, align1);
+
+    case LABEL_DECL:     case CONST_DECL:
+    case VAR_DECL:       case PARM_DECL:   case RESULT_DECL:
+      if (DECL_ALIGN (t) != 0)
+       return DECL_ALIGN (t);
+      break;
+
+    case FUNCTION_DECL:
+      return FUNCTION_BOUNDARY;
+
+    default:
+      break;
+    }
+
+  /* Otherwise take the alignment from that of the type.  */
+  return TYPE_ALIGN (TREE_TYPE (t));
+}
+\f
+/* Return, as a tree node, the number of elements for TYPE (which is an
+   ARRAY_TYPE) minus one. This counts only elements of the top array.  */
 
 tree
 array_type_nelts (type)
@@ -2241,26 +2422,6 @@ array_type_nelts (type)
   min = TYPE_MIN_VALUE (index_type);
   max = TYPE_MAX_VALUE (index_type);
 
-  if (! TREE_CONSTANT (min))
-    {
-      STRIP_NOPS (min);
-      if (TREE_CODE (min) == SAVE_EXPR && SAVE_EXPR_RTL (min))
-       min = build (RTL_EXPR, TREE_TYPE (TYPE_MIN_VALUE (index_type)), 0,
-                    SAVE_EXPR_RTL (min));
-      else
-       min = TYPE_MIN_VALUE (index_type);
-    }
-
-  if (! TREE_CONSTANT (max))
-    {
-      STRIP_NOPS (max);
-      if (TREE_CODE (max) == SAVE_EXPR && SAVE_EXPR_RTL (max))
-       max = build (RTL_EXPR, TREE_TYPE (TYPE_MAX_VALUE (index_type)), 0,
-                    SAVE_EXPR_RTL (max));
-      else
-       max = TYPE_MAX_VALUE (index_type);
-    }
-
   return (integer_zerop (min)
          ? max
          : fold (build (MINUS_EXPR, TREE_TYPE (max), max, min)));
@@ -2278,16 +2439,17 @@ staticp (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);
+      return (decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg))
+       && ! DECL_NON_ADDR_CONST_P (arg);
 
     case VAR_DECL:
       return (TREE_STATIC (arg) || DECL_EXTERNAL (arg))
-             && ! DECL_NON_ADDR_CONST_P (arg);
+       && ! DECL_NON_ADDR_CONST_P (arg);
 
     case CONSTRUCTOR:
       return TREE_STATIC (arg);
 
+    case LABEL_DECL:
     case STRING_CST:
       return 1;
 
@@ -2423,37 +2585,32 @@ first_rtl_op (code)
     case METHOD_CALL_EXPR:
       return 3;
     default:
-      return tree_code_length [(int) code];
+      return TREE_CODE_LENGTH (code);
     }
 }
 
-/* Modify a tree in place so that all the evaluate only once things
-   are cleared out.  Return the EXPR given.  
-
-   LANG_UNSAVE_EXPR_NOW, if set, is a pointer to a function to handle
-   language specific nodes.
-*/
+/* Perform any modifications to EXPR required when it is unsaved.  Does
+   not recurse into EXPR's subtrees.  */
 
-tree
-unsave_expr_now (expr)
+void
+unsave_expr_1 (expr)
      tree expr;
 {
-  enum tree_code code;
-  register int i;
-  int first_rtl;
-
-  if (expr == NULL_TREE)
-    return expr;
-
-  code = TREE_CODE (expr);
-  first_rtl = first_rtl_op (code);
-  switch (code)
+  switch (TREE_CODE (expr))
     {
     case SAVE_EXPR:
-      SAVE_EXPR_RTL (expr) = 0;
+      if (! SAVE_EXPR_PERSISTENT_P (expr))
+       SAVE_EXPR_RTL (expr) = 0;
       break;
 
     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;
@@ -2466,21 +2623,137 @@ unsave_expr_now (expr)
 
     case CALL_EXPR:
       CALL_EXPR_RTL (expr) = 0;
-      if (TREE_OPERAND (expr, 1)
-         && TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST)
+      break;
+
+    default:
+      if (lang_unsave_expr_now != 0)
+       (*lang_unsave_expr_now) (expr);
+      break;
+    }
+}
+
+/* Helper function for unsave_expr_now.  */
+
+static void
+unsave_expr_now_r (expr)
+     tree expr;
+{
+  enum tree_code code;
+
+  /* There's nothing to do for NULL_TREE.  */
+  if (expr == 0)
+    return;
+
+  unsave_expr_1 (expr);
+
+  code = TREE_CODE (expr);
+  switch (TREE_CODE_CLASS (code))
+    {
+    case 'c':  /* a constant */
+    case 't':  /* a type node */
+    case 'd':  /* A decl node */
+    case 'b':  /* A block node */
+      break;
+
+    case 'x':  /* miscellaneous: e.g., identifier, TREE_LIST or ERROR_MARK.  */
+      if (code == TREE_LIST)
        {
-         tree exp = TREE_OPERAND (expr, 1);
-         while (exp)
-           {
-             unsave_expr_now (TREE_VALUE (exp));
-             exp = TREE_CHAIN (exp);
-           }
+         unsave_expr_now_r (TREE_VALUE (expr));
+         unsave_expr_now_r (TREE_CHAIN (expr));
        }
       break;
 
+    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 */
+      {
+       int i;
+       
+       for (i = first_rtl_op (code) - 1; i >= 0; i--)
+         unsave_expr_now_r (TREE_OPERAND (expr, i));
+      }
+      break;
+
     default:
-      if (lang_unsave_expr_now)
-       (*lang_unsave_expr_now) (expr);
+      abort ();
+    }
+}
+
+/* Modify a tree in place so that all the evaluate only once things
+   are cleared out.  Return the EXPR given.  */
+
+tree
+unsave_expr_now (expr)
+     tree expr;
+{
+  if (lang_unsave!= 0)
+    (*lang_unsave) (&expr);
+  else
+    unsave_expr_now_r (expr);
+
+  return expr;
+}
+
+/* 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.
+
+   RTL_EXPRs consume their rtl during evaluation.  It is therefore 
+   never possible to unsave them.  */
+
+int
+unsafe_for_reeval (expr)
+     tree expr;
+{
+  int unsafeness = 0;
+  enum tree_code code;
+  int i, tmp;
+  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:
+    case RTL_EXPR:
+      return 2;
+
+    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:
+      tmp = unsafe_for_reeval (TREE_OPERAND (expr, 1));
+      return MAX (tmp, 1);
+
+    case TARGET_EXPR:
+      unsafeness = 1;
+      break;
+
+    default:
+      /* ??? Add a lang hook if it becomes necessary.  */
       break;
     }
 
@@ -2491,7 +2764,7 @@ unsave_expr_now (expr)
     case 'x':  /* something random, like an identifier or an ERROR_MARK.  */
     case 'd':  /* A decl node */
     case 'b':  /* A block node */
-      return expr;
+      return 0;
 
     case 'e':  /* an expression */
     case 'r':  /* a reference */
@@ -2500,11 +2773,15 @@ unsave_expr_now (expr)
     case '2':  /* a binary arithmetic expression */
     case '1':  /* a unary arithmetic expression */
       for (i = first_rtl - 1; i >= 0; i--)
-       unsave_expr_now (TREE_OPERAND (expr, i));
-      return expr;
+       {
+         tmp = unsafe_for_reeval (TREE_OPERAND (expr, i));
+         unsafeness = MAX (tmp, unsafeness);
+       }
+
+      return unsafeness;
 
     default:
-      abort ();
+      return 2;
     }
 }
 \f
@@ -2580,7 +2857,7 @@ contains_placeholder_p (exp)
          break;
        }
 
-      switch (tree_code_length[(int) code])
+      switch (TREE_CODE_LENGTH (code))
        {
        case 1:
          return contains_placeholder_p (TREE_OPERAND (exp, 0));
@@ -2699,7 +2976,7 @@ substitute_in_expr (exp, f, r)
     case '2':
     case '<':
     case 'e':
-      switch (tree_code_length[(int) code])
+      switch (TREE_CODE_LENGTH (code))
        {
        case 1:
          op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
@@ -2905,7 +3182,6 @@ stabilize_reference (ref)
   TREE_READONLY (result) = TREE_READONLY (ref);
   TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
   TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
-  TREE_RAISES (result) = TREE_RAISES (ref);
 
   return result;
 }
@@ -2988,7 +3264,6 @@ stabilize_reference_1 (e)
   TREE_READONLY (result) = TREE_READONLY (e);
   TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e);
   TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);
-  TREE_RAISES (result) = TREE_RAISES (e);
 
   return result;
 }
@@ -3001,7 +3276,7 @@ stabilize_reference_1 (e)
    Constants, decls, types and misc nodes cannot be.  */
 
 tree
-build VPROTO((enum tree_code code, tree tt, ...))
+build VPARAMS ((enum tree_code code, tree tt, ...))
 {
 #ifndef ANSI_PROTOTYPES
   enum tree_code code;
@@ -3021,7 +3296,7 @@ build VPROTO((enum tree_code code, tree tt, ...))
 #endif
 
   t = make_node (code);
-  length = tree_code_length[(int) code];
+  length = TREE_CODE_LENGTH (code);
   TREE_TYPE (t) = tt;
 
   /* Below, we automatically set TREE_SIDE_EFFECTS and TREE_RAISED for
@@ -3041,15 +3316,11 @@ build VPROTO((enum tree_code code, tree tt, ...))
        {
          if (TREE_SIDE_EFFECTS (arg0))
            TREE_SIDE_EFFECTS (t) = 1;
-         if (TREE_RAISES (arg0))
-           TREE_RAISES (t) = 1;
        }
       if (arg1 && fro > 1)
        {
          if (TREE_SIDE_EFFECTS (arg1))
            TREE_SIDE_EFFECTS (t) = 1;
-         if (TREE_RAISES (arg1))
-           TREE_RAISES (t) = 1;
        }
     }
   else if (length == 1)
@@ -3064,7 +3335,6 @@ build VPROTO((enum tree_code code, tree tt, ...))
        {
          if (arg0 && TREE_SIDE_EFFECTS (arg0))
            TREE_SIDE_EFFECTS (t) = 1;
-         TREE_RAISES (t) = (arg0 && TREE_RAISES (arg0));
        }
     }
   else
@@ -3077,8 +3347,6 @@ build VPROTO((enum tree_code code, tree tt, ...))
            {
              if (TREE_SIDE_EFFECTS (operand))
                TREE_SIDE_EFFECTS (t) = 1;
-             if (TREE_RAISES (operand))
-               TREE_RAISES (t) = 1;
            }
        }
     }
@@ -3115,30 +3383,23 @@ build1 (code, type, node)
   if (ggc_p)
     t = ggc_alloc_tree (length);
   else
-    {
-      t = (tree) obstack_alloc (obstack, length);
-      memset ((PTR) t, 0, length);
-    }
+    t = (tree) obstack_alloc (obstack, 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_TYPE (t) = type;
   TREE_SET_CODE (t, code);
+  TREE_SET_PERMANENT (t);
 
-  if (obstack == &permanent_obstack)
-    TREE_PERMANENT (t) = 1;
-
+  TREE_TYPE (t) = type;
+  TREE_COMPLEXITY (t) = 0;
   TREE_OPERAND (t, 0) = node;
-  if (node && first_rtl_op (code) != 0)
-    {
-      if (TREE_SIDE_EFFECTS (node))
-       TREE_SIDE_EFFECTS (t) = 1;
-      if (TREE_RAISES (node))
-       TREE_RAISES (t) = 1;
-    }
+  if (node && first_rtl_op (code) != 0 && TREE_SIDE_EFFECTS (node))
+    TREE_SIDE_EFFECTS (t) = 1;
 
   switch (code)
     {
@@ -3168,7 +3429,7 @@ build1 (code, type, node)
    or even garbage if their values do not matter.  */
 
 tree
-build_nt VPROTO((enum tree_code code, ...))
+build_nt VPARAMS ((enum tree_code code, ...))
 {
 #ifndef ANSI_PROTOTYPES
   enum tree_code code;
@@ -3185,7 +3446,7 @@ build_nt VPROTO((enum tree_code code, ...))
 #endif
 
   t = make_node (code);
-  length = tree_code_length[(int) code];
+  length = TREE_CODE_LENGTH (code);
 
   for (i = 0; i < length; i++)
     TREE_OPERAND (t, i) = va_arg (p, tree);
@@ -3198,7 +3459,7 @@ build_nt VPROTO((enum tree_code code, ...))
    on the temp_decl_obstack, regardless.  */
 
 tree
-build_parse_node VPROTO((enum tree_code code, ...))
+build_parse_node VPARAMS ((enum tree_code code, ...))
 {
 #ifndef ANSI_PROTOTYPES
   enum tree_code code;
@@ -3218,7 +3479,7 @@ build_parse_node VPROTO((enum tree_code code, ...))
   expression_obstack = &temp_decl_obstack;
 
   t = make_node (code);
-  length = tree_code_length[(int) code];
+  length = TREE_CODE_LENGTH (code);
 
   for (i = 0; i < length; i++)
     TREE_OPERAND (t, i) = va_arg (p, tree);
@@ -3280,11 +3541,11 @@ build_decl (code, name, type)
 
 tree
 build_block (vars, tags, subblocks, supercontext, chain)
-     tree vars, tags, subblocks, supercontext, chain;
+     tree vars, tags ATTRIBUTE_UNUSED, subblocks, supercontext, chain;
 {
   register tree block = make_node (BLOCK);
+
   BLOCK_VARS (block) = vars;
-  BLOCK_TYPE_TAGS (block) = tags;
   BLOCK_SUBBLOCKS (block) = subblocks;
   BLOCK_SUPERCONTEXT (block) = supercontext;
   BLOCK_CHAIN (block) = chain;
@@ -3303,7 +3564,7 @@ build_expr_wfl (node, file, line, col)
      int line, col;
 {
   static const char *last_file = 0;
-  static tree  last_filenode = NULL_TREE;
+  static tree last_filenode = NULL_TREE;
   register tree wfl = make_node (EXPR_WITH_FILE_LOCATION);
 
   EXPR_WFL_NODE (wfl) = node;
@@ -3313,12 +3574,14 @@ build_expr_wfl (node, file, line, col)
       last_file = file;
       last_filenode = file ? get_identifier (file) : NULL_TREE;
     }
+
   EXPR_WFL_FILENAME_NODE (wfl) = last_filenode;
   if (node)
     {
       TREE_SIDE_EFFECTS (wfl) = TREE_SIDE_EFFECTS (node);
       TREE_TYPE (wfl) = TREE_TYPE (node);
     }
+
   return wfl;
 }
 \f
@@ -3344,13 +3607,10 @@ build_type_attribute_variant (ttype, attribute)
 {
   if ( ! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute))
     {
-      register int hashcode;
-      register struct obstack *ambient_obstack = current_obstack;
+      unsigned int hashcode;
       tree ntype;
 
-      if (ambient_obstack != &permanent_obstack)
-        current_obstack = TYPE_OBSTACK (ttype);
-
+      push_obstacks (TYPE_OBSTACK (ttype), TYPE_OBSTACK (ttype));
       ntype = copy_node (ttype);
 
       TYPE_POINTER_TO (ntype) = 0;
@@ -3362,9 +3622,9 @@ build_type_attribute_variant (ttype, attribute)
       TYPE_NEXT_VARIANT (ntype) = 0;
       set_type_quals (ntype, TYPE_UNQUALIFIED);
 
-      hashcode = TYPE_HASH (TREE_CODE (ntype))
-                + TYPE_HASH (TREE_TYPE (ntype))
-                + attribute_hash_list (attribute);
+      hashcode = (TYPE_HASH (TREE_CODE (ntype))
+                 + TYPE_HASH (TREE_TYPE (ntype))
+                 + attribute_hash_list (attribute));
 
       switch (TREE_CODE (ntype))
         {
@@ -3386,12 +3646,7 @@ build_type_attribute_variant (ttype, attribute)
 
       ntype = type_hash_canon (hashcode, ntype);
       ttype = build_qualified_type (ntype, TYPE_QUALS (ttype));
-
-      /* We must restore the current obstack after the type_hash_canon call,
-        because type_hash_canon calls type_hash_add for permanent types, and
-        then type_hash_add calls oballoc expecting to get something permanent
-        back.  */
-      current_obstack = ambient_obstack;
+      pop_obstacks ();
     }
 
   return ttype;
@@ -3421,7 +3676,8 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
 
 #ifdef VALID_MACHINE_DECL_ATTRIBUTE
   if (decl != 0
-      && VALID_MACHINE_DECL_ATTRIBUTE (decl, decl_attr_list, attr_name, attr_args))
+      && VALID_MACHINE_DECL_ATTRIBUTE (decl, decl_attr_list, attr_name,
+                                      attr_args))
     {
       tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
                                    decl_attr_list);
@@ -3470,8 +3726,10 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
          else
            TYPE_ATTRIBUTES (type) = type_attr_list;
        }
+
       if (decl != 0)
        TREE_TYPE (decl) = type;
+
       validated = 1;
     }
 
@@ -3594,12 +3852,12 @@ merge_attributes (a1, a2)
 
   /* Either one unset?  Take the set one.  */
 
-  if (! (attributes = a1))
+  if ((attributes = a1) == 0)
     attributes = a2;
 
   /* One that completely contains the other?  Take it.  */
 
-  else if (a2 && ! attribute_list_contained (a1, a2))
+  else if (a2 != 0 && ! attribute_list_contained (a1, a2))
   {
     if (attribute_list_contained (a2, a1))
       attributes = a2;
@@ -3611,7 +3869,7 @@ merge_attributes (a1, a2)
        if (list_length (a1) < list_length (a2))
          attributes = a2, a2 = a1;
 
-       for (; a2; a2 = TREE_CHAIN (a2))
+       for (; a2 != 0; a2 = TREE_CHAIN (a2))
          if (lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
                                attributes) == NULL_TREE)
            {
@@ -3726,54 +3984,83 @@ build_type_copy (type)
    with types in the TREE_VALUE slots), by adding the hash codes
    of the individual types.  */
 
-int
+unsigned int
 type_hash_list (list)
      tree list;
 {
-  register int hashcode;
+  unsigned int hashcode;
   register tree tail;
+
   for (hashcode = 0, tail = list; tail; tail = TREE_CHAIN (tail))
     hashcode += TYPE_HASH (TREE_VALUE (tail));
+
   return hashcode;
 }
 
+/* These are the Hashtable callback functions.  */
+
+/* Returns true if the types are equal.  */
+
+static int
+type_hash_eq (va, vb)
+     const void *va;
+     const void *vb;
+{
+  const struct type_hash *a = va, *b = vb;
+  if (a->hash == b->hash
+      && TREE_CODE (a->type) == TREE_CODE (b->type)
+      && TREE_TYPE (a->type) == TREE_TYPE (b->type)
+      && attribute_list_equal (TYPE_ATTRIBUTES (a->type),
+                              TYPE_ATTRIBUTES (b->type))
+      && TYPE_ALIGN (a->type) == TYPE_ALIGN (b->type)
+      && (TYPE_MAX_VALUE (a->type) == TYPE_MAX_VALUE (b->type)
+         || tree_int_cst_equal (TYPE_MAX_VALUE (a->type),
+                                TYPE_MAX_VALUE (b->type)))
+      && (TYPE_MIN_VALUE (a->type) == TYPE_MIN_VALUE (b->type)
+         || tree_int_cst_equal (TYPE_MIN_VALUE (a->type),
+                                TYPE_MIN_VALUE (b->type)))
+      /* Note that TYPE_DOMAIN is TYPE_ARG_TYPES for FUNCTION_TYPE.  */
+      && (TYPE_DOMAIN (a->type) == TYPE_DOMAIN (b->type)
+         || (TYPE_DOMAIN (a->type)
+             && TREE_CODE (TYPE_DOMAIN (a->type)) == TREE_LIST
+             && TYPE_DOMAIN (b->type)
+             && TREE_CODE (TYPE_DOMAIN (b->type)) == TREE_LIST
+             && type_list_equal (TYPE_DOMAIN (a->type),
+                                 TYPE_DOMAIN (b->type)))))
+    return 1;
+  return 0;
+}
+
+/* Return the cached hash value.  */
+
+static unsigned int
+type_hash_hash (item)
+     const void *item;
+{
+  return ((const struct type_hash*)item)->hash;
+}
+
 /* Look in the type hash table for a type isomorphic to TYPE.
    If one is found, return it.  Otherwise return 0.  */
 
 tree
 type_hash_lookup (hashcode, type)
-     int hashcode;
+     unsigned int hashcode;
      tree type;
 {
-  register struct type_hash *h;
+  struct type_hash *h, in;
 
   /* The TYPE_ALIGN field of a type is set by layout_type(), so we
      must call that routine before comparing TYPE_ALIGNs. */
   layout_type (type);
 
-  for (h = type_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next)
-    if (h->hashcode == hashcode
-       && TREE_CODE (h->type) == TREE_CODE (type)
-       && TREE_TYPE (h->type) == TREE_TYPE (type)
-        && attribute_list_equal (TYPE_ATTRIBUTES (h->type),
-                                  TYPE_ATTRIBUTES (type))
-       && TYPE_ALIGN (h->type) == TYPE_ALIGN (type)
-       && (TYPE_MAX_VALUE (h->type) == TYPE_MAX_VALUE (type)
-           || tree_int_cst_equal (TYPE_MAX_VALUE (h->type),
-                                  TYPE_MAX_VALUE (type)))
-       && (TYPE_MIN_VALUE (h->type) == TYPE_MIN_VALUE (type)
-           || tree_int_cst_equal (TYPE_MIN_VALUE (h->type),
-                                  TYPE_MIN_VALUE (type)))
-       /* Note that TYPE_DOMAIN is TYPE_ARG_TYPES for FUNCTION_TYPE.  */
-       && (TYPE_DOMAIN (h->type) == TYPE_DOMAIN (type)
-           || (TYPE_DOMAIN (h->type)
-               && TREE_CODE (TYPE_DOMAIN (h->type)) == TREE_LIST
-               && TYPE_DOMAIN (type)
-               && TREE_CODE (TYPE_DOMAIN (type)) == TREE_LIST
-               && type_list_equal (TYPE_DOMAIN (h->type),
-                                   TYPE_DOMAIN (type)))))
-      return h->type;
-  return 0;
+  in.hash = hashcode;
+  in.type = type;
+
+  h = htab_find_with_hash (type_hash_table, &in, hashcode);
+  if (h)
+    return h->type;
+  return NULL_TREE;
 }
 
 /* Add an entry to the type-hash-table
@@ -3781,16 +4068,17 @@ type_hash_lookup (hashcode, type)
 
 void
 type_hash_add (hashcode, type)
-     int hashcode;
+     unsigned int hashcode;
      tree type;
 {
-  register struct type_hash *h;
+  struct type_hash *h;
+  void **loc;
 
   h = (struct type_hash *) permalloc (sizeof (struct type_hash));
-  h->hashcode = hashcode;
+  h->hash = hashcode;
   h->type = type;
-  h->next = type_hash_table[hashcode % TYPE_HASH_SIZE];
-  type_hash_table[hashcode % TYPE_HASH_SIZE] = h;
+  loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT);
+  *(struct type_hash**) loc = h;
 }
 
 /* Given TYPE, and HASHCODE its hash code, return the canonical
@@ -3809,7 +4097,7 @@ int debug_no_type_hash = 0;
 
 tree
 type_hash_canon (hashcode, type)
-     int hashcode;
+     unsigned int hashcode;
      tree type;
 {
   tree t1;
@@ -3822,9 +4110,10 @@ type_hash_canon (hashcode, type)
     {
       if (!ggc_p)
        obstack_free (TYPE_OBSTACK (type), type);
+
 #ifdef GATHER_STATISTICS
-      tree_node_counts[(int)t_kind]--;
-      tree_node_sizes[(int)t_kind] -= sizeof (struct tree_type);
+      tree_node_counts[(int) t_kind]--;
+      tree_node_sizes[(int) t_kind] -= sizeof (struct tree_type);
 #endif
       return t1;
     }
@@ -3836,31 +4125,52 @@ type_hash_canon (hashcode, type)
   return type;
 }
 
-/* Mark ARG (which is really a struct type_hash **) for GC.  */
+/* Callback function for htab_traverse.  */
+
+static int
+mark_hash_entry (entry, param)
+     void **entry;
+     void *param ATTRIBUTE_UNUSED;
+{
+  struct type_hash *p = *(struct type_hash **)entry;
+
+  ggc_mark_tree (p->type);
+
+  /* Continue scan.  */
+  return 1;
+}
+
+/* Mark ARG (which is really a htab_t *) for GC.  */
 
 static void
 mark_type_hash (arg)
      void *arg;
 {
-  struct type_hash *t = *(struct type_hash **) arg;
+  htab_t t = *(htab_t *) arg;
 
-  while (t)
-    {
-      ggc_mark_tree (t->type);
-      t = t->next;
-    }
+  htab_traverse (t, mark_hash_entry, 0);
+}
+
+static void
+print_type_hash_statistics ()
+{
+  fprintf (stderr, "Type hash: size %ld, %ld elements, %f collisions\n",
+          (long) htab_size (type_hash_table),
+          (long) htab_elements (type_hash_table),
+          htab_collisions (type_hash_table));
 }
 
 /* Compute a hash code for a list of attributes (chain of TREE_LIST nodes
    with names in the TREE_PURPOSE slots and args in the TREE_VALUE slots),
    by adding the hash codes of the individual attributes.  */
 
-int
+unsigned int
 attribute_hash_list (list)
      tree list;
 {
-  register int hashcode;
+  unsigned int hashcode;
   register tree tail;
+
   for (hashcode = 0, tail = list; tail; tail = TREE_CHAIN (tail))
     /* ??? Do we want to add in TREE_VALUE too? */
     hashcode += TYPE_HASH (TREE_PURPOSE (tail));
@@ -3898,7 +4208,7 @@ attribute_list_contained (l1, l2)
 
   /* Maybe the lists are similar.  */
   for (t1 = l1, t2 = l2;
-       t1 && t2
+       t1 != 0 && t2 != 0
         && TREE_PURPOSE (t1) == TREE_PURPOSE (t2)
         && TREE_VALUE (t1) == TREE_VALUE (t2);
        t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2));
@@ -3907,13 +4217,14 @@ attribute_list_contained (l1, l2)
   if (t1 == 0 && t2 == 0)
      return 1;
 
-  for (; t2; t2 = TREE_CHAIN (t2))
+  for (; t2 != 0; t2 = TREE_CHAIN (t2))
     {
       tree attr
        = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1);
 
-      if (attr == NULL_TREE)
+      if (attr == 0)
        return 0;
+
       if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) != 1)
        return 0;
     }
@@ -3952,13 +4263,16 @@ tree_int_cst_equal (t1, t2)
 {
   if (t1 == t2)
     return 1;
+
   if (t1 == 0 || t2 == 0)
     return 0;
+
   if (TREE_CODE (t1) == INTEGER_CST
       && TREE_CODE (t2) == INTEGER_CST
       && TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
       && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2))
     return 1;
+
   return 0;
 }
 
@@ -3972,11 +4286,63 @@ tree_int_cst_lt (t1, t2)
   if (t1 == t2)
     return 0;
 
-  if (!TREE_UNSIGNED (TREE_TYPE (t1)))
+  if (! TREE_UNSIGNED (TREE_TYPE (t1)))
     return INT_CST_LT (t1, t2);
+
   return INT_CST_LT_UNSIGNED (t1, t2);
 }
 
+/* Return 1 if T is an INTEGER_CST that can be represented in a single
+   HOST_WIDE_INT value.  If POS is nonzero, the result must be positive.  */
+
+int
+host_integerp (t, pos)
+     tree t;
+     int pos;
+{
+  return (TREE_CODE (t) == INTEGER_CST
+         && ! TREE_OVERFLOW (t)
+         && ((TREE_INT_CST_HIGH (t) == 0
+              && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)
+             || (! pos && TREE_INT_CST_HIGH (t) == -1
+                 && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0)
+             || (! pos && TREE_INT_CST_HIGH (t) == 0
+                 && TREE_UNSIGNED (TREE_TYPE (t)))));
+}
+
+/* Return the HOST_WIDE_INT least significant bits of T if it is an
+   INTEGER_CST and there is no overflow.  POS is nonzero if the result must
+   be positive.  Abort if we cannot satisfy the above conditions.  */
+
+HOST_WIDE_INT
+tree_low_cst (t, pos)
+     tree t;
+     int pos;
+{
+  if (host_integerp (t, pos))
+    return TREE_INT_CST_LOW (t);
+  else
+    abort ();
+}  
+
+/* Return the most significant bit of the integer constant T.  */
+
+int
+tree_int_cst_msb (t)
+     tree t;
+{
+  register int prec;
+  HOST_WIDE_INT h;
+  unsigned HOST_WIDE_INT l;
+
+  /* Note that using TYPE_PRECISION here is wrong.  We care about the
+     actual bits, not the (arbitrary) range of the type.  */
+  prec = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (t))) - 1;
+  rshift_double (TREE_INT_CST_LOW (t), TREE_INT_CST_HIGH (t), prec,
+                2 * HOST_BITS_PER_WIDE_INT, &l, &h, 0);
+  return (l & 1) == 1;
+  }
+
 /* Return an indication of the sign of the integer constant T.
    The return value is -1 if T < 0, 0 if T == 0, and 1 if T > 0.
    Note that -1 will never be returned it T's type is unsigned.  */
@@ -3995,6 +4361,25 @@ tree_int_cst_sgn (t)
     return 1;
 }
 
+/* Return true if `t' is known to be non-negative.  */
+
+int
+tree_expr_nonnegative_p (t)
+     tree t;
+{
+  switch (TREE_CODE (t))
+    {
+    case INTEGER_CST:
+      return tree_int_cst_sgn (t) >= 0;
+    case COND_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 1))
+       && tree_expr_nonnegative_p (TREE_OPERAND (t, 2));
+    default:
+      /* We don't know sign of `t', so be safe and return false.  */
+      return 0;
+    }
+}
+
 /* Compare two constructor-element-type constants.  Return 1 if the lists
    are known to be equal; otherwise return 0.  */
 
@@ -4011,7 +4396,7 @@ simple_cst_list_equal (l1, l2)
       l2 = TREE_CHAIN (l2);
     }
 
-  return (l1 == l2);
+  return l1 == l2;
 }
 
 /* Return truthvalue of whether T1 is the same tree structure as T2.
@@ -4026,6 +4411,7 @@ simple_cst_equal (t1, t2)
 {
   register enum tree_code code1, code2;
   int cmp;
+  int i;
 
   if (t1 == t2)
     return 1;
@@ -4043,6 +4429,7 @@ simple_cst_equal (t1, t2)
       else
        return simple_cst_equal (TREE_OPERAND (t1, 0), t2);
     }
+
   else if (code2 == NOP_EXPR || code2 == CONVERT_EXPR
           || code2 == NON_LVALUE_EXPR)
     return simple_cst_equal (t1, TREE_OPERAND (t2, 0));
@@ -4053,16 +4440,16 @@ simple_cst_equal (t1, t2)
   switch (code1)
     {
     case INTEGER_CST:
-      return TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
-       && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2);
+      return (TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
+             && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2));
 
     case REAL_CST:
       return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
 
     case STRING_CST:
-      return TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
-       && !bcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
-                 TREE_STRING_LENGTH (t1));
+      return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
+             && ! bcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
+                        TREE_STRING_LENGTH (t1)));
 
     case CONSTRUCTOR:
       if (CONSTRUCTOR_ELTS (t1) == CONSTRUCTOR_ELTS (t2))
@@ -4077,7 +4464,8 @@ simple_cst_equal (t1, t2)
       cmp = simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
       if (cmp <= 0)
        return cmp;
-      return simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+      return
+       simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
 
     case TARGET_EXPR:
       /* Special case: if either target is an unallocated VAR_DECL,
@@ -4093,19 +4481,23 @@ simple_cst_equal (t1, t2)
        cmp = 1;
       else
        cmp = simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+
       if (cmp <= 0)
        return cmp;
+
       return simple_cst_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
 
     case WITH_CLEANUP_EXPR:
       cmp = simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
       if (cmp <= 0)
        return cmp;
+
       return simple_cst_equal (TREE_OPERAND (t1, 2), TREE_OPERAND (t1, 2));
 
     case COMPONENT_REF:
       if (TREE_OPERAND (t1, 1) == TREE_OPERAND (t2, 1))
        return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+
       return 0;
 
     case VAR_DECL:
@@ -4127,7 +4519,6 @@ simple_cst_equal (t1, t2)
 
   switch (TREE_CODE_CLASS (code1))
     {
-      int i;
     case '1':
     case '2':
     case '<':
@@ -4135,18 +4526,40 @@ simple_cst_equal (t1, t2)
     case 'r':
     case 's':
       cmp = 1;
-      for (i=0; i<tree_code_length[(int) code1]; ++i)
+      for (i = 0; i < TREE_CODE_LENGTH (code1); i++)
        {
          cmp = simple_cst_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i));
          if (cmp <= 0)
            return cmp;
        }
+
       return cmp;
 
     default:
       return -1;
     }
 }
+
+/* Compare the value of T, an INTEGER_CST, with U, an unsigned integer value.
+   Return -1, 0, or 1 if the value of T is less than, equal to, or greater
+   than U, respectively.  */
+
+int
+compare_tree_int (t, u)
+     tree t;
+     unsigned int u;
+{
+  if (tree_int_cst_sgn (t) < 0)
+    return -1;
+  else if (TREE_INT_CST_HIGH (t) != 0)
+    return 1;
+  else if (TREE_INT_CST_LOW (t) == u)
+    return 0;
+  else if (TREE_INT_CST_LOW (t) < u)
+    return -1;
+  else
+    return 1;
+}
 \f
 /* Constructors for pointer, array and function types.
    (RECORD_TYPE, UNION_TYPE and ENUMERAL_TYPE nodes are
@@ -4163,7 +4576,7 @@ build_pointer_type (to_type)
 
   /* First, if we already have a type for pointers to TO_TYPE, use it.  */
 
-  if (t)
+  if (t != 0)
     return t;
 
   /* We need a new one.  Put this in the same obstack as TO_TYPE.   */
@@ -4184,6 +4597,34 @@ build_pointer_type (to_type)
   return t;
 }
 
+/* Build the node for the type of references-to-TO_TYPE.  */
+
+tree
+build_reference_type (to_type)
+     tree to_type;
+{
+  register tree t = TYPE_REFERENCE_TO (to_type);
+
+  /* First, if we already have a type for pointers to TO_TYPE, use it.  */
+
+  if (t)
+    return t;
+
+  /* We need a new one.  Put this in the same obstack as TO_TYPE.   */
+  push_obstacks (TYPE_OBSTACK (to_type), TYPE_OBSTACK (to_type));
+  t = make_node (REFERENCE_TYPE);
+  pop_obstacks ();
+
+  TREE_TYPE (t) = to_type;
+
+  /* Record this type as the pointer to TO_TYPE.  */
+  TYPE_REFERENCE_TO (to_type) = t;
+
+  layout_type (t);
+
+  return t;
+}
+
 /* Create a type of integers to be the TYPE_DOMAIN of an ARRAY_TYPE.
    MAXVAL should be the maximum value in the domain
    (one less than the length of the array).
@@ -4199,6 +4640,7 @@ build_index_type (maxval)
 {
   register tree itype = make_node (INTEGER_TYPE);
 
+  TREE_TYPE (itype) = sizetype;
   TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype);
   TYPE_MIN_VALUE (itype) = size_zero_node;
 
@@ -4210,18 +4652,10 @@ build_index_type (maxval)
   TYPE_SIZE (itype) = TYPE_SIZE (sizetype);
   TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (sizetype);
   TYPE_ALIGN (itype) = TYPE_ALIGN (sizetype);
-  if (TREE_CODE (maxval) == INTEGER_CST)
-    {
-      int maxint = (int) TREE_INT_CST_LOW (maxval);
-      /* If the domain should be empty, make sure the maxval
-        remains -1 and is not spoiled by truncation.  */
-      if (INT_CST_LT (maxval, integer_zero_node))
-       {
-         TYPE_MAX_VALUE (itype) = build_int_2 (-1, -1);
-         TREE_TYPE (TYPE_MAX_VALUE (itype)) = sizetype;
-       }
-      return type_hash_canon (maxint < 0 ? ~maxint : maxint, itype);
-    }
+  TYPE_USER_ALIGN (itype) = TYPE_USER_ALIGN (sizetype);
+
+  if (host_integerp (maxval, 1))
+    return type_hash_canon (tree_low_cst (maxval, 1), itype);
   else
     return itype;
 }
@@ -4251,20 +4685,12 @@ build_range_type (type, lowval, highval)
   TYPE_SIZE (itype) = TYPE_SIZE (type);
   TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (type);
   TYPE_ALIGN (itype) = TYPE_ALIGN (type);
-  if (TREE_CODE (lowval) == INTEGER_CST)
-    {
-      HOST_WIDE_INT lowint, highint;
-      int maxint;
+  TYPE_USER_ALIGN (itype) = TYPE_USER_ALIGN (type);
 
-      lowint = TREE_INT_CST_LOW (lowval);
-      if (highval && TREE_CODE (highval) == INTEGER_CST)
-       highint = TREE_INT_CST_LOW (highval);
-      else
-       highint = (~(unsigned HOST_WIDE_INT)0) >> 1;
-
-      maxint = (int) (highint - lowint);
-      return type_hash_canon (maxint < 0 ? ~maxint : maxint, itype);
-    }
+  if (host_integerp (lowval, 0) && highval != 0 && host_integerp (highval, 0))
+    return type_hash_canon (tree_low_cst (highval, 0)
+                           - tree_low_cst (lowval, 0),
+                           itype);
   else
     return itype;
 }
@@ -4276,7 +4702,7 @@ tree
 build_index_2_type (lowval,highval)
      tree lowval, highval;
 {
-  return build_range_type (NULL_TREE, lowval, highval);
+  return build_range_type (sizetype, lowval, highval);
 }
 
 /* Return nonzero iff ITYPE1 and ITYPE2 are equal (in the LISP sense).
@@ -4290,6 +4716,7 @@ index_type_equal (itype1, itype2)
 {
   if (TREE_CODE (itype1) != TREE_CODE (itype2))
     return 0;
+
   if (TREE_CODE (itype1) == INTEGER_TYPE)
     {
       if (TYPE_PRECISION (itype1) != TYPE_PRECISION (itype2)
@@ -4297,6 +4724,7 @@ index_type_equal (itype1, 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),
@@ -4316,7 +4744,7 @@ build_array_type (elt_type, index_type)
      tree elt_type, index_type;
 {
   register tree t;
-  int hashcode;
+  unsigned int hashcode;
 
   if (TREE_CODE (elt_type) == FUNCTION_TYPE)
     {
@@ -4341,7 +4769,7 @@ build_array_type (elt_type, index_type)
   hashcode = TYPE_HASH (elt_type) + TYPE_HASH (index_type);
   t = type_hash_canon (hashcode, t);
 
-  if (TYPE_SIZE (t) == 0)
+  if (!COMPLETE_TYPE_P (t))
     layout_type (t);
   return t;
 }
@@ -4373,7 +4801,7 @@ build_function_type (value_type, arg_types)
      tree value_type, arg_types;
 {
   register tree t;
-  int hashcode;
+  unsigned int hashcode;
 
   if (TREE_CODE (value_type) == FUNCTION_TYPE)
     {
@@ -4390,39 +4818,11 @@ build_function_type (value_type, arg_types)
   hashcode = TYPE_HASH (value_type) + type_hash_list (arg_types);
   t = type_hash_canon (hashcode, t);
 
-  if (TYPE_SIZE (t) == 0)
+  if (!COMPLETE_TYPE_P (t))
     layout_type (t);
   return t;
 }
 
-/* Build the node for the type of references-to-TO_TYPE.  */
-
-tree
-build_reference_type (to_type)
-     tree to_type;
-{
-  register tree t = TYPE_REFERENCE_TO (to_type);
-
-  /* First, if we already have a type for pointers to TO_TYPE, use it.  */
-
-  if (t)
-    return t;
-
-  /* We need a new one.  Put this in the same obstack as TO_TYPE.   */
-  push_obstacks (TYPE_OBSTACK (to_type), TYPE_OBSTACK (to_type));
-  t = make_node (REFERENCE_TYPE);
-  pop_obstacks ();
-
-  TREE_TYPE (t) = to_type;
-
-  /* Record this type as the pointer to TO_TYPE.  */
-  TYPE_REFERENCE_TO (to_type) = t;
-
-  layout_type (t);
-
-  return t;
-}
-
 /* Construct, lay out and return the type of methods belonging to class
    BASETYPE and whose arguments and values are described by TYPE.
    If that type exists already, reuse it.
@@ -4433,7 +4833,7 @@ build_method_type (basetype, type)
      tree basetype, type;
 {
   register tree t;
-  int hashcode;
+  unsigned int hashcode;
 
   /* Make a node of the sort we want.  */
   t = make_node (METHOD_TYPE);
@@ -4455,7 +4855,7 @@ build_method_type (basetype, type)
   hashcode = TYPE_HASH (basetype) + TYPE_HASH (type);
   t = type_hash_canon (hashcode, t);
 
-  if (TYPE_SIZE (t) == 0)
+  if (!COMPLETE_TYPE_P (t))
     layout_type (t);
 
   return t;
@@ -4470,7 +4870,7 @@ build_offset_type (basetype, type)
      tree basetype, type;
 {
   register tree t;
-  int hashcode;
+  unsigned int hashcode;
 
   /* Make a node of the sort we want.  */
   t = make_node (OFFSET_TYPE);
@@ -4482,7 +4882,7 @@ build_offset_type (basetype, type)
   hashcode = TYPE_HASH (basetype) + TYPE_HASH (type);
   t = type_hash_canon (hashcode, t);
 
-  if (TYPE_SIZE (t) == 0)
+  if (!COMPLETE_TYPE_P (t))
     layout_type (t);
 
   return t;
@@ -4495,7 +4895,7 @@ build_complex_type (component_type)
      tree component_type;
 {
   register tree t;
-  int hashcode;
+  unsigned int hashcode;
 
   /* Make a node of the sort we want.  */
   t = make_node (COMPLEX_TYPE);
@@ -4507,14 +4907,14 @@ build_complex_type (component_type)
   hashcode = TYPE_HASH (component_type);
   t = type_hash_canon (hashcode, t);
 
-  if (TYPE_SIZE (t) == 0)
+  if (!COMPLETE_TYPE_P (t))
     layout_type (t);
 
   /* If we are writing Dwarf2 output we need to create a name,
      since complex is a fundamental type.  */
   if (write_symbols == DWARF2_DEBUG && ! TYPE_NAME (t))
     {
-      char *name;
+      const char *name;
       if (component_type == char_type_node)
        name = "complex char";
       else if (component_type == signed_char_type_node)
@@ -4538,9 +4938,9 @@ build_complex_type (component_type)
       else if (component_type == long_long_unsigned_type_node)
        name = "complex long long unsigned int";
       else
-       name = (char *)0;
+       name = 0;
 
-      if (name)
+      if (name != 0)
        TYPE_NAME (t) = get_identifier (name);
     }
 
@@ -4630,7 +5030,9 @@ get_unwidened (op, for_type)
       /* Don't crash if field not laid out yet.  */
       && DECL_SIZE (TREE_OPERAND (op, 1)) != 0)
     {
-      unsigned innerprec = TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (op, 1)));
+      unsigned int innerprec
+       = TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (op, 1)));
+
       type = type_for_size (innerprec, TREE_UNSIGNED (TREE_OPERAND (op, 1)));
 
       /* We can get this structure field in the narrowest type it fits in.
@@ -4649,7 +5051,6 @@ get_unwidened (op, for_type)
                       TREE_OPERAND (op, 1));
          TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op);
          TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op);
-         TREE_RAISES (win) = TREE_RAISES (op);
        }
     }
   return win;
@@ -4672,8 +5073,8 @@ get_narrower (op, unsignedp_ptr)
   while (TREE_CODE (op) == NOP_EXPR)
     {
       register int bitschange
-       = TYPE_PRECISION (TREE_TYPE (op))
-         - TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op, 0)));
+       = (TYPE_PRECISION (TREE_TYPE (op))
+          - TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op, 0))));
 
       /* Truncations are many-one so cannot be removed.  */
       if (bitschange < 0)
@@ -4712,7 +5113,9 @@ get_narrower (op, unsignedp_ptr)
       /* Since type_for_size always gives an integer type.  */
       && TREE_CODE (TREE_TYPE (op)) != REAL_TYPE)
     {
-      unsigned innerprec = TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (op, 1)));
+      unsigned int innerprec
+       = TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (op, 1)));
+
       tree type = type_for_size (innerprec, TREE_UNSIGNED (op));
 
       /* We can get this structure field in a narrower type that fits it,
@@ -4734,7 +5137,6 @@ get_narrower (op, unsignedp_ptr)
                       TREE_OPERAND (op, 1));
          TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op);
          TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op);
-         TREE_RAISES (win) = TREE_RAISES (op);
        }
     }
   *unsignedp_ptr = uns;
@@ -4766,6 +5168,16 @@ int_fits_type_p (c, type)
                  && TREE_UNSIGNED (TREE_TYPE (c))));
 }
 
+/* Given a DECL or TYPE, return the scope in which it was declared, or
+   NULL_TREE if there is no containing scope.  */
+
+tree
+get_containing_scope (t)
+     tree t;
+{
+  return (TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t));
+}
+
 /* Return the innermost context enclosing DECL that is
    a FUNCTION_DECL, or zero if none.  */
 
@@ -4780,20 +5192,26 @@ decl_function_context (decl)
 
   if (TREE_CODE (decl) == SAVE_EXPR)
     context = SAVE_EXPR_CONTEXT (decl);
+
+  /* C++ virtual functions use DECL_CONTEXT for the class of the vtable
+     where we look up the function at runtime.  Such functions always take
+     a first argument of type 'pointer to real context'.
+
+     C++ should really be fixed to use DECL_CONTEXT for the real context,
+     and use something else for the "virtual context".  */
+  else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VINDEX (decl))
+    context
+      = TYPE_MAIN_VARIANT
+       (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
   else
     context = DECL_CONTEXT (decl);
 
   while (context && TREE_CODE (context) != FUNCTION_DECL)
     {
-      if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
-       context = TYPE_CONTEXT (context);
-      else if (TREE_CODE_CLASS (TREE_CODE (context)) == 'd')
-       context = DECL_CONTEXT (context);
-      else if (TREE_CODE (context) == BLOCK)
+      if (TREE_CODE (context) == BLOCK)
        context = BLOCK_SUPERCONTEXT (context);
-      else
-       /* Unhandled CONTEXT !?  */
-       abort ();
+      else 
+       context = get_containing_scope (context);
     }
 
   return context;
@@ -4815,11 +5233,14 @@ decl_type_context (decl)
          || TREE_CODE (context) == UNION_TYPE
          || TREE_CODE (context) == QUAL_UNION_TYPE)
        return context;
+
       if (TREE_CODE (context) == TYPE_DECL
          || TREE_CODE (context) == FUNCTION_DECL)
        context = DECL_CONTEXT (context);
+
       else if (TREE_CODE (context) == BLOCK)
        context = BLOCK_SUPERCONTEXT (context);
+
       else
        /* Unhandled CONTEXT!?  */
        abort ();
@@ -4827,6 +5248,43 @@ decl_type_context (decl)
   return NULL_TREE;
 }
 
+/* CALL is a CALL_EXPR.  Return the declaration for the function
+   called, or NULL_TREE if the called function cannot be 
+   determined.  */
+
+tree
+get_callee_fndecl (call)
+     tree call;
+{
+  tree addr;
+
+  /* It's invalid to call this function with anything but a
+     CALL_EXPR.  */
+  if (TREE_CODE (call) != CALL_EXPR)
+    abort ();
+
+  /* The first operand to the CALL is the address of the function
+     called.  */
+  addr = TREE_OPERAND (call, 0);
+
+  STRIP_NOPS (addr);
+
+  /* If this is a readonly function pointer, extract its initial value.  */
+  if (DECL_P (addr) && TREE_CODE (addr) != FUNCTION_DECL
+      && TREE_READONLY (addr) && ! TREE_THIS_VOLATILE (addr)
+      && DECL_INITIAL (addr))
+    addr = DECL_INITIAL (addr);
+
+  /* If the address is just `&f' for some function `f', then we know
+     that `f' is being called.  */
+  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.  */
+  return NULL_TREE;
+}
+
 /* Print debugging information about the obstack O, named STR.  */
 
 void
@@ -4885,6 +5343,7 @@ dump_tree_statistics ()
   print_obstack_statistics ("temporary_obstack", &temporary_obstack);
   print_obstack_statistics ("momentary_obstack", &momentary_obstack);
   print_obstack_statistics ("temp_decl_obstack", &temp_decl_obstack);
+  print_type_hash_statistics ();
   print_lang_statistics ();
 }
 \f
@@ -4900,9 +5359,6 @@ dump_tree_statistics ()
 #endif /* NO_DOT_IN_LABEL */
 #endif /* NO_DOLLAR_IN_LABEL */
 
-extern char * first_global_object_name;
-extern char * weak_global_object_name;
-
 /* Appends 6 random characters to TEMPLATE to (hopefully) avoid name
    clashes in cases where we can't reliably choose a unique name.
 
@@ -4958,7 +5414,8 @@ get_file_function_name_long (type)
      const char *type;
 {
   char *buf;
-  register char *p;
+  const char *p;
+  char *q;
 
   if (first_global_object_name)
     p = first_global_object_name;
@@ -4975,40 +5432,36 @@ get_file_function_name_long (type)
       if (! file)
        file = input_filename;
 
-      p = (char *) alloca (7 + strlen (name) + strlen (file));
+      q = (char *) alloca (7 + strlen (name) + strlen (file));
 
-      sprintf (p, "%s%s", name, file);
-      append_random_chars (p);
+      sprintf (q, "%s%s", name, file);
+      append_random_chars (q);
+      p = q;
     }
 
   buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p)
                         + strlen (type));
 
-  /* Set up the name of the file-level functions we may need.  */
-  /* Use a global object (which is already required to be unique over
+  /* Set up the name of the file-level functions we may need. 
+     Use a global object (which is already required to be unique over
      the program) rather than the file name (which imposes extra
-     constraints).  -- Raeburn@MIT.EDU, 10 Jan 1990.  */
+     constraints).  */
   sprintf (buf, FILE_FUNCTION_FORMAT, type, p);
 
   /* Don't need to pull weird characters out of global names.  */
   if (p != first_global_object_name)
     {
-      for (p = buf+11; *p; p++)
-       if (! ( ISDIGIT(*p)
-#if 0 /* we always want labels, which are valid C++ identifiers (+ `$') */
-#ifndef ASM_IDENTIFY_GCC       /* this is required if `.' is invalid -- k. raeburn */
-              || *p == '.'
-#endif
-#endif
+      for (q = buf+11; *q; q++)
+       if (! ( ISDIGIT(*q)
 #ifndef NO_DOLLAR_IN_LABEL     /* this for `$'; unlikely, but... -- kr */
-              || *p == '$'
+              || *q == '$'
 #endif
 #ifndef NO_DOT_IN_LABEL                /* this for `.'; unlikely, but...  */
-              || *p == '.'
+              || *q == '.'
 #endif
-              || ISUPPER(*p)
-              || ISLOWER(*p)))
-         *p = '_';
+              || ISUPPER(*q)
+              || ISLOWER(*q)))
+         *q = '_';
     }
 
   return get_identifier (buf);
@@ -5022,12 +5475,12 @@ get_file_function_name (kind)
      int kind;
 {
   char p[2];
+
   p[0] = kind;
   p[1] = 0;
 
   return get_file_function_name_long (p);
 }
-
 \f
 /* Expand (the constant part of) a SET_TYPE CONSTRUCTOR node.
    The result is placed in BUFFER (which has length BIT_SIZE),
@@ -5065,6 +5518,7 @@ get_set_constructor_bits (init, buffer, bit_size)
            = TREE_INT_CST_LOW (TREE_PURPOSE (vals)) - domain_min;
          HOST_WIDE_INT hi_index
            = TREE_INT_CST_LOW (TREE_VALUE (vals)) - domain_min;
+
          if (lo_index < 0 || lo_index >= bit_size
            || hi_index < 0 || hi_index >= bit_size)
            abort ();
@@ -5125,7 +5579,7 @@ get_set_constructor_bytes (init, buffer, wd_size)
   return non_const_bits;
 }
 \f
-#if defined ENABLE_CHECKING && (__GNUC__ > 2 || __GNUC_MINOR__ > 6)
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 /* Complain that the tree code of NODE does not match the expected CODE.
    FILE, LINE, and FUNCTION are of the caller.  */
 void
@@ -5146,7 +5600,7 @@ tree_check_failed (node, code, file, line, function)
 void
 tree_class_check_failed (node, cl, file, line, function)
      const tree node;
-     char cl;
+     int cl;
      const char *file;
      int line;
      const char *function;
@@ -5157,35 +5611,35 @@ tree_class_check_failed (node, cl, file, line, function)
   fancy_abort (file, line, function);
 }
 
-#endif /* ENABLE_CHECKING */
+#endif /* ENABLE_TREE_CHECKING */
 
-/* Return the alias set for T, which may be either a type or an
-   expression.  */
-
-int
-get_alias_set (t)
+\f
+/* For a new vector type node T, build the information necessary for
+   debuggint output.  */
+static void
+finish_vector_type (t)
      tree t;
 {
-  if (!flag_strict_aliasing || !lang_get_alias_set)
-    /* If we're not doing any lanaguage-specific alias analysis, just
-       assume everything aliases everything else.  */
-    return 0;
-  else
-    return (*lang_get_alias_set) (t);
-}
-
-/* Return a brand-new alias set.  */
+  layout_type (t);
 
-int
-new_alias_set ()
-{
-  static int last_alias_set;
-  if (flag_strict_aliasing)
-    return ++last_alias_set;
-  else
-    return 0;
+  {
+    tree index = build_int_2 (TYPE_VECTOR_SUBPARTS (t) - 1, 0);
+    tree array = build_array_type (TREE_TYPE (t),
+                                  build_index_type (index));
+    tree rt = make_node (RECORD_TYPE);
+
+    TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);
+    DECL_CONTEXT (TYPE_FIELDS (rt)) = rt;
+    layout_type (rt);
+    TYPE_DEBUG_REPRESENTATION_TYPE (t) = rt;
+    /* In dwarfout.c, type lookup uses TYPE_UID numbers.  We want to output
+       the representation type, and we want to find that die when looking up
+       the vector type.  This is most easily achieved by making the TYPE_UID
+       numbers equal.  */
+    TYPE_UID (rt) = TYPE_UID (t);
+  }
 }
-\f
+
 #ifndef CHAR_TYPE_SIZE
 #define CHAR_TYPE_SIZE BITS_PER_UNIT
 #endif
@@ -5229,6 +5683,8 @@ build_common_tree_nodes (signed_char)
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
 
+  initialize_sizetypes ();
+
   /* Define both `signed char' and `unsigned char'.  */
   signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
   unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
@@ -5243,10 +5699,6 @@ build_common_tree_nodes (signed_char)
   short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
   short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
   integer_type_node = make_signed_type (INT_TYPE_SIZE);
-  /* Define an unsigned integer first.  make_unsigned_type and make_signed_type
-     both call set_sizetype for the first type that we create, and we want this
-     to be large enough to hold the sizes of various types until we switch to
-     the real sizetype.  */
   unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
   long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
   long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
@@ -5257,70 +5709,43 @@ build_common_tree_nodes (signed_char)
   intHI_type_node = make_signed_type (GET_MODE_BITSIZE (HImode));
   intSI_type_node = make_signed_type (GET_MODE_BITSIZE (SImode));
   intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
+#if HOST_BITS_PER_WIDE_INT >= 64
   intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
+#endif
 
   unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
   unsigned_intHI_type_node = make_unsigned_type (GET_MODE_BITSIZE (HImode));
   unsigned_intSI_type_node = make_unsigned_type (GET_MODE_BITSIZE (SImode));
   unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
+#if HOST_BITS_PER_WIDE_INT >= 64
   unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
-}
-
-/* For type TYPE, fill in the proper type for TYPE_SIZE and
-   TYPE_SIZE_UNIT.  */
-static void
-fix_sizetype (type)
-     tree type;
-{
-  TREE_TYPE (TYPE_SIZE (type)) = bitsizetype;
-  TREE_TYPE (TYPE_SIZE_UNIT (type)) = sizetype;
+#endif
 }
 
 /* Call this function after calling build_common_tree_nodes and set_sizetype.
-   It will fix the previously made nodes to have proper references to
-   sizetype, and it will create several other common tree nodes.  */
+   It will create several other common tree nodes.  */
+
 void
 build_common_tree_nodes_2 (short_double)
      int short_double;
 {
-  fix_sizetype (signed_char_type_node);
-  fix_sizetype (unsigned_char_type_node);
-  fix_sizetype (char_type_node);
-  fix_sizetype (short_integer_type_node);
-  fix_sizetype (short_unsigned_type_node);
-  fix_sizetype (integer_type_node);
-  fix_sizetype (unsigned_type_node);
-  fix_sizetype (long_unsigned_type_node);
-  fix_sizetype (long_integer_type_node);
-  fix_sizetype (long_long_integer_type_node);
-  fix_sizetype (long_long_unsigned_type_node);
-
-  fix_sizetype (intQI_type_node);
-  fix_sizetype (intHI_type_node);
-  fix_sizetype (intSI_type_node);
-  fix_sizetype (intDI_type_node);
-  fix_sizetype (intTI_type_node);
-  fix_sizetype (unsigned_intQI_type_node);
-  fix_sizetype (unsigned_intHI_type_node);
-  fix_sizetype (unsigned_intSI_type_node);
-  fix_sizetype (unsigned_intDI_type_node);
-  fix_sizetype (unsigned_intTI_type_node);
-
+  /* Define these next since types below may used them.  */
   integer_zero_node = build_int_2 (0, 0);
-  TREE_TYPE (integer_zero_node) = integer_type_node;
   integer_one_node = build_int_2 (1, 0);
-  TREE_TYPE (integer_one_node) = integer_type_node;
 
-  size_zero_node = build_int_2 (0, 0);
-  TREE_TYPE (size_zero_node) = sizetype;
-  size_one_node = build_int_2 (1, 0);
-  TREE_TYPE (size_one_node) = sizetype;
+  size_zero_node = size_int (0);
+  size_one_node = size_int (1);
+  bitsize_zero_node = bitsize_int (0);
+  bitsize_one_node = bitsize_int (1);
+  bitsize_unit_node = bitsize_int (BITS_PER_UNIT);
 
   void_type_node = make_node (VOID_TYPE);
-  layout_type (void_type_node);        /* Uses size_zero_node */
+  layout_type (void_type_node);
+
   /* We are not going to have real types in C with less than byte alignment,
      so we might as well not have any types that claim to have it.  */
   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);
@@ -5366,4 +5791,29 @@ build_common_tree_nodes_2 (short_double)
 #else
   va_list_type_node = ptr_type_node;
 #endif
+
+  V4SF_type_node = make_node (VECTOR_TYPE);
+  TREE_TYPE (V4SF_type_node) = float_type_node;
+  TYPE_MODE (V4SF_type_node) = V4SFmode;
+  finish_vector_type (V4SF_type_node);
+
+  V4SI_type_node = make_node (VECTOR_TYPE);
+  TREE_TYPE (V4SI_type_node) = intSI_type_node;
+  TYPE_MODE (V4SI_type_node) = V4SImode;
+  finish_vector_type (V4SI_type_node);
+
+  V2SI_type_node = make_node (VECTOR_TYPE);
+  TREE_TYPE (V2SI_type_node) = intSI_type_node;
+  TYPE_MODE (V2SI_type_node) = V2SImode;
+  finish_vector_type (V2SI_type_node);
+
+  V4HI_type_node = make_node (VECTOR_TYPE);
+  TREE_TYPE (V4HI_type_node) = intHI_type_node;
+  TYPE_MODE (V4HI_type_node) = V4HImode;
+  finish_vector_type (V4HI_type_node);
+
+  V8QI_type_node = make_node (VECTOR_TYPE);
+  TREE_TYPE (V8QI_type_node) = intQI_type_node;
+  TYPE_MODE (V8QI_type_node) = V8QImode;
+  finish_vector_type (V8QI_type_node);
 }