OSDN Git Service

PR 44103
[pf3gnuchains/gcc-fork.git] / gcc / java / class.c
index eb9ea71..7e9659b 100644 (file)
@@ -1,12 +1,12 @@
 /* Functions related to building classes and their related objects.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-   Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -15,9 +15,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 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, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.
 
 Java and all Java-based marks are trademarks or registered trademarks
 of Sun Microsystems, Inc. in the United States and other countries.
@@ -39,6 +38,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "output.h"
 #include "parse.h"
 #include "function.h"
+#include "tm_p.h"
 #include "ggc.h"
 #include "stdio.h"
 #include "target.h"
@@ -46,6 +46,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "cgraph.h"
 #include "tree-iterator.h"
 #include "cgraph.h"
+#include "vecprim.h"
 
 /* DOS brain-damage */
 #ifndef O_BINARY
@@ -62,12 +63,14 @@ static int supers_all_compiled (tree type);
 static tree maybe_layout_super_class (tree, tree);
 static void add_miranda_methods (tree, tree);
 static int assume_compiled (const char *);
-static tree build_symbol_entry (tree);
+static tree build_symbol_entry (tree, tree);
 static tree emit_assertion_table (tree);
 static void register_class (void);
 
 struct obstack temporary_obstack;
 
+static const char *cyclic_inheritance_report;
+
 /* The compiler generates different code depending on whether or not
    it can assume certain classes have been compiled down to native
    code or not.  The compiler options -fassume-compiled= and
@@ -107,6 +110,10 @@ static GTY(()) tree class_roots[4];
 
 static GTY(()) VEC(tree,gc) *registered_class;
 
+/* A tree that returns the address of the class$ of the class
+   currently being compiled.  */
+static GTY(()) tree this_classdollar;
+
 /* Return the node that most closely represents the class whose name
    is IDENT.  Start the search from NODE (followed by its siblings).
    Return NULL if an appropriate node does not exist.  */
@@ -156,7 +163,7 @@ add_class_flag (class_flag_node **rootp, const char *ident, int value)
 
   if (NULL == root)
     {
-      root = xmalloc (sizeof (class_flag_node));
+      root = XNEW (class_flag_node);
       root->ident = "";
       root->value = 0;
       root->sibling = NULL;
@@ -183,7 +190,7 @@ add_class_flag (class_flag_node **rootp, const char *ident, int value)
   else
     {
       /* Insert new node into the tree.  */
-      node = xmalloc (sizeof (class_flag_node));
+      node = XNEW (class_flag_node);
 
       node->ident = xstrdup (ident);
       node->value = value;
@@ -206,7 +213,7 @@ add_assume_compiled (const char *ident, int excludep)
 
 /* The default value returned by enable_assertions. */
 
-#define DEFAULT_ENABLE_ASSERT (flag_emit_class_files || optimize == 0)
+#define DEFAULT_ENABLE_ASSERT (optimize == 0)
 
 /* Enter IDENT (a class or package name) into the enable-assertions table.
    VALUE is true to enable and false to disable. */
@@ -273,7 +280,7 @@ ident_subst (const char* old_name,
   int prefix_len = strlen (prefix);
   int suffix_len = strlen (suffix);
   int i = prefix_len + old_length + suffix_len + 1;
-  char *buffer = alloca (i);
+  char *buffer = (char *) alloca (i);
 
   strcpy (buffer, prefix);
   for (i = 0; i < old_length; i++)
@@ -308,10 +315,63 @@ identifier_subst (const tree old_id,
 tree
 mangled_classname (const char *prefix, tree type)
 {
+  tree result;
   tree ident = TYPE_NAME (type);
   if (TREE_CODE (ident) != IDENTIFIER_NODE)
     ident = DECL_NAME (ident);
-  return identifier_subst (ident, prefix, '.', '_', "");
+  result = identifier_subst (ident, prefix, '.', '_', "");
+
+  /* Replace any characters that aren't in the set [0-9a-zA-Z_$] with
+     "_0xXX".  Class names containing such chracters are uncommon, but
+     they do sometimes occur in class files.  Without this check,
+     these names cause assembly errors.
+
+     There is a possibility that a real class name could conflict with
+     the identifier we generate, but it is unlikely and will
+     immediately be detected as an assembler error.  At some point we
+     should do something more elaborate (perhaps using the full
+     unicode mangling scheme) in order to prevent such a conflict.  */
+  {
+    int i;
+    const int len = IDENTIFIER_LENGTH (result);
+    const char *p = IDENTIFIER_POINTER (result);
+    int illegal_chars = 0;
+
+    /* Make two passes over the identifier.  The first pass is merely
+       to count illegal characters; we need to do this in order to
+       allocate a buffer.  */
+    for (i = 0; i < len; i++)
+      {
+       char c = p[i];
+       illegal_chars += (! ISALNUM (c) && c != '_' && c != '$');
+      }
+
+    /* And the second pass, which is rarely executed, does the
+       rewriting.  */
+    if (illegal_chars != 0)
+      {
+       char *buffer = (char *) alloca (illegal_chars * 4 + len + 1);
+       int j;
+
+       for (i = 0, j = 0; i < len; i++)
+         {
+           char c = p[i];
+           if (! ISALNUM (c) && c != '_' && c != '$')
+             {
+               buffer[j++] = '_';
+               sprintf (&buffer[j], "0x%02x", c);
+               j += 4;
+             }
+           else
+             buffer[j++] = c;
+         }
+
+       buffer[j] = 0;
+       result = get_identifier (buffer);
+      }
+  }
+
+  return result;
 }
 
 tree
@@ -353,13 +413,14 @@ unmangle_classname (const char *name, int name_length)
 #define GEN_TABLE(TABLE, NAME, TABLE_TYPE, TYPE)                       \
 do                                                                     \
 {                                                                      \
-  const char *typename = IDENTIFIER_POINTER (mangled_classname ("", TYPE)); \
-  char *buf = alloca (strlen (typename) + strlen (#NAME "_syms_") + 1);        \
+  const char *type_name = IDENTIFIER_POINTER (mangled_classname ("", TYPE)); \
+  char *buf = (char *) alloca (strlen (type_name)                      \
+                               + strlen (#NAME "_syms_") + 1);         \
   tree decl;                                                           \
                                                                        \
-  sprintf (buf, #NAME "_%s", typename);                                        \
+  sprintf (buf, #NAME "_%s", type_name);                               \
   TYPE_## TABLE ##_DECL (type) = decl =                                        \
-    build_decl (VAR_DECL, get_identifier (buf), TABLE_TYPE);           \
+    build_decl (input_location, VAR_DECL, get_identifier (buf), TABLE_TYPE); \
   DECL_EXTERNAL (decl) = 1;                                            \
   TREE_STATIC (decl) = 1;                                              \
   TREE_READONLY (decl) = 1;                                            \
@@ -369,13 +430,12 @@ do                                                                        \
   pushdecl (decl);                                                     \
   MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);                          \
   DECL_OWNER (decl) = TYPE;                                            \
-  sprintf (buf, #NAME "_syms_%s", typename);                           \
+  sprintf (buf, #NAME "_syms_%s", type_name);                          \
   TYPE_## TABLE ##_SYMS_DECL (TYPE) =                                  \
-    build_decl (VAR_DECL, get_identifier (buf), symbols_array_type);   \
+    build_decl (input_location, VAR_DECL, get_identifier (buf), symbols_array_type); \
   TREE_STATIC (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1;                 \
   TREE_CONSTANT (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1;               \
   DECL_IGNORED_P (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1;              \
-  pushdecl (TYPE_## TABLE ##_SYMS_DECL (TYPE));                                \
 }                                                                      \
 while (0)
 
@@ -384,19 +444,22 @@ while (0)
 void
 gen_indirect_dispatch_tables (tree type)
 {
-  const char *typename = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+  const char *type_name = IDENTIFIER_POINTER (mangled_classname ("", type));
   {  
     tree field = NULL;
-    char *buf = alloca (strlen (typename) + strlen ("_catch_classes_") + 1);
+    char *buf = (char *) alloca (strlen (type_name)
+                                + strlen ("_catch_classes_") + 1);
     tree catch_class_type = make_node (RECORD_TYPE);
 
-    sprintf (buf, "_catch_classes_%s", typename);
-    PUSH_FIELD (catch_class_type, field, "address", utf8const_ptr_type);
-    PUSH_FIELD (catch_class_type, field, "classname", ptr_type_node);
+    sprintf (buf, "_catch_classes_%s", type_name);
+    PUSH_FIELD (input_location,
+               catch_class_type, field, "address", utf8const_ptr_type);
+    PUSH_FIELD (input_location,
+               catch_class_type, field, "classname", ptr_type_node);
     FINISH_RECORD (catch_class_type);
     
     TYPE_CTABLE_DECL (type) 
-      = build_decl (VAR_DECL, get_identifier (buf),
+      = build_decl (input_location, VAR_DECL, get_identifier (buf),
                    build_array_type (catch_class_type, 0));
     DECL_EXTERNAL (TYPE_CTABLE_DECL (type)) = 1;
     TREE_STATIC (TYPE_CTABLE_DECL (type)) = 1;
@@ -421,13 +484,8 @@ push_class (tree class_type, tree class_name)
 {
   tree decl, signature;
   location_t saved_loc = input_location;
-#ifndef USE_MAPPED_LOCATION
-  tree source_name = identifier_subst (class_name, "", '.', '/', ".java");
-  input_filename = IDENTIFIER_POINTER (source_name);
-  input_line = 0;
-#endif
   CLASS_P (class_type) = 1;
-  decl = build_decl (TYPE_DECL, class_name, class_type);
+  decl = build_decl (input_location, TYPE_DECL, class_name, class_type);
   TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
 
   /* dbxout needs a DECL_SIZE if in gstabs mode */
@@ -498,6 +556,9 @@ set_class_decl_access_flags (int access_flags, tree class_decl)
   if (access_flags & ACC_PRIVATE)   CLASS_PRIVATE (class_decl) = 1;
   if (access_flags & ACC_PROTECTED) CLASS_PROTECTED (class_decl) = 1;
   if (access_flags & ACC_STRICT)    CLASS_STRICTFP (class_decl) = 1;
+  if (access_flags & ACC_ENUM)      CLASS_ENUM (class_decl) = 1;
+  if (access_flags & ACC_SYNTHETIC) CLASS_SYNTHETIC (class_decl) = 1;
+  if (access_flags & ACC_ANNOTATION) CLASS_ANNOTATION (class_decl) = 1;
 }
 
 /* Return length of inheritance chain of CLAS, where java.lang.Object is 0,
@@ -664,25 +725,31 @@ add_interface (tree this_class, tree interface_class)
   BINFO_BASE_APPEND (TYPE_BINFO (this_class), interface_binfo);
 }
 
-#if 0
-/* Return the address of a pointer to the first FUNCTION_DECL
-   in the list (*LIST) whose DECL_NAME is NAME. */
-
-static tree *
-find_named_method (tree *list, tree name)
-{
-  while (*list && DECL_NAME (*list) != name)
-    list = &TREE_CHAIN (*list);
-  return list;
-}
-#endif
-
 static tree
 build_java_method_type (tree fntype, tree this_class, int access_flags)
 {
   if (access_flags & ACC_STATIC)
     return fntype;
-  return build_method_type (this_class, fntype);
+  fntype = build_method_type (this_class, fntype);
+
+  /* We know that arg 1 of every nonstatic method is non-null; tell
+     the back-end so.  */
+  TYPE_ATTRIBUTES (fntype) = (tree_cons 
+                             (get_identifier ("nonnull"),
+                              tree_cons (NULL_TREE, 
+                                         build_int_cst (NULL_TREE, 1),
+                                         NULL_TREE),
+                              TYPE_ATTRIBUTES (fntype)));
+  return fntype;
+}
+
+void
+java_hide_decl (tree decl ATTRIBUTE_UNUSED)
+{
+#ifdef HAVE_GAS_HIDDEN
+  DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+  DECL_VISIBILITY_SPECIFIED (decl) = 1;
+#endif
 }
 
 tree
@@ -693,11 +760,11 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
   method_type = build_java_method_type (function_type,
                                        this_class, access_flags);
 
-  fndecl = build_decl (FUNCTION_DECL, name, method_type);
+  fndecl = build_decl (input_location, FUNCTION_DECL, name, method_type);
   DECL_CONTEXT (fndecl) = this_class;
 
   DECL_LANG_SPECIFIC (fndecl)
-    = ggc_alloc_cleared (sizeof (struct lang_decl));
+    = GGC_CNEW (struct lang_decl);
   DECL_LANG_SPECIFIC (fndecl)->desc = LANG_DECL_FUNC;
 
   /* Initialize the static initializer test table.  */
@@ -710,12 +777,17 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
     DECL_FUNCTION_INITIALIZED_CLASS_TABLE (fndecl) =
       htab_create_ggc (50, htab_hash_pointer, htab_eq_pointer, NULL);
 
-  /* Initialize the static method invocation compound list */
-  DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (fndecl) = NULL_TREE;
-
   TREE_CHAIN (fndecl) = TYPE_METHODS (this_class);
   TYPE_METHODS (this_class) = fndecl;
 
+  /* If pointers to member functions use the least significant bit to
+     indicate whether a function is virtual, ensure a pointer
+     to this function will have that bit clear.  */
+  if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
+      && !(access_flags & ACC_STATIC)
+      && DECL_ALIGN (fndecl) < 2 * BITS_PER_UNIT)
+    DECL_ALIGN (fndecl) = 2 * BITS_PER_UNIT;
+
   /* Notice that this is a finalizer and update the class type
      accordingly. This is used to optimize instance allocation. */
   if (name == finalize_identifier_node
@@ -726,19 +798,26 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
   if (access_flags & ACC_PUBLIC) METHOD_PUBLIC (fndecl) = 1;
   if (access_flags & ACC_PROTECTED) METHOD_PROTECTED (fndecl) = 1;
   if (access_flags & ACC_PRIVATE)
-    METHOD_PRIVATE (fndecl) = DECL_INLINE (fndecl) = 1;
+    METHOD_PRIVATE (fndecl) = 1;
   if (access_flags & ACC_NATIVE)
     {
       METHOD_NATIVE (fndecl) = 1;
       DECL_EXTERNAL (fndecl) = 1;
     }
+  else
+    /* FNDECL is external unless we are compiling it into this object
+       file.  */
+    DECL_EXTERNAL (fndecl) = CLASS_FROM_CURRENTLY_COMPILED_P (this_class) == 0;
   if (access_flags & ACC_STATIC) 
-    METHOD_STATIC (fndecl) = DECL_INLINE (fndecl) = 1;
+    METHOD_STATIC (fndecl) = 1;
   if (access_flags & ACC_FINAL) 
-    METHOD_FINAL (fndecl) = DECL_INLINE (fndecl) = 1;
+    METHOD_FINAL (fndecl) = 1;
   if (access_flags & ACC_SYNCHRONIZED) METHOD_SYNCHRONIZED (fndecl) = 1;
   if (access_flags & ACC_ABSTRACT) METHOD_ABSTRACT (fndecl) = 1;
   if (access_flags & ACC_STRICT) METHOD_STRICTFP (fndecl) = 1;
+  if (access_flags & ACC_SYNTHETIC) DECL_ARTIFICIAL (fndecl) = 1;
+  if (access_flags & ACC_BRIDGE) METHOD_BRIDGE (fndecl) = 1;
+  if (access_flags & ACC_VARARGS) METHOD_VARARGS (fndecl) = 1;
   return fndecl;
 }
 
@@ -763,30 +842,42 @@ add_method (tree this_class, int access_flags, tree name, tree method_sig)
 }
 
 tree
-add_field (tree class, tree name, tree field_type, int flags)
+add_field (tree klass, tree name, tree field_type, int flags)
 {
   int is_static = (flags & ACC_STATIC) != 0;
   tree field;
-  field = build_decl (is_static ? VAR_DECL : FIELD_DECL, name, field_type);
-  TREE_CHAIN (field) = TYPE_FIELDS (class);
-  TYPE_FIELDS (class) = field;
-  DECL_CONTEXT (field) = class;
+  field = build_decl (input_location,
+                     is_static ? VAR_DECL : FIELD_DECL, name, field_type);
+  TREE_CHAIN (field) = TYPE_FIELDS (klass);
+  TYPE_FIELDS (klass) = field;
+  DECL_CONTEXT (field) = klass;
+  MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (field);
 
   if (flags & ACC_PUBLIC) FIELD_PUBLIC (field) = 1;
   if (flags & ACC_PROTECTED) FIELD_PROTECTED (field) = 1;
   if (flags & ACC_PRIVATE) FIELD_PRIVATE (field) = 1;
   if (flags & ACC_FINAL) FIELD_FINAL (field) = 1;
-  if (flags & ACC_VOLATILE) FIELD_VOLATILE (field) = 1;
+  if (flags & ACC_VOLATILE) 
+    {
+      FIELD_VOLATILE (field) = 1;
+      TREE_THIS_VOLATILE (field) = 1;
+    }
   if (flags & ACC_TRANSIENT) FIELD_TRANSIENT (field) = 1;
+  if (flags & ACC_ENUM) FIELD_ENUM (field) = 1;
+  if (flags & ACC_SYNTHETIC) FIELD_SYNTHETIC (field) = 1;
   if (is_static)
     {
       FIELD_STATIC (field) = 1;
       /* Always make field externally visible.  This is required so
         that native methods can always access the field.  */
       TREE_PUBLIC (field) = 1;
-      /* Considered external until we know what classes are being
-        compiled into this object file.  */
-      DECL_EXTERNAL (field) = 1;
+      /* Hide everything that shouldn't be visible outside a DSO.  */
+      if (flag_indirect_classes
+         || (FIELD_PRIVATE (field)))
+       java_hide_decl (field);
+      /* Considered external unless we are compiling it into this
+        object file.  */
+      DECL_EXTERNAL (field) = (is_compiled_class (klass) != 2);
     }
 
   return field;
@@ -815,29 +906,9 @@ set_constant_value (tree field, tree constant)
                && TREE_TYPE (field) == string_ptr_type_node))
        error ("ConstantValue attribute of field '%s' has wrong type",
               IDENTIFIER_POINTER (DECL_NAME (field)));
-      if (FIELD_FINAL (field))
-       DECL_FIELD_FINAL_IUD (field) = 1;
     }
 }
 
-/* Count the number of Unicode chars encoded in a given Ut8 string. */
-
-#if 0
-int
-strLengthUtf8 (char *str, int len)
-{
-  register unsigned char* ptr = (unsigned char*) str;
-  register unsigned char *limit = ptr + len;
-  int str_length = 0;
-  for (; ptr < limit; str_length++) {
-    if (UTF8_GET (ptr, limit) < 0)
-      return -1;
-  }
-  return str_length;
-}
-#endif
-
-
 /* Calculate a hash value for a string encoded in Utf8 format.
  * This returns the same hash value as specified for java.lang.String.hashCode.
  */
@@ -863,39 +934,44 @@ static GTY(()) tree utf8_decl_list = NULL_TREE;
 tree
 build_utf8_ref (tree name)
 {
-  const char * name_ptr = IDENTIFIER_POINTER(name);
-  int name_len = IDENTIFIER_LENGTH(name);
+  const char * name_ptr = IDENTIFIER_POINTER (name);
+  int name_len = IDENTIFIER_LENGTH (name), name_pad;
   char buf[60];
   tree ctype, field = NULL_TREE, str_type, cinit, string;
   static int utf8_count = 0;
   int name_hash;
   tree ref = IDENTIFIER_UTF8_REF (name);
   tree decl;
+  VEC(constructor_elt,gc) *v = NULL;
   if (ref != NULL_TREE)
     return ref;
 
   ctype = make_node (RECORD_TYPE);
+  /* '\0' byte plus padding to utf8const_type's alignment.  */
+  name_pad = TYPE_ALIGN_UNIT (utf8const_type)
+            - (name_len & (TYPE_ALIGN_UNIT (utf8const_type) - 1));
   str_type = build_prim_array_type (unsigned_byte_type_node,
-                                   name_len + 1); /* Allow for final '\0'. */
-  PUSH_FIELD (ctype, field, "hash", unsigned_short_type_node);
-  PUSH_FIELD (ctype, field, "length", unsigned_short_type_node);
-  PUSH_FIELD (ctype, field, "data", str_type);
+                                   name_len + name_pad);
+  PUSH_FIELD (input_location, ctype, field, "hash", unsigned_short_type_node);
+  PUSH_FIELD (input_location,
+             ctype, field, "length", unsigned_short_type_node);
+  PUSH_FIELD (input_location, ctype, field, "data", str_type);
   FINISH_RECORD (ctype);
-  START_RECORD_CONSTRUCTOR (cinit, ctype);
+  START_RECORD_CONSTRUCTOR (v, ctype);
   name_hash = hashUtf8String (name_ptr, name_len) & 0xFFFF;
-  PUSH_FIELD_VALUE (cinit, "hash", build_int_cst (NULL_TREE, name_hash));
-  PUSH_FIELD_VALUE (cinit, "length", build_int_cst (NULL_TREE, name_len));
+  PUSH_FIELD_VALUE (v, "hash", build_int_cst (NULL_TREE, name_hash));
+  PUSH_FIELD_VALUE (v, "length", build_int_cst (NULL_TREE, name_len));
   string = build_string (name_len, name_ptr);
   TREE_TYPE (string) = str_type;
-  PUSH_FIELD_VALUE (cinit, "data", string);
-  FINISH_RECORD_CONSTRUCTOR (cinit);
+  PUSH_FIELD_VALUE (v, "data", string);
+  FINISH_RECORD_CONSTRUCTOR (cinit, v, ctype);
   TREE_CONSTANT (cinit) = 1;
-  TREE_INVARIANT (cinit) = 1;
 
   /* Generate a unique-enough identifier.  */
   sprintf(buf, "_Utf%d", ++utf8_count);
 
-  decl = build_decl (VAR_DECL, get_identifier (buf), utf8const_type);
+  decl = build_decl (input_location,
+                    VAR_DECL, get_identifier (buf), utf8const_type);
   TREE_STATIC (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
   DECL_IGNORED_P (decl) = 1;
@@ -907,24 +983,25 @@ build_utf8_ref (tree name)
     {
       int decl_size;
       /* Ensure decl_size is a multiple of utf8const_type's alignment. */
-      decl_size = (name_len + 5 + TYPE_ALIGN_UNIT (utf8const_type) - 1)
-       & ~(TYPE_ALIGN_UNIT (utf8const_type) - 1);
+      decl_size = name_len + 4 + name_pad;
       if (flag_merge_constants && decl_size < 256)
        {
          char buf[32];
          int flags = (SECTION_OVERRIDE
                       | SECTION_MERGE | (SECTION_ENTSIZE & decl_size));
          sprintf (buf, ".rodata.jutf8.%d", decl_size);
-         named_section_flags (buf, flags);
+         switch_to_section (get_section (buf, flags, NULL));
          DECL_SECTION_NAME (decl) = build_string (strlen (buf), buf);
        }
     }
 
   TREE_CHAIN (decl) = utf8_decl_list;
   layout_decl (decl, 0);
+  DECL_SIZE (decl) = TYPE_SIZE (ctype);
+  DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (ctype);
   pushdecl (decl);
   rest_of_decl_compilation (decl, global_bindings_p (), 0);
-  cgraph_varpool_mark_needed_node (cgraph_varpool_node (decl));
+  varpool_mark_needed_node (varpool_node (decl));
   utf8_decl_list = decl;
   ref = build1 (ADDR_EXPR, utf8const_ptr_type, decl);
   IDENTIFIER_UTF8_REF (name) = ref;
@@ -944,6 +1021,123 @@ build_indirect_class_ref (tree type)
   return convert (promote_type (class_ptr_type), cl);
 }
 
+static tree
+build_static_class_ref (tree type)
+{
+  tree decl_name, decl, ref;
+
+  if (TYPE_SIZE (type) == error_mark_node)
+    return null_pointer_node;
+  decl_name = identifier_subst (DECL_NAME (TYPE_NAME (type)),
+                               "", '/', '/', ".class$$");
+  decl = IDENTIFIER_GLOBAL_VALUE (decl_name);
+  if (decl == NULL_TREE)
+    {
+      decl = build_decl (input_location, VAR_DECL, decl_name, class_type_node);
+      TREE_STATIC (decl) = 1;
+      if (! flag_indirect_classes)
+       {
+         TREE_PUBLIC (decl) = 1;
+         if (CLASS_PRIVATE (TYPE_NAME (type)))
+           java_hide_decl (decl);
+       }
+      DECL_IGNORED_P (decl) = 1;
+      DECL_ARTIFICIAL (decl) = 1;
+      if (is_compiled_class (type) == 1)
+       DECL_EXTERNAL (decl) = 1;
+      MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
+      DECL_CLASS_FIELD_P (decl) = 1;
+      DECL_CONTEXT (decl) = type;
+
+      /* ??? We want to preserve the DECL_CONTEXT we set just above,
+        that that means not calling pushdecl_top_level.  */
+      IDENTIFIER_GLOBAL_VALUE (decl_name) = decl;
+    }
+
+  ref = build1 (ADDR_EXPR, class_ptr_type, decl);
+  return ref;
+}
+
+static tree
+build_classdollar_field (tree type)
+{
+  tree decl_name = identifier_subst (DECL_NAME (TYPE_NAME (type)),
+                                    "", '/', '/', ".class$");
+  tree decl = IDENTIFIER_GLOBAL_VALUE (decl_name);
+
+  if (decl == NULL_TREE)
+    {
+      decl 
+       = build_decl (input_location,
+                     VAR_DECL, decl_name, 
+                     (build_type_variant 
+                      (build_pointer_type 
+                       (build_type_variant (class_type_node, 
+                                            /* const */ 1, 0)),
+                       /* const */ 1, 0)));
+      TREE_STATIC (decl) = 1;
+      TREE_CONSTANT (decl) = 1;
+      TREE_READONLY (decl) = 1;
+      TREE_PUBLIC (decl) = 1;
+      java_hide_decl (decl);
+      DECL_IGNORED_P (decl) = 1;
+      DECL_ARTIFICIAL (decl) = 1;
+      MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
+      IDENTIFIER_GLOBAL_VALUE (decl_name) = decl;
+      DECL_CLASS_FIELD_P (decl) = 1;
+      DECL_CONTEXT (decl) = type;
+    }
+
+  return decl;
+}
+
+/* Create a local variable that holds the current class$.  */
+
+void
+cache_this_class_ref (tree fndecl)
+{
+  if (optimize)
+    {
+      tree classdollar_field;
+      if (flag_indirect_classes)
+       classdollar_field = build_classdollar_field (output_class);
+      else
+       classdollar_field = build_static_class_ref (output_class);
+
+      this_classdollar = build_decl (input_location,
+                                    VAR_DECL, NULL_TREE, 
+                                    TREE_TYPE (classdollar_field));
+      
+      java_add_local_var (this_classdollar);
+      java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (this_classdollar), 
+                            this_classdollar, classdollar_field));
+    }
+  else
+    this_classdollar = build_classdollar_field (output_class);
+
+  /* Prepend class initialization for static methods reachable from
+     other classes.  */
+  if (METHOD_STATIC (fndecl)
+      && (! METHOD_PRIVATE (fndecl)
+          || INNER_CLASS_P (DECL_CONTEXT (fndecl)))
+      && ! DECL_CLINIT_P (fndecl)
+      && ! CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (fndecl))))
+    {
+      tree init = build_call_expr (soft_initclass_node, 1,
+                                  this_classdollar);
+      java_add_stmt (init);
+    }
+}
+
+/* Remove the reference to the local variable that holds the current
+   class$.  */
+
+void
+uncache_this_class_ref (tree fndecl ATTRIBUTE_UNUSED)
+{
+  this_classdollar = build_classdollar_field (output_class);
+}
+
 /* Build a reference to the class TYPE.
    Also handles primitive types and array types. */
 
@@ -953,7 +1147,7 @@ build_class_ref (tree type)
   int is_compiled = is_compiled_class (type);
   if (is_compiled)
     {
-      tree ref, decl_name, decl;
+      tree ref, decl;
       if (TREE_CODE (type) == POINTER_TYPE)
        type = TREE_TYPE (type);
 
@@ -962,69 +1156,22 @@ build_class_ref (tree type)
          && TREE_CODE (type) == RECORD_TYPE)
        return build_indirect_class_ref (type);
 
-      if (TREE_CODE (type) == RECORD_TYPE)
+      if (type == output_class && flag_indirect_classes)
        {
-         if (TYPE_SIZE (type) == error_mark_node)
-           return null_pointer_node;
-         decl_name = identifier_subst (DECL_NAME (TYPE_NAME (type)),
-                                       "", '/', '/', ".class");
-         decl = IDENTIFIER_GLOBAL_VALUE (decl_name);
-         if (decl == NULL_TREE)
-           {
-             decl = build_decl (VAR_DECL, decl_name, class_type_node);
-             TREE_STATIC (decl) = 1;
-             TREE_PUBLIC (decl) = 1;
-             DECL_IGNORED_P (decl) = 1;
-             DECL_ARTIFICIAL (decl) = 1;
-             if (is_compiled == 1)
-               DECL_EXTERNAL (decl) = 1;
-             MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
-             DECL_CLASS_FIELD_P (decl) = 1;
-             DECL_CONTEXT (decl) = type;
-
-             /* ??? We want to preserve the DECL_CONTEXT we set just above,
-                that that means not calling pushdecl_top_level.  */
-             IDENTIFIER_GLOBAL_VALUE (decl_name) = decl;
-           }
+         /* This can be NULL if we see a JNI stub before we see any
+            other method.  */
+         if (! this_classdollar)
+           this_classdollar = build_classdollar_field (output_class);
+         return this_classdollar;
        }
+      
+      if (TREE_CODE (type) == RECORD_TYPE)
+       return build_static_class_ref (type);
       else
        {
          const char *name;
+         tree decl_name;
          char buffer[25];
-         if (flag_emit_class_files)
-           {
-             const char *prim_class_name;
-             tree prim_class;
-             if (type == char_type_node)
-               prim_class_name = "java.lang.Character";
-             else if (type == boolean_type_node)
-               prim_class_name = "java.lang.Boolean";
-             else if (type == byte_type_node)
-               prim_class_name = "java.lang.Byte";
-             else if (type == short_type_node)
-               prim_class_name = "java.lang.Short";
-             else if (type == int_type_node)
-               prim_class_name = "java.lang.Integer";
-             else if (type == long_type_node)
-               prim_class_name = "java.lang.Long";
-             else if (type == float_type_node)
-                prim_class_name = "java.lang.Float";
-             else if (type == double_type_node)
-                prim_class_name = "java.lang.Double";
-             else if (type == void_type_node)
-                prim_class_name = "java.lang.Void";
-             else
-               abort ();
-
-             prim_class = lookup_class (get_identifier (prim_class_name));
-             /* We wrap the class in a NOP_EXPR, because it is a
-                type.  We can't hold it in the COMPONENT_REF itself,
-                as that type must remain NULL.  */
-             prim_class = build1 (NOP_EXPR, prim_class, NULL_TREE);
-             
-             return build3 (COMPONENT_REF, NULL_TREE,
-                            prim_class, TYPE_identifier_node, NULL_TREE);
-           }
          decl_name = TYPE_NAME (type);
          if (TREE_CODE (decl_name) == TYPE_DECL)
            decl_name = DECL_NAME (decl_name);
@@ -1036,7 +1183,8 @@ build_class_ref (tree type)
          decl = IDENTIFIER_GLOBAL_VALUE (decl_name);
          if (decl == NULL_TREE)
            {
-             decl = build_decl (VAR_DECL, decl_name, class_type_node);
+             decl = build_decl (input_location,
+                                VAR_DECL, decl_name, class_type_node);
              TREE_STATIC (decl) = 1;
              TREE_PUBLIC (decl) = 1;
              DECL_EXTERNAL (decl) = 1;
@@ -1060,17 +1208,19 @@ build_fieldref_cache_entry (int index, tree fdecl ATTRIBUTE_UNUSED)
 {
   tree decl, decl_name;
   const char *name = IDENTIFIER_POINTER (mangled_classname ("_cpool_", output_class));
-  char *buf = alloca (strlen (name) + 20);
+  char *buf = (char *) alloca (strlen (name) + 20);
   sprintf (buf, "%s_%d_ref", name, index);
   decl_name = get_identifier (buf);
   decl = IDENTIFIER_GLOBAL_VALUE (decl_name);
   if (decl == NULL_TREE)
     {
-      decl = build_decl (VAR_DECL, decl_name, ptr_type_node);
+      decl = build_decl (input_location,
+                        VAR_DECL, decl_name, ptr_type_node);
       TREE_STATIC (decl) = 1;
       TREE_PUBLIC (decl) = 0;
       DECL_EXTERNAL (decl) = 0;
       DECL_ARTIFICIAL (decl) = 1;
+      DECL_IGNORED_P (decl) = 1;
       pushdecl_top_level (decl);
     }
   return decl;
@@ -1081,13 +1231,12 @@ build_static_field_ref (tree fdecl)
 {
   tree fclass = DECL_CONTEXT (fdecl);
   int is_compiled = is_compiled_class (fclass);
-  int from_class = ! CLASS_FROM_SOURCE_P (current_class);
 
   /* Allow static final fields to fold to a constant.  When using
      -findirect-dispatch, we simply never do this folding if compiling
      from .class; in the .class file constants will be referred to via
      the constant pool.  */
-  if ((!flag_indirect_dispatch || !from_class)
+  if (!flag_indirect_dispatch
       && (is_compiled
          || (FIELD_FINAL (fdecl) && DECL_INITIAL (fdecl) != NULL_TREE
              && (JSTRING_TYPE_P (TREE_TYPE (fdecl))
@@ -1117,20 +1266,16 @@ build_static_field_ref (tree fdecl)
 
       int cpool_index = alloc_constant_fieldref (output_class, fdecl);
       tree cache_entry = build_fieldref_cache_entry (cpool_index, fdecl);
-      tree test 
-       = build3 (CALL_EXPR, boolean_type_node, 
-                 build_address_of (built_in_decls[BUILT_IN_EXPECT]),
-                 tree_cons (NULL_TREE, build2 (EQ_EXPR, boolean_type_node,
-                                               cache_entry, null_pointer_node),
-                            build_tree_list (NULL_TREE, boolean_false_node)),
-                 NULL_TREE);
+      tree test
+        = build_call_expr (built_in_decls[BUILT_IN_EXPECT], 2,
+                          build2 (EQ_EXPR, boolean_type_node,
+                                  cache_entry, null_pointer_node),
+                          boolean_false_node);
       tree cpool_index_cst = build_int_cst (NULL_TREE, cpool_index);
       tree init
-       = build3 (CALL_EXPR, ptr_type_node,
-                 build_address_of (soft_resolvepoolentry_node),
-                 tree_cons (NULL_TREE, build_class_ref (output_class),
-                            build_tree_list (NULL_TREE, cpool_index_cst)),
-                 NULL_TREE);
+       = build_call_expr (soft_resolvepoolentry_node, 2,
+                          build_class_ref (output_class),
+                          cpool_index_cst);
       init = build2 (MODIFY_EXPR, ptr_type_node, cache_entry, init);
       init = build3 (COND_EXPR, ptr_type_node, test, init, cache_entry);
       init = fold_convert (build_pointer_type (TREE_TYPE (fdecl)), init);
@@ -1159,6 +1304,10 @@ get_access_flags_from_decl (tree decl)
        access_flags |= ACC_VOLATILE;
       if (FIELD_TRANSIENT (decl))
        access_flags |= ACC_TRANSIENT;
+      if (FIELD_ENUM (decl))
+       access_flags |= ACC_ENUM;
+      if (FIELD_SYNTHETIC (decl))
+       access_flags |= ACC_SYNTHETIC;
       return access_flags;
     }
   if (TREE_CODE (decl) == TYPE_DECL)
@@ -1181,6 +1330,12 @@ get_access_flags_from_decl (tree decl)
        access_flags |= ACC_PROTECTED;
       if (CLASS_STRICTFP (decl))
        access_flags |= ACC_STRICT;
+      if (CLASS_ENUM (decl))
+       access_flags |= ACC_ENUM;
+      if (CLASS_SYNTHETIC (decl))
+       access_flags |= ACC_SYNTHETIC;
+      if (CLASS_ANNOTATION (decl))
+       access_flags |= ACC_ANNOTATION;
       return access_flags;
     }
   if (TREE_CODE (decl) == FUNCTION_DECL)
@@ -1205,9 +1360,15 @@ get_access_flags_from_decl (tree decl)
        access_flags |= ACC_STRICT;
       if (METHOD_INVISIBLE (decl))
        access_flags |= ACC_INVISIBLE;
+      if (DECL_ARTIFICIAL (decl))
+       access_flags |= ACC_SYNTHETIC;
+      if (METHOD_BRIDGE (decl))
+       access_flags |= ACC_BRIDGE;
+      if (METHOD_VARARGS (decl))
+       access_flags |= ACC_VARARGS;
       return access_flags;
     }
-  abort ();
+  gcc_unreachable ();
 }
 
 static GTY (()) int alias_labelno = 0;
@@ -1223,8 +1384,8 @@ make_local_function_alias (tree method)
   tree alias;
   
   const char *method_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (method));
-  char *name = alloca (strlen (method_name) + 2);
-  char *buf = alloca (strlen (method_name) + 128);
+  char *name = (char *) alloca (strlen (method_name) + 2);
+  char *buf = (char *) alloca (strlen (method_name) + 128);
 
   /* Only create aliases for local functions.  */
   if (DECL_EXTERNAL (method))
@@ -1235,7 +1396,8 @@ make_local_function_alias (tree method)
   strcpy (name + 1, method_name);
 
   ASM_GENERATE_INTERNAL_LABEL (buf, name, alias_labelno++);  
-  alias = build_decl (FUNCTION_DECL, get_identifier (buf),
+  alias = build_decl (input_location,
+                     FUNCTION_DECL, get_identifier (buf),
                      TREE_TYPE (method));
   DECL_CONTEXT (alias) = NULL;
   TREE_READONLY (alias) = TREE_READONLY (method);
@@ -1243,7 +1405,6 @@ make_local_function_alias (tree method)
   TREE_PUBLIC (alias) = 0;
   DECL_EXTERNAL (alias) = 0;
   DECL_ARTIFICIAL (alias) = 1;
-  DECL_INLINE (alias) = 0;
   DECL_INITIAL (alias) = error_mark_node;
   TREE_ADDRESSABLE (alias) = 1;
   TREE_USED (alias) = 1;
@@ -1265,9 +1426,10 @@ make_field_value (tree fdecl)
   int flags;
   tree type = TREE_TYPE (fdecl);
   int resolved = is_compiled_class (type) && ! flag_indirect_dispatch;
+  VEC(constructor_elt,gc) *v = NULL;
 
-  START_RECORD_CONSTRUCTOR (finit, field_type_node);
-  PUSH_FIELD_VALUE (finit, "name", build_utf8_ref (DECL_NAME (fdecl)));
+  START_RECORD_CONSTRUCTOR (v, field_type_node);
+  PUSH_FIELD_VALUE (v, "name", build_utf8_ref (DECL_NAME (fdecl)));
   if (resolved)
     type = build_class_ref (type);
   else
@@ -1278,27 +1440,34 @@ make_field_value (tree fdecl)
                             (IDENTIFIER_POINTER (signature),
                              IDENTIFIER_LENGTH (signature)));
     }
-  PUSH_FIELD_VALUE (finit, "type", type);
+  PUSH_FIELD_VALUE (v, "type", type);
 
   flags = get_access_flags_from_decl (fdecl);
   if (! resolved)
     flags |= 0x8000 /* FIELD_UNRESOLVED_FLAG */;
 
-  PUSH_FIELD_VALUE (finit, "accflags", build_int_cst (NULL_TREE, flags));
-  PUSH_FIELD_VALUE (finit, "bsize", TYPE_SIZE_UNIT (TREE_TYPE (fdecl)));
-
-  PUSH_FIELD_VALUE
-    (finit, "info",
-     build_constructor_from_list (field_info_union_node,
-           build_tree_list
-           ((FIELD_STATIC (fdecl)
-             ? TREE_CHAIN (TYPE_FIELDS (field_info_union_node))
-             : TYPE_FIELDS (field_info_union_node)),
-            (FIELD_STATIC (fdecl)
-             ? build_address_of (fdecl)
-             : byte_position (fdecl)))));
-
-  FINISH_RECORD_CONSTRUCTOR (finit);
+  PUSH_FIELD_VALUE (v, "accflags", build_int_cst (NULL_TREE, flags));
+  PUSH_FIELD_VALUE (v, "bsize", TYPE_SIZE_UNIT (TREE_TYPE (fdecl)));
+
+  {
+    tree field_address = integer_zero_node;
+    if ((DECL_INITIAL (fdecl) || ! flag_indirect_classes) 
+       && FIELD_STATIC (fdecl))
+      field_address = build_address_of (fdecl);
+
+    PUSH_FIELD_VALUE
+      (v, "info",
+       build_constructor_from_list (field_info_union_node,
+        build_tree_list
+          ((FIELD_STATIC (fdecl)
+            ? TREE_CHAIN (TYPE_FIELDS (field_info_union_node))
+            : TYPE_FIELDS (field_info_union_node)),
+           (FIELD_STATIC (fdecl)
+            ? field_address
+            : byte_position (fdecl)))));
+  }
+
+  FINISH_RECORD_CONSTRUCTOR (finit, v, field_type_node);
   return finit;
 }
 
@@ -1314,6 +1483,7 @@ make_method_value (tree mdecl)
   tree class_decl;
 #define ACC_TRANSLATED          0x4000
   int accflags = get_access_flags_from_decl (mdecl) | ACC_TRANSLATED;
+  VEC(constructor_elt,gc) *v = NULL;
 
   class_decl = DECL_CONTEXT (mdecl);
   /* For interfaces, the index field contains the dispatch index. */
@@ -1332,22 +1502,22 @@ make_method_value (tree mdecl)
   else
     code = build1 (ADDR_EXPR, nativecode_ptr_type_node, 
                   make_local_function_alias (mdecl));
-  START_RECORD_CONSTRUCTOR (minit, method_type_node);
-  PUSH_FIELD_VALUE (minit, "name",
+  START_RECORD_CONSTRUCTOR (v, method_type_node);
+  PUSH_FIELD_VALUE (v, "name",
                    build_utf8_ref (DECL_CONSTRUCTOR_P (mdecl) ?
                                    init_identifier_node
                                    : DECL_NAME (mdecl)));
   {
     tree signature = build_java_signature (TREE_TYPE (mdecl));
-    PUSH_FIELD_VALUE (minit, "signature", 
+    PUSH_FIELD_VALUE (v, "signature", 
                      (build_utf8_ref 
                       (unmangle_classname 
                        (IDENTIFIER_POINTER(signature),
                         IDENTIFIER_LENGTH(signature)))));
   }
-  PUSH_FIELD_VALUE (minit, "accflags", build_int_cst (NULL_TREE, accflags));
-  PUSH_FIELD_VALUE (minit, "index", index);
-  PUSH_FIELD_VALUE (minit, "ncode", code);
+  PUSH_FIELD_VALUE (v, "accflags", build_int_cst (NULL_TREE, accflags));
+  PUSH_FIELD_VALUE (v, "index", index);
+  PUSH_FIELD_VALUE (v, "ncode", code);
 
   {
     /* Compute the `throws' information for the method.  */
@@ -1373,7 +1543,8 @@ make_method_value (tree mdecl)
        table = build_constructor_from_list (type, table);
        /* Compute something unique enough.  */
        sprintf (buf, "_methods%d", method_name_count++);
-       array = build_decl (VAR_DECL, get_identifier (buf), type);
+       array = build_decl (input_location,
+                           VAR_DECL, get_identifier (buf), type);
        DECL_INITIAL (array) = table;
        TREE_STATIC (array) = 1;
        DECL_ARTIFICIAL (array) = 1;
@@ -1383,10 +1554,10 @@ make_method_value (tree mdecl)
        table = build1 (ADDR_EXPR, ptr_type_node, array);
       }
 
-    PUSH_FIELD_VALUE (minit, "throws", table);
+    PUSH_FIELD_VALUE (v, "throws", table);
   }
 
-  FINISH_RECORD_CONSTRUCTOR (minit);
+  FINISH_RECORD_CONSTRUCTOR (minit, v, method_type_node);
   return minit;
 }
 
@@ -1441,7 +1612,8 @@ get_dispatch_table (tree type, tree this_class_addr)
       if (METHOD_ABSTRACT (method))
        {
          if (! abstract_p)
-           warning (0, "%Jabstract method in non-abstract class", method);
+           warning_at (DECL_SOURCE_LOCATION (method), 0,
+                       "abstract method in non-abstract class");
 
          if (TARGET_VTABLE_USES_DESCRIPTORS)
            for (j = 0; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j)
@@ -1457,7 +1629,6 @@ get_dispatch_table (tree type, tree this_class_addr)
                tree fdesc = build2 (FDESC_EXPR, nativecode_ptr_type_node, 
                                     method, build_int_cst (NULL_TREE, j));
                TREE_CONSTANT (fdesc) = 1;
-               TREE_INVARIANT (fdesc) = 1;
                list = tree_cons (NULL_TREE, fdesc, list);
              }
          else
@@ -1549,6 +1720,29 @@ supers_all_compiled (tree type)
   return 1;
 }
 
+static void
+add_table_and_syms (VEC(constructor_elt,gc) **v,
+                    tree method_slot,
+                    const char *table_name, tree table_slot, tree table_type,
+                    const char *syms_name, tree syms_slot)
+{
+  if (method_slot == NULL_TREE)
+    {
+      PUSH_FIELD_VALUE (*v, table_name, null_pointer_node);
+      PUSH_FIELD_VALUE (*v, syms_name, null_pointer_node);
+    }
+  else
+    {
+      pushdecl_top_level (syms_slot);
+      PUSH_FIELD_VALUE (*v, table_name,
+                        build1 (ADDR_EXPR, table_type, table_slot));
+      PUSH_FIELD_VALUE (*v, syms_name,
+                        build1 (ADDR_EXPR, symbols_array_ptr_type,
+                                syms_slot));
+      TREE_CONSTANT (table_slot) = 1;
+    }
+}
+                    
 void
 make_class_data (tree type)
 {
@@ -1571,30 +1765,120 @@ make_class_data (tree type)
   tree constant_pool_constructor;
   tree interfaces = null_pointer_node;
   int interface_len = 0;
+  int uses_jv_markobj = 0;
   tree type_decl = TYPE_NAME (type);
+  tree id_main = get_identifier("main");
+  tree id_class = get_identifier("java.lang.Class");
   /** Offset from start of virtual function table declaration
       to where objects actually point at, following new g++ ABI. */
-  tree dtable_start_offset = build_int_cst (NULL_TREE,
-                                           2 * POINTER_SIZE / BITS_PER_UNIT);
+  tree dtable_start_offset = size_int (2 * POINTER_SIZE / BITS_PER_UNIT);
+  VEC(int, heap) *field_indexes;
+  tree first_real_field;
+  VEC(constructor_elt,gc) *v1 = NULL, *v2 = NULL;
+  tree reflection_data;
 
-  this_class_addr = build_class_ref (type);
+  this_class_addr = build_static_class_ref (type);
   decl = TREE_OPERAND (this_class_addr, 0);
 
+  if (supers_all_compiled (type) && ! CLASS_INTERFACE (type_decl)
+      && !flag_indirect_dispatch)
+    {
+      tree dtable = get_dispatch_table (type, this_class_addr);
+      uses_jv_markobj = uses_jv_markobj_p (dtable);
+      if (type == class_type_node && class_dtable_decl != NULL_TREE)
+       {
+         /* We've already created some other class, and consequently
+            we made class_dtable_decl.  Now we just want to fill it
+            in.  */
+         dtable_decl = class_dtable_decl;
+       }
+      else
+       {
+         dtable_decl = build_dtable_decl (type);
+         TREE_STATIC (dtable_decl) = 1;
+         DECL_ARTIFICIAL (dtable_decl) = 1;
+         DECL_IGNORED_P (dtable_decl) = 1;
+       }
+
+      TREE_PUBLIC (dtable_decl) = 1;
+      DECL_INITIAL (dtable_decl) = dtable;
+      /* The only dispatch table exported from a DSO is the dispatch
+        table for java.lang.Class.  */
+      if (DECL_NAME (type_decl) != id_class)
+       java_hide_decl (dtable_decl);
+      if (! flag_indirect_classes)
+       rest_of_decl_compilation (dtable_decl, 1, 0);
+      /* Maybe we're compiling Class as the first class.  If so, set
+        class_dtable_decl to the decl we just made.  */
+      if (type == class_type_node && class_dtable_decl == NULL_TREE)
+       class_dtable_decl = dtable_decl;
+    }
+
   /* Build Field array. */
   field = TYPE_FIELDS (type);
   while (field && DECL_ARTIFICIAL (field))
     field = TREE_CHAIN (field);  /* Skip dummy fields.  */
   if (field && DECL_NAME (field) == NULL_TREE)
     field = TREE_CHAIN (field);  /* Skip dummy field for inherited data. */
-  for ( ;  field != NULL_TREE;  field = TREE_CHAIN (field))
+  first_real_field = field;
+
+  /* First count static and instance fields.  */
+  for ( ; field != NULL_TREE; field = TREE_CHAIN (field))
+    {
+      if (! DECL_ARTIFICIAL (field))
+       {
+         if (FIELD_STATIC (field))
+           static_field_count++;
+         else if (uses_jv_markobj || !flag_reduced_reflection)
+           instance_field_count++;
+       }
+    }
+  field_count = static_field_count + instance_field_count;
+  field_indexes = VEC_alloc (int, heap, field_count);
+  
+  /* gcj sorts fields so that static fields come first, followed by
+     instance fields.  Unfortunately, by the time this takes place we
+     have already generated the reflection_data for this class, and
+     that data contains indexes into the fields.  So, we generate a
+     permutation that maps each original field index to its final
+     position.  Then we pass this permutation to
+     rewrite_reflection_indexes(), which fixes up the reflection
+     data.  */
+  {
+    int i;
+    int static_count = 0;
+    int instance_count = static_field_count;
+    int field_index;
+
+    for (i = 0, field = first_real_field; 
+        field != NULL_TREE; 
+        field = TREE_CHAIN (field), i++)
+    {
+      if (! DECL_ARTIFICIAL (field))
+       {
+         field_index = 0;
+         if (FIELD_STATIC (field))
+           field_index = static_count++;
+         else if (uses_jv_markobj || !flag_reduced_reflection)
+           field_index = instance_count++;
+         else
+           continue;
+         VEC_quick_push (int, field_indexes, field_index);
+       }
+    }
+  }
+
+  for (field = first_real_field; field != NULL_TREE; 
+       field = TREE_CHAIN (field))
     {
       if (! DECL_ARTIFICIAL (field))
        {
-         tree init = make_field_value (field);
          if (FIELD_STATIC (field))
            {
+              /* We must always create reflection data for static fields
+                 as it is used in the creation of the field itself. */
+              tree init = make_field_value (field);
              tree initial = DECL_INITIAL (field);
-             static_field_count++;
              static_fields = tree_cons (NULL_TREE, init, static_fields);
              /* If the initial value is a string constant,
                 prevent output_constant from trying to assemble the value. */
@@ -1604,21 +1888,22 @@ make_class_data (tree type)
              rest_of_decl_compilation (field, 1, 1);
              DECL_INITIAL (field) = initial;
            }
-         else
+         else if (uses_jv_markobj || !flag_reduced_reflection)
            {
-             instance_field_count++;
+              tree init = make_field_value (field);
              instance_fields = tree_cons (NULL_TREE, init, instance_fields);
            }
        }
     }
-  field_count = static_field_count + instance_field_count;
+
   if (field_count > 0)
     {
       static_fields = nreverse (static_fields);
       instance_fields = nreverse (instance_fields);
       static_fields = chainon (static_fields, instance_fields);
       field_array_type = build_prim_array_type (field_type_node, field_count);
-      fields_decl = build_decl (VAR_DECL, mangled_classname ("_FL_", type),
+      fields_decl = build_decl (input_location,
+                               VAR_DECL, mangled_classname ("_FL_", type),
                                field_array_type);
       DECL_INITIAL (fields_decl) = build_constructor_from_list
                                    (field_array_type, static_fields);
@@ -1644,12 +1929,38 @@ make_class_data (tree type)
         which we don't have a .class file.  */
       if (METHOD_DUMMY (method))
        continue;
-      init = make_method_value (method);
-      method_count++;
-      methods = tree_cons (NULL_TREE, init, methods);
+
+      /* Generate method reflection data if:
+
+          - !flag_reduced_reflection.
+
+          - <clinit> -- The runtime uses reflection to initialize the
+            class.
+
+          - Any method in class java.lang.Class -- Class.forName() and
+            perhaps other things require it.
+
+          - class$ -- It does not work if reflection data missing.
+
+          - main -- Reflection is used to find main(String[]) methods.
+
+          - public not static -- It is potentially part of an
+            interface.  The runtime uses reflection data to build
+            interface dispatch tables.  */
+      if (!flag_reduced_reflection
+          || DECL_CLINIT_P (method)
+          || DECL_NAME (type_decl) == id_class
+          || DECL_NAME (method) == id_main
+          || (METHOD_PUBLIC (method) && !METHOD_STATIC (method)))
+        {
+          init = make_method_value (method);
+          method_count++;
+          methods = tree_cons (NULL_TREE, init, methods);
+        }
     }
   method_array_type = build_prim_array_type (method_type_node, method_count);
-  methods_decl = build_decl (VAR_DECL, mangled_classname ("_MT_", type),
+  methods_decl = build_decl (input_location,
+                            VAR_DECL, mangled_classname ("_MT_", type),
                             method_array_type);
   DECL_INITIAL (methods_decl) = build_constructor_from_list
                                 (method_array_type, nreverse (methods));
@@ -1658,21 +1969,6 @@ make_class_data (tree type)
   DECL_IGNORED_P (methods_decl) = 1;
   rest_of_decl_compilation (methods_decl, 1, 0);
 
-  if (supers_all_compiled (type) && ! CLASS_INTERFACE (type_decl)
-      && !flag_indirect_dispatch)
-    {
-      tree dtable = get_dispatch_table (type, this_class_addr);
-      dtable_decl = build_dtable_decl (type);
-      DECL_INITIAL (dtable_decl) = dtable;
-      TREE_STATIC (dtable_decl) = 1;
-      DECL_ARTIFICIAL (dtable_decl) = 1;
-      DECL_IGNORED_P (dtable_decl) = 1;
-      TREE_PUBLIC (dtable_decl) = 1;
-      rest_of_decl_compilation (dtable_decl, 1, 0);
-      if (type == class_type_node)
-       class_dtable_decl = dtable_decl;
-    }
-
   if (class_dtable_decl == NULL_TREE)
     {
       class_dtable_decl = build_dtable_decl (class_type_node);
@@ -1680,8 +1976,10 @@ make_class_data (tree type)
       DECL_ARTIFICIAL (class_dtable_decl) = 1;
       DECL_IGNORED_P (class_dtable_decl) = 1;
       if (is_compiled_class (class_type_node) != 2)
-       DECL_EXTERNAL (class_dtable_decl) = 1;
-      rest_of_decl_compilation (class_dtable_decl, 1, 0);
+       {
+         DECL_EXTERNAL (class_dtable_decl) = 1;
+         rest_of_decl_compilation (class_dtable_decl, 1, 0);
+       }
     }
 
   super = CLASSTYPE_SUPER (type);
@@ -1708,7 +2006,8 @@ make_class_data (tree type)
       tree interface_array_type, idecl;
       interface_array_type
        = build_prim_array_type (class_ptr_type, interface_len);
-      idecl = build_decl (VAR_DECL, mangled_classname ("_IF_", type),
+      idecl = build_decl (input_location,
+                         VAR_DECL, mangled_classname ("_IF_", type),
                          interface_array_type);
       
       for (i = interface_len;  i > 0; i--)
@@ -1761,121 +2060,86 @@ make_class_data (tree type)
   
   TYPE_CTABLE_DECL (type) = emit_catch_table (type);
 
-  START_RECORD_CONSTRUCTOR (temp, object_type_node);
-  PUSH_FIELD_VALUE (temp, "vtable",
-                   build2 (PLUS_EXPR, dtable_ptr_type,
-                           build1 (ADDR_EXPR, dtable_ptr_type,
-                                   class_dtable_decl),
-                           dtable_start_offset));
+  START_RECORD_CONSTRUCTOR (v1, object_type_node);
+  PUSH_FIELD_VALUE (v1, "vtable",
+                   (flag_indirect_classes 
+                    ? null_pointer_node
+                    : build2 (POINTER_PLUS_EXPR, dtable_ptr_type,
+                              build1 (ADDR_EXPR, dtable_ptr_type,
+                                      class_dtable_decl),
+                              dtable_start_offset)));
   if (! flag_hash_synchronization)
-    PUSH_FIELD_VALUE (temp, "sync_info", null_pointer_node);
-  FINISH_RECORD_CONSTRUCTOR (temp);
-  START_RECORD_CONSTRUCTOR (cons, class_type_node);
-  PUSH_SUPER_VALUE (cons, temp);
-  PUSH_FIELD_VALUE (cons, "next_or_version", gcj_abi_version);
-  PUSH_FIELD_VALUE (cons, "name", build_utf8_ref (DECL_NAME (type_decl)));
-  PUSH_FIELD_VALUE (cons, "accflags",
+    PUSH_FIELD_VALUE (v1, "sync_info", null_pointer_node);
+  FINISH_RECORD_CONSTRUCTOR (temp, v1, object_type_node);
+  START_RECORD_CONSTRUCTOR (v2, class_type_node);
+  PUSH_SUPER_VALUE (v2, temp);
+  PUSH_FIELD_VALUE (v2, "next_or_version", gcj_abi_version);
+  PUSH_FIELD_VALUE (v2, "name", build_utf8_ref (DECL_NAME (type_decl)));
+  PUSH_FIELD_VALUE (v2, "accflags",
                    build_int_cst (NULL_TREE,
                                   get_access_flags_from_decl (type_decl)));
 
-  PUSH_FIELD_VALUE (cons, "superclass", 
+  PUSH_FIELD_VALUE (v2, "superclass", 
                    CLASS_INTERFACE (type_decl) ? null_pointer_node : super);
-  PUSH_FIELD_VALUE (cons, "constants", constant_pool_constructor);
-  PUSH_FIELD_VALUE (cons, "methods",
-                   build1 (ADDR_EXPR, method_ptr_type_node, methods_decl));
-  PUSH_FIELD_VALUE (cons, "method_count",
+  PUSH_FIELD_VALUE (v2, "constants", constant_pool_constructor);
+  PUSH_FIELD_VALUE (v2, "methods",
+                    methods_decl == NULL_TREE ? null_pointer_node
+                   : build1 (ADDR_EXPR, method_ptr_type_node, methods_decl));
+  PUSH_FIELD_VALUE (v2, "method_count",
                    build_int_cst (NULL_TREE, method_count));
 
-  if (flag_indirect_dispatch)
-    PUSH_FIELD_VALUE (cons, "vtable_method_count", integer_minus_one_node);
-  else
-    PUSH_FIELD_VALUE (cons, "vtable_method_count", TYPE_NVIRTUALS (type));
+  PUSH_FIELD_VALUE (v2, "vtable_method_count",
+                    (flag_indirect_dispatch
+                     ? integer_minus_one_node
+                     : TYPE_NVIRTUALS (type)));
     
-  PUSH_FIELD_VALUE (cons, "fields",
+  PUSH_FIELD_VALUE (v2, "fields",
                    fields_decl == NULL_TREE ? null_pointer_node
                    : build1 (ADDR_EXPR, field_ptr_type_node, fields_decl));
   /* If we're using the binary compatibility ABI we don't know the
      size until load time.  */
-  PUSH_FIELD_VALUE (cons, "size_in_bytes", 
+  PUSH_FIELD_VALUE (v2, "size_in_bytes", 
                    (flag_indirect_dispatch 
                     ? integer_minus_one_node 
                     : size_in_bytes (type)));
-  PUSH_FIELD_VALUE (cons, "field_count", 
+  PUSH_FIELD_VALUE (v2, "field_count", 
                    build_int_cst (NULL_TREE, field_count));
-  PUSH_FIELD_VALUE (cons, "static_field_count",
+  PUSH_FIELD_VALUE (v2, "static_field_count",
                    build_int_cst (NULL_TREE, static_field_count));
 
-  if (flag_indirect_dispatch)
-    PUSH_FIELD_VALUE (cons, "vtable", null_pointer_node);
-  else
-    PUSH_FIELD_VALUE (cons, "vtable",
-                     dtable_decl == NULL_TREE ? null_pointer_node
-                     : build2 (PLUS_EXPR, dtable_ptr_type,
+  PUSH_FIELD_VALUE (v2, "vtable",
+                    (flag_indirect_dispatch || dtable_decl == NULL_TREE
+                     ? null_pointer_node
+                     : build2 (POINTER_PLUS_EXPR, dtable_ptr_type,
                                build1 (ADDR_EXPR, dtable_ptr_type,
                                        dtable_decl),
-                               dtable_start_offset));
-  if (TYPE_OTABLE_METHODS (type) == NULL_TREE)
-    {
-      PUSH_FIELD_VALUE (cons, "otable", null_pointer_node);
-      PUSH_FIELD_VALUE (cons, "otable_syms", null_pointer_node);
-    }
-  else
-    {
-      PUSH_FIELD_VALUE (cons, "otable",
-                       build1 (ADDR_EXPR, otable_ptr_type, TYPE_OTABLE_DECL (type)));
-      PUSH_FIELD_VALUE (cons, "otable_syms",
-                       build1 (ADDR_EXPR, symbols_array_ptr_type,
-                               TYPE_OTABLE_SYMS_DECL (type)));
-      TREE_CONSTANT (TYPE_OTABLE_DECL (type)) = 1;
-      TREE_INVARIANT (TYPE_OTABLE_DECL (type)) = 1;
-    }
-  if (TYPE_ATABLE_METHODS(type) == NULL_TREE)
-    {
-      PUSH_FIELD_VALUE (cons, "atable", null_pointer_node);
-      PUSH_FIELD_VALUE (cons, "atable_syms", null_pointer_node);
-    }
-  else
-    {
-      PUSH_FIELD_VALUE (cons, "atable",
-                       build1 (ADDR_EXPR, atable_ptr_type, TYPE_ATABLE_DECL (type)));
-      PUSH_FIELD_VALUE (cons, "atable_syms",
-                       build1 (ADDR_EXPR, symbols_array_ptr_type,
-                               TYPE_ATABLE_SYMS_DECL (type)));
-      TREE_CONSTANT (TYPE_ATABLE_DECL (type)) = 1;
-      TREE_INVARIANT (TYPE_ATABLE_DECL (type)) = 1;
-    }
-   if (TYPE_ITABLE_METHODS(type) == NULL_TREE)
-    {
-      PUSH_FIELD_VALUE (cons, "itable", null_pointer_node);
-      PUSH_FIELD_VALUE (cons, "itable_syms", null_pointer_node);
-    }
-  else
-    {
-      PUSH_FIELD_VALUE (cons, "itable",
-                       build1 (ADDR_EXPR, itable_ptr_type, TYPE_ITABLE_DECL (type)));
-      PUSH_FIELD_VALUE (cons, "itable_syms",
-                       build1 (ADDR_EXPR, symbols_array_ptr_type,
-                               TYPE_ITABLE_SYMS_DECL (type)));
-      TREE_CONSTANT (TYPE_ITABLE_DECL (type)) = 1;
-      TREE_INVARIANT (TYPE_ITABLE_DECL (type)) = 1;
-    }
+                               dtable_start_offset)));
+  add_table_and_syms (&v2, TYPE_OTABLE_METHODS (type),
+                      "otable", TYPE_OTABLE_DECL (type), otable_ptr_type,
+                      "otable_syms", TYPE_OTABLE_SYMS_DECL (type));
+  add_table_and_syms (&v2, TYPE_ATABLE_METHODS (type),
+                      "atable", TYPE_ATABLE_DECL (type), atable_ptr_type,
+                      "atable_syms", TYPE_ATABLE_SYMS_DECL (type));
+  add_table_and_syms (&v2, TYPE_ITABLE_METHODS (type),
+                      "itable", TYPE_ITABLE_DECL (type), itable_ptr_type,
+                      "itable_syms", TYPE_ITABLE_SYMS_DECL (type));
  
-  PUSH_FIELD_VALUE (cons, "catch_classes",
+  PUSH_FIELD_VALUE (v2, "catch_classes",
                    build1 (ADDR_EXPR, ptr_type_node, TYPE_CTABLE_DECL (type))); 
-  PUSH_FIELD_VALUE (cons, "interfaces", interfaces);
-  PUSH_FIELD_VALUE (cons, "loader", null_pointer_node);
-  PUSH_FIELD_VALUE (cons, "interface_count",
+  PUSH_FIELD_VALUE (v2, "interfaces", interfaces);
+  PUSH_FIELD_VALUE (v2, "loader", null_pointer_node);
+  PUSH_FIELD_VALUE (v2, "interface_count",
                    build_int_cst (NULL_TREE, interface_len));
-  PUSH_FIELD_VALUE (cons, "state",
+  PUSH_FIELD_VALUE (v2, "state",
                    convert (byte_type_node,
                             build_int_cst (NULL_TREE, JV_STATE_PRELOADING)));
 
-  PUSH_FIELD_VALUE (cons, "thread", null_pointer_node);
-  PUSH_FIELD_VALUE (cons, "depth", integer_zero_node);
-  PUSH_FIELD_VALUE (cons, "ancestors", null_pointer_node);
-  PUSH_FIELD_VALUE (cons, "idt", null_pointer_node);
-  PUSH_FIELD_VALUE (cons, "arrayclass", null_pointer_node);
-  PUSH_FIELD_VALUE (cons, "protectionDomain", null_pointer_node);
+  PUSH_FIELD_VALUE (v2, "thread", null_pointer_node);
+  PUSH_FIELD_VALUE (v2, "depth", integer_zero_node);
+  PUSH_FIELD_VALUE (v2, "ancestors", null_pointer_node);
+  PUSH_FIELD_VALUE (v2, "idt", null_pointer_node);
+  PUSH_FIELD_VALUE (v2, "arrayclass", null_pointer_node);
+  PUSH_FIELD_VALUE (v2, "protectionDomain", null_pointer_node);
 
   {
     tree assertion_table_ref;
@@ -1886,15 +2150,59 @@ make_class_data (tree type)
                                    build_pointer_type (assertion_table_type),
                                    emit_assertion_table (type));
     
-    PUSH_FIELD_VALUE (cons, "assertion_table", assertion_table_ref);
+    PUSH_FIELD_VALUE (v2, "assertion_table", assertion_table_ref);
   }
 
-  PUSH_FIELD_VALUE (cons, "hack_signers", null_pointer_node);
-  PUSH_FIELD_VALUE (cons, "chain", null_pointer_node);
-  PUSH_FIELD_VALUE (cons, "aux_info", null_pointer_node);
-  PUSH_FIELD_VALUE (cons, "engine", null_pointer_node);
+  PUSH_FIELD_VALUE (v2, "hack_signers", null_pointer_node);
+  PUSH_FIELD_VALUE (v2, "chain", null_pointer_node);
+  PUSH_FIELD_VALUE (v2, "aux_info", null_pointer_node);
+  PUSH_FIELD_VALUE (v2, "engine", null_pointer_node);
+
+  if (TYPE_REFLECTION_DATA (current_class))
+    {
+      int i;
+      int count = TYPE_REFLECTION_DATASIZE (current_class);
+      VEC (constructor_elt, gc) *v
+       = VEC_alloc (constructor_elt, gc, count);
+      unsigned char *data = TYPE_REFLECTION_DATA (current_class);
+      tree max_index = build_int_cst (sizetype, count);
+      tree index = build_index_type (max_index);
+      tree type = build_array_type (unsigned_byte_type_node, index);
+      char buf[64];
+      tree array;
+      static int reflection_data_count;
+
+      sprintf (buf, "_reflection_data_%d", reflection_data_count++);
+      array = build_decl (input_location,
+                         VAR_DECL, get_identifier (buf), type);
+
+      rewrite_reflection_indexes (field_indexes);
+
+      for (i = 0; i < count; i++)
+       {
+         constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL);
+         elt->index = build_int_cst (sizetype, i);
+         elt->value = build_int_cstu (byte_type_node, data[i]);
+       }
+
+      DECL_INITIAL (array) = build_constructor (type, v);
+      TREE_STATIC (array) = 1;
+      DECL_ARTIFICIAL (array) = 1;
+      DECL_IGNORED_P (array) = 1;
+      TREE_READONLY (array) = 1;
+      TREE_CONSTANT (DECL_INITIAL (array)) = 1;
+      rest_of_decl_compilation (array, 1, 0);
+
+      reflection_data = build_address_of (array);
+
+      free (data);
+      TYPE_REFLECTION_DATA (current_class) = NULL;
+    }
+  else
+    reflection_data = null_pointer_node;
 
-  FINISH_RECORD_CONSTRUCTOR (cons);
+  PUSH_FIELD_VALUE (v2, "reflection_data", reflection_data);
+  FINISH_RECORD_CONSTRUCTOR (cons, v2, class_type_node);
 
   DECL_INITIAL (decl) = cons;
   
@@ -1902,8 +2210,21 @@ make_class_data (tree type)
   if (flag_hash_synchronization && POINTER_SIZE < 64)
     DECL_ALIGN (decl) = 64; 
   
+  if (flag_indirect_classes)
+    {
+      TREE_READONLY (decl) = 1;
+      TREE_CONSTANT (DECL_INITIAL (decl)) = 1;
+    }
+
   rest_of_decl_compilation (decl, 1, 0);
   
+  {
+    tree classdollar_field = build_classdollar_field (type);
+    if (!flag_indirect_classes)
+      DECL_INITIAL (classdollar_field) = build_static_class_ref (type);
+    rest_of_decl_compilation (classdollar_field, 1, 0);
+  }
+
   TYPE_OTABLE_DECL (type) = NULL_TREE;
   TYPE_ATABLE_DECL (type) = NULL_TREE;
   TYPE_CTABLE_DECL (type) = NULL_TREE;
@@ -1912,17 +2233,6 @@ make_class_data (tree type)
 void
 finish_class (void)
 {
-  if (TYPE_VERIFY_METHOD (output_class))
-    {
-      tree verify_method = TYPE_VERIFY_METHOD (output_class);
-      DECL_SAVED_TREE (verify_method) 
-       = add_stmt_to_compound (DECL_SAVED_TREE (verify_method), void_type_node,
-                               build (RETURN_EXPR, void_type_node, NULL));
-      java_genericize (verify_method);
-      cgraph_finalize_function (verify_method, false);
-      TYPE_ASSERTIONS (current_class) = NULL;
-    }
-
   java_expand_catch_classes (current_class);
 
   current_function_decl = NULL_TREE;
@@ -1932,47 +2242,43 @@ finish_class (void)
   rest_of_decl_compilation (TYPE_NAME (current_class), 1, 0);
 }
 
-/* Return 2 if CLASS is compiled by this compilation job;
-   return 1 if CLASS can otherwise be assumed to be compiled;
-   return 0 if we cannot assume that CLASS is compiled.
+/* Return 2 if KLASS is compiled by this compilation job;
+   return 1 if KLASS can otherwise be assumed to be compiled;
+   return 0 if we cannot assume that KLASS is compiled.
    Returns 1 for primitive and 0 for array types.  */
 int
-is_compiled_class (tree class)
+is_compiled_class (tree klass)
 {
   int seen_in_zip;
-  if (TREE_CODE (class) == POINTER_TYPE)
-    class = TREE_TYPE (class);
-  if (TREE_CODE (class) != RECORD_TYPE)  /* Primitive types are static. */
+  if (TREE_CODE (klass) == POINTER_TYPE)
+    klass = TREE_TYPE (klass);
+  if (TREE_CODE (klass) != RECORD_TYPE)  /* Primitive types are static. */
     return 1;
-  if (TYPE_ARRAY_P (class))
+  if (TYPE_ARRAY_P (klass))
     return 0;
-  if (class == current_class)
-    return 2;
 
-  seen_in_zip = (TYPE_JCF (class) && JCF_SEEN_IN_ZIP (TYPE_JCF (class)));
-  if (CLASS_FROM_CURRENTLY_COMPILED_P (class) || seen_in_zip)
+  seen_in_zip = (TYPE_JCF (klass) && JCF_SEEN_IN_ZIP (TYPE_JCF (klass)));
+  if (CLASS_FROM_CURRENTLY_COMPILED_P (klass))
     {
       /* The class was seen in the current ZIP file and will be
         available as a compiled class in the future but may not have
         been loaded already. Load it if necessary. This prevent
         build_class_ref () from crashing. */
 
-      if (seen_in_zip && !CLASS_LOADED_P (class))
-        load_class (class, 1);
+      if (seen_in_zip && !CLASS_LOADED_P (klass) && (klass != current_class))
+        load_class (klass, 1);
 
       /* We return 2 for class seen in ZIP and class from files
          belonging to the same compilation unit */
       return 2;
     }
 
-  if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class)))))
+  if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (klass)))))
     {
-      if (!CLASS_LOADED_P (class))
+      if (!CLASS_LOADED_P (klass))
        {
-         if (CLASS_FROM_SOURCE_P (class))
-           safe_layout_class (class);
-         else
-           load_class (class, 1);
+         if (klass != current_class)
+           load_class (klass, 1);
        }
       return 1;
     }
@@ -1999,23 +2305,25 @@ build_dtable_decl (tree type)
 
       dtype = make_node (RECORD_TYPE);
 
-      PUSH_FIELD (dtype, dummy, "top_offset", ptr_type_node);
-      PUSH_FIELD (dtype, dummy, "type_info", ptr_type_node);
+      PUSH_FIELD (input_location, dtype, dummy, "top_offset", ptr_type_node);
+      PUSH_FIELD (input_location, dtype, dummy, "type_info", ptr_type_node);
 
-      PUSH_FIELD (dtype, dummy, "class", class_ptr_type);
+      PUSH_FIELD (input_location, dtype, dummy, "class", class_ptr_type);
       for (n = 1; n < TARGET_VTABLE_USES_DESCRIPTORS; ++n)
        {
-         tree tmp_field = build_decl (FIELD_DECL, NULL_TREE, ptr_type_node);
+         tree tmp_field = build_decl (input_location,
+                                      FIELD_DECL, NULL_TREE, ptr_type_node);
          TREE_CHAIN (dummy) = tmp_field;
          DECL_CONTEXT (tmp_field) = dtype;
          DECL_ARTIFICIAL (tmp_field) = 1;
          dummy = tmp_field;
        }
 
-      PUSH_FIELD (dtype, dummy, "gc_descr", ptr_type_node);
+      PUSH_FIELD (input_location, dtype, dummy, "gc_descr", ptr_type_node);
       for (n = 1; n < TARGET_VTABLE_USES_DESCRIPTORS; ++n)
        {
-         tree tmp_field = build_decl (FIELD_DECL, NULL_TREE, ptr_type_node);
+         tree tmp_field = build_decl (input_location,
+                                      FIELD_DECL, NULL_TREE, ptr_type_node);
          TREE_CHAIN (dummy) = tmp_field;
          DECL_CONTEXT (tmp_field) = dtype;
          DECL_ARTIFICIAL (tmp_field) = 1;
@@ -2026,14 +2334,15 @@ build_dtable_decl (tree type)
       if (TARGET_VTABLE_USES_DESCRIPTORS)
        n *= TARGET_VTABLE_USES_DESCRIPTORS;
 
-      PUSH_FIELD (dtype, dummy, "methods",
+      PUSH_FIELD (input_location, dtype, dummy, "methods",
                  build_prim_array_type (nativecode_ptr_type_node, n));
       layout_type (dtype);
     }
   else
     dtype = dtable_type;
 
-  decl = build_decl (VAR_DECL, get_identifier ("vt$"), dtype);
+  decl = build_decl (input_location,
+                    VAR_DECL, get_identifier ("vt$"), dtype);
   DECL_CONTEXT (decl) = type;
   MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
   DECL_VTABLE_P (decl) = 1;
@@ -2051,7 +2360,8 @@ push_super_field (tree this_class, tree super_class)
   /* Don't insert the field if we're just re-laying the class out. */ 
   if (TYPE_FIELDS (this_class) && !DECL_NAME (TYPE_FIELDS (this_class)))
     return;
-  base_decl = build_decl (FIELD_DECL, NULL_TREE, super_class);
+  base_decl = build_decl (input_location,
+                         FIELD_DECL, NULL_TREE, super_class);
   DECL_IGNORED_P (base_decl) = 1;
   TREE_CHAIN (base_decl) = TYPE_FIELDS (this_class);
   TYPE_FIELDS (this_class) = base_decl;
@@ -2062,14 +2372,12 @@ push_super_field (tree this_class, tree super_class)
 /* Handle the different manners we may have to lay out a super class.  */
 
 static tree
-maybe_layout_super_class (tree super_class, tree this_class)
+maybe_layout_super_class (tree super_class, tree this_class ATTRIBUTE_UNUSED)
 {
   if (!super_class)
     return NULL_TREE;
   else if (TREE_CODE (super_class) == RECORD_TYPE)
     {
-      if (!CLASS_LOADED_P (super_class) && CLASS_FROM_SOURCE_P (super_class))
-       safe_layout_class (super_class);
       if (!CLASS_LOADED_P (super_class))
        load_class (super_class, 1);
     }
@@ -2080,30 +2388,7 @@ maybe_layout_super_class (tree super_class, tree this_class)
       if (TREE_TYPE (super_class) != NULL_TREE)
        super_class = TREE_TYPE (super_class);
       else
-       {
-         /* do_resolve_class expects an EXPR_WITH_FILE_LOCATION, so
-            we give it one.  */
-         tree this_wrap = NULL_TREE;
-
-         if (this_class)
-           {
-             tree this_decl = TYPE_NAME (this_class);
-#ifdef USE_MAPPED_LOCATION
-             this_wrap = build_expr_wfl (this_class,
-                                         DECL_SOURCE_LOCATION (this_decl));
-#else
-             this_wrap = build_expr_wfl (this_class,
-                                         DECL_SOURCE_FILE (this_decl),
-                                         DECL_SOURCE_LINE (this_decl), 0);
-#endif
-           }
-         super_class
-           = do_resolve_class (DECL_CONTEXT (TYPE_NAME (this_class)),
-                               this_class, super_class, NULL_TREE, this_wrap);
-         if (!super_class)
-           return NULL_TREE;   /* FIXME, NULL_TREE not checked by caller. */
-         super_class = TREE_TYPE (super_class);
-       }
+       gcc_unreachable ();
     }
   if (!TYPE_SIZE (super_class))
     safe_layout_class (super_class);
@@ -2111,9 +2396,26 @@ maybe_layout_super_class (tree super_class, tree this_class)
   return super_class;
 }
 
+/* safe_layout_class just makes sure that we can load a class without
+   disrupting the current_class, input_file, input_line, etc, information
+   about the class processed currently.  */
+
+void
+safe_layout_class (tree klass)
+{
+  tree save_current_class = current_class;
+  location_t save_location = input_location;
+
+  layout_class (klass);
+
+  current_class = save_current_class;
+  input_location = save_location;
+}
+
 void
 layout_class (tree this_class)
 {
+  int i;
   tree super_class = CLASSTYPE_SUPER (this_class);
 
   class_list = tree_cons (this_class, NULL_TREE, class_list);
@@ -2138,7 +2440,7 @@ layout_class (tree this_class)
          obstack_grow (&temporary_obstack, buffer, strlen (buffer));
        }
       obstack_1grow (&temporary_obstack, '\0');
-      report = obstack_finish (&temporary_obstack);
+      report = XOBFINISH (&temporary_obstack, char *);
       cyclic_inheritance_report = ggc_strdup (report);
       obstack_free (&temporary_obstack, report);
       TYPE_SIZE (this_class) = error_mark_node;
@@ -2164,28 +2466,22 @@ layout_class (tree this_class)
 
   layout_type (this_class);
 
-  /* Also recursively load/layout any superinterfaces, but only if
-     class was loaded from bytecode.  The source parser will take care
-     of this itself.  */
-  if (!CLASS_FROM_SOURCE_P (this_class))
+  /* Also recursively load/layout any superinterfaces.  */
+  if (TYPE_BINFO (this_class))
     {
-      int i;
-            if (TYPE_BINFO (this_class))
+      for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (this_class)) - 1; i > 0; i--)
        {
-         for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (this_class)) - 1; i > 0; i--)
+         tree binfo = BINFO_BASE_BINFO (TYPE_BINFO (this_class), i);
+         tree super_interface = BINFO_TYPE (binfo);
+         tree maybe_super_interface 
+           = maybe_layout_super_class (super_interface, NULL_TREE);
+         if (maybe_super_interface == NULL
+             || TREE_CODE (TYPE_SIZE (maybe_super_interface)) == ERROR_MARK)
            {
-             tree binfo = BINFO_BASE_BINFO (TYPE_BINFO (this_class), i);
-             tree super_interface = BINFO_TYPE (binfo);
-             tree maybe_super_interface 
-               = maybe_layout_super_class (super_interface, NULL_TREE);
-             if (maybe_super_interface == NULL
-                 || TREE_CODE (TYPE_SIZE (maybe_super_interface)) == ERROR_MARK)
-               {
-                 TYPE_SIZE (this_class) = error_mark_node;
-                 CLASS_BEING_LAIDOUT (this_class) = 0;
-                 class_list = TREE_CHAIN (class_list);
-                 return;
-               }
+             TYPE_SIZE (this_class) = error_mark_node;
+             CLASS_BEING_LAIDOUT (this_class) = 0;
+             class_list = TREE_CHAIN (class_list);
+             return;
            }
        }
     }
@@ -2264,7 +2560,7 @@ layout_class_methods (tree this_class)
 
   if (TYPE_NVIRTUALS (this_class))
     return;
-
+  
   super_class = CLASSTYPE_SUPER (this_class);
 
   if (super_class)
@@ -2298,20 +2594,22 @@ layout_class_methods (tree this_class)
   TYPE_NVIRTUALS (this_class) = dtable_count;
 }
 
-/* Return the index of METHOD in INTERFACE.  This index begins at 1 and is used as an
-   argument for _Jv_LookupInterfaceMethodIdx(). */
+/* Return the index of METHOD in INTERFACE.  This index begins at 1
+   and is used as an argument for _Jv_LookupInterfaceMethodIdx(). */
 int
 get_interface_method_index (tree method, tree interface)
 {
   tree meth;
   int i = 1;
 
-  for (meth = TYPE_METHODS (interface); ; meth = TREE_CHAIN (meth), i++)
+  for (meth = TYPE_METHODS (interface); ; meth = TREE_CHAIN (meth))
     {
       if (meth == method)
        return i;
-      if (meth == NULL_TREE)
-       abort ();
+      /* We don't want to put <clinit> into the interface table.  */
+      if (! ID_CLINIT_P (DECL_NAME (meth)))
+       ++i;
+      gcc_assert (meth != NULL_TREE);
     }
 }
 
@@ -2325,9 +2623,18 @@ layout_class_method (tree this_class, tree super_class,
   tree method_name = DECL_NAME (method_decl);
 
   TREE_PUBLIC (method_decl) = 1;
-  /* Considered external until we know what classes are being
-     compiled into this object file.  */
-  DECL_EXTERNAL (method_decl) = 1;
+
+  if (flag_indirect_classes
+      || (METHOD_PRIVATE (method_decl) && METHOD_STATIC (method_decl)
+         && ! METHOD_NATIVE (method_decl)
+         && ! special_method_p (method_decl)))
+    java_hide_decl (method_decl);
+
+  /* Considered external unless it is being compiled into this object
+     file, or it was already flagged as external.  */
+  if (!DECL_EXTERNAL (method_decl))
+    DECL_EXTERNAL (method_decl) = ((is_compiled_class (this_class) != 2)
+                                   || METHOD_NATIVE (method_decl));
 
   if (ID_INIT_P (method_name))
     {
@@ -2339,14 +2646,14 @@ layout_class_method (tree this_class, tree super_class,
            p = ptr;
        }
       DECL_CONSTRUCTOR_P (method_decl) = 1;
-      build_java_argument_signature (TREE_TYPE (method_decl));
+      build_java_signature (TREE_TYPE (method_decl));
     }
   else if (! METHOD_STATIC (method_decl))
     {
       tree method_sig =
-       build_java_argument_signature (TREE_TYPE (method_decl));
+       build_java_signature (TREE_TYPE (method_decl));
       bool method_override = false;
-      tree super_method = lookup_argument_method (super_class, method_name,
+      tree super_method = lookup_java_method (super_class, method_name,
                                                  method_sig);
       if (super_method != NULL_TREE
          && ! METHOD_DUMMY (super_method))
@@ -2369,7 +2676,6 @@ layout_class_method (tree this_class, tree super_class,
          set_method_index (method_decl, method_index);
          if (method_index == NULL_TREE 
              && ! flag_indirect_dispatch
-             && !CLASS_FROM_SOURCE_P (this_class)
              && ! DECL_ARTIFICIAL (super_method))
            error ("non-static method %q+D overrides static method",
                    method_decl);
@@ -2404,10 +2710,66 @@ register_class (void)
   if (!registered_class)
     registered_class = VEC_alloc (tree, gc, 8);
 
-  node = TREE_OPERAND (build_class_ref (current_class), 0);
+  if (flag_indirect_classes)
+    node = current_class;
+  else
+    node = TREE_OPERAND (build_class_ref (current_class), 0);
   VEC_safe_push (tree, gc, registered_class, node);
 }
 
+/* Emit a function that calls _Jv_RegisterNewClasses with a list of
+   all the classes we have emitted.  */
+
+static void
+emit_indirect_register_classes (tree *list_p)
+{
+  tree klass, t, register_class_fn;
+  int i;
+
+  tree init = NULL_TREE;
+  int size = VEC_length (tree, registered_class) * 2 + 1;
+  tree class_array_type
+    = build_prim_array_type (ptr_type_node, size);
+  tree cdecl = build_decl (input_location,
+                          VAR_DECL, get_identifier ("_Jv_CLS"),
+                          class_array_type);
+  tree reg_class_list;
+  for (i = 0; VEC_iterate (tree, registered_class, i, klass); ++i)
+    {
+      init = tree_cons (NULL_TREE, 
+                       fold_convert (ptr_type_node, 
+                                     build_static_class_ref (klass)), init);
+      init = tree_cons 
+       (NULL_TREE, 
+        fold_convert (ptr_type_node, 
+                      build_address_of (build_classdollar_field (klass))),
+        init);
+    }
+  init = tree_cons (NULL_TREE, integer_zero_node, init); 
+  DECL_INITIAL (cdecl) = build_constructor_from_list (class_array_type,
+                                                     nreverse (init));
+  TREE_CONSTANT (DECL_INITIAL (cdecl)) = 1;
+  TREE_STATIC (cdecl) = 1;
+  DECL_ARTIFICIAL (cdecl) = 1;
+  DECL_IGNORED_P (cdecl) = 1;
+  TREE_READONLY (cdecl) = 1;
+  TREE_CONSTANT (cdecl) = 1;
+  rest_of_decl_compilation (cdecl, 1, 0);
+  reg_class_list = fold_convert (ptr_type_node, build_address_of (cdecl));
+
+  t = build_function_type_list (void_type_node, 
+                               build_pointer_type (ptr_type_node), NULL);
+  t = build_decl (input_location,
+                 FUNCTION_DECL, 
+                 get_identifier ("_Jv_RegisterNewClasses"), t);
+  TREE_PUBLIC (t) = 1;
+  DECL_EXTERNAL (t) = 1;
+  register_class_fn = t;
+  t = build_call_expr (register_class_fn, 1, reg_class_list);
+  append_to_statement_list (t, list_p);
+}
+
+
 /* Emit something to register classes at start-up time.
 
    The preferred mechanism is through the .jcr section, which contain
@@ -2424,17 +2786,23 @@ emit_register_classes (tree *list_p)
   if (registered_class == NULL)
     return;
 
+  if (flag_indirect_classes)
+    {
+      emit_indirect_register_classes (list_p);
+      return;
+    }
+
   /* TARGET_USE_JCR_SECTION defaults to 1 if SUPPORTS_WEAK and
      TARGET_ASM_NAMED_SECTION, else 0.  Some targets meet those conditions
      but lack suitable crtbegin/end objects or linker support.  These
-     targets can overide the default in tm.h to use the fallback mechanism.  */
+     targets can override the default in tm.h to use the fallback mechanism.  */
   if (TARGET_USE_JCR_SECTION)
     {
       tree klass, t;
       int i;
 
 #ifdef JCR_SECTION_NAME
-      named_section_flags (JCR_SECTION_NAME, SECTION_WRITE);
+      switch_to_section (get_section (JCR_SECTION_NAME, SECTION_WRITE, NULL));
 #else
       /* A target has defined TARGET_USE_JCR_SECTION,
         but doesn't have a JCR_SECTION_NAME.  */
@@ -2454,7 +2822,8 @@ emit_register_classes (tree *list_p)
       int i;
 
       t = build_function_type_list (void_type_node, class_ptr_type, NULL);
-      t = build_decl (FUNCTION_DECL, get_identifier ("_Jv_RegisterClass"), t);
+      t = build_decl (input_location,
+                     FUNCTION_DECL, get_identifier ("_Jv_RegisterClass"), t);
       TREE_PUBLIC (t) = 1;
       DECL_EXTERNAL (t) = 1;
       register_class_fn = t;
@@ -2462,19 +2831,36 @@ emit_register_classes (tree *list_p)
       for (i = 0; VEC_iterate (tree, registered_class, i, klass); ++i)
        {
          t = build_fold_addr_expr (klass);
-         t = tree_cons (NULL, t, NULL);
-         t = build_function_call_expr (register_class_fn, t);
+         t = build_call_expr (register_class_fn, 1, t);
          append_to_statement_list (t, list_p);
        }
     }
 }
 
+/* Build a constructor for an entry in the symbol table.  */
+
+static tree
+build_symbol_table_entry (tree clname, tree name, tree signature)
+{
+  tree symbol;
+  VEC(constructor_elt,gc) *v = NULL;
+
+  START_RECORD_CONSTRUCTOR (v, symbol_type);
+  PUSH_FIELD_VALUE (v, "clname", clname);
+  PUSH_FIELD_VALUE (v, "name", name);
+  PUSH_FIELD_VALUE (v, "signature", signature);
+  FINISH_RECORD_CONSTRUCTOR (symbol, v, symbol_type);
+  TREE_CONSTANT (symbol) = 1;
+
+  return symbol;
+}
+
 /* Make a symbol_type (_Jv_MethodSymbol) node for DECL. */
 
 static tree
-build_symbol_entry (tree decl)
+build_symbol_entry (tree decl, tree special)
 {
-  tree clname, name, signature, sym;
+  tree clname, name, signature;
   clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
   /* ???  Constructors are given the name foo.foo all the way through
      the compiler, but in the method table they're all renamed
@@ -2488,16 +2874,15 @@ build_symbol_entry (tree decl)
   signature = build_utf8_ref (unmangle_classname 
                              (IDENTIFIER_POINTER (signature),
                               IDENTIFIER_LENGTH (signature)));
-      
-  START_RECORD_CONSTRUCTOR (sym, symbol_type);
-  PUSH_FIELD_VALUE (sym, "clname", clname);
-  PUSH_FIELD_VALUE (sym, "name", name);
-  PUSH_FIELD_VALUE (sym, "signature", signature);
-  FINISH_RECORD_CONSTRUCTOR (sym);
-  TREE_CONSTANT (sym) = 1;
-  TREE_INVARIANT (sym) = 1;
-
-  return sym;
+  /* SPECIAL is either NULL_TREE or integer_one_node.  We emit
+     signature addr+1 if SPECIAL, and this indicates to the runtime
+     system that this is a "special" symbol, i.e. one that should
+     bypass access controls.  */
+  if (special != NULL_TREE)
+    signature = build2 (POINTER_PLUS_EXPR, TREE_TYPE (signature), signature,
+                       fold_convert (sizetype, special));
+
+  return build_symbol_table_entry (clname, name, signature);
 } 
 
 /* Emit a symbol table: used by -findirect-dispatch.  */
@@ -2522,20 +2907,17 @@ emit_symbol_table (tree name, tree the_table, tree decl_list,
   list = NULL_TREE;  
   while (method_list != NULL_TREE)
     {
+      tree special = TREE_PURPOSE (method_list);
       method = TREE_VALUE (method_list);
-      list = tree_cons (NULL_TREE, build_symbol_entry (method), list);
+      list = tree_cons (NULL_TREE, build_symbol_entry (method, special), list);
       method_list = TREE_CHAIN (method_list);
       index++;
     }
 
   /* Terminate the list with a "null" entry. */
-  START_RECORD_CONSTRUCTOR (null_symbol, symbol_type);
-  PUSH_FIELD_VALUE (null_symbol, "clname", null_pointer_node);
-  PUSH_FIELD_VALUE (null_symbol, "name", null_pointer_node);
-  PUSH_FIELD_VALUE (null_symbol, "signature", null_pointer_node);
-  FINISH_RECORD_CONSTRUCTOR (null_symbol);
-  TREE_CONSTANT (null_symbol) = 1;  
-  TREE_INVARIANT (null_symbol) = 1;  
+  null_symbol = build_symbol_table_entry (null_pointer_node,
+                                          null_pointer_node,
+                                          null_pointer_node);
   list = tree_cons (NULL_TREE, null_symbol, list);
 
   /* Put the list in the right order and make it a constructor. */
@@ -2555,7 +2937,8 @@ emit_symbol_table (tree name, tree the_table, tree decl_list,
   table_size 
     = build_index_type (build_int_cst (NULL_TREE, index * element_size + 1));
   the_array_type = build_array_type (the_array_element_type, table_size);
-  the_table = build_decl (VAR_DECL, name, the_array_type);
+  the_table = build_decl (input_location,
+                         VAR_DECL, name, the_array_type);
   TREE_STATIC (the_table) = 1;
   TREE_READONLY (the_table) = 1;  
   rest_of_decl_compilation (the_table, 1, 0);
@@ -2569,10 +2952,11 @@ make_catch_class_record (tree catch_class, tree classname)
 {
   tree entry;
   tree type = TREE_TYPE (TREE_TYPE (TYPE_CTABLE_DECL (output_class)));
-  START_RECORD_CONSTRUCTOR (entry, type);
-  PUSH_FIELD_VALUE (entry, "address", catch_class);
-  PUSH_FIELD_VALUE (entry, "classname", classname);
-  FINISH_RECORD_CONSTRUCTOR (entry);
+  VEC(constructor_elt,gc) *v = NULL;
+  START_RECORD_CONSTRUCTOR (v, type);
+  PUSH_FIELD_VALUE (v, "address", catch_class);
+  PUSH_FIELD_VALUE (v, "classname", classname);
+  FINISH_RECORD_CONSTRUCTOR (entry, v, type);
   return entry;
 }
 
@@ -2599,7 +2983,8 @@ emit_catch_table (tree this_class)
     = build_array_type (TREE_TYPE (TREE_TYPE (TYPE_CTABLE_DECL (this_class))),
                        table_size);
   table = 
-    build_decl (VAR_DECL, DECL_NAME (TYPE_CTABLE_DECL (this_class)), array_type);
+    build_decl (input_location,
+               VAR_DECL, DECL_NAME (TYPE_CTABLE_DECL (this_class)), array_type);
   DECL_INITIAL (table) = 
     build_constructor_from_list (array_type, TYPE_CATCH_CLASSES (this_class));
   TREE_STATIC (table) = 1;
@@ -2625,6 +3010,23 @@ build_signature_for_libgcj (tree type)
   return ref;
 }
 
+/* Build an entry in the type assertion table.  */
+
+static tree
+build_assertion_table_entry (tree code, tree op1, tree op2)
+{
+  VEC(constructor_elt,gc) *v = NULL;
+  tree entry;
+
+  START_RECORD_CONSTRUCTOR (v, assertion_entry_type);
+  PUSH_FIELD_VALUE (v, "assertion_code", code);
+  PUSH_FIELD_VALUE (v, "op1", op1);
+  PUSH_FIELD_VALUE (v, "op2", op2);
+  FINISH_RECORD_CONSTRUCTOR (entry, v, assertion_entry_type);
+
+  return entry;
+}
+
 /* Add an entry to the type assertion table. Callback used during hashtable
    traversal.  */
 
@@ -2647,35 +3049,29 @@ add_assertion_table_entry (void **htab_entry, void *ptr)
     op2_utf8 = null_pointer_node;
   else
     op2_utf8 = build_signature_for_libgcj (as->op2);
-  
-  START_RECORD_CONSTRUCTOR (entry, assertion_entry_type);
-  PUSH_FIELD_VALUE (entry, "assertion_code", code_val);
-  PUSH_FIELD_VALUE (entry, "op1", op1_utf8);
-  PUSH_FIELD_VALUE (entry, "op2", op2_utf8);
-  FINISH_RECORD_CONSTRUCTOR (entry);
+
+  entry = build_assertion_table_entry (code_val, op1_utf8, op2_utf8);
   
   *list = tree_cons (NULL_TREE, entry, *list);
   return true;
 }
 
-/* Generate the type assertion table for CLASS, and return its DECL.  */
+/* Generate the type assertion table for KLASS, and return its DECL.  */
 
 static tree
-emit_assertion_table (tree class)
+emit_assertion_table (tree klass)
 {
   tree null_entry, ctor, table_decl;
   tree list = NULL_TREE;
-  htab_t assertions_htab = TYPE_ASSERTIONS (class);
+  htab_t assertions_htab = TYPE_ASSERTIONS (klass);
 
   /* Iterate through the hash table.  */
   htab_traverse (assertions_htab, add_assertion_table_entry, &list);
 
   /* Finish with a null entry.  */
-  START_RECORD_CONSTRUCTOR (null_entry, assertion_entry_type);
-  PUSH_FIELD_VALUE (null_entry, "assertion_code", integer_zero_node);
-  PUSH_FIELD_VALUE (null_entry, "op1", null_pointer_node);
-  PUSH_FIELD_VALUE (null_entry, "op2", null_pointer_node);
-  FINISH_RECORD_CONSTRUCTOR (null_entry);
+  null_entry = build_assertion_table_entry (integer_zero_node,
+                                            null_pointer_node,
+                                            null_pointer_node);
   
   list = tree_cons (NULL_TREE, null_entry, list);
   
@@ -2683,7 +3079,8 @@ emit_assertion_table (tree class)
   list = nreverse (list);
   ctor = build_constructor_from_list (assertion_table_type, list);
 
-  table_decl = build_decl (VAR_DECL, mangled_classname ("_type_assert_", class),
+  table_decl = build_decl (input_location,
+                          VAR_DECL, mangled_classname ("_type_assert_", klass),
                           assertion_table_type);
 
   TREE_STATIC (table_decl) = 1;
@@ -2712,20 +3109,22 @@ static int java_treetreehash_compare (const void *, const void *);
 
 /* A hash table mapping trees to trees.  Used generally.  */
 
-#define JAVA_TREEHASHHASH_H(t) (htab_hash_pointer (t))
+#define JAVA_TREEHASHHASH_H(t) ((hashval_t)TYPE_UID (t))
 
 static hashval_t
 java_treetreehash_hash (const void *k_p)
 {
-  struct treetreehash_entry *k = (struct treetreehash_entry *) k_p;
+  const struct treetreehash_entry *const k
+    = (const struct treetreehash_entry *) k_p;
   return JAVA_TREEHASHHASH_H (k->key);
 }
 
 static int
 java_treetreehash_compare (const void * k1_p, const void * k2_p)
 {
-  struct treetreehash_entry * k1 = (struct treetreehash_entry *) k1_p;
-  tree k2 = (tree) k2_p;
+  const struct treetreehash_entry *const k1
+    = (const struct treetreehash_entry *) k1_p;
+  const_tree const k2 = (const_tree) k2_p;
   return (k1->key == k2);
 }
 
@@ -2734,7 +3133,7 @@ java_treetreehash_find (htab_t ht, tree t)
 {
   struct treetreehash_entry *e;
   hashval_t hv = JAVA_TREEHASHHASH_H (t);
-  e = htab_find_with_hash (ht, t, hv);
+  e = (struct treetreehash_entry *) htab_find_with_hash (ht, t, hv);
   if (e == NULL)
     return NULL;
   else
@@ -2751,7 +3150,7 @@ java_treetreehash_new (htab_t ht, tree t)
   e = htab_find_slot_with_hash (ht, t, hv, INSERT);
   if (*e == NULL)
     {
-      tthe = (*ht->alloc_f) (1, sizeof (*tthe));
+      tthe = (struct treetreehash_entry *) (*ht->alloc_f) (1, sizeof (*tthe));
       tthe->key = t;
       *e = tthe;
     }
@@ -2781,7 +3180,7 @@ split_qualified_name (tree *left, tree *right, tree source)
   char *p, *base;
   int l = IDENTIFIER_LENGTH (source);
 
-  base = alloca (l + 1);
+  base = (char *) alloca (l + 1);
   memcpy (base, IDENTIFIER_POINTER (source), l + 1);
 
   /* Breakdown NAME into REMAINDER . IDENTIFIER.  */