OSDN Git Service

* java-tree.h (push_labeled_block, pop_labeled_block): Remove.
[pf3gnuchains/gcc-fork.git] / gcc / java / decl.c
index 074a093..8822c9e 100644 (file)
@@ -1,7 +1,7 @@
 /* Process declarations and variables for the GNU compiler for the
    Java(TM) language.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007,
+   2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -17,8 +17,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
 
 Java and all Java-based marks are trademarks or registered trademarks
 of Sun Microsystems, Inc. in the United States and other countries.
@@ -44,7 +44,12 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "java-except.h"
 #include "ggc.h"
 #include "timevar.h"
+#include "cgraph.h"
 #include "tree-inline.h"
+#include "target.h"
+#include "version.h"
+#include "tree-iterator.h"
+#include "langhooks.h"
 
 #if defined (DEBUG_JAVA_BINDING_LEVELS)
 extern void indent (void);
@@ -55,8 +60,37 @@ static tree lookup_name_current_level (tree);
 static tree push_promoted_type (const char *, tree);
 static struct binding_level *make_binding_level (void);
 static tree create_primitive_vtable (const char *);
-static tree check_local_named_variable (tree, tree, int, int *);
 static tree check_local_unnamed_variable (tree, tree, tree);
+static void parse_version (void);
+
+
+/* The following ABI flags are used in the high-order bits of the version
+   ID field. The version ID number itself should never be larger than 
+   0xfffff, so it should be safe to use top 12 bits for these flags. */
+
+#define FLAG_BINARYCOMPAT_ABI (1<<31)  /* Class is built with the BC-ABI. */
+
+#define FLAG_BOOTSTRAP_LOADER (1<<30)  /* Used when defining a class that 
+                                         should be loaded by the bootstrap
+                                         loader.  */
+
+/* If an ABI change is made within a GCC release series, rendering current
+   binaries incompatible with the old runtimes, this number must be set to
+   enforce the compatibility rules. */
+#define MINOR_BINARYCOMPAT_ABI_VERSION 1
+
+/* The runtime may recognize a variety of BC ABIs (objects generated by 
+   different version of gcj), but will probably always require strict 
+   matching for the ordinary (C++) ABI.  */
+
+/* The version ID of the BC ABI that we generate.  This must be kept in
+   sync with parse_version(), libgcj, and reality (if the BC format changes, 
+   this must change).  */
+#define GCJ_CURRENT_BC_ABI_VERSION \
+  (4 * 100000 + 0 * 1000 + MINOR_BINARYCOMPAT_ABI_VERSION)
+
+/* The ABI version number.  */
+tree gcj_abi_version;
 
 /* Name of the Cloneable class.  */
 tree java_lang_cloneable_identifier_node;
@@ -64,10 +98,6 @@ tree java_lang_cloneable_identifier_node;
 /* Name of the Serializable class.  */
 tree java_io_serializable_identifier_node;
 
-/* Set to nonzero value in order to emit class initialization code
-   before static field references.  */
-extern int always_initialize_class_p;
-
 /* The DECL_MAP is a mapping from (index, type) to a decl node.
    If index < max_locals, it is the index of a local variable.
    if index >= max_locals, then index-max_locals is a stack slot.
@@ -78,13 +108,28 @@ extern int always_initialize_class_p;
 
 static GTY(()) tree decl_map;
 
+/* The base_decl_map is contains one variable of ptr_type: this is
+   used to contain every variable of reference type that is ever
+   stored in a local variable slot.  */
+
+static GTY(()) tree base_decl_map;
+
+/* An index used to make temporary identifiers unique.  */
+static int uniq;
+
 /* A list of local variables VAR_DECLs for this method that we have seen
    debug information, but we have not reached their starting (byte) PC yet. */
 
 static GTY(()) tree pending_local_decls;
 
-/* Push a local variable or stack slot into the decl_map,
-   and assign it an rtl. */
+/* The decl for "_Jv_ResolvePoolEntry".  */
+tree soft_resolvepoolentry_node;
+
+/* The decl for the .constants field of an instance of Class.  */
+tree constants_field_decl_node;
+
+/* The decl for the .data field of an instance of Class.  */
+tree constants_data_field_decl_node;
 
 #if defined(DEBUG_JAVA_BINDING_LEVELS)
 int binding_depth = 0;
@@ -94,43 +139,34 @@ int current_pc;
 void
 indent (void)
 {
-  register unsigned i;
+  int i;
 
   for (i = 0; i < binding_depth*2; i++)
     putc (' ', stderr);
 }
 #endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
 
+/* True if decl is a named local variable, i.e. if it is an alias
+   that's used only for debugging purposes.  */
+
+static bool
+debug_variable_p (tree decl)
+{
+  if (TREE_CODE (decl) == PARM_DECL)
+    return false;
+
+  if (LOCAL_SLOT_P (decl))
+    return false;
+
+  return true;
+}
 static tree
 push_jvm_slot (int index, tree decl)
 {
-  struct rtx_def *rtl = NULL;
-  tree type = TREE_TYPE (decl);
-  tree tmp;
-
   DECL_CONTEXT (decl) = current_function_decl;
   layout_decl (decl, 0);
 
-  /* See if we have an appropriate rtl (i.e. same mode) at this index.
-     If so, we must use it. */ 
-  tmp = TREE_VEC_ELT (decl_map, index);
-  while (tmp != NULL_TREE)
-    {
-      if (TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (tmp)))
-       rtl = DECL_RTL_IF_SET (tmp);
-      if (rtl != NULL)
-       break;
-     tmp = DECL_LOCAL_SLOT_CHAIN (tmp);
-    }
-  if (rtl != NULL)
-    SET_DECL_RTL (decl, rtl);
-  else
-    {
-      if (index >= DECL_MAX_LOCALS (current_function_decl))
-       DECL_REGISTER (decl) = 1;
-      expand_decl (decl);
-    }
-
   /* Now link the decl into the decl_map. */
   if (DECL_LANG_SPECIFIC (decl) == NULL)
     {
@@ -141,29 +177,8 @@ push_jvm_slot (int index, tree decl)
     }
   DECL_LOCAL_SLOT_CHAIN (decl) = TREE_VEC_ELT (decl_map, index);
   TREE_VEC_ELT (decl_map, index) = decl;
-  return decl;
-}
 
-/* Find out if 'decl' passed in fits the defined PC location better than
-   'best'.  Return decl if it does, return best if it doesn't.  If decl
-   is returned, then updated is set to true.  */
-
-static tree
-check_local_named_variable (tree best, tree decl, int pc, int *updated)
-{
-  if (pc >= DECL_LOCAL_START_PC (decl)
-      && pc < DECL_LOCAL_END_PC (decl))
-    {
-      if (best == NULL_TREE
-         || (DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best)
-             && DECL_LOCAL_END_PC (decl) < DECL_LOCAL_END_PC (best)))
-        {
-         *updated = 1;
-         return decl;
-       }
-    }
-  
-  return best;
+  return decl;
 }
 
 /* Find the best declaration based upon type.  If 'decl' fits 'type' better
@@ -172,20 +187,45 @@ check_local_named_variable (tree best, tree decl, int pc, int *updated)
 static tree
 check_local_unnamed_variable (tree best, tree decl, tree type)
 {
-    if (TREE_TYPE (decl) == type
-       || (TREE_CODE (TREE_TYPE (decl)) == TREE_CODE (type)
-           && TYPE_PRECISION (TREE_TYPE (decl)) <= 32
-           && TYPE_PRECISION (type) <= 32
-           && TREE_CODE (type) != POINTER_TYPE)
-       || (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
-           && type == ptr_type_node))
-      {
-       if (best == NULL_TREE
-           || (TREE_TYPE (decl) == type && TREE_TYPE (best) != type))
-         return decl;
-      }
+  tree decl_type = TREE_TYPE (decl);
+  
+  gcc_assert (! LOCAL_VAR_OUT_OF_SCOPE_P (decl));
+
+  /* Use the same decl for all integer types <= 32 bits.  This is
+     necessary because sometimes a value is stored as (for example)
+     boolean but loaded as int.  */
+  if (decl_type == type
+      || (INTEGRAL_TYPE_P (decl_type)
+         && INTEGRAL_TYPE_P (type)
+         && TYPE_PRECISION (decl_type) <= 32
+         && TYPE_PRECISION (type) <= 32
+         && TYPE_PRECISION (decl_type) >= TYPE_PRECISION (type))      
+      /*  ptr_type_node is used for null pointers, which are
+         assignment compatible with everything.  */
+      || (TREE_CODE (decl_type) == POINTER_TYPE
+         && type == ptr_type_node)
+      /* Whenever anyone wants to use a slot that is initially
+        occupied by a PARM_DECL of pointer type they must get that
+        decl, even if they asked for a pointer to a different type.
+        However, if someone wants a scalar variable in a slot that
+        initially held a pointer arg -- or vice versa -- we create a
+        new VAR_DECL.  
+
+        ???: As long as verification is correct, this will be a
+        compatible type.  But maybe we should create a dummy variable
+        and replace all references to it with the DECL and a
+        NOP_EXPR.  
+      */
+      || (TREE_CODE (decl_type) == POINTER_TYPE
+         && TREE_CODE (decl) == PARM_DECL
+         && TREE_CODE (type) == POINTER_TYPE))
+    {
+      if (best == NULL_TREE
+         || (decl_type == type && TREE_TYPE (best) != type))
+       return decl;
+    }
 
-    return best;
+  return best;
 }
 
 
@@ -194,46 +234,111 @@ check_local_unnamed_variable (tree best, tree decl, tree type)
    If there is no existing matching decl, allocate one.  */
 
 tree
-find_local_variable (int index, tree type, int pc)
+find_local_variable (int index, tree type, int pc ATTRIBUTE_UNUSED)
 {
-  tree decl = TREE_VEC_ELT (decl_map, index);
-  tree best = NULL_TREE;
-  int found_scoped_var = 0;
+  tree tmp = TREE_VEC_ELT (decl_map, index);
+  tree decl = NULL_TREE;
 
-  /* Scan through every declaration that has been created in this slot. */
-  while (decl != NULL_TREE)
+  /* Scan through every declaration that has been created in this
+     slot.  We're only looking for variables that correspond to local
+     index declarations and PARM_DECLs, not named variables: such
+     local variables are used only for debugging information.  */
+  while (tmp != NULL_TREE)
     {
-       /* Variables created in give_name_to_locals() have a name and have
-        a specified scope, so we can handle them specifically.  We want
-        to use the specific decls created for those so they are assigned
-        the right variables in the debugging information. */
-      if (DECL_NAME (decl) != NULL_TREE)
-       {
-         /* This is a variable we have a name for, so it has a scope
-            supplied in the class file.  But it only matters when we
-            actually have a PC to use.  If pc<0, then we are asking
-            for a stack slot and this decl won't be one of those. */
-         if (pc >= 0)
-           best = check_local_named_variable (best, decl, pc,
-                                              &found_scoped_var);
-       }
-      /* We scan for type information unless we found a variable in the
-        proper scope already. */
-      else if (!found_scoped_var)
-       {
-         /* If we don't have scoping information for a variable, we use
-            a different method to look it up. */
-         best = check_local_unnamed_variable (best, decl, type);
-       }
-
-      decl = DECL_LOCAL_SLOT_CHAIN (decl);
+      if (! debug_variable_p (tmp))
+       decl = check_local_unnamed_variable (decl, tmp, type);
+      tmp = DECL_LOCAL_SLOT_CHAIN (tmp);
+    }
+
+  /* gcj has a function called promote_type(), which is used by both
+     the bytecode compiler and the source compiler.  Unfortunately,
+     the type systems for the Java VM and the Java language are not
+     the same: a boolean in the VM promotes to an int, not to a wide
+     boolean.  If our caller wants something to hold a boolean, that
+     had better be an int, because that slot might be re-used
+     later in integer context.  */
+  if (TREE_CODE (type) == BOOLEAN_TYPE)
+    type = integer_type_node;
+
+  /* If we don't find a match, create one with the type passed in.
+     The name of the variable is #n#m, which n is the variable index
+     in the local variable area and m is a dummy identifier for
+     uniqueness -- multiple variables may share the same local
+     variable index.  We don't call pushdecl() to push pointer types
+     into a binding expr because they'll all be replaced by a single
+     variable that is used for every reference in that local variable
+     slot.  */
+  if (! decl)
+    {
+      char buf[64];
+      tree name;
+      sprintf (buf, "#slot#%d#%d", index, uniq++);
+      name = get_identifier (buf);
+      decl = build_decl (VAR_DECL, name, type);
+      DECL_IGNORED_P (decl) = 1;
+      DECL_ARTIFICIAL (decl) = 1;
+      decl = push_jvm_slot (index, decl);
+      LOCAL_SLOT_P (decl) = 1;
+
+      if (TREE_CODE (type) != POINTER_TYPE)
+       pushdecl_function_level (decl);
+    }
+
+  /* As well as creating a local variable that matches the type, we
+     also create a base variable (of ptr_type) that will hold all its
+     aliases.  */
+  if (TREE_CODE (type) == POINTER_TYPE
+      && ! TREE_VEC_ELT (base_decl_map, index))
+    {
+      char buf[64];
+      tree name;
+      tree base_decl;
+      sprintf (buf, "#ref#%d#%d", index, uniq++);
+      name = get_identifier (buf);
+      base_decl
+       = TREE_VEC_ELT (base_decl_map, index)
+       = build_decl (VAR_DECL, name, ptr_type_node);
+      pushdecl_function_level (base_decl);
+      DECL_IGNORED_P (base_decl) = 1;
+      DECL_ARTIFICIAL (base_decl) = 1;
     }
 
-  if (best != NULL_TREE)
-    return best;
+  return decl;
+}
+
+/* Called during gimplification for every variable.  If the variable
+   is a temporary of pointer type, replace it with a common variable
+   thath is used to hold all pointer types that are ever stored in
+   that slot.  Set WANT_LVALUE if you want a variable that is to be
+   written to.  */
+
+tree 
+java_replace_reference (tree var_decl, bool want_lvalue)
+{
+  tree decl_type;
+
+  if (! base_decl_map)
+    return var_decl;
+
+  decl_type = TREE_TYPE (var_decl);
+
+  if (TREE_CODE (decl_type) == POINTER_TYPE)
+    {
+      if (DECL_LANG_SPECIFIC (var_decl)
+         && LOCAL_SLOT_P (var_decl))
+       {
+         int index = DECL_LOCAL_SLOT_NUMBER (var_decl);
+         tree base_decl = TREE_VEC_ELT (base_decl_map, index); 
+
+         gcc_assert (base_decl);
+         if (! want_lvalue)
+           base_decl = build1 (NOP_EXPR, decl_type, base_decl);
 
-  /* If we don't find a match, create one with the type passed in. */
-  return push_jvm_slot (index, build_decl (VAR_DECL, NULL_TREE, type));
+         return base_decl;
+       }
+    }
+
+  return var_decl;
 }
 
 
@@ -246,7 +351,7 @@ find_stack_slot (int index, tree type)
                              type, -1);
 }
 
-struct binding_level
+struct binding_level GTY(())
   {
     /* A chain of _DECL nodes for all variables, constants, functions,
      * and typedef types.  These are in the reverse of the order supplied.
@@ -264,10 +369,6 @@ struct binding_level
        that were entered and exited one level down.  */
     tree blocks;
 
-    /* The BLOCK node for this level, if one has been preallocated.
-       If 0, the BLOCK is allocated (if needed) when the level is popped.  */
-    tree this_block;
-
     /* The binding level which this one is contained in (inherits from).  */
     struct binding_level *level_chain;
 
@@ -276,27 +377,36 @@ struct binding_level
     /* The bytecode PC that marks the start of this level. */
     int start_pc;
 
-#if defined(DEBUG_JAVA_BINDING_LEVELS)
-    /* Binding depth at which this level began.  */
+    /* The statements in this binding level.  */
+    tree stmts;
+
+    /* An exception range associated with this binding level.  */
+    struct eh_range * GTY((skip (""))) exception_range;
+
+    /* Binding depth at which this level began.  Used only for debugging.  */
     unsigned binding_depth;
-#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
   };
 
 #define NULL_BINDING_LEVEL (struct binding_level *) NULL
 
 /* The binding level currently in effect.  */
 
-static struct binding_level *current_binding_level;
+static GTY(()) struct binding_level *current_binding_level;
 
 /* A chain of binding_level structures awaiting reuse.  */
 
-static struct binding_level *free_binding_level;
+static GTY(()) struct binding_level *free_binding_level;
 
 /* The outermost binding level, for names of file scope.
    This is created when the compiler is started and exists
    through the entire run.  */
 
-static struct binding_level *global_binding_level;
+static GTY(()) struct binding_level *global_binding_level;
+
+/* The binding level that holds variables declared at the outermost
+   level within a function body.  */
+
+static struct binding_level *function_binding_level;
 
 /* A PC value bigger than any PC value we may ever may encounter. */
 
@@ -305,20 +415,17 @@ static struct binding_level *global_binding_level;
 /* Binding level structures are initialized by copying this one.  */
 
 static const struct binding_level clear_binding_level
-  = {NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE,
-       NULL_BINDING_LEVEL, LARGEST_PC, 0};
-
-#if 0
-/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
-   that have names.  Here so we can clear out their names' definitions
-   at the end of the function.  */
-
-static tree named_labels;
-
-/* A list of LABEL_DECLs from outer contexts that are currently shadowed.  */
-
-static tree shadowed_labels;
-#endif
+= {
+    NULL_TREE, /* names */
+    NULL_TREE, /* shadowed */
+    NULL_TREE, /* blocks */
+    NULL_BINDING_LEVEL, /* level_chain */
+    LARGEST_PC, /* end_pc */
+    0, /* start_pc */
+    NULL, /* stmts */
+    NULL, /* exception_range */
+    0, /* binding_depth */
+  };
 
 tree java_global_trees[JTI_MAX];
   
@@ -341,40 +448,12 @@ push_promoted_type (const char *name, tree actual_type)
   TYPE_MAX_VALUE (type) = copy_node (in_max);
   TREE_TYPE (TYPE_MAX_VALUE (type)) = type;
   TYPE_PRECISION (type) = TYPE_PRECISION (int_type_node);
+  TYPE_STRING_FLAG (type) = TYPE_STRING_FLAG (actual_type);
   layout_type (type);
   pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
   return type;
 }
 
-/* Return a definition for a builtin function named NAME and whose data type
-   is TYPE.  TYPE should be a function type with argument types.
-   FUNCTION_CODE tells later passes how to compile calls to this function.
-   See tree.h for its possible values.
-
-   If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
-   the name to be called if we can't opencode the function.  If
-   ATTRS is nonzero, use that for the function's attribute list.  */
-
-tree
-builtin_function (const char *name,
-                 tree type,
-                 int function_code,
-                 enum built_in_class class,
-                 const char *library_name,
-                 tree attrs ATTRIBUTE_UNUSED)
-{
-  tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
-  DECL_EXTERNAL (decl) = 1;
-  TREE_PUBLIC (decl) = 1;
-  if (library_name)
-    SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
-  make_decl_rtl (decl, NULL);
-  pushdecl (decl);
-  DECL_BUILT_IN_CLASS (decl) = class;
-  DECL_FUNCTION_CODE (decl) = function_code;
-  return decl;
-}
-
 /* Return tree that represents a vtable for a primitive array.  */
 static tree
 create_primitive_vtable (const char *name)
@@ -388,15 +467,68 @@ create_primitive_vtable (const char *name)
   return r;
 }
 
+static tree
+do_nothing (tree t)
+{
+  return t;
+}
+
+/* Parse the version string and compute the ABI version number.  */
+static void
+parse_version (void)
+{
+  const char *p = version_string;
+  unsigned int major = 0, minor = 0;
+  unsigned int abi_version;
+
+  /* Skip leading junk.  */
+  while (*p && !ISDIGIT (*p))
+    ++p;
+  gcc_assert (*p);
+
+  /* Extract major version.  */
+  while (ISDIGIT (*p))
+    {
+      major = major * 10 + *p - '0';
+      ++p;
+    }
+
+  gcc_assert (*p == '.' && ISDIGIT (p[1]));
+  ++p;
+
+  /* Extract minor version.  */
+  while (ISDIGIT (*p))
+    {
+      minor = minor * 10 + *p - '0';
+      ++p;
+    }
+
+  if (flag_indirect_dispatch)
+    {
+      abi_version = GCJ_CURRENT_BC_ABI_VERSION;
+      abi_version |= FLAG_BINARYCOMPAT_ABI;
+    }
+  else /* C++ ABI */
+    {
+      /* Implicit in this computation is the idea that we won't break the
+        old-style binary ABI in a sub-minor release (e.g., from 4.0.0 to
+        4.0.1).  */
+      abi_version = 100000 * major + 1000 * minor;
+    }
+  if (flag_bootstrap_classes)
+    abi_version |= FLAG_BOOTSTRAP_LOADER;
+
+  gcj_abi_version = build_int_cstu (ptr_type_node, abi_version);
+}
+
 void
 java_init_decl_processing (void)
 {
-  register tree endlink;
+  tree endlink;
   tree field = NULL_TREE;
   tree t;
 
   init_class_processing ();
-  init_resource_processing ();
 
   current_function_decl = NULL;
   current_binding_level = NULL_BINDING_LEVEL;
@@ -410,7 +542,7 @@ java_init_decl_processing (void)
   TREE_TYPE (error_mark_node) = error_mark_node;
 
   /* Create sizetype first - needed for other types. */
-  initialize_sizetypes ();
+  initialize_sizetypes (false);
 
   byte_type_node = make_signed_type (8);
   pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"), byte_type_node));
@@ -434,29 +566,30 @@ java_init_decl_processing (void)
   pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned long"),
                        unsigned_long_type_node));
 
-  set_sizetype (make_unsigned_type (POINTER_SIZE));
+  /* This is not a java type, however tree-dfa requires a definition for
+     size_type_node.  */
+  size_type_node = make_unsigned_type (POINTER_SIZE);
+  set_sizetype (size_type_node);
 
   /* Define these next since types below may used them.  */
   integer_type_node = java_type_for_size (INT_TYPE_SIZE, 0);
-  integer_zero_node = build_int_2 (0, 0);
-  integer_one_node = build_int_2 (1, 0);
-  integer_two_node = build_int_2 (2, 0);
-  integer_four_node = build_int_2 (4, 0);
-  integer_minus_one_node = build_int_2 (-1, -1);
+  integer_zero_node = build_int_cst (NULL_TREE, 0);
+  integer_one_node = build_int_cst (NULL_TREE, 1);
+  integer_two_node = build_int_cst (NULL_TREE, 2);
+  integer_four_node = build_int_cst (NULL_TREE, 4);
+  integer_minus_one_node = build_int_cst (NULL_TREE, -1);
 
   /* A few values used for range checking in the lexer.  */
-  decimal_int_max = build_int_2 (0x80000000, 0);
-  TREE_TYPE (decimal_int_max) = unsigned_int_type_node;
+  decimal_int_max = build_int_cstu (unsigned_int_type_node, 0x80000000);
 #if HOST_BITS_PER_WIDE_INT == 64
-  decimal_long_max = build_int_2 (0x8000000000000000LL, 0);
-#else
-#if HOST_BITS_PER_WIDE_INT == 32
-  decimal_long_max = build_int_2 (0, 0x80000000);
+  decimal_long_max = build_int_cstu (unsigned_long_type_node,
+                                    0x8000000000000000LL);
+#elif HOST_BITS_PER_WIDE_INT == 32
+  decimal_long_max = build_int_cst_wide (unsigned_long_type_node,
+                                        0, 0x80000000);
 #else
  #error "unsupported size"
 #endif
-#endif
-  TREE_TYPE (decimal_long_max) = unsigned_long_type_node;
 
   size_zero_node = size_int (0);
   size_one_node = size_int (1);
@@ -464,33 +597,24 @@ java_init_decl_processing (void)
   bitsize_one_node = bitsize_int (1);
   bitsize_unit_node = bitsize_int (BITS_PER_UNIT);
 
-  long_zero_node = build_int_2 (0, 0);
-  TREE_TYPE (long_zero_node) = long_type_node;
+  long_zero_node = build_int_cst (long_type_node, 0);
 
   void_type_node = make_node (VOID_TYPE);
   pushdecl (build_decl (TYPE_DECL, get_identifier ("void"), void_type_node));
   layout_type (void_type_node);        /* Uses size_zero_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));
+
   t = make_node (VOID_TYPE);
   layout_type (t); /* Uses size_zero_node */
   return_address_type_node = build_pointer_type (t);
 
-  null_pointer_node = build_int_2 (0, 0);
-  TREE_TYPE (null_pointer_node) = ptr_type_node;
-
-  /* Used by the parser to represent empty statements and blocks. */
-  empty_stmt_node = build1 (NOP_EXPR, void_type_node, size_zero_node);
-  CAN_COMPLETE_NORMALLY (empty_stmt_node) = 1;
+  null_pointer_node = build_int_cst (ptr_type_node, 0);
 
-#if 0
-  /* Make a type to be the domain of a few array types
-     whose domains don't really matter.
-     200 is small enough that it always fits in size_t
-     and large enough that it can hold most function names for the
-     initializations of __FUNCTION__ and __PRETTY_FUNCTION__.  */
-  short_array_type_node = build_prim_array_type (short_type_node, 200);
-#endif
-  char_type_node = make_node (CHAR_TYPE);
+  char_type_node = make_node (INTEGER_TYPE);
+  TYPE_STRING_FLAG (char_type_node) = 1;
   TYPE_PRECISION (char_type_node) = 16;
   fixup_unsigned_type (char_type_node);
   pushdecl (build_decl (TYPE_DECL, get_identifier ("char"), char_type_node));
@@ -537,6 +661,42 @@ java_init_decl_processing (void)
   float_array_vtable = create_primitive_vtable ("float");
   double_array_vtable = create_primitive_vtable ("double");
 
+  one_elt_array_domain_type = build_index_type (integer_one_node);
+  utf8const_type = make_node (RECORD_TYPE);
+  PUSH_FIELD (utf8const_type, field, "hash", unsigned_short_type_node);
+  PUSH_FIELD (utf8const_type, field, "length", unsigned_short_type_node);
+  FINISH_RECORD (utf8const_type);
+  utf8const_ptr_type = build_pointer_type (utf8const_type);
+
+  atable_type = build_array_type (ptr_type_node, 
+                                 one_elt_array_domain_type);
+  TYPE_NONALIASED_COMPONENT (atable_type) = 1;
+  atable_ptr_type = build_pointer_type (atable_type);
+
+  itable_type = build_array_type (ptr_type_node, 
+                                 one_elt_array_domain_type);
+  TYPE_NONALIASED_COMPONENT (itable_type) = 1;
+  itable_ptr_type = build_pointer_type (itable_type);
+
+  symbol_type = make_node (RECORD_TYPE);
+  PUSH_FIELD (symbol_type, field, "clname", utf8const_ptr_type);
+  PUSH_FIELD (symbol_type, field, "name", utf8const_ptr_type);
+  PUSH_FIELD (symbol_type, field, "signature", utf8const_ptr_type);
+  FINISH_RECORD (symbol_type);
+
+  symbols_array_type = build_array_type (symbol_type, 
+                                        one_elt_array_domain_type);
+  symbols_array_ptr_type = build_pointer_type (symbols_array_type);
+
+  assertion_entry_type = make_node (RECORD_TYPE);
+  PUSH_FIELD (assertion_entry_type, field, "assertion_code", integer_type_node);
+  PUSH_FIELD (assertion_entry_type, field, "op1", utf8const_ptr_type);
+  PUSH_FIELD (assertion_entry_type, field, "op2", utf8const_ptr_type);
+  FINISH_RECORD (assertion_entry_type);
+  
+  assertion_table_type = build_array_type (assertion_entry_type,
+                                           one_elt_array_domain_type);
+
   /* As you're adding items here, please update the code right after
      this section, so that the filename containing the source code of
      the pre-defined class gets registered correctly. */
@@ -552,10 +712,6 @@ java_init_decl_processing (void)
     lookup_class (get_identifier ("java.lang.RuntimeException"));
   error_exception_type_node = 
     lookup_class (get_identifier ("java.lang.Error"));
-  class_not_found_type_node = 
-    lookup_class (get_identifier ("java.lang.ClassNotFoundException"));
-  no_class_def_found_type_node = 
-    lookup_class (get_identifier ("java.lang.NoClassDefFoundError"));
 
   rawdata_ptr_type_node
     = promote_type (lookup_class (get_identifier ("gnu.gcj.RawData")));
@@ -570,7 +726,6 @@ java_init_decl_processing (void)
   add_predefined_file (get_identifier ("java/lang/Exception.java"));
   add_predefined_file (get_identifier ("java/lang/ClassNotFoundException.java"));
   add_predefined_file (get_identifier ("java/lang/NoClassDefFoundError.java"));
-  add_predefined_file (get_identifier ("gnu/gcj/RawData.java"));
 
   methodtable_type = make_node (RECORD_TYPE);
   layout_type (methodtable_type);
@@ -580,15 +735,9 @@ java_init_decl_processing (void)
   TYPE_identifier_node = get_identifier ("TYPE");
   init_identifier_node = get_identifier ("<init>");
   clinit_identifier_node = get_identifier ("<clinit>");
-  finit_identifier_node = get_identifier ("finit$");
-  instinit_identifier_node = get_identifier ("instinit$");
   void_signature_node = get_identifier ("()V");
-  length_identifier_node = get_identifier ("length");
   finalize_identifier_node = get_identifier ("finalize");
   this_identifier_node = get_identifier ("this");
-  super_identifier_node = get_identifier ("super");
-  continue_identifier_node = get_identifier ("continue");
-  access0_identifier_node = get_identifier ("access$0");
   classdollar_identifier_node = get_identifier ("class$");
 
   java_lang_cloneable_identifier_node = get_identifier ("java.lang.Cloneable");
@@ -598,16 +747,11 @@ java_init_decl_processing (void)
   /* for lack of a better place to put this stub call */
   init_expr_processing();
 
-  utf8const_type = make_node (RECORD_TYPE);
-  PUSH_FIELD (utf8const_type, field, "hash", unsigned_short_type_node);
-  PUSH_FIELD (utf8const_type, field, "length", unsigned_short_type_node);
-  FINISH_RECORD (utf8const_type);
-  utf8const_ptr_type = build_pointer_type (utf8const_type);
-
   constants_type_node = make_node (RECORD_TYPE);
   PUSH_FIELD (constants_type_node, field, "size", unsigned_int_type_node);
   PUSH_FIELD (constants_type_node, field, "tags", ptr_type_node);
   PUSH_FIELD (constants_type_node, field, "data", ptr_type_node);
+  constants_data_field_decl_node = field;
   FINISH_RECORD (constants_type_node);
   build_decl (TYPE_DECL, get_identifier ("constants"), constants_type_node);
 
@@ -616,40 +760,15 @@ java_init_decl_processing (void)
   dtable_type = make_node (RECORD_TYPE);
   dtable_ptr_type = build_pointer_type (dtable_type);
 
-  one_elt_array_domain_type = build_index_type (integer_one_node);
   otable_type = build_array_type (integer_type_node, 
                                  one_elt_array_domain_type);
   TYPE_NONALIASED_COMPONENT (otable_type) = 1;
   otable_ptr_type = build_pointer_type (otable_type);
 
-  method_symbol_type = make_node (RECORD_TYPE);
-  PUSH_FIELD (method_symbol_type, field, "clname", utf8const_ptr_type);
-  PUSH_FIELD (method_symbol_type, field, "name", utf8const_ptr_type);
-  PUSH_FIELD (method_symbol_type, field, "signature", utf8const_ptr_type);
-  FINISH_RECORD (method_symbol_type);
-
-  method_symbols_array_type = build_array_type (method_symbol_type, 
-                                               one_elt_array_domain_type);
-  method_symbols_array_ptr_type = build_pointer_type 
-                                 (method_symbols_array_type);
-
-  if (flag_indirect_dispatch)
-    {
-      otable_decl = build_decl (VAR_DECL, get_identifier ("otable"),
-                               otable_type);
-      DECL_EXTERNAL (otable_decl) = 1;
-      TREE_STATIC (otable_decl) = 1;
-      TREE_READONLY (otable_decl) = 1;
-      pushdecl (otable_decl);
-  
-      otable_syms_decl = build_decl (VAR_DECL, get_identifier ("otable_syms"), 
-                                    method_symbols_array_type);
-      TREE_STATIC (otable_syms_decl) = 1;
-      TREE_CONSTANT (otable_syms_decl) = 1;
-      pushdecl (otable_syms_decl);
-    }
-  
   PUSH_FIELD (object_type_node, field, "vtable", dtable_ptr_type);
+  DECL_FCONTEXT (field) = object_type_node;
+  TYPE_VFIELD (object_type_node) = field;
+
   /* This isn't exactly true, but it is what we have in the source.
      There is an unresolved issue here, which is whether the vtable
      should be marked by the GC.  */
@@ -669,11 +788,12 @@ java_init_decl_processing (void)
   set_super_info (0, string_type_node, object_type_node, 0);
   class_ptr_type = build_pointer_type (class_type_node);
 
-  PUSH_FIELD (class_type_node, field, "next", class_ptr_type);
+  PUSH_FIELD (class_type_node, field, "next_or_version", class_ptr_type);
   PUSH_FIELD (class_type_node, field, "name", utf8const_ptr_type);
   PUSH_FIELD (class_type_node, field, "accflags", access_flags_type_node);
   PUSH_FIELD (class_type_node, field, "superclass", class_ptr_type);
   PUSH_FIELD (class_type_node, field, "constants", constants_type_node);
+  constants_field_decl_node = field;
   PUSH_FIELD (class_type_node, field, "methods", method_ptr_type_node);
   PUSH_FIELD (class_type_node, field, "method_count", short_type_node);
   PUSH_FIELD (class_type_node, field, "vtable_method_count", short_type_node);
@@ -684,7 +804,14 @@ java_init_decl_processing (void)
   PUSH_FIELD (class_type_node, field, "vtable", dtable_ptr_type);
   PUSH_FIELD (class_type_node, field, "otable", otable_ptr_type);
   PUSH_FIELD (class_type_node, field, "otable_syms", 
-             method_symbols_array_ptr_type);
+             symbols_array_ptr_type);
+  PUSH_FIELD (class_type_node, field, "atable", atable_ptr_type);
+  PUSH_FIELD (class_type_node, field, "atable_syms", 
+             symbols_array_ptr_type);
+  PUSH_FIELD (class_type_node, field, "itable", itable_ptr_type);
+  PUSH_FIELD (class_type_node, field, "itable_syms", 
+             symbols_array_ptr_type);
+  PUSH_FIELD (class_type_node, field, "catch_classes", ptr_type_node);
   PUSH_FIELD (class_type_node, field, "interfaces",
              build_pointer_type (class_ptr_type));
   PUSH_FIELD (class_type_node, field, "loader", ptr_type_node);
@@ -696,7 +823,12 @@ java_init_decl_processing (void)
   PUSH_FIELD (class_type_node, field, "idt", ptr_type_node);  
   PUSH_FIELD (class_type_node, field, "arrayclass", ptr_type_node);  
   PUSH_FIELD (class_type_node, field, "protectionDomain", ptr_type_node);
+  PUSH_FIELD (class_type_node, field, "assertion_table", ptr_type_node);
+  PUSH_FIELD (class_type_node, field, "hack_signers", ptr_type_node);
   PUSH_FIELD (class_type_node, field, "chain", ptr_type_node);
+  PUSH_FIELD (class_type_node, field, "aux_info", ptr_type_node);
+  PUSH_FIELD (class_type_node, field, "engine", ptr_type_node);
+  PUSH_FIELD (class_type_node, field, "reflection_data", ptr_type_node);
   for (t = TYPE_FIELDS (class_type_node);  t != NULL_TREE;  t = TREE_CHAIN (t))
     FIELD_PRIVATE (t) = 1;
   push_super_field (class_type_node, object_type_node);
@@ -707,9 +839,6 @@ java_init_decl_processing (void)
   field_info_union_node = make_node (UNION_TYPE);
   PUSH_FIELD (field_info_union_node, field, "boffset", int_type_node);
   PUSH_FIELD (field_info_union_node, field, "addr", ptr_type_node);
-#if 0
-  PUSH_FIELD (field_info_union_node, field, "idx", unsigned_short_type_node);
-#endif
   layout_type (field_info_union_node);
 
   PUSH_FIELD (field_type_node, field, "name", utf8const_ptr_type);
@@ -728,9 +857,6 @@ java_init_decl_processing (void)
   FINISH_RECORD (dtable_type);
   build_decl (TYPE_DECL, get_identifier ("dispatchTable"), dtable_type);
 
-#define jint_type int_type_node
-#define jint_ptr_type ptr_type_node
-
   jexception_type = make_node (RECORD_TYPE);
   PUSH_FIELD (jexception_type, field, "start_pc", ptr_type_node);
   PUSH_FIELD (jexception_type, field, "end_pc", ptr_type_node);
@@ -749,10 +875,6 @@ java_init_decl_processing (void)
   PUSH_FIELD (lineNumbers_type, field, "length", unsigned_int_type_node);
   FINISH_RECORD (lineNumbers_type);
 
-#define instn_ptr_type_node ptr_type_node      /* XXX JH */
-
-#define lineNumbers_ptr_type_node build_pointer_type(lineNumbers_type)
-
   PUSH_FIELD (method_type_node, field, "name", utf8const_ptr_type);
   PUSH_FIELD (method_type_node, field, "signature", utf8const_ptr_type);
   PUSH_FIELD (method_type_node, field, "accflags", access_flags_type_node);
@@ -764,54 +886,61 @@ java_init_decl_processing (void)
 
   endlink = end_params_node = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
 
-  t = tree_cons (NULL_TREE, class_ptr_type,
-                tree_cons (NULL_TREE, int_type_node, endlink));
-  alloc_object_node = builtin_function ("_Jv_AllocObject",
-                                       build_function_type (ptr_type_node, t),
-                                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+  t = tree_cons (NULL_TREE, class_ptr_type, endlink);
+  alloc_object_node = add_builtin_function ("_Jv_AllocObject",
+                                           build_function_type (ptr_type_node, t),
+                                           0, NOT_BUILT_IN, NULL, NULL_TREE);
   DECL_IS_MALLOC (alloc_object_node) = 1;
-  alloc_no_finalizer_node = 
-    builtin_function ("_Jv_AllocObjectNoFinalizer",
-                     build_function_type (ptr_type_node, t),
-                     0, NOT_BUILT_IN, NULL, NULL_TREE);
+  alloc_no_finalizer_node =
+    add_builtin_function ("_Jv_AllocObjectNoFinalizer",
+                         build_function_type (ptr_type_node, t),
+                         0, NOT_BUILT_IN, NULL, NULL_TREE);
   DECL_IS_MALLOC (alloc_no_finalizer_node) = 1;
 
   t = tree_cons (NULL_TREE, ptr_type_node, endlink);
-  soft_initclass_node = builtin_function ("_Jv_InitClass",
-                                         build_function_type (void_type_node,
-                                                              t),
-                                         0, NOT_BUILT_IN, NULL, NULL_TREE);
-
-  throw_node = builtin_function ("_Jv_Throw",
-                                build_function_type (ptr_type_node, t),
-                                0, NOT_BUILT_IN, NULL, NULL_TREE);
+  soft_initclass_node = add_builtin_function ("_Jv_InitClass",
+                                             build_function_type (void_type_node,
+                                                                  t),
+                                             0, NOT_BUILT_IN, NULL, NULL_TREE);
+  t = tree_cons (NULL_TREE, class_ptr_type,
+                tree_cons (NULL_TREE, int_type_node, endlink));
+  soft_resolvepoolentry_node
+    = add_builtin_function ("_Jv_ResolvePoolEntry",
+                           build_function_type (ptr_type_node, t),
+                           0,NOT_BUILT_IN, NULL, NULL_TREE);
+  DECL_IS_PURE (soft_resolvepoolentry_node) = 1;
+  throw_node = add_builtin_function ("_Jv_Throw",
+                                    build_function_type (void_type_node, t),
+                                    0, NOT_BUILT_IN, NULL, NULL_TREE);
   /* Mark throw_nodes as `noreturn' functions with side effects.  */
   TREE_THIS_VOLATILE (throw_node) = 1;
   TREE_SIDE_EFFECTS (throw_node) = 1;
 
-  t = build_function_type (int_type_node, endlink);
-  soft_monitorenter_node 
-    = builtin_function ("_Jv_MonitorEnter", t, 0, NOT_BUILT_IN,
-                       NULL, NULL_TREE);
-  soft_monitorexit_node 
-    = builtin_function ("_Jv_MonitorExit", t, 0, NOT_BUILT_IN,
-                       NULL, NULL_TREE);
-  
-  t = tree_cons (NULL_TREE, int_type_node, 
+  t = build_function_type (void_type_node, tree_cons (NULL_TREE, ptr_type_node,
+                                                     endlink));
+  soft_monitorenter_node
+    = add_builtin_function ("_Jv_MonitorEnter", t, 0, NOT_BUILT_IN,
+                           NULL, NULL_TREE);
+  soft_monitorexit_node
+    = add_builtin_function ("_Jv_MonitorExit", t, 0, NOT_BUILT_IN,
+                           NULL, NULL_TREE);
+
+  t = tree_cons (NULL_TREE, ptr_type_node,
                 tree_cons (NULL_TREE, int_type_node, endlink));
   soft_newarray_node
-      = builtin_function ("_Jv_NewPrimArray",
-                         build_function_type(ptr_type_node, t),
-                         0, NOT_BUILT_IN, NULL, NULL_TREE);
+      = add_builtin_function ("_Jv_NewPrimArray",
+                             build_function_type (ptr_type_node, t),
+                             0, NOT_BUILT_IN, NULL, NULL_TREE);
   DECL_IS_MALLOC (soft_newarray_node) = 1;
 
   t = tree_cons (NULL_TREE, int_type_node,
                 tree_cons (NULL_TREE, class_ptr_type,
-                           tree_cons (NULL_TREE, object_ptr_type_node, endlink)));
+                           tree_cons (NULL_TREE, object_ptr_type_node,
+                                      endlink)));
   soft_anewarray_node
-      = builtin_function ("_Jv_NewObjectArray",
-                         build_function_type (ptr_type_node, t),
-                         0, NOT_BUILT_IN, NULL, NULL_TREE);
+      = add_builtin_function ("_Jv_NewObjectArray",
+                             build_function_type (ptr_type_node, t),
+                             0, NOT_BUILT_IN, NULL, NULL_TREE);
   DECL_IS_MALLOC (soft_anewarray_node) = 1;
 
   /* There is no endlink here because _Jv_NewMultiArray is a varargs
@@ -819,109 +948,143 @@ java_init_decl_processing (void)
   t = tree_cons (NULL_TREE, ptr_type_node,
                 tree_cons (NULL_TREE, int_type_node, NULL_TREE));
   soft_multianewarray_node
-      = builtin_function ("_Jv_NewMultiArray",
-                         build_function_type (ptr_type_node, t),
-                         0, NOT_BUILT_IN, NULL, NULL_TREE);
+      = add_builtin_function ("_Jv_NewMultiArray",
+                             build_function_type (ptr_type_node, t),
+                             0, NOT_BUILT_IN, NULL, NULL_TREE);
   DECL_IS_MALLOC (soft_multianewarray_node) = 1;
 
   t = build_function_type (void_type_node, 
                           tree_cons (NULL_TREE, int_type_node, endlink));
   soft_badarrayindex_node
-      = builtin_function ("_Jv_ThrowBadArrayIndex", t, 
-                         0, NOT_BUILT_IN, NULL, NULL_TREE);
+      = add_builtin_function ("_Jv_ThrowBadArrayIndex", t,
+                             0, NOT_BUILT_IN, NULL, NULL_TREE);
   /* Mark soft_badarrayindex_node as a `noreturn' function with side
      effects.  */
   TREE_THIS_VOLATILE (soft_badarrayindex_node) = 1;
   TREE_SIDE_EFFECTS (soft_badarrayindex_node) = 1;
 
   soft_nullpointer_node
-    = builtin_function ("_Jv_ThrowNullPointerException",
-                       build_function_type (void_type_node, endlink),
-                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = add_builtin_function ("_Jv_ThrowNullPointerException",
+                           build_function_type (void_type_node, endlink),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
   /* Mark soft_nullpointer_node as a `noreturn' function with side
      effects.  */
   TREE_THIS_VOLATILE (soft_nullpointer_node) = 1;
   TREE_SIDE_EFFECTS (soft_nullpointer_node) = 1;
 
+  soft_abstractmethod_node
+    = add_builtin_function ("_Jv_ThrowAbstractMethodError",
+                           build_function_type (void_type_node, endlink),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
+  /* Mark soft_abstractmethod_node as a `noreturn' function with side
+     effects.  */
+  TREE_THIS_VOLATILE (soft_abstractmethod_node) = 1;
+  TREE_SIDE_EFFECTS (soft_abstractmethod_node) = 1;
+
+  soft_nosuchfield_node
+    = add_builtin_function ("_Jv_ThrowNoSuchFieldError",
+                           build_function_type (void_type_node, endlink),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
+  /* Mark soft_nosuchfield_node as a `noreturn' function with side
+     effects.  */
+  TREE_THIS_VOLATILE (soft_nosuchfield_node) = 1;
+  TREE_SIDE_EFFECTS (soft_nosuchfield_node) = 1;
+
   t = tree_cons (NULL_TREE, class_ptr_type,
                 tree_cons (NULL_TREE, object_ptr_type_node, endlink));
   soft_checkcast_node
-    = builtin_function ("_Jv_CheckCast",
-                       build_function_type (ptr_type_node, t),
-                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = add_builtin_function ("_Jv_CheckCast",
+                           build_function_type (ptr_type_node, t),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
   t = tree_cons (NULL_TREE, object_ptr_type_node,
                 tree_cons (NULL_TREE, class_ptr_type, endlink));
   soft_instanceof_node
-    = builtin_function ("_Jv_IsInstanceOf",
-                       build_function_type (boolean_type_node, t),
-                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = add_builtin_function ("_Jv_IsInstanceOf",
+                           build_function_type (boolean_type_node, t),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
+  DECL_IS_PURE (soft_instanceof_node) = 1;
   t = tree_cons (NULL_TREE, object_ptr_type_node,
                 tree_cons (NULL_TREE, object_ptr_type_node, endlink));
   soft_checkarraystore_node
-    = builtin_function ("_Jv_CheckArrayStore",
-                       build_function_type (void_type_node, t),
-                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = add_builtin_function ("_Jv_CheckArrayStore",
+                           build_function_type (void_type_node, t),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
   t = tree_cons (NULL_TREE, ptr_type_node,
                 tree_cons (NULL_TREE, ptr_type_node,
                            tree_cons (NULL_TREE, int_type_node, endlink)));
-  soft_lookupinterfacemethod_node 
-    = builtin_function ("_Jv_LookupInterfaceMethodIdx",
-                       build_function_type (ptr_type_node, t),
-                       0, NOT_BUILT_IN, NULL, NULL_TREE);
-
+  soft_lookupinterfacemethod_node
+    = add_builtin_function ("_Jv_LookupInterfaceMethodIdx",
+                           build_function_type (ptr_type_node, t),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
+  DECL_IS_PURE (soft_lookupinterfacemethod_node) = 1;
+  t = tree_cons (NULL_TREE, ptr_type_node,
+                tree_cons (NULL_TREE, ptr_type_node,
+                           tree_cons (NULL_TREE, ptr_type_node, endlink)));
+  soft_lookupinterfacemethodbyname_node
+    = add_builtin_function ("_Jv_LookupInterfaceMethod",
+                           build_function_type (ptr_type_node, t),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
   t = tree_cons (NULL_TREE, object_ptr_type_node,
                 tree_cons (NULL_TREE, ptr_type_node,
                            tree_cons (NULL_TREE, ptr_type_node, 
                                       tree_cons (NULL_TREE, int_type_node, 
                                                  endlink))));
   soft_lookupjnimethod_node
-    = builtin_function ("_Jv_LookupJNIMethod",
-                       build_function_type (ptr_type_node, t),
-                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = add_builtin_function ("_Jv_LookupJNIMethod",
+                           build_function_type (ptr_type_node, t),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
   t = tree_cons (NULL_TREE, ptr_type_node, endlink);
   soft_getjnienvnewframe_node
-    = builtin_function ("_Jv_GetJNIEnvNewFrame",
-                       build_function_type (ptr_type_node, t),
-                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = add_builtin_function ("_Jv_GetJNIEnvNewFrame",
+                           build_function_type (ptr_type_node, t),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
   soft_jnipopsystemframe_node
-    = builtin_function ("_Jv_JNI_PopSystemFrame",
-                       build_function_type (ptr_type_node, t),
-                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = add_builtin_function ("_Jv_JNI_PopSystemFrame",
+                           build_function_type (void_type_node, t),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
 
+  t = tree_cons (NULL_TREE, object_ptr_type_node, endlink);
+  soft_unwrapjni_node
+    = add_builtin_function ("_Jv_UnwrapJNIweakReference",
+                           build_function_type (object_ptr_type_node, t),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
+
+  t = tree_cons (NULL_TREE, int_type_node,
+                tree_cons (NULL_TREE, int_type_node, endlink));
   soft_idiv_node
-    = builtin_function ("_Jv_divI",
-                       build_function_type (int_type_node, t),
-                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = add_builtin_function ("_Jv_divI",
+                           build_function_type (int_type_node, t),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
 
   soft_irem_node
-    = builtin_function ("_Jv_remI",
-                       build_function_type (int_type_node, t),
-                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = add_builtin_function ("_Jv_remI",
+                           build_function_type (int_type_node, t),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
 
+  t = tree_cons (NULL_TREE, long_type_node,
+                tree_cons (NULL_TREE, long_type_node, endlink));
   soft_ldiv_node
-    = builtin_function ("_Jv_divJ",
-                       build_function_type (long_type_node, t),
-                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = add_builtin_function ("_Jv_divJ",
+                           build_function_type (long_type_node, t),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
 
   soft_lrem_node
-    = builtin_function ("_Jv_remJ",
-                       build_function_type (long_type_node, t),
-                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = add_builtin_function ("_Jv_remJ",
+                           build_function_type (long_type_node, t),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
 
   /* Initialize variables for except.c.  */
   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
                                              ? "__gcj_personality_sj0"
                                              : "__gcj_personality_v0");
-  lang_eh_runtime_type = prepare_eh_table_type;
+  default_init_unwind_resume_libfunc ();
 
-  init_jcf_parse ();
-    
-  initialize_builtins ();
+  lang_eh_runtime_type = do_nothing;
 
+  initialize_builtins ();
   soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
-#if 0
-  soft_fmodf_node = built_in_decls[BUILT_IN_FMODF];
-#endif
+
+  parse_version ();
 }
 
 
@@ -933,7 +1096,7 @@ java_init_decl_processing (void)
 tree
 lookup_name (tree name)
 {
-  register tree val;
+  tree val;
   if (current_binding_level != global_binding_level
       && IDENTIFIER_LOCAL_VALUE (name))
     val = IDENTIFIER_LOCAL_VALUE (name);
@@ -943,12 +1106,12 @@ lookup_name (tree name)
 }
 
 /* Similar to `lookup_name' but look only at current binding level and
-   the previous one if its the parameter level.  */
+   the previous one if it's the parameter level.  */
 
 static tree
 lookup_name_current_level (tree name)
 {
-  register tree t;
+  tree t;
 
   if (current_binding_level == global_binding_level)
     return IDENTIFIER_GLOBAL_VALUE (name);
@@ -963,41 +1126,6 @@ lookup_name_current_level (tree name)
   return t;
 }
 
-/* Use a binding level to record a labeled block declaration */
-
-void
-push_labeled_block (tree lb)
-{
-  register tree name = DECL_NAME (LABELED_BLOCK_LABEL (lb));
-  register struct binding_level *b = current_binding_level;
-  tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
-  if (oldlocal != 0)
-      b->shadowed = tree_cons (name, oldlocal, b->shadowed);
-  TREE_CHAIN (lb) = b->names;
-  b->names = lb;
-  IDENTIFIER_LOCAL_VALUE (name) = lb;
-}
-
-/* Pop the current binding level, reinstalling values for the previous
-   labeled block */
-
-void
-pop_labeled_block (void)
-{
-  struct binding_level *b = current_binding_level;
-  tree label =  b->names;
-  IDENTIFIER_LOCAL_VALUE (DECL_NAME (LABELED_BLOCK_LABEL (label))) = 
-    NULL_TREE;
-  if (b->shadowed)
-    IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (b->shadowed)) = 
-      TREE_VALUE (b->shadowed);
-
-  /* Pop the current level, and free the structure for reuse.  */
-  current_binding_level = current_binding_level->level_chain;
-  b->level_chain = free_binding_level;
-  free_binding_level = b;
-}
-
 /* Record a decl-node X as belonging to the current lexical scope.
    Check for errors (such as an incompatible declaration for the same
    name already seen in the same scope).
@@ -1009,9 +1137,9 @@ pop_labeled_block (void)
 tree
 pushdecl (tree x)
 {
-  register tree t;
-  register tree name = DECL_NAME (x);
-  register struct binding_level *b = current_binding_level;
+  tree t;
+  tree name = DECL_NAME (x);
+  struct binding_level *b = current_binding_level;
   
   if (TREE_CODE (x) != TYPE_DECL)
     DECL_CONTEXT (x) = current_function_decl;
@@ -1022,7 +1150,7 @@ pushdecl (tree x)
        /* error_mark_node is 0 for a while during initialization!  */
        {
          t = 0;
-         error ("%J'%D' used prior to declaration", x, x);
+         error ("%q+D used prior to declaration", x);
        }
 
       /* If we're naming a hitherto-unnamed type, set its TYPE_NAME
@@ -1051,55 +1179,6 @@ pushdecl (tree x)
          tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
          IDENTIFIER_LOCAL_VALUE (name) = x;
 
-#if 0
-         /* Warn if shadowing an argument at the top level of the body.  */
-         if (oldlocal != 0 && !DECL_EXTERNAL (x)
-             /* This warning doesn't apply to the parms of a nested fcn.  */
-             && ! current_binding_level->parm_flag
-             /* Check that this is one level down from the parms.  */
-             && current_binding_level->level_chain->parm_flag
-             /* Check that the decl being shadowed
-                comes from the parm level, one level up.  */
-             && chain_member (oldlocal, current_binding_level->level_chain->names))
-           {
-             if (TREE_CODE (oldlocal) == PARM_DECL)
-               pedwarn ("declaration of `%s' shadows a parameter",
-                        IDENTIFIER_POINTER (name));
-             else
-               pedwarn ("declaration of `%s' shadows a symbol from the parameter list",
-                        IDENTIFIER_POINTER (name));
-           }
-
-         /* Maybe warn if shadowing something else.  */
-         else if (warn_shadow && !DECL_EXTERNAL (x)
-                  /* No shadow warnings for internally generated vars.  */
-                  && DECL_SOURCE_LINE (x) != 0
-                  /* No shadow warnings for vars made for inlining.  */
-                  && ! DECL_FROM_INLINE (x))
-           {
-             const char *warnstring = 0;
-
-             if (TREE_CODE (x) == PARM_DECL
-                 && current_binding_level->level_chain->parm_flag)
-               /* Don't warn about the parm names in function declarator
-                  within a function declarator.
-                  It would be nice to avoid warning in any function
-                  declarator in a declaration, as opposed to a definition,
-                  but there is no way to tell it's not a definition.  */
-               ;
-             else if (oldlocal != 0 && TREE_CODE (oldlocal) == PARM_DECL)
-               warnstring = "declaration of `%s' shadows a parameter";
-             else if (oldlocal != 0)
-               warnstring = "declaration of `%s' shadows previous local";
-             else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
-                      && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
-               warnstring = "declaration of `%s' shadows global declaration";
-
-             if (warnstring)
-               warning (warnstring, IDENTIFIER_POINTER (name));
-           }
-#endif
-
          /* If storing a local value, there may already be one (inherited).
             If so, record it for restoration when this binding level ends.  */
          if (oldlocal != 0)
@@ -1126,8 +1205,8 @@ pushdecl_force_head (tree x)
 tree
 pushdecl_top_level (tree x)
 {
-  register tree t;
-  register struct binding_level *b = current_binding_level;
+  tree t;
+  struct binding_level *b = current_binding_level;
 
   current_binding_level = global_binding_level;
   t = pushdecl (x);
@@ -1135,6 +1214,20 @@ pushdecl_top_level (tree x)
   return t;
 }
 
+/* Like pushdecl, only it places X in FUNCTION_BINDING_LEVEL, if appropriate.  */
+
+tree
+pushdecl_function_level (tree x)
+{
+  tree t;
+  struct binding_level *b = current_binding_level;
+
+  current_binding_level = function_binding_level;
+  t = pushdecl (x);
+  current_binding_level = b;
+  return t;
+}
+
 /* Nonzero if we are currently in the global binding level.  */
 
 int
@@ -1160,21 +1253,13 @@ static struct binding_level *
 make_binding_level (void)
 {
   /* NOSTRICT */
-  return xmalloc (sizeof (struct binding_level));
+  return ggc_alloc_cleared (sizeof (struct binding_level));
 }
 
 void
 pushlevel (int unused ATTRIBUTE_UNUSED)
 {
-  register struct binding_level *newlevel = NULL_BINDING_LEVEL;
-
-#if 0
-  /* If this is the top level of a function,
-     just make sure that NAMED_LABELS is 0.  */
-
-  if (current_binding_level == global_binding_level)
-    named_labels = 0;
-#endif
+  struct binding_level *newlevel = NULL_BINDING_LEVEL;
 
   /* Reuse or create a struct for this binding level.  */
 
@@ -1197,7 +1282,7 @@ pushlevel (int unused ATTRIBUTE_UNUSED)
 #if defined(DEBUG_JAVA_BINDING_LEVELS)
   newlevel->binding_depth = binding_depth;
   indent ();
-  fprintf (stderr, "push %s level 0x%08x pc %d\n",
+  fprintf (stderr, "push %s level %p pc %d\n",
           (is_class_level) ? "class" : "block", newlevel, current_pc);
   is_class_level = 0;
   binding_depth++;
@@ -1222,33 +1307,25 @@ pushlevel (int unused ATTRIBUTE_UNUSED)
 tree
 poplevel (int keep, int reverse, int functionbody)
 {
-  register tree link;
+  tree link;
   /* The chain of decls was accumulated in reverse order.
      Put it into forward order, just for cleanliness.  */
   tree decls;
   tree subblocks = current_binding_level->blocks;
   tree block = 0;
   tree decl;
-  int block_previously_created;
+  tree bind = 0;
 
 #if defined(DEBUG_JAVA_BINDING_LEVELS)
   binding_depth--;
   indent ();
   if (current_binding_level->end_pc != LARGEST_PC)
-    fprintf (stderr, "pop  %s level 0x%08x pc %d (end pc %d)\n",
+    fprintf (stderr, "pop  %s level %p pc %d (end pc %d)\n",
             (is_class_level) ? "class" : "block", current_binding_level, current_pc,
             current_binding_level->end_pc);
   else
-    fprintf (stderr, "pop  %s level 0x%08x pc %d\n",
+    fprintf (stderr, "pop  %s level %p pc %d\n",
             (is_class_level) ? "class" : "block", current_binding_level, current_pc);
-#if 0
-  if (is_class_level != (current_binding_level == class_binding_level))
-    {
-      indent ();
-      fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
-    }
-  is_class_level = 0;
-#endif
 #endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
 
   /* Get the decls in the order they were written.
@@ -1261,47 +1338,69 @@ poplevel (int keep, int reverse, int functionbody)
   else
     decls = current_binding_level->names;
 
-  /* Output any nested inline functions within this block
-     if they weren't already output.  */
-
   for (decl = decls; decl; decl = TREE_CHAIN (decl))
-    if (TREE_CODE (decl) == FUNCTION_DECL
-       && ! TREE_ASM_WRITTEN (decl)
-       && DECL_INITIAL (decl) != 0
-       && TREE_ADDRESSABLE (decl))
-      {
-       /* If this decl was copied from a file-scope decl
-          on account of a block-scope extern decl,
-          propagate TREE_ADDRESSABLE to the file-scope decl.
-
-          DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
-          true, since then the decl goes through save_for_inline_copying.  */
-       if (DECL_ABSTRACT_ORIGIN (decl) != 0
-           && DECL_ABSTRACT_ORIGIN (decl) != decl)
-         TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
-       else
-         {
-           push_function_context ();
-           output_inline_function (decl);
-           pop_function_context ();
-         }
-      }
+    if (TREE_CODE (decl) == VAR_DECL
+       && DECL_LANG_SPECIFIC (decl) != NULL
+       && DECL_LOCAL_SLOT_NUMBER (decl))
+      LOCAL_VAR_OUT_OF_SCOPE_P (decl) = 1;
 
   /* If there were any declarations in that level,
      or if this level is a function body,
      create a BLOCK to record them for the life of this function.  */
 
   block = 0;
-  block_previously_created = (current_binding_level->this_block != 0);
-  if (block_previously_created)
-    block = current_binding_level->this_block;
-  else if (keep || functionbody)
-    block = make_node (BLOCK);
+  if (keep || functionbody)
+    {
+      block = make_node (BLOCK);
+      TREE_TYPE (block) = void_type_node;
+    }
+
+  if (current_binding_level->exception_range)
+    expand_end_java_handler (current_binding_level->exception_range);
+
   if (block != 0)
     {
-      BLOCK_VARS (block) = decls;
+      /* If any statements have been generated at this level, create a
+        BIND_EXPR to hold them and copy the variables to it.  This
+        only applies to the bytecode compiler.  */
+      if (current_binding_level->stmts)
+       {
+         tree decl = decls;
+         tree *var = &BLOCK_VARS (block);
+
+         /* Copy decls from names list, ignoring labels.  */
+         while (decl)
+           {
+             tree next = TREE_CHAIN (decl);
+             if (TREE_CODE (decl) != LABEL_DECL)
+               {
+                 *var = decl;
+                 var = &TREE_CHAIN (decl);
+               }
+             decl = next;
+           }
+         *var = NULL;
+           
+         bind = build3 (BIND_EXPR, TREE_TYPE (block), BLOCK_VARS (block), 
+                        BLOCK_EXPR_BODY (block), block);
+         BIND_EXPR_BODY (bind) = current_binding_level->stmts;
+         
+         if (BIND_EXPR_BODY (bind)
+             && TREE_SIDE_EFFECTS (BIND_EXPR_BODY (bind)))
+           TREE_SIDE_EFFECTS (bind) = 1;
+         
+         /* FIXME: gimplifier brain damage.  */
+         if (BIND_EXPR_BODY (bind) == NULL)
+           BIND_EXPR_BODY (bind) = build_java_empty_stmt ();
+
+         current_binding_level->stmts = NULL;
+       }
+      else
+       {
+         BLOCK_VARS (block) = decls;
+       }
       BLOCK_SUBBLOCKS (block) = subblocks;
-    }
+    }  
 
   /* In each subblock, record that this is its superior.  */
 
@@ -1346,38 +1445,12 @@ poplevel (int keep, int reverse, int functionbody)
         found in the FUNCTION_DECL instead.  */
 
       BLOCK_VARS (block) = 0;
-
-      /* Clear out the definitions of all label names,
-        since their scopes end here,
-        and add them to BLOCK_VARS.  */
-
-#if 0
-      for (link = named_labels; link; link = TREE_CHAIN (link))
-       {
-         register tree label = TREE_VALUE (link);
-
-         if (DECL_INITIAL (label) == 0)
-           {
-             error ("%Jlabel '%D' used but not defined", label, label);
-             /* Avoid crashing later.  */
-             define_label (input_location, DECL_NAME (label));
-           }
-         else if (warn_unused[UNUSED_LABEL] && !TREE_USED (label))
-           warning ("%Jlabel '%D' defined but not used", label, label);
-         IDENTIFIER_LABEL_VALUE (DECL_NAME (label)) = 0;
-
-         /* Put the labels into the "variables" of the
-            top-level block, so debugger can see them.  */
-         TREE_CHAIN (label) = BLOCK_VARS (block);
-         BLOCK_VARS (block) = label;
-       }
-#endif
     }
 
   /* Pop the current level, and free the structure for reuse.  */
 
   {
-    register struct binding_level *level = current_binding_level;
+    struct binding_level *level = current_binding_level;
     current_binding_level = current_binding_level->level_chain;
 
     level->level_chain = free_binding_level;
@@ -1386,36 +1459,29 @@ poplevel (int keep, int reverse, int functionbody)
 
   /* Dispose of the block that we just made inside some higher level.  */
   if (functionbody)
-    DECL_INITIAL (current_function_decl) = block;
-  else if (block)
     {
-      if (!block_previously_created)
-        current_binding_level->blocks
-          = chainon (current_binding_level->blocks, block);
+      DECL_INITIAL (current_function_decl) = block;
+      DECL_SAVED_TREE (current_function_decl) = bind;
+    }
+  else 
+    {
+      if (block)
+       {
+         current_binding_level->blocks
+           = chainon (current_binding_level->blocks, block);
+       }
+      /* If we did not make a block for the level just exited,
+        any blocks made for inner levels
+        (since they cannot be recorded as subblocks in that level)
+        must be carried forward so they will later become subblocks
+        of something else.  */
+      else if (subblocks)
+       current_binding_level->blocks
+         = chainon (current_binding_level->blocks, subblocks);
+
+      if (bind)
+       java_add_stmt (bind);
     }
-  /* If we did not make a block for the level just exited,
-     any blocks made for inner levels
-     (since they cannot be recorded as subblocks in that level)
-     must be carried forward so they will later become subblocks
-     of something else.  */
-  else if (subblocks)
-    current_binding_level->blocks
-      = chainon (current_binding_level->blocks, subblocks);
-
-  /* Set the TYPE_CONTEXTs for all of the tagged types belonging to this
-     binding contour so that they point to the appropriate construct, i.e.
-     either to the current FUNCTION_DECL node, or else to the BLOCK node
-     we just constructed.
-
-     Note that for tagged types whose scope is just the formal parameter
-     list for some function type specification, we can't properly set
-     their TYPE_CONTEXTs here, because we don't have a pointer to the
-     appropriate FUNCTION_TYPE node readily available to us.  For those
-     cases, the TYPE_CONTEXTs of the relevant tagged type nodes get set
-     in `grokdeclarator' as soon as we have created the FUNCTION_TYPE
-     node which will represent the "scope" for these "parameter list local"
-     tagged types.
-  */
 
   if (block)
     TREE_USED (block) = 1;
@@ -1433,7 +1499,7 @@ maybe_pushlevels (int pc)
         DECL_LOCAL_START_PC (pending_local_decls) <= pc)
     {
       tree *ptr = &pending_local_decls;
-      tree decl = *ptr;
+      tree decl = *ptr, next;
       int end_pc = DECL_LOCAL_END_PC (decl);
 
       while (*ptr != NULL_TREE
@@ -1443,21 +1509,36 @@ maybe_pushlevels (int pc)
       pending_local_decls = *ptr;
       *ptr = NULL_TREE;
 
-      /* Force non-nested range to be nested in current range. */
+      /* Force non-nested range to be nested in current range by
+        truncating variable lifetimes. */
       if (end_pc > current_binding_level->end_pc)
-       end_pc = current_binding_level->end_pc;
+       {
+         tree t;
+         end_pc = current_binding_level->end_pc;
+         for (t = decl; t != NULL_TREE; t = TREE_CHAIN (t))
+           DECL_LOCAL_END_PC (t) = end_pc;
+       }
 
       maybe_start_try (pc, end_pc);
       
       pushlevel (1);
-      expand_start_bindings (0);
 
       current_binding_level->end_pc = end_pc;
       current_binding_level->start_pc = pc;      
-      current_binding_level->names = decl;
-      for ( ; decl != NULL_TREE;  decl = TREE_CHAIN (decl))
+      current_binding_level->names = NULL;
+      for ( ; decl != NULL_TREE; decl = next)
        {
-         push_jvm_slot (DECL_LOCAL_SLOT_NUMBER (decl), decl);
+         int index = DECL_LOCAL_SLOT_NUMBER (decl);
+         tree base_decl;
+         next = TREE_CHAIN (decl);
+         push_jvm_slot (index, decl);
+         pushdecl (decl);
+         base_decl
+           = find_local_variable (index, TREE_TYPE (decl), pc);
+         if (TREE_CODE (TREE_TYPE (base_decl)) == POINTER_TYPE)
+           base_decl = TREE_VEC_ELT (base_decl_map, index);
+         SET_DECL_VALUE_EXPR (decl, base_decl);
+         DECL_HAS_VALUE_EXPR_P (decl) = 1;
        }
     }      
 
@@ -1471,13 +1552,14 @@ maybe_poplevels (int pc)
   current_pc = pc;
 #endif
 
+  /* FIXME: I'm pretty sure that this is wrong.  Variable scopes are
+     inclusive, so a variable is live if pc == end_pc.  Here, we
+     terminate a range if the current pc is equal to the end of the
+     range, and this is *before* we have generated code for the
+     instruction at end_pc.  We're closing a binding level one
+     instruction too early.*/
   while (current_binding_level->end_pc <= pc)
-    {
-      expand_end_bindings (getdecls (), 1, 0);
-      maybe_end_try (current_binding_level->start_pc, pc);
-      poplevel (1, 0, 0);
-    }
-  maybe_end_try (0, pc);
+    poplevel (1, 0, 0);
 }
 
 /* Terminate any binding which began during the range beginning at
@@ -1491,10 +1573,9 @@ force_poplevels (int start_pc)
   while (current_binding_level->start_pc > start_pc)
     {
       if (pedantic && current_binding_level->start_pc > start_pc)
-       warning ("%JIn %D: overlapped variable and exception ranges at %d",
-                 current_function_decl, current_function_decl,
+       warning (0, "In %+D: overlapped variable and exception ranges at %d",
+                 current_function_decl,
                 current_binding_level->start_pc);
-      expand_end_bindings (getdecls (), 1, 0);
       poplevel (1, 0, 0);
     }
 }
@@ -1511,19 +1592,6 @@ insert_block (tree block)
     = chainon (current_binding_level->blocks, block);
 }
 
-/* Set the BLOCK node for the innermost scope
-   (the one we are currently in).  */
-
-void
-set_block (tree block)
-{
-  current_binding_level->this_block = block;
-  current_binding_level->names = chainon (current_binding_level->names,
-                                         BLOCK_VARS (block));
-  current_binding_level->blocks = chainon (current_binding_level->blocks,
-                                          BLOCK_SUBBLOCKS (block));
-}
-
 /* integrate_decl_tree calls this function. */
 
 void
@@ -1567,9 +1635,8 @@ give_name_to_locals (JCF *jcf)
        {
          tree decl = TREE_VEC_ELT (decl_map, slot);
          DECL_NAME (decl) = name;
-         SET_DECL_ASSEMBLER_NAME (decl, name);
          if (TREE_CODE (decl) != PARM_DECL || TREE_TYPE (decl) != type)
-           warning ("bad type in parameter debug info");
+           warning (0, "bad type in parameter debug info");
        }
       else
        {
@@ -1578,8 +1645,8 @@ give_name_to_locals (JCF *jcf)
          tree decl = build_decl (VAR_DECL, name, type);
          if (end_pc > DECL_CODE_LENGTH (current_function_decl))
            {
-             warning ("%Jbad PC range for debug info for local '%D'",
-                      decl, decl);
+             warning (0, "bad PC range for debug info for local %q+D",
+                       decl);
              end_pc = DECL_CODE_LENGTH (current_function_decl);
            }
 
@@ -1592,14 +1659,6 @@ give_name_to_locals (JCF *jcf)
          MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
          DECL_LOCAL_SLOT_NUMBER (decl) = slot;
          DECL_LOCAL_START_PC (decl) = start_pc;
-#if 0
-         /* FIXME: The range used internally for exceptions and local
-            variable ranges, is a half-open interval: 
-            start_pc <= pc < end_pc.  However, the range used in the
-            Java VM spec is inclusive at both ends: 
-            start_pc <= pc <= end_pc. */
-         end_pc++;
-#endif
          DECL_LOCAL_END_PC (decl) = end_pc;
 
          /* Now insert the new decl in the proper place in
@@ -1634,7 +1693,6 @@ give_name_to_locals (JCF *jcf)
              sprintf (buffer, "ARG_%d", arg_i);
              DECL_NAME (parm) = get_identifier (buffer);
            }
-         SET_DECL_ASSEMBLER_NAME (parm, DECL_NAME (parm));
        }
     }
 }
@@ -1651,6 +1709,8 @@ build_result_decl (tree fndecl)
          && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
        restype = integer_type_node;
       result = build_decl (RESULT_DECL, NULL_TREE, restype);
+      DECL_ARTIFICIAL (result) = 1;
+      DECL_IGNORED_P (result) = 1;
       DECL_CONTEXT (result) = fndecl;
       DECL_RESULT (fndecl) = result;
     }
@@ -1658,88 +1718,19 @@ build_result_decl (tree fndecl)
 }
 
 void
-complete_start_java_method (tree fndecl)
-{
-  if (! flag_emit_class_files)
-    {
-      /* Initialize the RTL code for the function.  */
-      init_function_start (fndecl);
-
-      /* Set up parameters and prepare for return, for the function.  */
-      expand_function_start (fndecl, 0);
-    }
-
-#if 0
-      /* If this fcn was already referenced via a block-scope `extern' decl (or
-         an implicit decl), propagate certain information about the usage. */
-      if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl)))
-        TREE_ADDRESSABLE (current_function_decl) = 1;
-
-#endif
-
-  if (METHOD_STATIC (fndecl) && ! METHOD_PRIVATE (fndecl)
-      && ! flag_emit_class_files
-      && ! DECL_CLINIT_P (fndecl)
-      && ! CLASS_INTERFACE (TYPE_NAME (current_class)))
-    {
-      tree clas = DECL_CONTEXT (fndecl);
-      tree init = build (CALL_EXPR, void_type_node,
-                        build_address_of (soft_initclass_node),
-                        build_tree_list (NULL_TREE, build_class_ref (clas)),
-                        NULL_TREE);
-      TREE_SIDE_EFFECTS (init) = 1;
-      expand_expr_stmt (init);
-    }
-
-  /* Push local variables. Function compiled from source code are
-     using a different local variables management, and for them,
-     pushlevel shouldn't be called from here.  */
-  if (!CLASS_FROM_SOURCE_P (DECL_CONTEXT (fndecl)))
-    {
-      pushlevel (2);
-      if (! flag_emit_class_files)
-       expand_start_bindings (1);
-    }
-
-  if (METHOD_SYNCHRONIZED (fndecl) && ! flag_emit_class_files)
-    {
-      /* Wrap function body with a monitorenter plus monitorexit cleanup. */
-      tree enter, exit, lock;
-      if (METHOD_STATIC (fndecl))
-       lock = build_class_ref (DECL_CONTEXT (fndecl));
-      else
-       lock = DECL_ARGUMENTS (fndecl);
-      BUILD_MONITOR_ENTER (enter, lock);
-      BUILD_MONITOR_EXIT (exit, lock);
-      if (!CLASS_FROM_SOURCE_P (DECL_CONTEXT (fndecl)))
-       {
-         expand_expr_stmt (enter);
-         expand_decl_cleanup (NULL_TREE, exit);
-       }
-      else
-       {
-         tree function_body = DECL_FUNCTION_BODY (fndecl);
-         tree body = BLOCK_EXPR_BODY (function_body);
-         lock = build (COMPOUND_EXPR, void_type_node,
-                       enter,
-                       build (TRY_FINALLY_EXPR, void_type_node, body, exit));
-         TREE_SIDE_EFFECTS (lock) = 1;
-         BLOCK_EXPR_BODY (function_body) = lock;
-       }
-    }
-}
-
-void
 start_java_method (tree fndecl)
 {
   tree tem, *ptr;
   int i;
 
+  uniq = 0;
+
   current_function_decl = fndecl;
   announce_function (fndecl);
 
   i = DECL_MAX_LOCALS(fndecl) + DECL_MAX_STACK(fndecl);
   decl_map = make_tree_vec (i);
+  base_decl_map = make_tree_vec (i);
   type_map = xrealloc (type_map, i * sizeof (tree));
 
 #if defined(DEBUG_JAVA_BINDING_LEVELS)
@@ -1754,12 +1745,11 @@ start_java_method (tree fndecl)
     {
       tree parm_name = NULL_TREE, parm_decl;
       tree parm_type = TREE_VALUE (tem);
-      if (i >= DECL_MAX_LOCALS (fndecl))
-       abort ();
+      gcc_assert (i < DECL_MAX_LOCALS (fndecl));
 
       parm_decl = build_decl (PARM_DECL, parm_name, parm_type);
       DECL_CONTEXT (parm_decl) = fndecl;
-      if (PROMOTE_PROTOTYPES
+      if (targetm.calls.promote_prototypes (parm_type)
          && TYPE_PRECISION (parm_type) < TYPE_PRECISION (integer_type_node)
          && INTEGRAL_TYPE_P (parm_type))
        parm_type = integer_type_node;
@@ -1785,7 +1775,11 @@ start_java_method (tree fndecl)
     type_map[i++] = NULL_TREE;
 
   build_result_decl (fndecl);
-  complete_start_java_method (fndecl);
+
+  /* Push local variables.  */
+  pushlevel (2);
+
+  function_binding_level = current_binding_level;
 }
 
 void
@@ -1793,7 +1787,6 @@ end_java_method (void)
 {
   tree fndecl = current_function_decl;
 
-  expand_end_bindings (getdecls (), 1, 0);
   /* pop out of function */
   poplevel (1, 1, 0);
 
@@ -1801,67 +1794,79 @@ end_java_method (void)
   poplevel (1, 0, 1);
 
   BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
+  
+  if (DECL_SAVED_TREE (fndecl))
+    {
+      tree fbody, block_body;
+      /* Before we check initialization, attached all class initialization
+        variable to the block_body */
+      fbody = DECL_SAVED_TREE (fndecl);
+      block_body = BIND_EXPR_BODY (fbody);
+      htab_traverse (DECL_FUNCTION_INIT_TEST_TABLE (fndecl),
+                    attach_init_test_initialization_flags, block_body);
+    }
 
-  /* Generate rtl for function exit.  */
-  expand_function_end ();
-
-  /* Run the optimizers and output assembler code for this function. */
-  rest_of_compilation (fndecl);
+  finish_method (fndecl);
 
+  if (! flag_unit_at_a_time)
+    {
+      /* Nulling these fields when we no longer need them saves
+        memory.  */
+      DECL_SAVED_TREE (fndecl) = NULL;
+      DECL_STRUCT_FUNCTION (fndecl) = NULL;
+      DECL_INITIAL (fndecl) = NULL_TREE;
+    }
   current_function_decl = NULL_TREE;
 }
 
-/* Expand a function's body.  */
+/* Prepare a method for expansion.  */
 
 void
-java_expand_body (tree fndecl)
+finish_method (tree fndecl)
 {
-  const char *saved_input_filename = input_filename;
-  int saved_lineno = input_line;
-
-  current_function_decl = fndecl;
-  input_filename = DECL_SOURCE_FILE (fndecl);
-  input_line = DECL_SOURCE_LINE (fndecl);
+  tree *tp = &DECL_SAVED_TREE (fndecl);
 
-  timevar_push (TV_EXPAND);
-
-  /* Prepare the function for tree completion.  */
-  start_complete_expand_method (fndecl);
-
-  if (! flag_emit_class_files && ! flag_emit_xref)
+  /* Wrap body of synchronized methods in a monitorenter,
+     plus monitorexit cleanup.  */
+  if (METHOD_SYNCHRONIZED (fndecl))
     {
-      /* Initialize the RTL code for the function.  */
-      init_function_start (fndecl);
-
-      /* Set up parameters and prepare for return, for the function.  */
-      expand_function_start (fndecl, 0);
-
-      /* Generate the RTL for this function.  */
-      expand_expr_stmt_value (DECL_SAVED_TREE (fndecl), 0, 1);
+      tree enter, exit, lock;
+      if (METHOD_STATIC (fndecl))
+       lock = build_class_ref (DECL_CONTEXT (fndecl));
+      else
+       lock = DECL_ARGUMENTS (fndecl);
+      BUILD_MONITOR_ENTER (enter, lock);
+      BUILD_MONITOR_EXIT (exit, lock);
+      *tp = build2 (COMPOUND_EXPR, void_type_node, enter,
+                   build2 (TRY_FINALLY_EXPR, void_type_node, *tp, exit));
     }
 
-  /* Pop out of its parameters.  */
-  pushdecl_force_head (DECL_ARGUMENTS (fndecl));
-  poplevel (1, 0, 1);
-  BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
-
-  if (! flag_emit_class_files && ! flag_emit_xref)
-    {
-      /* Generate RTL for function exit.  */
-      input_line = DECL_FUNCTION_LAST_LINE (fndecl);
-      expand_function_end ();
+  /* Convert function tree to GENERIC prior to inlining.  */
+  java_genericize (fndecl);
 
-      /* Run the optimizers and output the assembler code
-        for this function.  */
-      rest_of_compilation (fndecl);
-    }
+  /* Store the end of the function, so that we get good line number
+     info for the epilogue.  */
+  if (DECL_STRUCT_FUNCTION (fndecl))
+    cfun = DECL_STRUCT_FUNCTION (fndecl);
+  else
+    allocate_struct_function (fndecl);
+#ifdef USE_MAPPED_LOCATION
+  cfun->function_end_locus = DECL_FUNCTION_LAST_LINE (fndecl);
+#else
+  cfun->function_end_locus.file = DECL_SOURCE_FILE (fndecl);
+  cfun->function_end_locus.line = DECL_FUNCTION_LAST_LINE (fndecl);
+#endif
 
-  timevar_pop (TV_EXPAND);
+  /* Defer inlining and expansion to the cgraph optimizers.  */
+  cgraph_finalize_function (fndecl, false);
+}
 
-  input_filename = saved_input_filename;
-  input_line = saved_lineno;
+/* Optimize and expand a function's entire body.  */
 
-  current_function_decl = NULL_TREE;
+void
+java_expand_body (tree fndecl)
+{
+  tree_rest_of_compilation (fndecl);
 }
 
 /* We pessimistically marked all methods and fields external until we
@@ -1875,10 +1880,39 @@ java_mark_decl_local (tree decl)
 
   /* If we've already constructed DECL_RTL, give encode_section_info
      a second chance, now that we've changed the flags.  */
+  /* ??? Ideally, we'd have flag_unit_at_a_time set, and not have done
+     anything that would have referenced DECL_RTL so far.  But at the
+     moment we force flag_unit_at_a_time off due to excessive memory
+     consumption when compiling large jar files.  Which probably means
+     that we need to re-order how we process jar files...  */
   if (DECL_RTL_SET_P (decl))
-    make_decl_rtl (decl, NULL);
+    make_decl_rtl (decl);
+}
+
+/* Given appropriate target support, G++ will emit hidden aliases for native
+   methods.  Using this hidden name is required for proper operation of
+   _Jv_Method::ncode, but it doesn't hurt to use it everywhere.  Look for
+   proper target support, then mark the method for aliasing.  */
+
+static void
+java_mark_cni_decl_local (tree decl)
+{
+  /* Setting DECL_LOCAL_CNI_METHOD_P changes the behavior of the mangler.
+     We expect that we should not yet have referenced this decl in a 
+     context that requires it.  Check this invariant even if we don't have
+     support for hidden aliases.  */
+  gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
+
+#if !defined(HAVE_GAS_HIDDEN) || !defined(ASM_OUTPUT_DEF)
+  return;
+#endif
+
+  DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+  DECL_LOCAL_CNI_METHOD_P (decl) = 1;
 }
 
+/* Use the preceding two functions and mark all members of the class.  */
+
 void
 java_mark_class_local (tree class)
 {
@@ -1889,8 +1923,101 @@ java_mark_class_local (tree class)
       java_mark_decl_local (t);
 
   for (t = TYPE_METHODS (class); t ; t = TREE_CHAIN (t))
-    if (!METHOD_ABSTRACT (t) && (!METHOD_NATIVE (t) || flag_jni))
-      java_mark_decl_local (t);
+    if (!METHOD_ABSTRACT (t))
+      {
+       if (METHOD_NATIVE (t) && !flag_jni)
+         java_mark_cni_decl_local (t);
+        else
+         java_mark_decl_local (t);
+      }
+}
+
+/* Add a statement to a compound_expr.  */
+
+tree
+add_stmt_to_compound (tree existing, tree type, tree stmt)
+{
+  if (!stmt)
+    return existing;
+  else if (existing)
+    {
+      tree expr = build2 (COMPOUND_EXPR, type, existing, stmt);
+      TREE_SIDE_EFFECTS (expr) = TREE_SIDE_EFFECTS (existing)
+                                | TREE_SIDE_EFFECTS (stmt);
+      return expr;
+    }
+  else
+    return stmt;
+}
+
+/* Add a statement to the statement_list currently being constructed.
+   If the statement_list is null, we don't create a singleton list.
+   This is necessary because poplevel() assumes that adding a
+   statement to a null statement_list returns the statement.  */
+
+tree
+java_add_stmt (tree new_stmt)
+{
+  tree stmts = current_binding_level->stmts;
+  tree_stmt_iterator i;
+
+  if (input_filename)
+    SET_EXPR_LOCATION (new_stmt, input_location);
+  
+  if (stmts == NULL)
+    return current_binding_level->stmts = new_stmt;
+
+  /* Force STMTS to be a statement_list.  */
+  if (TREE_CODE (stmts) != STATEMENT_LIST)
+    {
+      tree t = make_node (STATEMENT_LIST);
+      i = tsi_last (t);
+      tsi_link_after (&i, stmts, TSI_CONTINUE_LINKING);
+      stmts = t;
+    }  
+      
+  i = tsi_last (stmts);
+  tsi_link_after (&i, new_stmt, TSI_CONTINUE_LINKING);
+  TREE_TYPE (stmts) = void_type_node;
+
+  return current_binding_level->stmts = stmts;
+}
+
+/* Add a variable to the current scope.  */
+
+tree
+java_add_local_var (tree decl)
+{
+  tree *vars = &current_binding_level->names;
+  tree next = *vars;
+  TREE_CHAIN (decl) = next;
+  *vars = decl;
+  DECL_CONTEXT (decl) = current_function_decl;
+  MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
+  return decl;
+}
+
+/* Return a pointer to the compound_expr currently being
+   constructed.  */
+
+tree *
+get_stmts (void)
+{
+  return &current_binding_level->stmts;
+}
+
+/* Register an exception range as belonging to the current binding
+   level.  There may only be one: if there are more, we'll create more
+   binding levels.  However, each range can have multiple handlers,
+   and these are expanded when we call expand_end_java_handler().  */
+
+void
+register_exception_range (struct eh_range *range, int pc, int end_pc)
+{
+  gcc_assert (! current_binding_level->exception_range);
+  current_binding_level->exception_range = range;
+  current_binding_level->end_pc = end_pc;
+  current_binding_level->start_pc = pc;      
 }
 
 #include "gt-java-decl.h"