OSDN Git Service

* c-parse.in (cast_expr): Constify.
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index 62d2a12..0d3a776 100644 (file)
@@ -1,5 +1,5 @@
 /* Language-independent node constructors for parse phase of GNU compiler.
-   Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -35,18 +35,18 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
-#include <setjmp.h>
 #include "flags.h"
 #include "tree.h"
-#include "except.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));
 
 /* Tree nodes of permanent duration are allocated in this obstack.
    They are the identifier nodes, and everything outside of
@@ -66,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.
@@ -195,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
@@ -225,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",
@@ -264,12 +249,44 @@ 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));
+static void mark_type_hash PROTO ((void *));
+static void fix_sizetype PROTO ((tree));
+
+/* If non-null, a language specific helper for unsave_expr_now. */
 
-extern char *mode_name[];
+void (*lang_unsave_expr_now) PROTO((tree));
 
-void gcc_obstack_init ();
+/* 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.  */
 
@@ -298,6 +315,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
@@ -316,20 +339,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;
@@ -343,50 +368,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);
 
@@ -406,9 +391,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;
@@ -416,41 +400,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;
@@ -463,7 +424,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.
@@ -480,7 +440,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
@@ -527,8 +486,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;
@@ -548,8 +508,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;
@@ -565,7 +526,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;
@@ -608,17 +571,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;
@@ -743,10 +695,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)
@@ -922,7 +874,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.
@@ -940,7 +894,6 @@ make_node (code)
   register int type = TREE_CODE_CLASS (code);
   register int length = 0;
   register struct obstack *obstack = current_obstack;
-  register int i;
 #ifdef GATHER_STATISTICS
   register tree_node_kind kind;
 #endif
@@ -1070,8 +1023,13 @@ make_node (code)
       abort ();
     }
 
-  t = (tree) obstack_alloc (obstack, length);
-  bzero (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]++;
@@ -1095,7 +1053,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.  */
@@ -1119,13 +1078,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)
@@ -1134,7 +1132,6 @@ copy_node (node)
   register tree t;
   register enum tree_code code = TREE_CODE (node);
   register int length = 0;
-  register int i;
 
   switch (TREE_CODE_CLASS (code))
     {
@@ -1182,8 +1179,11 @@ copy_node (node)
        length += (TREE_VEC_LENGTH (node) - 1) * sizeof (char *);
     }
 
-  t = (tree) obstack_alloc (current_obstack, length);
-  bzero (t, 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)
@@ -1243,7 +1243,7 @@ copy_list (list)
 
 tree
 get_identifier (text)
-     register char *text;
+     register const char *text;
 {
   register int hi;
   register int i;
@@ -1293,7 +1293,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;
@@ -1306,7 +1309,7 @@ get_identifier (text)
 
 tree
 maybe_get_identifier (text)
-     register char *text;
+     register const char *text;
 {
   register int hi;
   register int i;
@@ -1449,6 +1452,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.  */
 
@@ -1460,32 +1486,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
@@ -1504,7 +1527,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
@@ -1512,7 +1535,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;
 }
 
@@ -1546,15 +1572,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);
-  bzero (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;
@@ -1931,14 +1961,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;
@@ -2051,15 +2085,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)
@@ -2219,7 +2259,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
@@ -2229,7 +2269,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
@@ -2387,6 +2427,7 @@ first_rtl_op (code)
     {
     case SAVE_EXPR:
       return 2;
+    case GOTO_SUBROUTINE_EXPR:
     case RTL_EXPR:
       return 0;
     case CALL_EXPR:
@@ -2402,7 +2443,11 @@ first_rtl_op (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)
@@ -2449,6 +2494,8 @@ unsave_expr_now (expr)
       break;
 
     default:
+      if (lang_unsave_expr_now)
+       (*lang_unsave_expr_now) (expr);
       break;
     }
 
@@ -2580,6 +2627,7 @@ has_cleanups (exp)
   switch (TREE_CODE (exp))
     {
     case TARGET_EXPR:
+    case GOTO_SUBROUTINE_EXPR:
     case WITH_CLEANUP_EXPR:
       return 1;
 
@@ -2978,6 +3026,7 @@ build VPROTO((enum tree_code code, tree tt, ...))
   register tree t;
   register int length;
   register int i;
+  int fro;
 
   VA_START (p, tt);
 
@@ -2990,6 +3039,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.  */
@@ -2997,11 +3052,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)
     {
@@ -3011,9 +3075,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
     {
@@ -3021,7 +3088,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;
@@ -3045,7 +3112,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
@@ -3060,8 +3127,13 @@ build1 (code, type, node)
 
   length = sizeof (struct tree_exp);
 
-  t = (tree) obstack_alloc (obstack, length);
-  bzero (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]++;
@@ -3075,7 +3147,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;
@@ -3083,6 +3155,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;
 }
 
@@ -3208,7 +3299,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;
@@ -3223,10 +3313,10 @@ build_block (vars, tags, subblocks, supercontext, chain)
 tree
 build_expr_wfl (node, file, line, col)
      tree node;
-     char *file;
+     const char *file;
      int line, col;
 {
-  static char *last_file = 0;
+  static const char *last_file = 0;
   static tree  last_filenode = NULL_TREE;
   register tree wfl = make_node (EXPR_WITH_FILE_LOCATION);
 
@@ -3276,7 +3366,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;
@@ -3311,6 +3400,12 @@ 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;
     }
 
   return ttype;
@@ -3327,7 +3422,7 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
   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
@@ -3357,12 +3452,12 @@ 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)
+  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))
@@ -3391,7 +3486,7 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
        }
       if (decl != 0)
        TREE_TYPE (decl) = type;
-      valid = 1;
+      validated = 1;
     }
 
   /* Handle putting a type attribute on pointer-to-function-type by putting
@@ -3417,12 +3512,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,
@@ -3435,7 +3537,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;
@@ -3480,7 +3582,7 @@ is_attribute_p (attr, ident)
 
 tree
 lookup_attribute (attr_name, list)
-     char *attr_name;
+     const char *attr_name;
      tree list;
 {
   tree l;
@@ -3634,26 +3736,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.  */
@@ -3678,12 +3760,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)))
@@ -3712,7 +3800,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];
@@ -3746,7 +3834,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);
@@ -3755,12 +3844,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.  */
@@ -4420,6 +4524,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
@@ -4703,37 +4841,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;
@@ -4787,7 +4899,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
@@ -4858,7 +4969,7 @@ append_random_chars (template)
 
 tree
 get_file_function_name_long (type)
-     char *type;
+     const char *type;
 {
   char *buf;
   register char *p;
@@ -4870,8 +4981,8 @@ get_file_function_name_long (type)
       /* 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.  */
 
-      char *name = weak_global_object_name;
-      char *file = main_input_filename;
+      const char *name = weak_global_object_name;
+      const char *file = main_input_filename;
 
       if (! name)
        name = "";
@@ -4897,7 +5008,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 == '.'
@@ -4909,8 +5020,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 = '_';
     }
 
@@ -5028,83 +5139,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 && HAVE_GCC_VERSION(2,7)
+/* 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;
-     char *file;
+     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;
-     char *file;
+     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;
-     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.  */
@@ -5127,5 +5194,190 @@ int
 new_alias_set ()
 {
   static int last_alias_set;
-  return ++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
 }