tree.c (decl_function_context): Handle virtual functions.
[gcc.git] / gcc / tree.c
index f0dc0ee4da5e439836168035009989adf73ac637..78ea4cf976a7a9d3d5cedafca27adf9ab6a98a46 100644 (file)
@@ -37,14 +37,18 @@ Boston, MA 02111-1307, USA.  */
 #include "system.h"
 #include "flags.h"
 #include "tree.h"
+#include "tm_p.h"
 #include "function.h"
 #include "obstack.h"
 #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, GENERIC_PTR obj));
+extern int _obstack_allocated_p PROTO ((struct obstack *h, PTR obj));
+
+static void unsave_expr_now_r PROTO ((tree));
 
 /* Tree nodes of permanent duration are allocated in this obstack.
    They are the identifier nodes, and everything outside of
@@ -64,21 +68,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.
@@ -193,7 +182,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
@@ -223,7 +212,7 @@ int tree_node_counts[(int)all_kinds];
 int tree_node_sizes[(int)all_kinds];
 int id_string_size = 0;
 
-const char *tree_node_kind_names[] = {
+static const char * const tree_node_kind_names[] = {
   "decls",
   "types",
   "blocks",
@@ -262,13 +251,48 @@ int (*lang_get_alias_set) PROTO((tree));
    codes are made.  */
 #define TYPE_HASH(TYPE) ((unsigned long) (TYPE) & 0777777)
 
+/* 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));
-
-extern char *mode_name[];
-
-void gcc_obstack_init ();
+static void mark_type_hash PROTO ((void *));
+static void fix_sizetype PROTO ((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) PROTO((tree *));
+void (*lang_unsave_expr_now) PROTO((tree));
+
+/* The string used as a placeholder instead of a source file name for
+   built-in tree nodes.  The variable, which is dynamically allocated,
+   should be used; the macro is only used to initialize it.  */
+
+static char *built_in_filename;
+#define BUILT_IN_FILENAME ("<built-in>")
+\f
+tree global_trees[TI_MAX];
 \f
 /* Init the principal obstacks.  */
 
@@ -297,6 +321,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
@@ -315,8 +345,8 @@ 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
@@ -329,9 +359,8 @@ gcc_obstack_init (obstack)
    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;
@@ -345,50 +374,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 (current_function_decl && 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);
 
@@ -408,9 +397,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;
@@ -418,41 +406,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;
@@ -465,7 +430,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.
@@ -482,7 +446,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
@@ -529,8 +492,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;
@@ -550,8 +514,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;
@@ -567,7 +532,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;
@@ -610,17 +577,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;
@@ -924,7 +880,9 @@ resume_momentary (yes)
 void
 init_tree_codes ()
 {
-  
+  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.
@@ -1071,8 +1029,13 @@ make_node (code)
       abort ();
     }
 
-  t = (tree) obstack_alloc (obstack, length);
-  bzero ((PTR) t, length);
+  if (ggc_p)
+    t = ggc_alloc_tree (length);
+  else
+    {
+      t = (tree) obstack_alloc (obstack, length);
+      memset ((PTR) t, 0, length);
+    }
 
 #ifdef GATHER_STATISTICS
   tree_node_counts[(int)kind]++;
@@ -1096,7 +1059,8 @@ make_node (code)
       DECL_IN_SYSTEM_HEADER (t)
        = in_system_header && (obstack == &permanent_obstack);
       DECL_SOURCE_LINE (t) = lineno;
-      DECL_SOURCE_FILE (t) = (input_filename) ? input_filename : "<built-in>";
+      DECL_SOURCE_FILE (t) = 
+       (input_filename) ? input_filename : built_in_filename;
       DECL_UID (t) = next_decl_uid++;
       /* Note that we have not yet computed the alias set for this
         declaration.  */
@@ -1120,13 +1084,52 @@ make_node (code)
     case 'c':
       TREE_CONSTANT (t) = 1;
       break;
+
+    case 'e':
+      switch (code)
+       {
+       case INIT_EXPR:
+       case MODIFY_EXPR:
+       case VA_ARG_EXPR:
+       case RTL_EXPR:
+       case PREDECREMENT_EXPR:
+       case PREINCREMENT_EXPR:
+       case POSTDECREMENT_EXPR:
+       case POSTINCREMENT_EXPR:
+         /* All of these have side-effects, no matter what their
+            operands are.  */
+         TREE_SIDE_EFFECTS (t) = 1;
+         break;
+         
+       default:
+         break;
+       }
+      break;
     }
 
   return t;
 }
+
+/* A front-end can reset this to an appropriate function if types need
+   special handling.  */
+
+tree (*make_lang_type_fn) PROTO((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.  */
+/* 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)
@@ -1182,12 +1185,13 @@ copy_node (node)
        length += (TREE_VEC_LENGTH (node) - 1) * sizeof (char *);
     }
 
-  t = (tree) obstack_alloc (current_obstack, length);
+  if (ggc_p)
+    t = ggc_alloc_tree (length);
+  else
+    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')
@@ -1293,7 +1297,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;
@@ -1532,7 +1539,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;
 }
 
@@ -1572,8 +1582,13 @@ make_tree_vec (len)
   tree_node_sizes[(int)vec_kind] += length;
 #endif
 
-  t = (tree) obstack_alloc (obstack, length);
-  bzero ((PTR) t, length);
+  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;
@@ -1950,7 +1965,9 @@ 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))
        ;
@@ -2072,15 +2089,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)
@@ -2217,10 +2240,7 @@ int_size_in_bytes (type)
 }
 \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.
-
-   Don't let any SAVE_EXPRs escape; if we are called as part of a cleanup
-   action, they would get unsaved.  */
+   ARRAY_TYPE) minus one. This counts only elements of the top array.  */
 
 tree
 array_type_nelts (type)
@@ -2237,26 +2257,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)
-       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)
-       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)));
@@ -2423,26 +2423,18 @@ first_rtl_op (code)
     }
 }
 
-/* Modify a tree in place so that all the evaluate only once things
-   are cleared out.  Return the EXPR given.  */
+/* 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:
@@ -2452,28 +2444,48 @@ unsave_expr_now (expr)
       
     case RTL_EXPR:
       /* I don't yet know how to emit a sequence multiple times.  */
-      if (RTL_EXPR_SEQUENCE (expr) != 0)
+      if (RTL_EXPR_SEQUENCE (expr))
        abort ();
       break;
 
     case CALL_EXPR:
       CALL_EXPR_RTL (expr) = 0;
-      if (TREE_OPERAND (expr, 1)
-         && TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST)
-       {
-         tree exp = TREE_OPERAND (expr, 1);
-         while (exp)
-           {
-             unsave_expr_now (TREE_VALUE (exp));
-             exp = TREE_CHAIN (exp);
-           }
-       }
       break;
 
     default:
+      if (lang_unsave_expr_now)
+       (*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)
+    return;
+
+  unsave_expr_1 (expr);
+
+  code = TREE_CODE (expr);
+  if (code == CALL_EXPR 
+      && TREE_OPERAND (expr, 1)
+      && TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST)
+    {
+      tree exp = TREE_OPERAND (expr, 1);
+      while (exp)
+       {
+         unsave_expr_now_r (TREE_VALUE (exp));
+         exp = TREE_CHAIN (exp);
+       }
+    }
   switch (TREE_CODE_CLASS (code))
     {
     case 'c':  /* a constant */
@@ -2481,7 +2493,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;
+      break;
 
     case 'e':  /* an expression */
     case 'r':  /* a reference */
@@ -2489,14 +2501,33 @@ unsave_expr_now (expr)
     case '<':  /* a comparison expression */
     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;
+      {
+       int i;
+       
+       for (i = first_rtl_op (code) - 1; i >= 0; i--)
+         unsave_expr_now_r (TREE_OPERAND (expr, i));
+      }
+      break;
 
     default:
       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)
+    (*lang_unsave) (&expr);
+  else
+    unsave_expr_now_r (expr);
+
+  return expr;
+}
 \f
 /* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size
    or offset that depends on a field within a record.  */
@@ -3001,6 +3032,7 @@ build VPROTO((enum tree_code code, tree tt, ...))
   register tree t;
   register int length;
   register int i;
+  int fro;
 
   VA_START (p, tt);
 
@@ -3013,6 +3045,12 @@ build VPROTO((enum tree_code code, tree tt, ...))
   length = tree_code_length[(int) code];
   TREE_TYPE (t) = tt;
 
+  /* Below, we automatically set TREE_SIDE_EFFECTS and TREE_RAISED for
+     the result based on those same flags for the arguments.  But, if
+     the arguments aren't really even `tree' expressions, we shouldn't
+     be trying to do this.  */
+  fro = first_rtl_op (code);
+
   if (length == 2)
     {
       /* This is equivalent to the loop below, but faster.  */
@@ -3020,11 +3058,20 @@ build VPROTO((enum tree_code code, tree tt, ...))
       register tree arg1 = va_arg (p, tree);
       TREE_OPERAND (t, 0) = arg0;
       TREE_OPERAND (t, 1) = arg1;
-      if ((arg0 && TREE_SIDE_EFFECTS (arg0))
-         || (arg1 && TREE_SIDE_EFFECTS (arg1)))
-       TREE_SIDE_EFFECTS (t) = 1;
-      TREE_RAISES (t)
-       = (arg0 && TREE_RAISES (arg0)) || (arg1 && TREE_RAISES (arg1));
+      if (arg0 && fro > 0)
+       {
+         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)
     {
@@ -3034,9 +3081,12 @@ build VPROTO((enum tree_code code, tree tt, ...))
       if (TREE_CODE_CLASS (code) != 's')
        abort ();
       TREE_OPERAND (t, 0) = arg0;
-      if (arg0 && TREE_SIDE_EFFECTS (arg0))
-       TREE_SIDE_EFFECTS (t) = 1;
-      TREE_RAISES (t) = (arg0 && TREE_RAISES (arg0));
+      if (fro > 0)
+       {
+         if (arg0 && TREE_SIDE_EFFECTS (arg0))
+           TREE_SIDE_EFFECTS (t) = 1;
+         TREE_RAISES (t) = (arg0 && TREE_RAISES (arg0));
+       }
     }
   else
     {
@@ -3044,7 +3094,7 @@ build VPROTO((enum tree_code code, tree tt, ...))
        {
          register tree operand = va_arg (p, tree);
          TREE_OPERAND (t, i) = operand;
-         if (operand)
+         if (operand && fro > i)
            {
              if (TREE_SIDE_EFFECTS (operand))
                TREE_SIDE_EFFECTS (t) = 1;
@@ -3083,8 +3133,13 @@ build1 (code, type, node)
 
   length = sizeof (struct tree_exp);
 
-  t = (tree) obstack_alloc (obstack, length);
-  bzero ((PTR) t, length);
+  if (ggc_p)
+    t = ggc_alloc_tree (length);
+  else
+    {
+      t = (tree) obstack_alloc (obstack, length);
+      memset ((PTR) t, 0, length);
+    }
 
 #ifdef GATHER_STATISTICS
   tree_node_counts[(int)kind]++;
@@ -3098,7 +3153,7 @@ build1 (code, type, node)
     TREE_PERMANENT (t) = 1;
 
   TREE_OPERAND (t, 0) = node;
-  if (node)
+  if (node && first_rtl_op (code) != 0)
     {
       if (TREE_SIDE_EFFECTS (node))
        TREE_SIDE_EFFECTS (t) = 1;
@@ -3106,6 +3161,25 @@ build1 (code, type, node)
        TREE_RAISES (t) = 1;
     }
 
+  switch (code)
+    {
+    case INIT_EXPR:
+    case MODIFY_EXPR:
+    case VA_ARG_EXPR:
+    case RTL_EXPR:
+    case PREDECREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+      /* All of these have side-effects, no matter what their
+        operands are.  */
+      TREE_SIDE_EFFECTS (t) = 1;
+      break;
+         
+    default:
+      break;
+    }
+
   return t;
 }
 
@@ -3231,7 +3305,6 @@ build_block (vars, tags, 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;
@@ -3292,12 +3365,9 @@ build_type_attribute_variant (ttype, attribute)
   if ( ! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute))
     {
       register int hashcode;
-      register struct obstack *ambient_obstack = current_obstack;
       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;
@@ -3333,12 +3403,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;
@@ -3669,26 +3734,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.  */
@@ -3713,12 +3758,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)))
@@ -3747,7 +3798,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];
@@ -3781,7 +3832,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);
@@ -3790,12 +3842,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.  */
@@ -4455,6 +4522,40 @@ build_complex_type (component_type)
   if (TYPE_SIZE (t) == 0)
     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))
+    {
+      const char *name;
+      if (component_type == char_type_node)
+       name = "complex char";
+      else if (component_type == signed_char_type_node)
+       name = "complex signed char";
+      else if (component_type == unsigned_char_type_node)
+       name = "complex unsigned char";
+      else if (component_type == short_integer_type_node)
+       name = "complex short int";
+      else if (component_type == short_unsigned_type_node)
+       name = "complex short unsigned int";
+      else if (component_type == integer_type_node)
+       name = "complex int";
+      else if (component_type == unsigned_type_node)
+       name = "complex unsigned int";
+      else if (component_type == long_integer_type_node)
+       name = "complex long int";
+      else if (component_type == long_unsigned_type_node)
+       name = "complex long unsigned int";
+      else if (component_type == long_long_integer_type_node)
+       name = "complex long long int";
+      else if (component_type == long_long_unsigned_type_node)
+       name = "complex long long unsigned int";
+      else
+       name = (char *)0;
+
+      if (name)
+       TYPE_NAME (t) = get_identifier (name);
+    }
+
   return t;
 }
 \f
@@ -4677,6 +4778,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
+   NUL_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.  */
 
@@ -4691,20 +4802,24 @@ 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;
@@ -4738,30 +4853,33 @@ decl_type_context (decl)
   return NULL_TREE;
 }
 
-/* Print debugging information about the size of the
-   toplev_inline_obstacks.  */
+/* CALL is a CALL_EXPR.  Return the declaration for the function
+   called, or NULL_TREE if the called function cannot be 
+   determined.  */
 
-void
-print_inline_obstack_statistics ()
+tree
+get_callee_fndecl (call)
+     tree call;
 {
-  struct simple_obstack_stack *current = toplev_inline_obstacks;
-  int n_obstacks = 0;
-  int n_alloc = 0;
-  int n_chunks = 0;
+  tree addr;
 
-  for (; current; current = current->next, ++n_obstacks)
-    {
-      struct obstack *o = current->obstack;
-      struct _obstack_chunk *chunk = o->chunk;
+  /* It's invalid to call this function with anything but a
+     CALL_EXPR.  */
+  if (TREE_CODE (call) != CALL_EXPR)
+    abort ();
 
-      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);
+  /* The first operand to the CALL is the address of the function
+     called.  */
+  addr = TREE_OPERAND (call, 0);
+
+  /* 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.  */
@@ -4822,7 +4940,6 @@ 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
@@ -4932,7 +5049,7 @@ get_file_function_name_long (type)
   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 == '.'
@@ -4944,8 +5061,8 @@ get_file_function_name_long (type)
 #ifndef NO_DOT_IN_LABEL                /* this for `.'; unlikely, but...  */
               || *p == '.'
 #endif
-              || (*p >= 'A' && *p <= 'Z')
-              || (*p >= 'a' && *p <= 'z')))
+              || ISUPPER(*p)
+              || ISLOWER(*p)))
          *p = '_';
     }
 
@@ -5063,83 +5180,39 @@ get_set_constructor_bytes (init, buffer, wd_size)
   return non_const_bits;
 }
 \f
-#ifdef ENABLE_CHECKING
-
-/* Complain if the tree code does not match the expected one.
-   NODE is the tree node in question, CODE is the expected tree code,
-   and FILE and LINE are the filename and line number, respectively,
-   of the line on which the check was done.  If NONFATAL is nonzero,
-   don't abort if the reference is invalid; instead, return 0.
-   If the reference is valid, return NODE.  */
-
-tree
-tree_check (node, code, file, line, nofatal)
-     tree node;
+#if defined ENABLE_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
+tree_check_failed (node, code, file, line, function)
+     const tree node;
      enum tree_code code;
      const char *file;
      int line;
-     int nofatal;
+     const char *function;
 {
-  if (TREE_CODE (node) == code)
-    return node;
-  else if (nofatal)
-    return 0;
-  else
-    fatal ("%s:%d: Expect %s, have %s\n", file, line,
-          tree_code_name[code], tree_code_name[TREE_CODE (node)]);
+  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.  */
-
-tree
-tree_class_check (node, cl, file, line, nofatal)
-     tree node;
+void
+tree_class_check_failed (node, cl, file, line, function)
+     const tree node;
      char cl;
      const char *file;
      int line;
-     int nofatal;
+     const char *function;
 {
-  if (TREE_CODE_CLASS (TREE_CODE (node)) == cl)
-    return node;
-  else if (nofatal)
-    return 0;
-  else
-    fatal ("%s:%d: Expect '%c', have '%s'\n", file, line,
-          cl, tree_code_name[TREE_CODE (node)]);
+  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);
 }
 
-/* Likewise, but complain if the tree node is not an expression.  */
-
-tree
-expr_check (node, ignored, file, line, nofatal)
-     tree node;
-     int ignored;
-     const char *file;
-     int line;
-     int nofatal;
-{
-  switch (TREE_CODE_CLASS (TREE_CODE (node)))
-    {
-    case 'r':
-    case 's':
-    case 'e':
-    case '<':
-    case '1':
-    case '2':
-      break;
-
-    default:
-      if (nofatal)
-       return 0;
-      else
-       fatal ("%s:%d: Expect expression, have '%s'\n", file, line,
-              tree_code_name[TREE_CODE (node)]);
-    }
-
-  return node;
-}
-#endif
+#endif /* ENABLE_CHECKING */
 
 /* Return the alias set for T, which may be either a type or an
    expression.  */
@@ -5167,3 +5240,185 @@ new_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
+}