OSDN Git Service

* gcc/config/elfos.h (MAKE_DECL_ONE_ONLY): Redefined to stop DECL_WEAK
[pf3gnuchains/gcc-fork.git] / gcc / java / decl.c
index 761ebb2..168d30d 100644 (file)
@@ -1,6 +1,6 @@
 /* Process declarations and variables for the GNU compiler for the
    Java(TM) language.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -47,6 +47,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "cgraph.h"
 #include "tree-inline.h"
 #include "target.h"
+#include "version.h"
 
 #if defined (DEBUG_JAVA_BINDING_LEVELS)
 extern void indent (void);
@@ -57,8 +58,21 @@ 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);
+
+/* Used when computing the ABI version.  */
+#define GCJ_BINARYCOMPAT_ADDITION 5
+
+/* The version of the BC ABI that we generate.  At the moment we are
+   compatible with what shipped in GCC 4.0.  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 * 10000 + 0 * 10 + GCJ_BINARYCOMPAT_ADDITION)
+
+/* The ABI version number.  */
+tree gcj_abi_version;
 
 /* Name of the Cloneable class.  */
 tree java_lang_cloneable_identifier_node;
@@ -76,14 +90,20 @@ tree java_io_serializable_identifier_node;
 
 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. */
-
 #if defined(DEBUG_JAVA_BINDING_LEVELS)
 int binding_depth = 0;
 int is_class_level = 0;
@@ -99,51 +119,69 @@ indent (void)
 }
 #endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
 
-/* Copy the value in decl into every alias in the same local variable
-   slot.  */
+/* 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;
+}
+/* Copy the value in decl into every live alias in the same local
+   variable slot.  Some of these will be dead stores removed by the
+   optimizer.  */
+
 void 
-update_aliases (tree decl, int index)
+update_aliases (tree decl, int index, int pc)
 {
-  tree tmp = TREE_VEC_ELT (decl_map, index);
-  tree type = TREE_TYPE (decl);
-  while (tmp != NULL_TREE)
+  tree decl_type = TREE_TYPE (decl);
+  tree tmp;
+
+  if (debug_variable_p (decl))
+    abort ();
+
+  for (tmp = TREE_VEC_ELT (decl_map, index); 
+       tmp != NULL_TREE; 
+       tmp = DECL_LOCAL_SLOT_CHAIN (tmp))
     {
+      tree tmp_type = TREE_TYPE (tmp);
       if (tmp != decl
-         && ! LOCAL_VAR_OUT_OF_SCOPE_P (tmp)
-         && TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (tmp)))
+         && LOCAL_SLOT_P (tmp) == 0
+         && (pc == -1
+             || (pc >= DECL_LOCAL_START_PC (tmp)
+                 && pc < DECL_LOCAL_END_PC (tmp)))
+         /* This test is < (rather than <=) because there's no point
+            updating an alias that's about to die at the end of this
+            instruction.  */
+         && (tmp_type == decl_type
+             || (INTEGRAL_TYPE_P (tmp_type)
+                 && INTEGRAL_TYPE_P (decl_type)
+                 && TYPE_PRECISION (decl_type) <= 32
+                 && TYPE_PRECISION (tmp_type) <= 32)
+             || (TREE_CODE (tmp_type) == POINTER_TYPE
+                 && TREE_CODE (decl_type) == POINTER_TYPE)))
        {
-         tree src = build1 (NOP_EXPR, TREE_TYPE (tmp), decl);
-         java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (tmp), tmp, src));
+         tree src = build1 (NOP_EXPR, tmp_type, decl);
+         if (LOCAL_VAR_OUT_OF_SCOPE_P (tmp))
+           abort ();
+         java_add_stmt (build2 (MODIFY_EXPR, tmp_type, tmp, src));
        }
-      tmp = DECL_LOCAL_SLOT_CHAIN (tmp);      
     }
 }
 
 static tree
 push_jvm_slot (int index, tree decl)
 {
-  tree type = TREE_TYPE (decl);
-  tree tmp;
-
   DECL_CONTEXT (decl) = current_function_decl;
   layout_decl (decl, 0);
 
-  /* Look for another variable of the same mode in this slot.  */ 
-  tmp = TREE_VEC_ELT (decl_map, index);
-  while (tmp != NULL_TREE)
-    {
-      if (! LOCAL_VAR_OUT_OF_SCOPE_P (tmp)
-         && TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (tmp)))
-       {
-         /* At the point of its creation this decl inherits whatever
-            is in the slot.  */
-         tree src = build1 (NOP_EXPR, TREE_TYPE (decl), tmp);
-         java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, src));    
-         break;
-       }
-      tmp = DECL_LOCAL_SLOT_CHAIN (tmp);
-    }
-
   /* Now link the decl into the decl_map. */
   if (DECL_LANG_SPECIFIC (decl) == NULL)
     {
@@ -155,31 +193,53 @@ 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;
 
-  if (TREE_CODE (decl) != PARM_DECL)
-    pushdecl (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.  */
+/*  At the point of its creation a local variable decl inherits
+    whatever is already in the same slot.  In the case of a local
+    variable that is declared but unused, we won't find anything.  */
 
-static tree
-check_local_named_variable (tree best, tree decl, int pc, int *updated)
+static void
+initialize_local_variable (tree decl, int index)
 {
-  if (pc >= DECL_LOCAL_START_PC (decl)
-      && pc < DECL_LOCAL_END_PC (decl))
+  tree decl_type = TREE_TYPE (decl);
+  if (TREE_CODE (decl_type) == POINTER_TYPE)
     {
-      if (best == NULL_TREE
-         || (DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best)
-             && DECL_LOCAL_END_PC (decl) < DECL_LOCAL_END_PC (best)))
+      tree tmp = TREE_VEC_ELT (base_decl_map, index);
+
+      if (tmp)
         {
-         *updated = 1;
-         return decl;
+         /* At the point of its creation this decl inherits whatever
+            is in the slot.  */
+         tree src = build1 (NOP_EXPR, decl_type, tmp);
+         java_add_stmt (build2 (MODIFY_EXPR, decl_type, decl, src));   
        }
     }
+  else
+    {
+      tree tmp;
   
-  return best;
+      for (tmp = TREE_VEC_ELT (decl_map, index); 
+          tmp != NULL_TREE; 
+          tmp = DECL_LOCAL_SLOT_CHAIN (tmp))
+       {
+         tree tmp_type = TREE_TYPE (tmp);
+         if (tmp != decl
+             && ! debug_variable_p (tmp)
+             && (tmp_type == decl_type
+                 || (INTEGRAL_TYPE_P (tmp_type)
+                     && INTEGRAL_TYPE_P (decl_type)
+                     && TYPE_PRECISION (decl_type) <= 32
+                     && TYPE_PRECISION (tmp_type) <= 32
+                     && TYPE_PRECISION (tmp_type)
+                        >= TYPE_PRECISION (decl_type))))
+           {
+             java_add_stmt (build2 (MODIFY_EXPR, decl_type, decl, tmp));       
+             return;
+           }
+       }  
+    }
 }
 
 /* Find the best declaration based upon type.  If 'decl' fits 'type' better
@@ -188,20 +248,46 @@ 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;
-      }
-
-    return best;
+  tree decl_type = TREE_TYPE (decl);
+  
+  if (LOCAL_VAR_OUT_OF_SCOPE_P (decl))
+    abort ();
+
+  /* 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;
 }
 
 
@@ -210,63 +296,113 @@ 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)
     {
-      bool has_name = false;
-      tree name = DECL_NAME (decl);
-      if (name && IDENTIFIER_POINTER (name))
-       has_name = IDENTIFIER_POINTER (name)[0] != '#';
-      
-       /* 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 (has_name)
-       {
-         /* 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);
     }
 
-  if (best != NULL_TREE)
-    return best;
+  /* 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.
-     Ths name of the variable is #n#m, which n is the variable index
+     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.  */
-  {
-    char buf[64];
-    tree name;
-    static int uniq;
-    sprintf (buf, "#%d#%d", index, uniq++);
-    name = get_identifier (buf);
+     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);
+    }
 
-    return push_jvm_slot (index, build_decl (VAR_DECL, name, type));
-  }
+  /* 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;
+    }
+
+  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); 
+
+         if (! base_decl)
+           abort ();
+
+         if (! want_lvalue)
+           base_decl = build1 (NOP_EXPR, decl_type, base_decl);
+
+         return base_decl;
+       }
+    }
+
+  return var_decl;
 }
 
 
@@ -331,6 +467,11 @@ static GTY(()) struct binding_level *free_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. */
 
 #define LARGEST_PC (( (unsigned int)1 << (HOST_BITS_PER_INT - 1)) - 1)
@@ -401,18 +542,18 @@ tree
 builtin_function (const char *name,
                  tree type,
                  int function_code,
-                 enum built_in_class class,
+                 enum built_in_class cl,
                  const char *library_name,
-                 tree attrs ATTRIBUTE_UNUSED)
+                 tree ARG_UNUSED (attrs))
 {
   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);
+  make_decl_rtl (decl);
   pushdecl (decl);
-  DECL_BUILT_IN_CLASS (decl) = class;
+  DECL_BUILT_IN_CLASS (decl) = cl;
   DECL_FUNCTION_CODE (decl) = function_code;
   return decl;
 }
@@ -436,6 +577,49 @@ 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;
+    }
+
+  /* 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 = 10000 * major + 10 * minor;
+  /* It is helpful to distinguish BC ABI from ordinary ABI at this
+     level, since at some point we will recognize a variety of BC ABIs
+     (objects generated by different version of gcj), but will
+     probably always require strict matching for ordinary ABI.  */
+  if (flag_indirect_dispatch)
+    abi_version = GCJ_CURRENT_BC_ABI_VERSION;
+
+  gcj_abi_version = build_int_cstu (ptr_type_node, abi_version);
+}
 
 void
 java_init_decl_processing (void)
@@ -458,7 +642,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));
@@ -489,25 +673,23 @@ java_init_decl_processing (void)
 
   /* 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);
@@ -515,19 +697,21 @@ 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;
+  null_pointer_node = build_int_cst (ptr_type_node, 0);
 
 #if 0
   /* Make a type to be the domain of a few array types
@@ -596,6 +780,11 @@ java_init_decl_processing (void)
   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);
@@ -606,6 +795,15 @@ java_init_decl_processing (void)
                                         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. */
@@ -702,7 +900,7 @@ 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);
@@ -721,6 +919,9 @@ java_init_decl_processing (void)
   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));
@@ -733,9 +934,11 @@ 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);
   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);
@@ -767,9 +970,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);
@@ -788,10 +988,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);
@@ -803,8 +999,7 @@ 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));
+  t = tree_cons (NULL_TREE, class_ptr_type, endlink);
   alloc_object_node = builtin_function ("_Jv_AllocObject",
                                        build_function_type (ptr_type_node, t),
                                        0, NOT_BUILT_IN, NULL, NULL_TREE);
@@ -822,31 +1017,33 @@ java_init_decl_processing (void)
                                          0, NOT_BUILT_IN, NULL, NULL_TREE);
 
   throw_node = builtin_function ("_Jv_Throw",
-                                build_function_type (ptr_type_node, t),
+                                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);
+  t = build_function_type (void_type_node, tree_cons (NULL_TREE, ptr_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 = 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),
+                         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),
@@ -894,6 +1091,7 @@ java_init_decl_processing (void)
     = 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
@@ -907,7 +1105,14 @@ java_init_decl_processing (void)
     = 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 
+    = 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, 
@@ -924,9 +1129,11 @@ java_init_decl_processing (void)
                        0, NOT_BUILT_IN, NULL, NULL_TREE);
   soft_jnipopsystemframe_node
     = builtin_function ("_Jv_JNI_PopSystemFrame",
-                       build_function_type (ptr_type_node, t),
+                       build_function_type (void_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),
@@ -937,6 +1144,8 @@ java_init_decl_processing (void)
                        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),
@@ -961,6 +1170,8 @@ java_init_decl_processing (void)
 #if 0
   soft_fmodf_node = built_in_decls[BUILT_IN_FMODF];
 #endif
+
+  parse_version ();
 }
 
 
@@ -1102,10 +1313,10 @@ pushdecl (tree x)
              && chain_member (oldlocal, current_binding_level->level_chain->names))
            {
              if (TREE_CODE (oldlocal) == PARM_DECL)
-               pedwarn ("declaration of `%s' shadows a parameter",
+               pedwarn ("declaration of %qs shadows a parameter",
                         IDENTIFIER_POINTER (name));
              else
-               pedwarn ("declaration of `%s' shadows a symbol from the parameter list",
+               pedwarn ("declaration of %qs shadows a symbol from the parameter list",
                         IDENTIFIER_POINTER (name));
            }
 
@@ -1127,12 +1338,12 @@ pushdecl (tree x)
                   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";
+               warnstring = "declaration of %qs shadows a parameter";
              else if (oldlocal != 0)
-               warnstring = "declaration of `%s' shadows previous local";
+               warnstring = "declaration of %qs shadows previous local";
              else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
                       && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
-               warnstring = "declaration of `%s' shadows global declaration";
+               warnstring = "declaration of %qs shadows global declaration";
 
              if (warnstring)
                warning (warnstring, IDENTIFIER_POINTER (name));
@@ -1174,6 +1385,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
@@ -1497,9 +1722,13 @@ 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;
+       {
+         end_pc = current_binding_level->end_pc;
+         DECL_LOCAL_END_PC (decl) = end_pc;
+       }
 
       maybe_start_try (pc, end_pc);
       
@@ -1512,6 +1741,8 @@ maybe_pushlevels (int pc)
        {
          next = TREE_CHAIN (decl);
          push_jvm_slot (DECL_LOCAL_SLOT_NUMBER (decl), decl);
+         pushdecl (decl);
+         initialize_local_variable (decl, DECL_LOCAL_SLOT_NUMBER (decl));
        }
     }      
 
@@ -1525,6 +1756,12 @@ 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)
     poplevel (1, 0, 0);
 }
@@ -1686,6 +1923,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;
     }
@@ -1698,11 +1937,14 @@ 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)
@@ -1751,6 +1993,8 @@ start_java_method (tree fndecl)
 
   /* Push local variables.  */
   pushlevel (2);
+
+  function_binding_level = current_binding_level;
 }
 
 void
@@ -1765,6 +2009,17 @@ 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);
+    }
 
   flag_unit_at_a_time = 0;
   finish_method (fndecl);
@@ -1802,9 +2057,18 @@ finish_method (tree fndecl)
                    build2 (TRY_FINALLY_EXPR, void_type_node, *tp, exit));
     }
 
+  /* Ensure non-abstract non-static non-private members are defined only once
+     when linking. This is an issue when using CNI to interface with C++ object
+     files.  */
+  if (! METHOD_STATIC (fndecl) && ! METHOD_PRIVATE (fndecl)
+      && ! METHOD_ABSTRACT (fndecl) && ! METHOD_FINAL (fndecl))
+    make_decl_one_only (fndecl);
+
   /* Prepend class initialization for static methods reachable from
      other classes.  */
-  if (METHOD_STATIC (fndecl) && ! METHOD_PRIVATE (fndecl)
+  if (METHOD_STATIC (fndecl)
+      && (! METHOD_PRIVATE (fndecl)
+          || INNER_CLASS_P (DECL_CONTEXT (fndecl)))
       && ! DECL_CLINIT_P (fndecl)
       && ! CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (fndecl))))
     {
@@ -1825,8 +2089,12 @@ finish_method (tree 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
 
   /* Defer inlining and expansion to the cgraph optimizers.  */
   cgraph_finalize_function (fndecl, false);
@@ -1837,7 +2105,7 @@ finish_method (tree fndecl)
 void
 java_expand_body (tree fndecl)
 {
-  tree_rest_of_compilation (fndecl, 0);
+  tree_rest_of_compilation (fndecl);
 }
 
 /* We pessimistically marked all methods and fields external until we
@@ -1852,7 +2120,7 @@ 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.  */
   if (DECL_RTL_SET_P (decl))
-    make_decl_rtl (decl, NULL);
+    make_decl_rtl (decl);
 }
 
 void
@@ -1894,7 +2162,7 @@ tree
 java_add_stmt (tree stmt)
 {
   if (input_filename)
-    annotate_with_locus (stmt, input_location);
+    SET_EXPR_LOCATION (stmt, input_location);
   
   return current_binding_level->stmts 
     = add_stmt_to_compound (current_binding_level->stmts,