OSDN Git Service

2007-02-07 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / java / class.c
index 3c8a2e4..804c239 100644 (file)
@@ -1,6 +1,6 @@
 /* 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 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -16,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
 
 Java and all Java-based marks are trademarks or registered trademarks
 of Sun Microsystems, Inc. in the United States and other countries.
@@ -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. */
@@ -319,6 +326,9 @@ make_class (void)
 {
   tree type;
   type = make_node (RECORD_TYPE);
+  /* Unfortunately we must create the binfo here, so that class
+     loading works.  */
+  TYPE_BINFO (type) = make_tree_binfo (0);
   MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type);
 
   return type;
@@ -372,7 +382,6 @@ do                                                                  \
   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)
 
@@ -468,7 +477,8 @@ set_super_info (int access_flags, tree this_class,
   if (super_class)
     total_supers++;
 
-  TYPE_BINFO (this_class) = make_tree_binfo (total_supers);
+  if (total_supers)
+    TYPE_BINFO (this_class) = make_tree_binfo (total_supers);
   TYPE_VFIELD (this_class) = TYPE_VFIELD (object_type_node);
   if (super_class)
     {
@@ -494,6 +504,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,
@@ -549,7 +562,11 @@ inherits_from_p (tree type1, tree type2)
     {
       if (type1 == type2)
        return 1;
-      type1 = CLASSTYPE_SUPER (type1);
+
+      if (! CLASS_LOADED_P (type1))
+       load_class (type1, 1);
+
+      type1 = maybe_layout_super_class (CLASSTYPE_SUPER (type1), type1);
     }
   return 0;
 }
@@ -656,25 +673,22 @@ 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;
 }
 
 tree
@@ -702,9 +716,6 @@ 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;
 
@@ -724,6 +735,10 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
       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;
   if (access_flags & ACC_FINAL) 
@@ -731,6 +746,9 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
   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,22 +781,29 @@ add_field (tree class, tree name, tree field_type, int flags)
   TREE_CHAIN (field) = TYPE_FIELDS (class);
   TYPE_FIELDS (class) = field;
   DECL_CONTEXT (field) = class;
+  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;
+      /* Considered external unless we are compiling it into this
+        object file.  */
+      DECL_EXTERNAL (field) = (is_compiled_class (class) != 2);
     }
 
   return field;
@@ -790,9 +815,11 @@ void
 set_constant_value (tree field, tree constant)
 {
   if (field == NULL_TREE)
-    warning (0, "misplaced ConstantValue attribute (not in any field)");
+    warning (OPT_Wattributes,
+            "misplaced ConstantValue attribute (not in any field)");
   else if (DECL_INITIAL (field) != NULL_TREE)
-    warning (0, "duplicate ConstantValue attribute for field '%s'",
+    warning (OPT_Wattributes,
+            "duplicate ConstantValue attribute for field '%s'",
             IDENTIFIER_POINTER (DECL_NAME (field)));
   else
     {
@@ -810,24 +837,6 @@ set_constant_value (tree field, tree constant)
     }
 }
 
-/* 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.
  */
@@ -905,7 +914,7 @@ build_utf8_ref (tree name)
          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);
        }
     }
@@ -914,9 +923,8 @@ build_utf8_ref (tree name)
   layout_decl (decl, 0);
   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;
-  make_decl_rtl (decl);
   ref = build1 (ADDR_EXPR, utf8const_ptr_type, decl);
   IDENTIFIER_UTF8_REF (name) = ref;
   return ref;
@@ -935,6 +943,119 @@ 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 (VAR_DECL, decl_name, class_type_node);
+      TREE_STATIC (decl) = 1;
+      if (! flag_indirect_classes)
+       TREE_PUBLIC (decl) = 1;
+      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 (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_INVARIANT (decl) = 1;
+      TREE_CONSTANT (decl) = 1;
+      TREE_READONLY (decl) = 1;
+      TREE_PUBLIC (decl) = 1;
+      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 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 (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 = build3 (CALL_EXPR, void_type_node,
+                         build_address_of (soft_initclass_node),
+                         build_tree_list (NULL_TREE, this_classdollar),
+                         NULL_TREE);
+      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. */
 
@@ -944,73 +1065,25 @@ 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);
 
-      if  (flag_indirect_dispatch
-          && type != output_class
-          && TREE_CODE (type) == RECORD_TYPE)
+      if (flag_indirect_dispatch
+         && type != output_class
+         && TREE_CODE (type) == RECORD_TYPE)
        return build_indirect_class_ref (type);
 
+      if (type == output_class && flag_indirect_classes)
+       return this_classdollar;
+      
       if (TREE_CODE (type) == RECORD_TYPE)
-       {
-         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);
-             DECL_SIZE (decl) = TYPE_SIZE (class_type_node);
-             DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (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;
-             SET_DECL_ASSEMBLER_NAME (decl, 
-                                      java_mangle_class_field
-                                      (&temporary_obstack, type));
-             make_decl_rtl (decl);
-             pushdecl_top_level (decl);
-           }
-       }
+       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));
-             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);
@@ -1027,7 +1100,6 @@ build_class_ref (tree type)
              TREE_PUBLIC (decl) = 1;
              DECL_EXTERNAL (decl) = 1;
              DECL_ARTIFICIAL (decl) = 1;
-             make_decl_rtl (decl);
              pushdecl_top_level (decl);
            }
        }
@@ -1058,7 +1130,7 @@ build_fieldref_cache_entry (int index, tree fdecl ATTRIBUTE_UNUSED)
       TREE_PUBLIC (decl) = 0;
       DECL_EXTERNAL (decl) = 0;
       DECL_ARTIFICIAL (decl) = 1;
-      make_decl_rtl (decl);
+      DECL_IGNORED_P (decl) = 1;
       pushdecl_top_level (decl);
     }
   return decl;
@@ -1069,26 +1141,21 @@ 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
-     -fno-assume-compiled, gcj will sometimes try to fold a field from
-     an uncompiled class.  This is required when the field in question
-     meets the appropriate criteria for a compile-time constant.
-     However, currently sometimes gcj is too eager and will end up
-     returning the field itself, leading to an incorrect external
-     reference being generated.  */
-  if ((is_compiled && !flag_indirect_dispatch)
-      || (FIELD_FINAL (fdecl) && DECL_INITIAL (fdecl) != NULL_TREE
-         && (JSTRING_TYPE_P (TREE_TYPE (fdecl))
-             || JNUMERIC_TYPE_P (TREE_TYPE (fdecl)))
-         && TREE_CONSTANT (DECL_INITIAL (fdecl))))
-    {
-      if (!DECL_RTL_SET_P (fdecl))
-       {
-         if (is_compiled == 1)
-           DECL_EXTERNAL (fdecl) = 1;
-         make_decl_rtl (fdecl);
-       }
+     -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)
+      && (is_compiled
+         || (FIELD_FINAL (fdecl) && DECL_INITIAL (fdecl) != NULL_TREE
+             && (JSTRING_TYPE_P (TREE_TYPE (fdecl))
+                 || JNUMERIC_TYPE_P (TREE_TYPE (fdecl)))
+             && TREE_CONSTANT (DECL_INITIAL (fdecl)))))
+    {
+      if (is_compiled == 1)
+       DECL_EXTERNAL (fdecl) = 1;
     }
   else
     {
@@ -1152,6 +1219,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)
@@ -1174,6 +1245,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)
@@ -1198,9 +1275,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;
@@ -1240,7 +1323,6 @@ make_local_function_alias (tree method)
   DECL_INITIAL (alias) = error_mark_node;
   TREE_ADDRESSABLE (alias) = 1;
   TREE_USED (alias) = 1;
-  SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
   TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
   if (!flag_syntax_only)
     assemble_alias (alias, DECL_ASSEMBLER_NAME (method));
@@ -1281,16 +1363,23 @@ make_field_value (tree fdecl)
   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 (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)))));
+  {
+    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
+      (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)
+            ? field_address
+            : byte_position (fdecl)))));
+  }
 
   FINISH_RECORD_CONSTRUCTOR (finit);
   return finit;
@@ -1320,7 +1409,10 @@ make_method_value (tree mdecl)
     index = integer_minus_one_node;
 
   code = null_pointer_node;
-  if (DECL_RTL_SET_P (mdecl))
+  if (METHOD_ABSTRACT (mdecl))
+    code = build1 (ADDR_EXPR, nativecode_ptr_type_node,
+                  soft_abstractmethod_node);
+  else
     code = build1 (ADDR_EXPR, nativecode_ptr_type_node, 
                   make_local_function_alias (mdecl));
   START_RECORD_CONSTRUCTOR (minit, method_type_node);
@@ -1361,7 +1453,7 @@ make_method_value (tree mdecl)
            table = tree_cons (NULL_TREE, utf8, table);
          }
        type = build_prim_array_type (ptr_type_node, length);
-       table = build_constructor (type, table);
+       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);
@@ -1442,9 +1534,6 @@ get_dispatch_table (tree type, tree this_class_addr)
        }
       else
        {
-         if (!DECL_RTL_SET_P (method))
-           make_decl_rtl (method);
-
          if (TARGET_VTABLE_USES_DESCRIPTORS)
            for (j = 0; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j)
              {
@@ -1485,8 +1574,9 @@ get_dispatch_table (tree type, tree this_class_addr)
   if (TARGET_VTABLE_USES_DESCRIPTORS)
     arraysize *= TARGET_VTABLE_USES_DESCRIPTORS;
   arraysize += 2;
-  return build_constructor (build_prim_array_type (nativecode_ptr_type_node,
-                                                  arraysize), list);
+  return build_constructor_from_list
+         (build_prim_array_type (nativecode_ptr_type_node,
+                                 arraysize), list);
 }
 
 
@@ -1564,30 +1654,113 @@ 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);
+  VEC(int, heap) *field_indexes;
+  tree first_real_field;
 
-  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;
+      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++;
+         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. */
@@ -1597,14 +1770,14 @@ 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);
@@ -1613,8 +1786,8 @@ make_class_data (tree type)
       field_array_type = build_prim_array_type (field_type_node, field_count);
       fields_decl = build_decl (VAR_DECL, mangled_classname ("_FL_", type),
                                field_array_type);
-      DECL_INITIAL (fields_decl) = build_constructor (field_array_type,
-                                                     static_fields);
+      DECL_INITIAL (fields_decl) = build_constructor_from_list
+                                   (field_array_type, static_fields);
       TREE_STATIC (fields_decl) = 1;
       DECL_ARTIFICIAL (fields_decl) = 1;
       DECL_IGNORED_P (fields_decl) = 1;
@@ -1637,35 +1810,46 @@ 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))
+          || TYPE_DOT_CLASS (type) == 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),
                             method_array_type);
-  DECL_INITIAL (methods_decl) = build_constructor (method_array_type,
-                                                  nreverse (methods));
+  DECL_INITIAL (methods_decl) = build_constructor_from_list
+                                (method_array_type, nreverse (methods));
   TREE_STATIC (methods_decl) = 1;
   DECL_ARTIFICIAL (methods_decl) = 1;
   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);
@@ -1673,8 +1857,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);
@@ -1720,7 +1906,8 @@ make_class_data (tree type)
            }
          init = tree_cons (NULL_TREE, index, init); 
        }
-      DECL_INITIAL (idecl) = build_constructor (interface_array_type, init);
+      DECL_INITIAL (idecl) = build_constructor_from_list (interface_array_type,
+                                                         init);
       TREE_STATIC (idecl) = 1;
       DECL_ARTIFICIAL (idecl) = 1;
       DECL_IGNORED_P (idecl) = 1;
@@ -1755,10 +1942,12 @@ make_class_data (tree 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));
+                   (flag_indirect_classes 
+                    ? null_pointer_node
+                    : build2 (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);
@@ -1774,7 +1963,8 @@ make_class_data (tree type)
                    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));
+                    methods_decl == NULL_TREE ? null_pointer_node
+                   : build1 (ADDR_EXPR, method_ptr_type_node, methods_decl));
   PUSH_FIELD_VALUE (cons, "method_count",
                    build_int_cst (NULL_TREE, method_count));
 
@@ -1813,6 +2003,7 @@ make_class_data (tree type)
     }
   else
     {
+      pushdecl_top_level (TYPE_OTABLE_SYMS_DECL (type));
       PUSH_FIELD_VALUE (cons, "otable",
                        build1 (ADDR_EXPR, otable_ptr_type, TYPE_OTABLE_DECL (type)));
       PUSH_FIELD_VALUE (cons, "otable_syms",
@@ -1828,6 +2019,7 @@ make_class_data (tree type)
     }
   else
     {
+      pushdecl_top_level (TYPE_ATABLE_SYMS_DECL (type));
       PUSH_FIELD_VALUE (cons, "atable",
                        build1 (ADDR_EXPR, atable_ptr_type, TYPE_ATABLE_DECL (type)));
       PUSH_FIELD_VALUE (cons, "atable_syms",
@@ -1843,6 +2035,7 @@ make_class_data (tree type)
     }
   else
     {
+      pushdecl_top_level (TYPE_ITABLE_SYMS_DECL (type));
       PUSH_FIELD_VALUE (cons, "itable",
                        build1 (ADDR_EXPR, itable_ptr_type, TYPE_ITABLE_DECL (type)));
       PUSH_FIELD_VALUE (cons, "itable_syms",
@@ -1858,13 +2051,9 @@ make_class_data (tree type)
   PUSH_FIELD_VALUE (cons, "loader", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "interface_count",
                    build_int_cst (NULL_TREE, interface_len));
-  PUSH_FIELD_VALUE 
-    (cons, "state",
-     convert (byte_type_node,
-             build_int_cst (NULL_TREE,
-                            flag_indirect_dispatch
-                            ? JV_STATE_PRELOADING
-                            : JV_STATE_COMPILED)));
+  PUSH_FIELD_VALUE (cons, "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);
@@ -1890,6 +2079,48 @@ make_class_data (tree type)
   PUSH_FIELD_VALUE (cons, "aux_info", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "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 (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);
+      
+      PUSH_FIELD_VALUE (cons, "reflection_data", build_address_of (array));
+
+      free (data);
+      TYPE_REFLECTION_DATA (current_class) = NULL;
+    }
+  else
+    PUSH_FIELD_VALUE (cons, "reflection_data", null_pointer_node);
+
   FINISH_RECORD_CONSTRUCTOR (cons);
 
   DECL_INITIAL (decl) = cons;
@@ -1898,8 +2129,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;
@@ -1913,7 +2157,7 @@ finish_class (void)
       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));
+                               build1 (RETURN_EXPR, void_type_node, NULL));
       java_genericize (verify_method);
       cgraph_finalize_function (verify_method, false);
       TYPE_ASSERTIONS (current_class) = NULL;
@@ -1942,18 +2186,16 @@ is_compiled_class (tree class)
     return 1;
   if (TYPE_ARRAY_P (class))
     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)
+  if (CLASS_FROM_CURRENTLY_COMPILED_P (class))
     {
       /* 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))
+      if (seen_in_zip && !CLASS_LOADED_P (class) && (class != current_class))
         load_class (class, 1);
 
       /* We return 2 for class seen in ZIP and class from files
@@ -1967,7 +2209,7 @@ is_compiled_class (tree class)
        {
          if (CLASS_FROM_SOURCE_P (class))
            safe_layout_class (class);
-         else
+         else if (class != current_class)
            load_class (class, 1);
        }
       return 1;
@@ -1981,7 +2223,7 @@ is_compiled_class (tree class)
 tree
 build_dtable_decl (tree type)
 {
-  tree dtype;
+  tree dtype, decl;
 
   /* We need to build a new dtable type so that its size is uniquely
      computed when we're dealing with the class for real and not just
@@ -2029,8 +2271,12 @@ build_dtable_decl (tree type)
   else
     dtype = dtable_type;
 
-  return build_decl (VAR_DECL, 
-                    java_mangle_vtable (&temporary_obstack, type), dtype);
+  decl = build_decl (VAR_DECL, get_identifier ("vt$"), dtype);
+  DECL_CONTEXT (decl) = type;
+  MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
+  DECL_VTABLE_P (decl) = 1;
+
+  return decl;
 }
 
 /* Pre-pend the TYPE_FIELDS of THIS_CLASS with a dummy FIELD_DECL for the
@@ -2054,9 +2300,11 @@ 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 (TREE_CODE (super_class) == RECORD_TYPE)
+  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);
@@ -2070,29 +2318,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 (NULL_TREE, 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);
@@ -2100,11 +2326,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 class)
+{
+  tree save_current_class = current_class;
+  location_t save_location = input_location;
+
+  layout_class (class);
+
+  current_class = save_current_class;
+  input_location = save_location;
+}
+
 void
 layout_class (tree this_class)
 {
   tree super_class = CLASSTYPE_SUPER (this_class);
-  tree field;
 
   class_list = tree_cons (this_class, NULL_TREE, class_list);
   if (CLASS_BEING_LAIDOUT (this_class))
@@ -2152,18 +2393,6 @@ layout_class (tree this_class)
        push_super_field (this_class, maybe_super_class);
     }
 
-  for (field = TYPE_FIELDS (this_class);
-       field != NULL_TREE;  field = TREE_CHAIN (field))
-    {
-      if (FIELD_STATIC (field))
-       {
-         /* Set DECL_ASSEMBLER_NAME to something suitably mangled. */
-         SET_DECL_ASSEMBLER_NAME (field,
-                                  java_mangle_decl
-                                  (&temporary_obstack, field));
-       }
-    }
-
   layout_type (this_class);
 
   /* Also recursively load/layout any superinterfaces, but only if
@@ -2266,7 +2495,7 @@ layout_class_methods (tree this_class)
 
   if (TYPE_NVIRTUALS (this_class))
     return;
-
+  
   super_class = CLASSTYPE_SUPER (this_class);
 
   if (super_class)
@@ -2300,20 +2529,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);
     }
 }
 
@@ -2327,20 +2558,12 @@ 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;
-
-  /* This is a good occasion to mangle the method's name */
-  SET_DECL_ASSEMBLER_NAME (method_decl,
-                          java_mangle_decl (&temporary_obstack, 
-                                            method_decl));
-  /* We don't generate a RTL for the method if it's abstract, or if
-     it's an interface method that isn't clinit. */
-  if (! METHOD_ABSTRACT (method_decl) 
-      || (CLASS_INTERFACE (TYPE_NAME (this_class)) 
-         && (DECL_CLINIT_P (method_decl))))
-    make_decl_rtl (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))
     {
@@ -2352,14 +2575,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))
@@ -2384,8 +2607,8 @@ layout_class_method (tree this_class, tree super_class,
              && ! flag_indirect_dispatch
              && !CLASS_FROM_SOURCE_P (this_class)
              && ! DECL_ARTIFICIAL (super_method))
-           error ("%Jnon-static method '%D' overrides static method",
-                   method_decl, method_decl);
+           error ("non-static method %q+D overrides static method",
+                   method_decl);
        }
       else if (this_class == object_type_node
               && (METHOD_FINAL (method_decl)
@@ -2401,8 +2624,8 @@ layout_class_method (tree this_class, tree super_class,
          /* We generate vtable entries for final methods because they
             may one day be changed to non-final.  */
          set_method_index (method_decl, dtable_count);
-         dtable_count = fold (build2 (PLUS_EXPR, integer_type_node,
-                                      dtable_count, integer_one_node));
+         dtable_count = fold_build2 (PLUS_EXPR, integer_type_node,
+                                     dtable_count, integer_one_node);
        }
     }
 
@@ -2417,10 +2640,65 @@ 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 (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 (FUNCTION_DECL, 
+                 get_identifier ("_Jv_RegisterNewClasses"), t);
+  TREE_PUBLIC (t) = 1;
+  DECL_EXTERNAL (t) = 1;
+  register_class_fn = t;
+  t = tree_cons (NULL, reg_class_list, NULL);
+  t = build_function_call_expr (register_class_fn, t);
+  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
@@ -2437,17 +2715,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.  */
@@ -2485,7 +2769,7 @@ emit_register_classes (tree *list_p)
 /* 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;
   clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
@@ -2501,6 +2785,12 @@ build_symbol_entry (tree decl)
   signature = build_utf8_ref (unmangle_classname 
                              (IDENTIFIER_POINTER (signature),
                               IDENTIFIER_LENGTH (signature)));
+  /* 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 (PLUS_EXPR, TREE_TYPE (signature), signature, special);
       
   START_RECORD_CONSTRUCTOR (sym, symbol_type);
   PUSH_FIELD_VALUE (sym, "clname", clname);
@@ -2535,8 +2825,9 @@ 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++;
     }
@@ -2553,7 +2844,7 @@ emit_symbol_table (tree name, tree the_table, tree decl_list,
 
   /* Put the list in the right order and make it a constructor. */
   list = nreverse (list);
-  table = build_constructor (symbols_array_type, list);  
+  table = build_constructor_from_list (symbols_array_type, list);  
 
   /* Make it the initial value for otable_syms and emit the decl. */
   DECL_INITIAL (the_syms_decl) = table;
@@ -2614,7 +2905,7 @@ emit_catch_table (tree this_class)
   table = 
     build_decl (VAR_DECL, DECL_NAME (TYPE_CTABLE_DECL (this_class)), array_type);
   DECL_INITIAL (table) = 
-    build_constructor (array_type, TYPE_CATCH_CLASSES (this_class));
+    build_constructor_from_list (array_type, TYPE_CATCH_CLASSES (this_class));
   TREE_STATIC (table) = 1;
   TREE_READONLY (table) = 1;  
   DECL_IGNORED_P (table) = 1;
@@ -2694,7 +2985,7 @@ emit_assertion_table (tree class)
   
   /* Put the list in the right order and make it a constructor. */
   list = nreverse (list);
-  ctor = build_constructor (assertion_table_type, list);
+  ctor = build_constructor_from_list (assertion_table_type, list);
 
   table_decl = build_decl (VAR_DECL, mangled_classname ("_type_assert_", class),
                           assertion_table_type);