OSDN Git Service

* config/i386/sol2.h (PREFERRED_DEBUGGING_TYPE): Use stabs.
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index e7138f7..752595c 100644 (file)
@@ -1,5 +1,5 @@
 /* Language-independent node constructors for parse phase of GNU compiler.
-   Copyright (C) 1987, 88, 92-96, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -34,33 +34,19 @@ Boston, MA 02111-1307, USA.  */
    by all passes of the compiler.  */
 
 #include "config.h"
-#include <setjmp.h>
+#include "system.h"
 #include "flags.h"
 #include "tree.h"
-#include "except.h"
+#include "tm_p.h"
 #include "function.h"
 #include "obstack.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-#include <stdio.h>
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#ifdef NEED_DECLARATION_FREE
-extern void free PROTO((void *));
-#endif
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
+#include "toplev.h"
+#include "ggc.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));
 
 /* Tree nodes of permanent duration are allocated in this obstack.
    They are the identifier nodes, and everything outside of
@@ -80,21 +66,6 @@ struct obstack *function_maybepermanent_obstack;
 
 struct obstack maybepermanent_obstack;
 
-/* This is a list of function_maybepermanent_obstacks for top-level inline
-   functions that are compiled in the middle of compiling other functions.  */
-
-struct simple_obstack_stack *toplev_inline_obstacks;
-
-/* Former elements of toplev_inline_obstacks that have been recycled.  */
-
-struct simple_obstack_stack *extra_inline_obstacks;
-
-/* This is a list of function_maybepermanent_obstacks for inline functions
-   nested in the current function that were compiled in the middle of
-   compiling other functions.  */
-
-struct simple_obstack_stack *inline_obstacks;
-
 /* The contents of the current function definition are allocated
    in this obstack, and all are freed at the end of the function.
    For top-level functions, this is temporary_obstack.
@@ -209,7 +180,7 @@ int tree_code_length[MAX_TREE_CODES] = {
    Used for printing out the tree and error messages.  */
 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
 
-char *tree_code_name[MAX_TREE_CODES] = {
+const char *tree_code_name[MAX_TREE_CODES] = {
 #include "tree.def"
 };
 #undef DEFTREECODE
@@ -239,7 +210,7 @@ int tree_node_counts[(int)all_kinds];
 int tree_node_sizes[(int)all_kinds];
 int id_string_size = 0;
 
-char *tree_node_kind_names[] = {
+static const char * const tree_node_kind_names[] = {
   "decls",
   "types",
   "blocks",
@@ -270,13 +241,45 @@ 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)
 
-extern char *mode_name[];
+/* Each hash table slot is a bucket containing a chain
+   of these structures.  */
+
+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.  */
+};
+
+/* 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 gcc_obstack_init ();
+void (*lang_unsave_expr_now) PROTO((tree));
+\f
+tree global_trees[TI_MAX];
 \f
 /* Init the principal obstacks.  */
 
@@ -305,6 +308,12 @@ init_obstacks ()
 
   /* Init the hash table of identifiers.  */
   bzero ((char *) hash_table, sizeof hash_table);
+
+  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);
+  ggc_add_tree_root (global_trees, TI_MAX);
 }
 
 void
@@ -323,20 +332,22 @@ gcc_obstack_init (obstack)
 #define OBSTACK_CHUNK_FREE free
 #endif
   _obstack_begin (obstack, OBSTACK_CHUNK_SIZE, 0,
-                 (void *(*) ()) OBSTACK_CHUNK_ALLOC,
-                 (void (*) ()) OBSTACK_CHUNK_FREE);
+                 (void *(*) PROTO ((long))) OBSTACK_CHUNK_ALLOC,
+                 (void (*) PROTO ((void *))) OBSTACK_CHUNK_FREE);
 }
 
-/* Save all variables describing the current status into the structure *P.
-   This is used before starting a nested function.
+/* Save all variables describing the current status into the structure
+   *P.  This function is called whenever we start compiling one
+   function in the midst of compiling another.  For example, when
+   compiling a nested function, or, in C++, a template instantiation
+   that is required by the function we are currently compiling.
 
    CONTEXT is the decl_function_context for the function we're about to
    compile; if it isn't current_function_decl, we have to play some games.  */
 
 void
-save_tree_status (p, context)
+save_tree_status (p)
      struct function *p;
-     tree context;
 {
   p->all_types_permanent = all_types_permanent;
   p->momentary_stack = momentary_stack;
@@ -350,50 +361,10 @@ save_tree_status (p, context)
   p->expression_obstack = expression_obstack;
   p->saveable_obstack = saveable_obstack;
   p->rtl_obstack = rtl_obstack;
-  p->inline_obstacks = inline_obstacks;
-
-  if (context == current_function_decl)
-    /* Objects that need to be saved in this function can be in the nonsaved
-       obstack of the enclosing function since they can't possibly be needed
-       once it has returned.  */
-    function_maybepermanent_obstack = function_obstack;
-  else
-    {
-      /* We're compiling a function which isn't nested in the current
-         function.  We need to create a new maybepermanent_obstack for this
-         function, since it can't go onto any of the existing obstacks.  */
-      struct simple_obstack_stack **head;
-      struct simple_obstack_stack *current;
-
-      if (context == NULL_TREE)
-       head = &toplev_inline_obstacks;
-      else
-       {
-         struct function *f = find_function_data (context);
-         head = &f->inline_obstacks;
-       }
-
-      if (context == NULL_TREE && extra_inline_obstacks)
-       {
-         current = extra_inline_obstacks;
-         extra_inline_obstacks = current->next;
-       }
-      else
-       {
-         current = ((struct simple_obstack_stack *)
-                    xmalloc (sizeof (struct simple_obstack_stack)));
-
-         current->obstack
-           = (struct obstack *) xmalloc (sizeof (struct obstack));
-         gcc_obstack_init (current->obstack);
-       }
-
-      function_maybepermanent_obstack = current->obstack;
-
-      current->next = *head;
-      *head = current;
-    }      
 
+  function_maybepermanent_obstack
+    = (struct obstack *) xmalloc (sizeof (struct obstack));
+  gcc_obstack_init (function_maybepermanent_obstack);
   maybepermanent_firstobj
     = (char *) obstack_finish (function_maybepermanent_obstack);
 
@@ -413,9 +384,8 @@ save_tree_status (p, context)
    This is used after a nested function.  */
 
 void
-restore_tree_status (p, context)
+restore_tree_status (p)
      struct function *p;
-     tree context;
 {
   all_types_permanent = p->all_types_permanent;
   momentary_stack = p->momentary_stack;
@@ -423,41 +393,18 @@ restore_tree_status (p, context)
   obstack_free (&momentary_obstack, momentary_function_firstobj);
 
   /* Free saveable storage used by the function just compiled and not
-     saved.
-
-     CAUTION: This is in function_obstack of the containing function.
-     So we must be sure that we never allocate from that obstack during
-     the compilation of a nested function if we expect it to survive
-     past the nested function's end.  */
+     saved.  */
   obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj);
-
-  /* If we were compiling a toplevel function, we can free this space now.  */
-  if (context == NULL_TREE)
+  if (obstack_empty_p (function_maybepermanent_obstack))
     {
-      obstack_free (&temporary_obstack, temporary_firstobj);
-      obstack_free (&momentary_obstack, momentary_function_firstobj);
+      obstack_free (function_maybepermanent_obstack, NULL);
+      free (function_maybepermanent_obstack);
     }
 
-  /* If we were compiling a toplevel function that we don't actually want
-     to save anything from, return the obstack to the pool.  */
-  if (context == NULL_TREE
-      && obstack_empty_p (function_maybepermanent_obstack))
-    {
-      struct simple_obstack_stack *current, **p = &toplev_inline_obstacks;
-
-      if ((*p) != NULL)
-       {
-         while ((*p)->obstack != function_maybepermanent_obstack)
-           p = &((*p)->next);
-         current = *p;
-         *p = current->next;
-
-         current->next = extra_inline_obstacks;
-         extra_inline_obstacks = current;
-       }
-    }
+  obstack_free (&temporary_obstack, temporary_firstobj);
+  obstack_free (&momentary_obstack, momentary_function_firstobj);
 
-  obstack_free (function_obstack, 0);
+  obstack_free (function_obstack, NULL);
   free (function_obstack);
 
   temporary_firstobj = p->temporary_firstobj;
@@ -470,7 +417,6 @@ restore_tree_status (p, context)
   expression_obstack = p->expression_obstack;
   saveable_obstack = p->saveable_obstack;
   rtl_obstack = p->rtl_obstack;
-  inline_obstacks = p->inline_obstacks;
 }
 \f
 /* Start allocating on the temporary (per function) obstack.
@@ -487,7 +433,6 @@ temporary_allocation ()
   expression_obstack = function_obstack;
   rtl_obstack = saveable_obstack = function_maybepermanent_obstack;
   momentary_stack = 0;
-  inline_obstacks = 0;
 }
 
 /* Start allocating on the permanent obstack but don't
@@ -534,8 +479,9 @@ void
 push_obstacks (current, saveable)
      struct obstack *current, *saveable;
 {
-  struct obstack_stack *p
-    = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
+  struct obstack_stack *p;
+
+  p = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
                                              (sizeof (struct obstack_stack)));
 
   p->current = current_obstack;
@@ -555,8 +501,9 @@ push_obstacks (current, saveable)
 void
 push_obstacks_nochange ()
 {
-  struct obstack_stack *p
-    = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
+  struct obstack_stack *p;
+  
+  p = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
                                              (sizeof (struct obstack_stack)));
 
   p->current = current_obstack;
@@ -572,7 +519,9 @@ push_obstacks_nochange ()
 void
 pop_obstacks ()
 {
-  struct obstack_stack *p = obstack_stack;
+  struct obstack_stack *p;
+
+  p = obstack_stack;
   obstack_stack = p->next;
 
   current_obstack = p->current;
@@ -615,17 +564,6 @@ permanent_allocation (function_end)
   obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj);
   obstack_free (&temp_decl_obstack, temp_decl_firstobj);
 
-  /* Free up the maybepermanent_obstacks for any of our nested functions
-     which were compiled at a lower level.  */
-  while (inline_obstacks)
-    {
-      struct simple_obstack_stack *current = inline_obstacks;
-      inline_obstacks = current->next;
-      obstack_free (current->obstack, 0);
-      free (current->obstack);
-      free (current);
-    }
-
   current_obstack = &permanent_obstack;
   expression_obstack = &permanent_obstack;
   rtl_obstack = saveable_obstack = &permanent_obstack;
@@ -750,10 +688,10 @@ void
 print_obstack_name (object, file, prefix)
      char *object;
      FILE *file;
-     char *prefix;
+     const char *prefix;
 {
   struct obstack *obstack = NULL;
-  char *obstack_name = NULL;
+  const char *obstack_name = NULL;
   struct function *p;
 
   for (p = outer_function_chain; p; p = p->next)
@@ -945,9 +883,8 @@ make_node (code)
 {
   register tree t;
   register int type = TREE_CODE_CLASS (code);
-  register int length;
+  register int length = 0;
   register struct obstack *obstack = current_obstack;
-  register int i;
 #ifdef GATHER_STATISTICS
   register tree_node_kind kind;
 #endif
@@ -1077,20 +1014,19 @@ make_node (code)
       abort ();
     }
 
-  t = (tree) obstack_alloc (obstack, length);
+  if (ggc_p)
+    t = ggc_alloc_tree (length);
+  else
+    {
+      t = (tree) obstack_alloc (obstack, length);
+      bzero ((PTR) t, length);
+    }
 
 #ifdef GATHER_STATISTICS
   tree_node_counts[(int)kind]++;
   tree_node_sizes[(int)kind] += length;
 #endif
 
-  /* Clear a word at a time.  */
-  for (i = (length / sizeof (int)) - 1; i >= 0; i--)
-    ((int *) t)[i] = 0;
-  /* Clear any extra bytes.  */
-  for (i = length / sizeof (int) * sizeof (int); i < length; i++)
-    ((char *) t)[i] = 0;
-
   TREE_SET_CODE (t, code);
   if (obstack == &permanent_obstack)
     TREE_PERMANENT (t) = 1;
@@ -1110,6 +1046,9 @@ make_node (code)
       DECL_SOURCE_LINE (t) = lineno;
       DECL_SOURCE_FILE (t) = (input_filename) ? input_filename : "<built-in>";
       DECL_UID (t) = next_decl_uid++;
+      /* Note that we have not yet computed the alias set for this
+        declaration.  */
+      DECL_POINTER_ALIAS_SET (t) = -1;
       break;
 
     case 't':
@@ -1121,6 +1060,9 @@ make_node (code)
 #ifdef SET_DEFAULT_TYPE_ATTRIBUTES
       SET_DEFAULT_TYPE_ATTRIBUTES (t);
 #endif
+      /* Note that we have not yet computed the alias set for this
+        type.  */
+      TYPE_ALIAS_SET (t) = -1;
       break;
 
     case 'c':
@@ -1131,8 +1073,11 @@ make_node (code)
   return t;
 }
 \f
-/* Return a new node with the same contents as NODE
-   except that its TREE_CHAIN is zero and it has a fresh uid.  */
+/* 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
+   function always performs the allocation on the CURRENT_OBSTACK;
+   it's up to the caller to pick the right obstack before calling this
+   function.  */
 
 tree
 copy_node (node)
@@ -1140,8 +1085,7 @@ copy_node (node)
 {
   register tree t;
   register enum tree_code code = TREE_CODE (node);
-  register int length;
-  register int i;
+  register int length = 0;
 
   switch (TREE_CODE_CLASS (code))
     {
@@ -1189,15 +1133,15 @@ copy_node (node)
        length += (TREE_VEC_LENGTH (node) - 1) * sizeof (char *);
     }
 
-  t = (tree) obstack_alloc (current_obstack, length);
-
-  for (i = (length / sizeof (int)) - 1; i >= 0; i--)
-    ((int *) t)[i] = ((int *) node)[i];
-  /* Clear any extra bytes.  */
-  for (i = length / sizeof (int) * sizeof (int); i < length; i++)
-    ((char *) t)[i] = ((char *) node)[i];
+  if (ggc_p)
+    t = ggc_alloc_tree (length);
+  else
+    t = (tree) obstack_alloc (current_obstack, length);
+  memcpy (t, node, length);
 
-  TREE_CHAIN (t) = 0;
+  /* 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_ASM_WRITTEN (t) = 0;
 
   if (TREE_CODE_CLASS (code) == 'd')
@@ -1253,7 +1197,7 @@ copy_list (list)
 
 tree
 get_identifier (text)
-     register char *text;
+     register const char *text;
 {
   register int hi;
   register int i;
@@ -1261,11 +1205,11 @@ get_identifier (text)
   register int len, hash_len;
 
   /* Compute length of text in len.  */
-  for (len = 0; text[len]; len++);
+  len = strlen (text);
 
   /* Decide how much of that length to hash on */
   hash_len = len;
-  if (warn_id_clash && len > id_clash_len)
+  if (warn_id_clash && (unsigned)len > id_clash_len)
     hash_len = id_clash_len;
 
   /* Compute hash code */
@@ -1284,7 +1228,7 @@ get_identifier (text)
       return idp;              /* <-- return if found */
 
   /* Not found; optionally warn about a similar identifier */
-  if (warn_id_clash && do_identifier_warnings && len >= id_clash_len)
+  if (warn_id_clash && do_identifier_warnings && (unsigned)len >= id_clash_len)
     for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
       if (!strncmp (IDENTIFIER_POINTER (idp), text, id_clash_len))
        {
@@ -1303,7 +1247,10 @@ get_identifier (text)
   id_string_size += len;
 #endif
 
-  IDENTIFIER_POINTER (idp) = obstack_copy0 (&permanent_obstack, text, len);
+  if (ggc_p)
+    IDENTIFIER_POINTER (idp) = ggc_alloc_string (text, len);
+  else
+    IDENTIFIER_POINTER (idp) = obstack_copy0 (&permanent_obstack, text, len);
 
   TREE_CHAIN (idp) = hash_table[hi];
   hash_table[hi] = idp;
@@ -1316,7 +1263,7 @@ get_identifier (text)
 
 tree
 maybe_get_identifier (text)
-     register char *text;
+     register const char *text;
 {
   register int hi;
   register int i;
@@ -1324,11 +1271,11 @@ maybe_get_identifier (text)
   register int len, hash_len;
 
   /* Compute length of text in len.  */
-  for (len = 0; text[len]; len++);
+  len = strlen (text);
 
   /* Decide how much of that length to hash on */
   hash_len = len;
-  if (warn_id_clash && len > id_clash_len)
+  if (warn_id_clash && (unsigned)len > id_clash_len)
     hash_len = id_clash_len;
 
   /* Compute hash code */
@@ -1459,6 +1406,29 @@ real_value_from_int_cst (type, i)
   return d;
 }
 
+struct brfic_args
+{
+  /* Input */
+  tree type, i;
+  /* Output */
+  REAL_VALUE_TYPE d;
+};
+
+static void
+build_real_from_int_cst_1 (data)
+  PTR 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));
+#endif
+}
+
 /* This function can't be implemented if we can't do arithmetic
    on the float representation.  */
 
@@ -1470,32 +1440,29 @@ build_real_from_int_cst (type, i)
   tree v;
   int overflow = TREE_OVERFLOW (i);
   REAL_VALUE_TYPE d;
-  jmp_buf float_error;
+  struct brfic_args args;
 
   v = make_node (REAL_CST);
   TREE_TYPE (v) = type;
 
-  if (setjmp (float_error))
+  /* Setup input for build_real_from_int_cst_1() */
+  args.type = type;
+  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;
+    }
+  else
+    {
+      /* We got an exception from build_real_from_int_cst_1() */
       d = dconst0;
       overflow = 1;
-      goto got_it;
     }
-
-  set_float_handler (float_error);
-
-#ifdef REAL_ARITHMETIC
-  d = real_value_from_int_cst (type, i);
-#else
-  d = REAL_VALUE_TRUNCATE (TYPE_MODE (type),
-                          real_value_from_int_cst (type, i));
-#endif
-
+  
   /* Check for valid float value for this type on this target machine.  */
 
- got_it:
-  set_float_handler (NULL_PTR);
-
 #ifdef CHECK_FLOAT_VALUE
   CHECK_FLOAT_VALUE (TYPE_MODE (type), d, overflow);
 #endif
@@ -1514,7 +1481,7 @@ build_real_from_int_cst (type, i)
 tree
 build_string (len, str)
      int len;
-     char *str;
+     const char *str;
 {
   /* Put the string in saveable_obstack since it will be placed in the RTL
      for an "asm" statement and will also be kept around a while if
@@ -1522,7 +1489,10 @@ build_string (len, str)
 
   register tree s = make_node (STRING_CST);
   TREE_STRING_LENGTH (s) = len;
-  TREE_STRING_POINTER (s) = obstack_copy0 (saveable_obstack, str, 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;
 }
 
@@ -1556,17 +1526,19 @@ make_tree_vec (len)
   register tree t;
   register int length = (len-1) * sizeof (tree) + sizeof (struct tree_vec);
   register struct obstack *obstack = current_obstack;
-  register int i;
 
 #ifdef GATHER_STATISTICS
   tree_node_counts[(int)vec_kind]++;
   tree_node_sizes[(int)vec_kind] += length;
 #endif
 
-  t = (tree) obstack_alloc (obstack, length);
-
-  for (i = (length / sizeof (int)) - 1; i >= 0; i--)
-    ((int *) t)[i] = 0;
+  if (ggc_p)
+    t = ggc_alloc_tree (length);
+  else
+    {
+      t = (tree) obstack_alloc (obstack, length);
+      bzero ((PTR) t, length);
+    }
 
   TREE_SET_CODE (t, TREE_VEC);
   TREE_VEC_LENGTH (t) = len;
@@ -1683,7 +1655,7 @@ integer_pow2p (expr)
   if (TREE_CODE (expr) != INTEGER_CST || TREE_CONSTANT_OVERFLOW (expr))
     return 0;
 
-  prec = (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
+  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);
@@ -1724,7 +1696,7 @@ tree_log2 (expr)
   if (TREE_CODE (expr) == COMPLEX_CST)
     return tree_log2 (TREE_REALPART (expr));
 
-  prec = (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
+  prec = (POINTER_TYPE_P (TREE_TYPE (expr))
          ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
 
   high = TREE_INT_CST_HIGH (expr);
@@ -1943,14 +1915,18 @@ chainon (op1, op2)
   if (op1)
     {
       register tree t1;
+#ifdef ENABLE_CHECKING
       register tree t2;
+#endif
 
       for (t1 = op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1))
        ;
       TREE_CHAIN (t1) = op2;
+#ifdef ENABLE_CHECKING
       for (t2 = op2; t2; t2 = TREE_CHAIN (t2))
         if (t2 == t1)
           abort ();  /* Circularity created.  */
+#endif
       return op1;
     }
   else return op2;
@@ -2063,15 +2039,21 @@ tree_cons (purpose, value, chain)
 #if 0
   register tree node = make_node (TREE_LIST);
 #else
-  register int i;
-  register tree node = (tree) obstack_alloc (current_obstack, sizeof (struct tree_list));
+  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));
+    }
+
 #ifdef GATHER_STATISTICS
   tree_node_counts[(int)x_kind]++;
   tree_node_sizes[(int)x_kind] += sizeof (struct tree_list);
 #endif
 
-  for (i = (sizeof (struct tree_common) / sizeof (int)) - 1; i >= 0; i--)
-    ((int *) node)[i] = 0;
 
   TREE_SET_CODE (node, TREE_LIST);
   if (current_obstack == &permanent_obstack)
@@ -2171,42 +2153,40 @@ size_in_bytes (type)
 
   if (type == error_mark_node)
     return integer_zero_node;
+
   type = TYPE_MAIN_VARIANT (type);
-  if (TYPE_SIZE (type) == 0)
+  t = TYPE_SIZE_UNIT (type);
+  if (t == 0)
     {
       incomplete_type_error (NULL_TREE, type);
       return integer_zero_node;
     }
-  t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
-                 size_int (BITS_PER_UNIT));
   if (TREE_CODE (t) == INTEGER_CST)
     force_fit_type (t, 0);
+
   return t;
 }
 
-/* Return the size of TYPE (in bytes) as an integer,
-   or return -1 if the size can vary.  */
+/* Return the size of TYPE (in bytes) as a wide integer
+   or return -1 if the size can vary or is larger than an integer.  */
 
-int
+HOST_WIDE_INT
 int_size_in_bytes (type)
      tree type;
 {
-  unsigned int size;
+  tree t;
+
   if (type == error_mark_node)
     return 0;
+
   type = TYPE_MAIN_VARIANT (type);
-  if (TYPE_SIZE (type) == 0)
-    return -1;
-  if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+  t = TYPE_SIZE_UNIT (type);
+  if (t == 0
+      || TREE_CODE (t) != INTEGER_CST
+      || TREE_INT_CST_HIGH (t) != 0)
     return -1;
-  if (TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0)
-    {
-      tree t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
-                          size_int (BITS_PER_UNIT));
-      return TREE_INT_CST_LOW (t);
-    }
-  size = TREE_INT_CST_LOW (TYPE_SIZE (type));
-  return (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
+
+  return TREE_INT_CST_LOW (t);
 }
 \f
 /* Return, as a tree node, the number of elements for TYPE (which is an
@@ -2233,7 +2213,7 @@ array_type_nelts (type)
   if (! TREE_CONSTANT (min))
     {
       STRIP_NOPS (min);
-      if (TREE_CODE (min) == SAVE_EXPR)
+      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
@@ -2243,7 +2223,7 @@ array_type_nelts (type)
   if (! TREE_CONSTANT (max))
     {
       STRIP_NOPS (max);
-      if (TREE_CODE (max) == SAVE_EXPR)
+      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
@@ -2267,9 +2247,12 @@ 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);
+       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);
+      return (TREE_STATIC (arg) || DECL_EXTERNAL (arg))
+             && ! DECL_NON_ADDR_CONST_P (arg);
 
     case CONSTRUCTOR:
       return TREE_STATIC (arg);
@@ -2387,8 +2370,38 @@ unsave_expr (expr)
   return t;
 }
 
+/* Returns the index of the first non-tree operand for CODE, or the number
+   of operands if all are trees.  */
+
+int
+first_rtl_op (code)
+     enum tree_code code;
+{
+  switch (code)
+    {
+    case SAVE_EXPR:
+      return 2;
+    case GOTO_SUBROUTINE_EXPR:
+    case RTL_EXPR:
+      return 0;
+    case CALL_EXPR:
+      return 2;
+    case WITH_CLEANUP_EXPR:
+      /* Should be defined to be 2.  */
+      return 1;
+    case METHOD_CALL_EXPR:
+      return 3;
+    default:
+      return tree_code_length [(int) code];
+    }
+}
+
 /* Modify a tree in place so that all the evaluate only once things
-   are cleared out.  Return the EXPR given.  */
+   are cleared out.  Return the EXPR given.  
+
+   LANG_UNSAVE_EXPR_NOW, if set, is a pointer to a function to handle
+   language specific nodes.
+*/
 
 tree
 unsave_expr_now (expr)
@@ -2402,12 +2415,11 @@ unsave_expr_now (expr)
     return expr;
 
   code = TREE_CODE (expr);
-  first_rtl = tree_code_length [(int) code];
+  first_rtl = first_rtl_op (code);
   switch (code)
     {
     case SAVE_EXPR:
       SAVE_EXPR_RTL (expr) = 0;
-      first_rtl = 2;
       break;
 
     case TARGET_EXPR:
@@ -2419,7 +2431,6 @@ unsave_expr_now (expr)
       /* I don't yet know how to emit a sequence multiple times.  */
       if (RTL_EXPR_SEQUENCE (expr) != 0)
        abort ();
-      first_rtl = 0;
       break;
 
     case CALL_EXPR:
@@ -2434,19 +2445,11 @@ unsave_expr_now (expr)
              exp = TREE_CHAIN (exp);
            }
        }
-      first_rtl = 2;
-      break;
-
-    case WITH_CLEANUP_EXPR:
-      /* Should be defined to be 2.  */
-      first_rtl = 1;
-      break;
-
-    case METHOD_CALL_EXPR:
-      first_rtl = 3;
       break;
 
     default:
+      if (lang_unsave_expr_now)
+       (*lang_unsave_expr_now) (expr);
       break;
     }
 
@@ -2560,6 +2563,66 @@ contains_placeholder_p (exp)
     default:
       return 0;
     }
+  return 0;
+}
+
+/* Return 1 if EXP contains any expressions that produce cleanups for an
+   outer scope to deal with.  Used by fold.  */
+
+int
+has_cleanups (exp)
+     tree exp;
+{
+  int i, nops, cmp;
+
+  if (! TREE_SIDE_EFFECTS (exp))
+    return 0;
+
+  switch (TREE_CODE (exp))
+    {
+    case TARGET_EXPR:
+    case GOTO_SUBROUTINE_EXPR:
+    case WITH_CLEANUP_EXPR:
+      return 1;
+
+    case CLEANUP_POINT_EXPR:
+      return 0;
+
+    case CALL_EXPR:
+      for (exp = TREE_OPERAND (exp, 1); exp; exp = TREE_CHAIN (exp))
+       {
+         cmp = has_cleanups (TREE_VALUE (exp));
+         if (cmp)
+           return cmp;
+       }
+      return 0;
+
+    default:
+      break;
+    }
+
+  /* This general rule works for most tree codes.  All exceptions should be
+     handled above.  If this is a language-specific tree code, we can't
+     trust what might be in the operand, so say we don't know
+     the situation.  */
+  if ((int) TREE_CODE (exp) >= (int) LAST_AND_UNUSED_TREE_CODE)
+    return -1;
+
+  nops = first_rtl_op (TREE_CODE (exp));
+  for (i = 0; i < nops; i++)
+    if (TREE_OPERAND (exp, i) != 0)
+      {
+       int type = TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, i)));
+       if (type == 'e' || type == '<' || type == '1' || type == '2'
+           || type == 'r' || type == 's')
+         {
+           cmp = has_cleanups (TREE_OPERAND (exp, i));
+           if (cmp)
+             return cmp;
+         }
+      }
+
+  return 0;
 }
 \f
 /* Given a tree EXP, a FIELD_DECL F, and a replacement value R,
@@ -2909,7 +2972,7 @@ stabilize_reference_1 (e)
 tree
 build VPROTO((enum tree_code code, tree tt, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   enum tree_code code;
   tree tt;
 #endif
@@ -2920,7 +2983,7 @@ build VPROTO((enum tree_code code, tree tt, ...))
 
   VA_START (p, tt);
 
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   code = va_arg (p, enum tree_code);
   tt = va_arg (p, tree);
 #endif
@@ -2984,7 +3047,7 @@ build1 (code, type, node)
      tree node;
 {
   register struct obstack *obstack = expression_obstack;
-  register int i, length;
+  register int length;
 #ifdef GATHER_STATISTICS
   register tree_node_kind kind;
 #endif
@@ -2999,16 +3062,17 @@ build1 (code, type, node)
 
   length = sizeof (struct tree_exp);
 
-  t = (tree) obstack_alloc (obstack, length);
+  if (ggc_p)
+    t = ggc_alloc_tree (length);
+  else
+    t = (tree) obstack_alloc (obstack, length);
+  bzero ((PTR) t, length);
 
 #ifdef GATHER_STATISTICS
   tree_node_counts[(int)kind]++;
   tree_node_sizes[(int)kind] += length;
 #endif
 
-  for (i = (length / sizeof (int)) - 1; i >= 0; i--)
-    ((int *) t)[i] = 0;
-
   TREE_TYPE (t) = type;
   TREE_SET_CODE (t, code);
 
@@ -3035,7 +3099,7 @@ build1 (code, type, node)
 tree
 build_nt VPROTO((enum tree_code code, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   enum tree_code code;
 #endif
   va_list p;
@@ -3045,7 +3109,7 @@ build_nt VPROTO((enum tree_code code, ...))
 
   VA_START (p, code);
 
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   code = va_arg (p, enum tree_code);
 #endif
 
@@ -3065,7 +3129,7 @@ build_nt VPROTO((enum tree_code code, ...))
 tree
 build_parse_node VPROTO((enum tree_code code, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   enum tree_code code;
 #endif
   register struct obstack *ambient_obstack = expression_obstack;
@@ -3076,7 +3140,7 @@ build_parse_node VPROTO((enum tree_code code, ...))
 
   VA_START (p, code);
 
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   code = va_arg (p, enum tree_code);
 #endif
 
@@ -3155,6 +3219,37 @@ build_block (vars, tags, subblocks, supercontext, chain)
   BLOCK_CHAIN (block) = chain;
   return block;
 }
+
+/* EXPR_WITH_FILE_LOCATION are used to keep track of the exact
+   location where an expression or an identifier were encountered. It
+   is necessary for languages where the frontend parser will handle
+   recursively more than one file (Java is one of them).  */
+
+tree
+build_expr_wfl (node, file, line, col)
+     tree node;
+     const char *file;
+     int line, col;
+{
+  static const char *last_file = 0;
+  static tree  last_filenode = NULL_TREE;
+  register tree wfl = make_node (EXPR_WITH_FILE_LOCATION);
+
+  EXPR_WFL_NODE (wfl) = node;
+  EXPR_WFL_SET_LINECOL (wfl, line, col);
+  if (file != last_file)
+    {
+      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
 /* Return a declaration like DDECL except that its DECL_MACHINE_ATTRIBUTE
    is ATTRIBUTE.  */
@@ -3186,7 +3281,6 @@ build_type_attribute_variant (ttype, attribute)
         current_obstack = TYPE_OBSTACK (ttype);
 
       ntype = copy_node (ttype);
-      current_obstack = ambient_obstack;
 
       TYPE_POINTER_TO (ntype) = 0;
       TYPE_REFERENCE_TO (ntype) = 0;
@@ -3195,7 +3289,7 @@ build_type_attribute_variant (ttype, attribute)
       /* Create a new main variant of TYPE.  */
       TYPE_MAIN_VARIANT (ntype) = ntype;
       TYPE_NEXT_VARIANT (ntype) = 0;
-      TYPE_READONLY (ntype) = TYPE_VOLATILE (ntype) = 0;
+      set_type_quals (ntype, TYPE_UNQUALIFIED);
 
       hashcode = TYPE_HASH (TREE_CODE (ntype))
                 + TYPE_HASH (TREE_TYPE (ntype))
@@ -3220,8 +3314,13 @@ build_type_attribute_variant (ttype, attribute)
         }
 
       ntype = type_hash_canon (hashcode, ntype);
-      ttype = build_type_variant (ntype, TYPE_READONLY (ttype),
-                                 TYPE_VOLATILE (ttype));
+      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;
     }
 
   return ttype;
@@ -3233,13 +3332,18 @@ build_type_attribute_variant (ttype, attribute)
 
 int
 valid_machine_attribute (attr_name, attr_args, decl, type)
-     tree attr_name, attr_args;
-     tree decl;
-     tree type;
+  tree attr_name;
+  tree attr_args ATTRIBUTE_UNUSED;
+  tree decl ATTRIBUTE_UNUSED;
+  tree type ATTRIBUTE_UNUSED;
 {
-  int valid = 0;
+  int validated = 0;
+#ifdef VALID_MACHINE_DECL_ATTRIBUTE
   tree decl_attr_list = decl != 0 ? DECL_MACHINE_ATTRIBUTES (decl) : 0;
+#endif
+#ifdef VALID_MACHINE_TYPE_ATTRIBUTE
   tree type_attr_list = TYPE_ATTRIBUTES (type);
+#endif
 
   if (TREE_CODE (attr_name) != IDENTIFIER_NODE)
     abort ();
@@ -3263,12 +3367,15 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
          decl = build_decl_attribute_variant (decl, decl_attr_list);
        }
 
-      valid = 1;
+      validated = 1;
     }
 #endif
 
 #ifdef VALID_MACHINE_TYPE_ATTRIBUTE
-  if (VALID_MACHINE_TYPE_ATTRIBUTE (type, type_attr_list, attr_name, attr_args))
+  if (validated)
+    /* Don't apply the attribute to both the decl and the type.  */;
+  else if (VALID_MACHINE_TYPE_ATTRIBUTE (type, type_attr_list, attr_name,
+                                        attr_args))
     {
       tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
                                    type_attr_list);
@@ -3283,17 +3390,23 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
        }
       else
        {
+         /* If this is part of a declaration, create a type variant,
+            otherwise, this is part of a type definition, so add it 
+            to the base type.  */
          type_attr_list = tree_cons (attr_name, attr_args, type_attr_list);
-         type = build_type_attribute_variant (type, type_attr_list);
+         if (decl != 0)
+           type = build_type_attribute_variant (type, type_attr_list);
+         else
+           TYPE_ATTRIBUTES (type) = type_attr_list;
        }
       if (decl != 0)
        TREE_TYPE (decl) = type;
-      valid = 1;
+      validated = 1;
     }
 
   /* Handle putting a type attribute on pointer-to-function-type by putting
      the attribute on the function type.  */
-  else if (TREE_CODE (type) == POINTER_TYPE
+  else if (POINTER_TYPE_P (type)
           && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
           && VALID_MACHINE_TYPE_ATTRIBUTE (TREE_TYPE (type), type_attr_list,
                                            attr_name, attr_args))
@@ -3314,12 +3427,19 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
 
       if (decl != 0)
        TREE_TYPE (decl) = build_pointer_type (inner_type);
+      else
+       {
+         /* Clear TYPE_POINTER_TO for the old inner type, since
+            `type' won't be pointing to it anymore.  */
+         TYPE_POINTER_TO (TREE_TYPE (type)) = NULL_TREE;
+         TREE_TYPE (type) = inner_type;
+       }
 
-      valid = 1;
+      validated = 1;
     }
 #endif
 
-  return valid;
+  return validated;
 }
 
 /* Return non-zero if IDENT is a valid name for attribute ATTR,
@@ -3332,7 +3452,7 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
 
 int
 is_attribute_p (attr, ident)
-     char *attr;
+     const char *attr;
      tree ident;
 {
   int ident_len, attr_len;
@@ -3377,7 +3497,7 @@ is_attribute_p (attr, ident)
 
 tree
 lookup_attribute (attr_name, list)
-     char *attr_name;
+     const char *attr_name;
      tree list;
 {
   tree l;
@@ -3409,6 +3529,7 @@ merge_attributes (a1, a2)
   /* One that completely contains the other?  Take it.  */
 
   else if (a2 && ! attribute_list_contained (a1, a2))
+  {
     if (attribute_list_contained (a2, a1))
       attributes = a2;
     else
@@ -3428,48 +3549,78 @@ merge_attributes (a1, a2)
              attributes = a1;
            }
       }
+  }
   return attributes;
 }
-\f
-/* Return a type like TYPE except that its TYPE_READONLY is CONSTP
-   and its TYPE_VOLATILE is VOLATILEP.
 
-   Such variant types already made are recorded so that duplicates
-   are not made.
+/* Given types T1 and T2, merge their attributes and return
+   the result.  */
 
-   A variant types should never be used as the type of an expression.
-   Always copy the variant information into the TREE_READONLY
-   and TREE_THIS_VOLATILE of the expression, and then give the expression
-   as its type the "main variant", the variant whose TYPE_READONLY
-   and TYPE_VOLATILE are zero.  Use TYPE_MAIN_VARIANT to find the
-   main variant.  */
+tree
+merge_machine_type_attributes (t1, t2)
+     tree t1, t2;
+{
+#ifdef MERGE_MACHINE_TYPE_ATTRIBUTES
+  return MERGE_MACHINE_TYPE_ATTRIBUTES (t1, t2);
+#else
+  return merge_attributes (TYPE_ATTRIBUTES (t1),
+                          TYPE_ATTRIBUTES (t2));
+#endif
+}
+
+/* Given decls OLDDECL and NEWDECL, merge their attributes and return
+   the result.  */
 
 tree
-build_type_variant (type, constp, volatilep)
+merge_machine_decl_attributes (olddecl, newdecl)
+     tree olddecl, newdecl;
+{
+#ifdef MERGE_MACHINE_DECL_ATTRIBUTES
+  return MERGE_MACHINE_DECL_ATTRIBUTES (olddecl, newdecl);
+#else
+  return merge_attributes (DECL_MACHINE_ATTRIBUTES (olddecl),
+                          DECL_MACHINE_ATTRIBUTES (newdecl));
+#endif
+}
+\f
+/* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask
+   of the various TYPE_QUAL values.  */
+
+static void
+set_type_quals (type, type_quals)
      tree type;
-     int constp, volatilep;
+     int  type_quals;
 {
-  register tree t;
+  TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;
+  TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
+  TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
+}
 
-  /* Treat any nonzero argument as 1.  */
-  constp = !!constp;
-  volatilep = !!volatilep;
+/* Given a type node TYPE and a TYPE_QUALIFIER_SET, return a type for
+   the same kind of data as TYPE describes.  Variants point to the
+   "main variant" (which has no qualifiers set) via TYPE_MAIN_VARIANT,
+   and it points to a chain of other variants so that duplicate
+   variants are never made.  Only main variants should ever appear as
+   types of expressions.  */
 
+tree
+build_qualified_type (type, type_quals)
+     tree type;
+     int type_quals;
+{
+  register tree t;
+  
   /* Search the chain of variants to see if there is already one there just
      like the one we need to have.  If so, use that existing one.  We must
      preserve the TYPE_NAME, since there is code that depends on this.  */
 
   for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
-    if (constp == TYPE_READONLY (t) && volatilep == TYPE_VOLATILE (t)
-       && TYPE_NAME (t) == TYPE_NAME (type))
+    if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type))
       return t;
 
   /* We need a new one.  */
-
   t = build_type_copy (type);
-  TYPE_READONLY (t) = constp;
-  TYPE_VOLATILE (t) = volatilep;
-
+  set_type_quals (t, type_quals);
   return t;
 }
 
@@ -3500,26 +3651,6 @@ build_type_copy (type)
 /* Hashing of types so that we don't make duplicates.
    The entry point is `type_hash_canon'.  */
 
-/* Each hash table slot is a bucket containing a chain
-   of these structures.  */
-
-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.  */
-};
-
-/* 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];
-
 /* Compute a hash code for a list of types (chain of TREE_LIST nodes
    with types in the TREE_VALUE slots), by adding the hash codes
    of the individual types.  */
@@ -3544,12 +3675,18 @@ type_hash_lookup (hashcode, type)
      tree type;
 {
   register struct type_hash *h;
+
+  /* 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)))
@@ -3578,7 +3715,7 @@ type_hash_add (hashcode, type)
 {
   register struct type_hash *h;
 
-  h = (struct type_hash *) oballoc (sizeof (struct type_hash));
+  h = (struct type_hash *) permalloc (sizeof (struct type_hash));
   h->hashcode = hashcode;
   h->type = type;
   h->next = type_hash_table[hashcode % TYPE_HASH_SIZE];
@@ -3612,7 +3749,8 @@ type_hash_canon (hashcode, type)
   t1 = type_hash_lookup (hashcode, type);
   if (t1 != 0)
     {
-      obstack_free (TYPE_OBSTACK (type), 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);
@@ -3621,12 +3759,27 @@ type_hash_canon (hashcode, type)
     }
 
   /* If this is a permanent type, record it for later reuse.  */
-  if (TREE_PERMANENT (type))
+  if (ggc_p || TREE_PERMANENT (type))
     type_hash_add (hashcode, type);
 
   return type;
 }
 
+/* Mark ARG (which is really a struct type_hash **) for GC.  */
+
+static void
+mark_type_hash (arg)
+     void *arg;
+{
+  struct type_hash *t = *(struct type_hash **) arg;
+
+  while (t)
+    {
+      ggc_mark_tree (t->type);
+      t = t->next;
+    }
+}
+
 /* 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.  */
@@ -3812,10 +3965,13 @@ simple_cst_equal (t1, t2)
   code2 = TREE_CODE (t2);
 
   if (code1 == NOP_EXPR || code1 == CONVERT_EXPR || code1 == NON_LVALUE_EXPR)
-    if (code2 == NOP_EXPR || code2 == CONVERT_EXPR || code2 == NON_LVALUE_EXPR)
-      return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
-    else
-      return simple_cst_equal (TREE_OPERAND (t1, 0), t2);
+    {
+      if (code2 == NOP_EXPR || code2 == CONVERT_EXPR
+         || code2 == NON_LVALUE_EXPR)
+       return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+      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));
@@ -3838,7 +3994,10 @@ simple_cst_equal (t1, t2)
                  TREE_STRING_LENGTH (t1));
 
     case CONSTRUCTOR:
-      abort ();
+      if (CONSTRUCTOR_ELTS (t1) == CONSTRUCTOR_ELTS (t2))
+       return 1;
+      else
+       abort ();
 
     case SAVE_EXPR:
       return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
@@ -3978,6 +4137,7 @@ build_index_type (maxval)
 
   TYPE_MODE (itype) = TYPE_MODE (sizetype);
   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)
     {
@@ -4018,6 +4178,7 @@ build_range_type (type, lowval, highval)
   TYPE_PRECISION (itype) = TYPE_PRECISION (type);
   TYPE_MODE (itype) = TYPE_MODE (type);
   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)
     {
@@ -4114,6 +4275,21 @@ build_array_type (elt_type, index_type)
   return t;
 }
 
+/* Return the TYPE of the elements comprising
+   the innermost dimension of ARRAY.  */
+
+tree
+get_inner_array_type (array)
+    tree array;
+{
+  tree type = TREE_TYPE (array);
+
+  while (TREE_CODE (type) == ARRAY_TYPE)
+    type = TREE_TYPE (type);
+
+  return type;
+}
+
 /* Construct, lay out and return
    the type of functions returning type VALUE_TYPE
    given arguments of types ARG_TYPES.
@@ -4155,22 +4331,17 @@ build_reference_type (to_type)
      tree to_type;
 {
   register tree t = TYPE_REFERENCE_TO (to_type);
-  register struct obstack *ambient_obstack = current_obstack;
-  register struct obstack *ambient_saveable_obstack = saveable_obstack;
 
   /* First, if we already have a type for pointers to TO_TYPE, use it.  */
 
   if (t)
     return t;
 
-  /* We need a new one.  If TO_TYPE is permanent, make this permanent too.  */
-  if (TREE_PERMANENT (to_type))
-    {
-      current_obstack = &permanent_obstack;
-      saveable_obstack = &permanent_obstack;
-    }
-
+  /* 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.  */
@@ -4178,8 +4349,6 @@ build_reference_type (to_type)
 
   layout_type (t);
 
-  current_obstack = ambient_obstack;
-  saveable_obstack = ambient_saveable_obstack;
   return t;
 }
 
@@ -4261,8 +4430,7 @@ build_complex_type (component_type)
   t = make_node (COMPLEX_TYPE);
 
   TREE_TYPE (t) = TYPE_MAIN_VARIANT (component_type);
-  TYPE_VOLATILE (t) = TYPE_VOLATILE (component_type);
-  TYPE_READONLY (t) = TYPE_READONLY (component_type);
+  set_type_quals (t, TYPE_QUALS (component_type));
 
   /* If we already have such a type, use the old one and free this one.  */
   hashcode = TYPE_HASH (component_type);
@@ -4303,8 +4471,6 @@ get_unwidened (op, for_type)
      tree for_type;
 {
   /* Set UNS initially if converting OP to FOR_TYPE is a zero-extension.  */
-  /* TYPE_PRECISION is safe in place of type_precision since
-     pointer types are not allowed.  */
   register tree type = TREE_TYPE (op);
   register unsigned final_prec
     = TYPE_PRECISION (for_type != 0 ? for_type : type);
@@ -4470,21 +4636,6 @@ get_narrower (op, unsignedp_ptr)
   return win;
 }
 \f
-/* Return the precision of a type, for arithmetic purposes.
-   Supports all types on which arithmetic is possible
-   (including pointer types).
-   It's not clear yet what will be right for complex types.  */
-
-int
-type_precision (type)
-     register tree type;
-{
-  return ((TREE_CODE (type) == INTEGER_TYPE
-          || TREE_CODE (type) == ENUMERAL_TYPE
-          || TREE_CODE (type) == REAL_TYPE)
-         ? TYPE_PRECISION (type) : POINTER_SIZE);
-}
-
 /* Nonzero if integer constant C has a value that is permissible
    for type TYPE (an INTEGER_TYPE).  */
 
@@ -4529,11 +4680,9 @@ decl_function_context (decl)
 
   while (context && TREE_CODE (context) != FUNCTION_DECL)
     {
-      if (TREE_CODE (context) == RECORD_TYPE
-         || TREE_CODE (context) == UNION_TYPE
-         || TREE_CODE (context) == QUAL_UNION_TYPE)
+      if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
        context = TYPE_CONTEXT (context);
-      else if (TREE_CODE (context) == TYPE_DECL)
+      else if (TREE_CODE_CLASS (TREE_CODE (context)) == 'd')
        context = DECL_CONTEXT (context);
       else if (TREE_CODE (context) == BLOCK)
        context = BLOCK_SUPERCONTEXT (context);
@@ -4573,37 +4722,11 @@ decl_type_context (decl)
   return NULL_TREE;
 }
 
-/* Print debugging information about the size of the
-   toplev_inline_obstacks.  */
-
-void
-print_inline_obstack_statistics ()
-{
-  struct simple_obstack_stack *current = toplev_inline_obstacks;
-  int n_obstacks = 0;
-  int n_alloc = 0;
-  int n_chunks = 0;
-
-  for (; current; current = current->next, ++n_obstacks)
-    {
-      struct obstack *o = current->obstack;
-      struct _obstack_chunk *chunk = o->chunk;
-
-      n_alloc += o->next_free - chunk->contents;
-      chunk = chunk->prev;
-      ++n_chunks;
-      for (; chunk; chunk = chunk->prev, ++n_chunks)
-       n_alloc += chunk->limit - &chunk->contents[0];
-    }
-  fprintf (stderr, "inline obstacks: %d obstacks, %d bytes, %d chunks\n",
-          n_obstacks, n_alloc, n_chunks);
-}
-
 /* Print debugging information about the obstack O, named STR.  */
 
 void
 print_obstack_statistics (str, o)
-     char *str;
+     const char *str;
      struct obstack *o;
 {
   struct _obstack_chunk *chunk = o->chunk;
@@ -4657,54 +4780,116 @@ 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_inline_obstack_statistics ();
   print_lang_statistics ();
 }
 \f
 #define FILE_FUNCTION_PREFIX_LEN 9
 
 #ifndef NO_DOLLAR_IN_LABEL
-#define FILE_FUNCTION_FORMAT "_GLOBAL_$D$%s"
+#define FILE_FUNCTION_FORMAT "_GLOBAL_$%s$%s"
 #else /* NO_DOLLAR_IN_LABEL */
 #ifndef NO_DOT_IN_LABEL
-#define FILE_FUNCTION_FORMAT "_GLOBAL_.D.%s"
+#define FILE_FUNCTION_FORMAT "_GLOBAL_.%s.%s"
 #else /* NO_DOT_IN_LABEL */
-#define FILE_FUNCTION_FORMAT "_GLOBAL__D_%s"
+#define FILE_FUNCTION_FORMAT "_GLOBAL__%s_%s"
 #endif /* NO_DOT_IN_LABEL */
 #endif /* NO_DOLLAR_IN_LABEL */
 
 extern char * first_global_object_name;
+extern char * weak_global_object_name;
 
-/* If KIND=='I', return a suitable global initializer (constructor) name.
-   If KIND=='D', return a suitable global clean-up (destructor) name.  */
+/* Appends 6 random characters to TEMPLATE to (hopefully) avoid name
+   clashes in cases where we can't reliably choose a unique name.
+
+   Derived from mkstemp.c in libiberty.  */
+
+static void
+append_random_chars (template)
+     char *template;
+{
+  static const char letters[]
+    = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+  static unsigned HOST_WIDE_INT value;
+  unsigned HOST_WIDE_INT v;
+
+#ifdef HAVE_GETTIMEOFDAY
+  struct timeval tv;
+#endif
+
+  template += strlen (template);
+
+#ifdef HAVE_GETTIMEOFDAY
+  /* Get some more or less random data.  */
+  gettimeofday (&tv, NULL);
+  value += ((unsigned HOST_WIDE_INT) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();
+#else
+  value += getpid ();
+#endif
+
+  v = value;
+
+  /* Fill in the random bits.  */
+  template[0] = letters[v % 62];
+  v /= 62;
+  template[1] = letters[v % 62];
+  v /= 62;
+  template[2] = letters[v % 62];
+  v /= 62;
+  template[3] = letters[v % 62];
+  v /= 62;
+  template[4] = letters[v % 62];
+  v /= 62;
+  template[5] = letters[v % 62];
+
+  template[6] = '\0';
+}
+
+/* Generate a name for a function unique to this translation unit.
+   TYPE is some string to identify the purpose of this function to the
+   linker or collect2.  */
 
 tree
-get_file_function_name (kind)
-     int kind;
+get_file_function_name_long (type)
+     const char *type;
 {
   char *buf;
   register char *p;
 
   if (first_global_object_name)
     p = first_global_object_name;
-  else if (main_input_filename)
-    p = main_input_filename;
   else
-    p = input_filename;
+    {
+      /* We don't have anything that we know to be unique to this translation
+        unit, so use what we do have and throw in some randomness.  */
+
+      const char *name = weak_global_object_name;
+      const char *file = main_input_filename;
 
-  buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p));
+      if (! name)
+       name = "";
+      if (! file)
+       file = input_filename;
+
+      p = (char *) alloca (7 + strlen (name) + strlen (file));
+
+      sprintf (p, "%s%s", name, file);
+      append_random_chars (p);
+    }
+
+  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
      the program) rather than the file name (which imposes extra
      constraints).  -- Raeburn@MIT.EDU, 10 Jan 1990.  */
-  sprintf (buf, FILE_FUNCTION_FORMAT, p);
+  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 (! ((*p >= '0' && *p <= '9')
+       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 == '.'
@@ -4716,15 +4901,28 @@ get_file_function_name (kind)
 #ifndef NO_DOT_IN_LABEL                /* this for `.'; unlikely, but...  */
               || *p == '.'
 #endif
-              || (*p >= 'A' && *p <= 'Z')
-              || (*p >= 'a' && *p <= 'z')))
+              || ISUPPER(*p)
+              || ISLOWER(*p)))
          *p = '_';
     }
 
-  buf[FILE_FUNCTION_PREFIX_LEN] = kind;
-
   return get_identifier (buf);
 }
+
+/* If KIND=='I', return a suitable global initializer (constructor) name.
+   If KIND=='D', return a suitable global clean-up (destructor) name.  */
+
+tree
+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),
@@ -4796,7 +4994,6 @@ get_set_constructor_bytes (init, buffer, wd_size)
      int wd_size;
 {
   int i;
-  tree vals = TREE_OPERAND (init, 1);
   int set_word_size = BITS_PER_UNIT;
   int bit_size = wd_size * set_word_size;
   int bit_pos = 0;
@@ -4822,3 +5019,246 @@ get_set_constructor_bytes (init, buffer, wd_size)
     }
   return non_const_bits;
 }
+\f
+#if defined ENABLE_CHECKING && (__GNUC__ > 2 || __GNUC_MINOR__ > 6)
+/* Complain that the tree code of NODE does not match the expected CODE.
+   FILE, LINE, and FUNCTION are of the caller.  */
+void
+tree_check_failed (node, code, file, line, function)
+     const tree node;
+     enum tree_code code;
+     const char *file;
+     int line;
+     const char *function;
+{
+  error ("Tree check: expected %s, have %s",
+        tree_code_name[code], tree_code_name[TREE_CODE (node)]);
+  fancy_abort (file, line, function);
+}
+
+/* Similar to above, except that we check for a class of tree
+   code, given in CL.  */
+void
+tree_class_check_failed (node, cl, file, line, function)
+     const tree node;
+     char cl;
+     const char *file;
+     int line;
+     const char *function;
+{
+  error ("Tree check: expected class '%c', have '%c' (%s)",
+        cl, TREE_CODE_CLASS (TREE_CODE (node)),
+        tree_code_name[TREE_CODE (node)]);
+  fancy_abort (file, line, function);
+}
+
+#endif /* ENABLE_CHECKING */
+
+/* Return the alias set for T, which may be either a type or an
+   expression.  */
+
+int
+get_alias_set (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.  */
+
+int
+new_alias_set ()
+{
+  static int last_alias_set;
+  if (flag_strict_aliasing)
+    return ++last_alias_set;
+  else
+    return 0;
+}
+\f
+#ifndef CHAR_TYPE_SIZE
+#define CHAR_TYPE_SIZE BITS_PER_UNIT
+#endif
+
+#ifndef SHORT_TYPE_SIZE
+#define SHORT_TYPE_SIZE (BITS_PER_UNIT * MIN ((UNITS_PER_WORD + 1) / 2, 2))
+#endif
+
+#ifndef INT_TYPE_SIZE
+#define INT_TYPE_SIZE BITS_PER_WORD
+#endif
+
+#ifndef LONG_TYPE_SIZE
+#define LONG_TYPE_SIZE BITS_PER_WORD
+#endif
+
+#ifndef LONG_LONG_TYPE_SIZE
+#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
+#endif
+
+#ifndef FLOAT_TYPE_SIZE
+#define FLOAT_TYPE_SIZE BITS_PER_WORD
+#endif
+
+#ifndef DOUBLE_TYPE_SIZE
+#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
+#endif
+
+#ifndef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
+#endif
+
+/* Create nodes for all integer types (and error_mark_node) using the sizes
+   of C datatypes.  The caller should call set_sizetype soon after calling
+   this function to select one of the types as sizetype.  */
+   
+void
+build_common_tree_nodes (signed_char)
+     int signed_char;
+{
+  error_mark_node = make_node (ERROR_MARK);
+  TREE_TYPE (error_mark_node) = error_mark_node;
+
+  /* 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);
+
+  /* Define `char', which is like either `signed char' or `unsigned char'
+     but not the same as either.  */
+  char_type_node
+    = (signed_char
+       ? make_signed_type (CHAR_TYPE_SIZE)
+       : make_unsigned_type (CHAR_TYPE_SIZE));
+
+  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);
+  long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
+  long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
+
+  intQI_type_node = make_signed_type (GET_MODE_BITSIZE (QImode));
+  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));
+  intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
+
+  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));
+  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;
+}
+
+/* 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.  */
+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);
+
+  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;
+
+  void_type_node = make_node (VOID_TYPE);
+  layout_type (void_type_node);        /* Uses size_zero_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;
+
+  null_pointer_node = build_int_2 (0, 0);
+  TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
+  layout_type (TREE_TYPE (null_pointer_node));
+
+  ptr_type_node = build_pointer_type (void_type_node);
+  const_ptr_type_node
+    = build_pointer_type (build_type_variant (void_type_node, 1, 0));
+
+  float_type_node = make_node (REAL_TYPE);
+  TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
+  layout_type (float_type_node);
+
+  double_type_node = make_node (REAL_TYPE);
+  if (short_double)
+    TYPE_PRECISION (double_type_node) = FLOAT_TYPE_SIZE;
+  else
+    TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
+  layout_type (double_type_node);
+
+  long_double_type_node = make_node (REAL_TYPE);
+  TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
+  layout_type (long_double_type_node);
+
+  complex_integer_type_node = make_node (COMPLEX_TYPE);
+  TREE_TYPE (complex_integer_type_node) = integer_type_node;
+  layout_type (complex_integer_type_node);
+
+  complex_float_type_node = make_node (COMPLEX_TYPE);
+  TREE_TYPE (complex_float_type_node) = float_type_node;
+  layout_type (complex_float_type_node);
+
+  complex_double_type_node = make_node (COMPLEX_TYPE);
+  TREE_TYPE (complex_double_type_node) = double_type_node;
+  layout_type (complex_double_type_node);
+
+  complex_long_double_type_node = make_node (COMPLEX_TYPE);
+  TREE_TYPE (complex_long_double_type_node) = long_double_type_node;
+  layout_type (complex_long_double_type_node);
+
+#ifdef BUILD_VA_LIST_TYPE
+  BUILD_VA_LIST_TYPE(va_list_type_node);
+#else
+  va_list_type_node = ptr_type_node;
+#endif
+}