OSDN Git Service

2004-12-03 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / java / class.c
index d24e033..c314950 100644 (file)
@@ -43,6 +43,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "stdio.h"
 #include "target.h"
 #include "except.h"
+#include "cgraph.h"
 #include "tree-iterator.h"
 
 /* DOS brain-damage */
@@ -61,6 +62,7 @@ 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 emit_assertion_table (tree);
 
 struct obstack temporary_obstack;
 
@@ -268,11 +270,8 @@ 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;
-#ifdef __GNUC__
-  char buffer[i];
-#else
   char *buffer = alloca (i);
-#endif
+
   strcpy (buffer, prefix);
   for (i = 0; i < old_length; i++)
     {
@@ -345,6 +344,34 @@ unmangle_classname (const char *name, int name_length)
   return to_return;
 }
 
+#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);        \
+  tree decl;                                                           \
+                                                                       \
+  sprintf (buf, #NAME "_%s", typename);                                        \
+  TYPE_## TABLE ##_DECL (type) = decl =                                        \
+    build_decl (VAR_DECL, get_identifier (buf), TABLE_TYPE);           \
+  DECL_EXTERNAL (decl) = 1;                                            \
+  TREE_STATIC (decl) = 1;                                              \
+  TREE_READONLY (decl) = 1;                                            \
+  TREE_CONSTANT (decl) = 1;                                            \
+  DECL_IGNORED_P (decl) = 1;                                           \
+  /* Mark the table as belonging to this class.  */                    \
+  pushdecl (decl);                                                     \
+  MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);                          \
+  DECL_OWNER (decl) = TYPE;                                            \
+  sprintf (buf, #NAME "_syms_%s", typename);                           \
+  TYPE_## TABLE ##_SYMS_DECL (TYPE) =                                  \
+    build_decl (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)
 
 /* Given a class, create the DECLs for all its associated indirect
    dispatch tables.  */
@@ -375,63 +402,25 @@ gen_indirect_dispatch_tables (tree type)
 
   if (flag_indirect_dispatch)
     {
-      {
-       char *buf = alloca (strlen (typename) + strlen ("_otable_syms_") + 1);
-
-       sprintf (buf, "_otable_%s", typename);
-       TYPE_OTABLE_DECL (type) = 
-         build_decl (VAR_DECL, get_identifier (buf), otable_type);
-       DECL_EXTERNAL (TYPE_OTABLE_DECL (type)) = 1;
-       TREE_STATIC (TYPE_OTABLE_DECL (type)) = 1;
-       TREE_READONLY (TYPE_OTABLE_DECL (type)) = 1;
-       TREE_CONSTANT (TYPE_OTABLE_DECL (type)) = 1;
-       DECL_IGNORED_P (TYPE_OTABLE_DECL (type)) = 1;
-       pushdecl (TYPE_OTABLE_DECL (type));  
-       sprintf (buf, "_otable_syms_%s", typename);
-       TYPE_OTABLE_SYMS_DECL (type) = 
-         build_decl (VAR_DECL, get_identifier (buf), symbols_array_type);
-       TREE_STATIC (TYPE_OTABLE_SYMS_DECL (type)) = 1;
-       TREE_CONSTANT (TYPE_OTABLE_SYMS_DECL (type)) = 1;
-       DECL_IGNORED_P(TYPE_OTABLE_SYMS_DECL (type)) = 1;
-       pushdecl (TYPE_OTABLE_SYMS_DECL (type));
-      }
-
-      {
-       char *buf = alloca (strlen (typename) + strlen ("_atable_syms_") + 1);
-       tree decl;
-
-       sprintf (buf, "_atable_%s", typename);
-       TYPE_ATABLE_DECL (type) = decl =
-         build_decl (VAR_DECL, get_identifier (buf), atable_type);
-       DECL_EXTERNAL (decl) = 1;
-       TREE_STATIC (decl) = 1;
-       TREE_READONLY (decl) = 1;
-       TREE_CONSTANT (decl) = 1;
-       DECL_IGNORED_P (decl) = 1;
-       /* Mark the atable as belonging to this class.  */
-       pushdecl (decl);  
-       MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
-       DECL_OWNER (decl) = type;
-       sprintf (buf, "_atable_syms_%s", typename);
-       TYPE_ATABLE_SYMS_DECL (type) = 
-         build_decl (VAR_DECL, get_identifier (buf), symbols_array_type);
-       TREE_STATIC (TYPE_ATABLE_SYMS_DECL (type)) = 1;
-       TREE_CONSTANT (TYPE_ATABLE_SYMS_DECL (type)) = 1;
-       DECL_IGNORED_P (TYPE_ATABLE_SYMS_DECL (type)) = 1;
-       pushdecl (TYPE_ATABLE_SYMS_DECL (type));
-      }
+      GEN_TABLE (ATABLE, _atable, atable_type, type);
+      GEN_TABLE (OTABLE, _otable, otable_type, type);
+      GEN_TABLE (ITABLE, _itable, itable_type, type);
     }
 }
 
+#undef GEN_TABLE
+
 tree
 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");
-  CLASS_P (class_type) = 1;
   input_filename = IDENTIFIER_POINTER (source_name);
   input_line = 0;
+#endif
+  CLASS_P (class_type) = 1;
   decl = build_decl (TYPE_DECL, class_name, class_type);
 
   /* dbxout needs a DECL_SIZE if in gstabs mode */
@@ -880,8 +869,8 @@ build_utf8_ref (tree name)
   FINISH_RECORD (ctype);
   START_RECORD_CONSTRUCTOR (cinit, ctype);
   name_hash = hashUtf8String (name_ptr, name_len) & 0xFFFF;
-  PUSH_FIELD_VALUE (cinit, "hash", build_int_cst (NULL_TREE, name_hash, 0));
-  PUSH_FIELD_VALUE (cinit, "length", build_int_cst (NULL_TREE, name_len, 0));
+  PUSH_FIELD_VALUE (cinit, "hash", build_int_cst (NULL_TREE, name_hash));
+  PUSH_FIELD_VALUE (cinit, "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);
@@ -954,13 +943,8 @@ build_class_ref (tree type)
       if (TREE_CODE (type) == POINTER_TYPE)
        type = TREE_TYPE (type);
 
-      /* FIXME: we really want an indirect reference to our
-        superclass.  However, libgcj assumes that a superclass
-        pointer always points directly to a class.  As a workaround
-        we always emit this hard superclass reference.  */
       if  (flag_indirect_dispatch
           && type != output_class
-          && type != CLASSTYPE_SUPER (output_class)
           && TREE_CODE (type) == RECORD_TYPE)
        return build_indirect_class_ref (type);
 
@@ -1037,6 +1021,7 @@ build_class_ref (tree type)
              TREE_STATIC (decl) = 1;
              TREE_PUBLIC (decl) = 1;
              DECL_EXTERNAL (decl) = 1;
+             DECL_ARTIFICIAL (decl) = 1;
              make_decl_rtl (decl);
              pushdecl_top_level (decl);
            }
@@ -1062,8 +1047,7 @@ build_static_field_ref (tree fdecl)
      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 || current_class == fclass))
+  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)))
@@ -1082,18 +1066,21 @@ build_static_field_ref (tree fdecl)
     {
       tree table_index 
        = build_int_cst (NULL_TREE, get_symbol_table_index 
-                        (fdecl, &TYPE_ATABLE_METHODS (output_class)), 0);
+                        (fdecl, &TYPE_ATABLE_METHODS (output_class)));
       tree field_address
-       = build4 (ARRAY_REF, build_pointer_type (TREE_TYPE (fdecl)), 
+       = build4 (ARRAY_REF, 
+                 TREE_TYPE (TREE_TYPE (TYPE_ATABLE_DECL (output_class))), 
                  TYPE_ATABLE_DECL (output_class), table_index,
                  NULL_TREE, NULL_TREE);
+      field_address = convert (build_pointer_type (TREE_TYPE (fdecl)),
+                              field_address);
       return fold (build1 (INDIRECT_REF, TREE_TYPE (fdecl), 
                           field_address));
     }
   else  
     {
       /* Compile as:
-       * *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr */
+       *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr */
       tree ref = build_class_ref (fclass);
       tree fld;
       int field_index = 0;
@@ -1114,10 +1101,10 @@ build_static_field_ref (tree fdecl)
        }
       field_index *= int_size_in_bytes (field_type_node);
       ref = fold (build2 (PLUS_EXPR, field_ptr_type_node,
-                         ref, build_int_cst (NULL_TREE, field_index, 0)));
+                         ref, build_int_cst (NULL_TREE, field_index)));
       ref = build1 (INDIRECT_REF, field_type_node, ref);
       ref = build3 (COMPONENT_REF, field_info_union_node,
-                   ref, lookup_field (&field_type_node, info_ident),
+                   ref, lookup_field (&field_type_node, info_ident), 
                    NULL_TREE);
       ref = build3 (COMPONENT_REF, ptr_type_node,
                    ref, TREE_CHAIN (TYPE_FIELDS (field_info_union_node)),
@@ -1209,10 +1196,15 @@ make_local_function_alias (tree method)
 {
 #ifdef ASM_OUTPUT_DEF
   tree alias;
+  
   const char *method_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (method));
-  char *name = alloca (strlen (method_name) + 1);
+  char *name = alloca (strlen (method_name) + 2);
   char *buf = alloca (strlen (method_name) + 128);
-  
+
+  /* Only create aliases for local functions.  */
+  if (DECL_EXTERNAL (method))
+    return method;
+    
   /* Prefix method_name with 'L' for the alias label.  */
   *name = 'L';
   strcpy (name + 1, method_name);
@@ -1268,7 +1260,7 @@ make_field_value (tree fdecl)
   if (! resolved)
     flags |= 0x8000 /* FIELD_UNRESOLVED_FLAG */;
 
-  PUSH_FIELD_VALUE (finit, "accflags", build_int_cst (NULL_TREE, flags, 0));
+  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
@@ -1279,7 +1271,7 @@ make_field_value (tree fdecl)
              ? TREE_CHAIN (TYPE_FIELDS (field_info_union_node))
              : TYPE_FIELDS (field_info_union_node)),
             (FIELD_STATIC (fdecl)
-             ? build_address_of (build_static_field_ref (fdecl))
+             ? build_address_of (fdecl)
              : byte_position (fdecl)))));
 
   FINISH_RECORD_CONSTRUCTOR (finit);
@@ -1303,7 +1295,7 @@ make_method_value (tree mdecl)
   /* For interfaces, the index field contains the dispatch index. */
   if (CLASS_INTERFACE (TYPE_NAME (class_decl)))
     index = build_int_cst (NULL_TREE,
-                          get_interface_method_index (mdecl, class_decl), 0);
+                          get_interface_method_index (mdecl, class_decl));
   else if (!flag_indirect_dispatch && get_method_index (mdecl) != NULL_TREE)
     index = get_method_index (mdecl);
   else
@@ -1326,7 +1318,7 @@ make_method_value (tree mdecl)
                        (IDENTIFIER_POINTER(signature),
                         IDENTIFIER_LENGTH(signature)))));
   }
-  PUSH_FIELD_VALUE (minit, "accflags", build_int_cst (NULL_TREE, accflags, 0));
+  PUSH_FIELD_VALUE (minit, "accflags", build_int_cst (NULL_TREE, accflags));
   PUSH_FIELD_VALUE (minit, "index", index);
   PUSH_FIELD_VALUE (minit, "ncode", code);
 
@@ -1439,7 +1431,7 @@ get_dispatch_table (tree type, tree this_class_addr)
            for (j = 0; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j)
              {
                tree fdesc = build2 (FDESC_EXPR, nativecode_ptr_type_node, 
-                                    method, build_int_cst (NULL_TREE, j, 0));
+                                    method, build_int_cst (NULL_TREE, j));
                TREE_CONSTANT (fdesc) = 1;
                TREE_INVARIANT (fdesc) = 1;
                list = tree_cons (NULL_TREE, fdesc, list);
@@ -1553,15 +1545,16 @@ make_class_data (tree type)
   /** 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,
-                                           0);
+                                           2 * POINTER_SIZE / BITS_PER_UNIT);
 
   this_class_addr = build_class_ref (type);
   decl = TREE_OPERAND (this_class_addr, 0);
 
   /* Build Field array. */
   field = TYPE_FIELDS (type);
-  if (DECL_NAME (field) == NULL_TREE)
+  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))
     {
@@ -1614,7 +1607,12 @@ make_class_data (tree type)
       tree init;
       if (METHOD_PRIVATE (method)
          && ! flag_keep_inline_functions
-         && (flag_inline_functions || optimize))
+         && optimize)
+       continue;
+      /* Even if we have a decl, we don't necessarily have the code.
+        This can happen if we inherit a method from a superclass for
+        which we don't have a .class file.  */
+      if (METHOD_DUMMY (method))
        continue;
       init = make_method_value (method);
       method_count++;
@@ -1659,16 +1657,14 @@ make_class_data (tree type)
   super = CLASSTYPE_SUPER (type);
   if (super == NULL_TREE)
     super = null_pointer_node;
-  else if (/* FIXME: we should also test for (!
-             flag_indirect_dispatch) here, but libgcj can't cope with
-             a symbolic reference a superclass in the class data.  */
-          assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl)))
+  else if (! flag_indirect_dispatch
+          && assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl)))
           && assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (super)))))
     super = build_class_ref (super);
   else
     {
       int super_index = alloc_class_constant (super);
-      super = build_int_cst (ptr_type_node, super_index, 0);
+      super = build_int_cst (ptr_type_node, super_index);
     }
 
   /* Build and emit the array of implemented interfaces. */
@@ -1697,7 +1693,7 @@ make_class_data (tree type)
          else
            {
              int int_index = alloc_class_constant (iclass);
-             index = build_int_cst (ptr_type_node, int_index, 0);
+             index = build_int_cst (ptr_type_node, int_index);
            }
          init = tree_cons (NULL_TREE, index, init); 
        }
@@ -1717,13 +1713,19 @@ make_class_data (tree type)
        = emit_symbol_table 
        (DECL_NAME (TYPE_OTABLE_DECL (type)), 
         TYPE_OTABLE_DECL (type), TYPE_OTABLE_METHODS (type), 
-        TYPE_OTABLE_SYMS_DECL (type), integer_type_node);
+        TYPE_OTABLE_SYMS_DECL (type), integer_type_node, 1);
        
       TYPE_ATABLE_DECL (type) 
        = emit_symbol_table 
        (DECL_NAME (TYPE_ATABLE_DECL (type)), 
         TYPE_ATABLE_DECL (type), TYPE_ATABLE_METHODS (type), 
-        TYPE_ATABLE_SYMS_DECL (type), ptr_type_node);
+        TYPE_ATABLE_SYMS_DECL (type), ptr_type_node, 1);
+       
+      TYPE_ITABLE_DECL (type) 
+       = emit_symbol_table 
+       (DECL_NAME (TYPE_ITABLE_DECL (type)), 
+        TYPE_ITABLE_DECL (type), TYPE_ITABLE_METHODS (type), 
+        TYPE_ITABLE_SYMS_DECL (type), ptr_type_node, 2);
     }
   
   TYPE_CTABLE_DECL (type) = emit_catch_table (type);
@@ -1743,7 +1745,7 @@ make_class_data (tree type)
   PUSH_FIELD_VALUE (cons, "name", build_utf8_ref (DECL_NAME (type_decl)));
   PUSH_FIELD_VALUE (cons, "accflags",
                    build_int_cst (NULL_TREE,
-                                  get_access_flags_from_decl (type_decl), 0));
+                                  get_access_flags_from_decl (type_decl)));
 
   PUSH_FIELD_VALUE (cons, "superclass", 
                    CLASS_INTERFACE (type_decl) ? null_pointer_node : super);
@@ -1751,7 +1753,7 @@ make_class_data (tree type)
   PUSH_FIELD_VALUE (cons, "methods",
                    build1 (ADDR_EXPR, method_ptr_type_node, methods_decl));
   PUSH_FIELD_VALUE (cons, "method_count",
-                   build_int_cst (NULL_TREE, method_count, 0));
+                   build_int_cst (NULL_TREE, method_count));
 
   if (flag_indirect_dispatch)
     PUSH_FIELD_VALUE (cons, "vtable_method_count", integer_minus_one_node);
@@ -1761,11 +1763,16 @@ make_class_data (tree type)
   PUSH_FIELD_VALUE (cons, "fields",
                    fields_decl == NULL_TREE ? null_pointer_node
                    : build1 (ADDR_EXPR, field_ptr_type_node, fields_decl));
-  PUSH_FIELD_VALUE (cons, "size_in_bytes", size_in_bytes (type));
-  PUSH_FIELD_VALUE (cons, "field_count",
-                   build_int_cst (NULL_TREE, field_count, 0));
+  /* If we're using the binary compatibility ABI we don't know the
+     size until load time.  */
+  PUSH_FIELD_VALUE (cons, "size_in_bytes", 
+                   (flag_indirect_dispatch 
+                    ? integer_minus_one_node 
+                    : size_in_bytes (type)));
+  PUSH_FIELD_VALUE (cons, "field_count", 
+                   build_int_cst (NULL_TREE, field_count));
   PUSH_FIELD_VALUE (cons, "static_field_count",
-                   build_int_cst (NULL_TREE, static_field_count, 0));
+                   build_int_cst (NULL_TREE, static_field_count));
 
   if (flag_indirect_dispatch)
     PUSH_FIELD_VALUE (cons, "vtable", null_pointer_node);
@@ -1806,14 +1813,35 @@ make_class_data (tree 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;
+    }
  
   PUSH_FIELD_VALUE (cons, "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",
-                   build_int_cst (NULL_TREE, interface_len, 0));
-  PUSH_FIELD_VALUE (cons, "state", integer_zero_node);
+                   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, "thread", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "depth", integer_zero_node);
@@ -1821,9 +1849,23 @@ make_class_data (tree type)
   PUSH_FIELD_VALUE (cons, "idt", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "arrayclass", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "protectionDomain", null_pointer_node);
+
+  {
+    tree assertion_table_ref;
+    if (TYPE_ASSERTIONS (type) == NULL)
+      assertion_table_ref = null_pointer_node;
+    else
+      assertion_table_ref = build1 (ADDR_EXPR, 
+                                   build_pointer_type (assertion_table_type),
+                                   emit_assertion_table (type));
+    
+    PUSH_FIELD_VALUE (cons, "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);
 
   FINISH_RECORD_CONSTRUCTOR (cons);
 
@@ -1834,11 +1876,26 @@ make_class_data (tree type)
     DECL_ALIGN (decl) = 64; 
   
   rest_of_decl_compilation (decl, 1, 0);
+  
+  TYPE_OTABLE_DECL (type) = NULL_TREE;
+  TYPE_ATABLE_DECL (type) = NULL_TREE;
+  TYPE_CTABLE_DECL (type) = NULL_TREE;
 }
 
 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;
@@ -1997,9 +2054,14 @@ maybe_layout_super_class (tree super_class, tree this_class)
          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, /* FIXME? */
                                          super_class, NULL_TREE, this_wrap);
@@ -2027,7 +2089,7 @@ layout_class (tree this_class)
       char *report;
       tree current;
 
-      sprintf (buffer, " with `%s'",
+      sprintf (buffer, " with '%s'",
               IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))));
       obstack_grow (&temporary_obstack, buffer, strlen (buffer));
 
@@ -2035,7 +2097,7 @@ layout_class (tree this_class)
           current = TREE_CHAIN (current))
        {
          tree decl = TYPE_NAME (TREE_PURPOSE (current));
-         sprintf (buffer, "\n  which inherits from `%s' (%s:%d)",
+         sprintf (buffer, "\n  which inherits from '%s' (%s:%d)",
                   IDENTIFIER_POINTER (DECL_NAME (decl)),
                   DECL_SOURCE_FILE (decl),
                   DECL_SOURCE_LINE (decl));
@@ -2086,20 +2148,22 @@ layout_class (tree this_class)
   if (!CLASS_FROM_SOURCE_P (this_class))
     {
       int i;
-      
-      for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (this_class)) - 1; i > 0; i--)
+            if (TYPE_BINFO (this_class))
        {
-         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)
+         for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (this_class)) - 1; i > 0; i--)
            {
-             TYPE_SIZE (this_class) = error_mark_node;
-             CLASS_BEING_LAIDOUT (this_class) = 0;
-             class_list = TREE_CHAIN (class_list);
-             return;
+             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;
+               }
            }
        }
     }
@@ -2115,8 +2179,11 @@ layout_class (tree this_class)
 static void
 add_miranda_methods (tree base_class, tree search_class)
 {
-  tree binfo, base_binfo;
   int i;
+  tree binfo, base_binfo;
+
+  if (!CLASS_PARSED_P (search_class))
+    load_class (search_class, 1);
   
   for (binfo = TYPE_BINFO (search_class), i = 1;
        BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
@@ -2124,7 +2191,14 @@ add_miranda_methods (tree base_class, tree search_class)
       tree method_decl;
       tree elt = BINFO_TYPE (base_binfo);
 
+      /* FIXME: This is totally bogus.  We should not be handling
+        Miranda methods at all if we're using the BC ABI.  */
+      if (TYPE_DUMMY (elt))
+       continue;
+
       /* Ensure that interface methods are seen in declared order.  */
+      if (!CLASS_LOADED_P (elt))
+       load_class (elt, 1);
       layout_class_methods (elt);
 
       /* All base classes will have been laid out at this point, so the order 
@@ -2182,7 +2256,8 @@ layout_class_methods (tree this_class)
     dtable_count = integer_zero_node;
 
   type_name = TYPE_NAME (this_class);
-  if (CLASS_ABSTRACT (type_name) || CLASS_INTERFACE (type_name))
+  if (!flag_indirect_dispatch
+      && (CLASS_ABSTRACT (type_name) || CLASS_INTERFACE (type_name)))
     {
       /* An abstract class can have methods which are declared only in
         an implemented interface.  These are called "Miranda
@@ -2255,14 +2330,15 @@ layout_class_method (tree this_class, tree super_class,
       DECL_CONSTRUCTOR_P (method_decl) = 1;
       build_java_argument_signature (TREE_TYPE (method_decl));
     }
-  else if (! METHOD_STATIC (method_decl) && !DECL_ARTIFICIAL (method_decl))
+  else if (! METHOD_STATIC (method_decl))
     {
       tree method_sig =
        build_java_argument_signature (TREE_TYPE (method_decl));
       bool method_override = false;
       tree super_method = lookup_argument_method (super_class, method_name,
                                                  method_sig);
-      if (super_method != NULL_TREE)
+      if (super_method != NULL_TREE
+         && ! METHOD_DUMMY (super_method))
         {
          method_override = true;
          if (! METHOD_PUBLIC (super_method) && 
@@ -2281,15 +2357,24 @@ layout_class_method (tree this_class, tree super_class,
          tree method_index = get_method_index (super_method);
          set_method_index (method_decl, method_index);
          if (method_index == NULL_TREE 
-             && !CLASS_FROM_SOURCE_P (this_class))
+             && !CLASS_FROM_SOURCE_P (this_class)
+             && ! DECL_ARTIFICIAL (super_method))
            error ("%Jnon-static method '%D' overrides static method",
                    method_decl, method_decl);
        }
-      else if (! METHOD_FINAL (method_decl)
-              && ! METHOD_PRIVATE (method_decl)
-              && ! CLASS_FINAL (TYPE_NAME (this_class))
+      else if (this_class == object_type_node
+              && (METHOD_FINAL (method_decl)
+                  || METHOD_PRIVATE (method_decl)))
+       {
+         /* We don't generate vtable entries for final Object
+            methods.  This is simply to save space, since every
+            object would otherwise have to define them.  */
+       }
+      else if (! METHOD_PRIVATE (method_decl)
               && dtable_count)
        {
+         /* 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));
@@ -2376,14 +2461,20 @@ static tree
 build_symbol_entry (tree decl)
 {
   tree clname, name, signature, sym;
-  
   clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
-  name = build_utf8_ref (DECL_NAME (decl));
+  /* ???  Constructors are given the name foo.foo all the way through
+     the compiler, but in the method table they're all renamed
+     foo.<init>.  So, we have to do the same here unless we want an
+     unresolved reference at runtime.  */
+  name = build_utf8_ref ((TREE_CODE (decl) == FUNCTION_DECL 
+                         && DECL_CONSTRUCTOR_P (decl))
+                        ? init_identifier_node
+                        : DECL_NAME (decl));
   signature = build_java_signature (TREE_TYPE (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);
@@ -2399,7 +2490,8 @@ build_symbol_entry (tree decl)
 
 tree
 emit_symbol_table (tree name, tree the_table, tree decl_list,
-                   tree the_syms_decl, tree the_array_element_type)
+                   tree the_syms_decl, tree the_array_element_type,
+                  int element_size)
 {
   tree method_list, method, table, list, null_symbol;
   tree table_size, the_array_type;
@@ -2446,7 +2538,8 @@ emit_symbol_table (tree name, tree the_table, tree decl_list,
      uninitialized static array of INDEX + 1 elements. The extra entry
      is used by the runtime to track whether the table has been
      initialized. */
-  table_size = build_index_type (build_int_cst (NULL_TREE, index, 0));
+  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);
   TREE_STATIC (the_table) = 1;
@@ -2456,7 +2549,7 @@ emit_symbol_table (tree name, tree the_table, tree decl_list,
   return the_table;
 }
 
-/* make an entry for the catch_classes list.  */
+/* Make an entry for the catch_classes list.  */
 tree
 make_catch_class_record (tree catch_class, tree classname)
 {
@@ -2487,7 +2580,7 @@ emit_catch_table (tree this_class)
               TYPE_CATCH_CLASSES (this_class));
   table_size = build_index_type
     (build_int_cst (NULL_TREE,
-                   list_length (TYPE_CATCH_CLASSES (this_class)), 0));
+                   list_length (TYPE_CATCH_CLASSES (this_class))));
   array_type 
     = build_array_type (TREE_TYPE (TREE_TYPE (TYPE_CTABLE_DECL (this_class))),
                        table_size);
@@ -2501,7 +2594,95 @@ emit_catch_table (tree this_class)
   rest_of_decl_compilation (table, 1, 0);
   return table;
 }
+
+/* Given a type, return the signature used by
+   _Jv_FindClassFromSignature() in libgcj.  This isn't exactly the
+   same as build_java_signature() because we want the canonical array
+   type.  */
+
+static tree
+build_signature_for_libgcj (tree type)
+{
+  tree sig, ref;
+
+  sig = build_java_signature (type);
+  ref = build_utf8_ref (unmangle_classname (IDENTIFIER_POINTER (sig),
+                                           IDENTIFIER_LENGTH (sig)));
+  return ref;
+}
+
+/* Add an entry to the type assertion table. Callback used during hashtable
+   traversal.  */
+
+static int
+add_assertion_table_entry (void **htab_entry, void *ptr)
+{
+  tree entry;
+  tree code_val, op1_utf8, op2_utf8;
+  tree *list = (tree *) ptr;
+  type_assertion *as = (type_assertion *) *htab_entry;
+
+  code_val = build_int_cst (NULL_TREE, as->assertion_code);
+
+  if (as->op1 == NULL_TREE)
+    op1_utf8 = null_pointer_node;
+  else
+    op1_utf8 = build_signature_for_libgcj (as->op1);
+
+  if (as->op2 == NULL_TREE)
+    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);
+  
+  *list = tree_cons (NULL_TREE, entry, *list);
+  return true;
+}
+
+/* Generate the type assertion table for CLASS, and return its DECL.  */
+
+static tree
+emit_assertion_table (tree class)
+{
+  tree null_entry, ctor, table_decl;
+  tree list = NULL_TREE;
+  htab_t assertions_htab = TYPE_ASSERTIONS (class);
+
+  /* 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);
+  
+  list = tree_cons (NULL_TREE, null_entry, list);
+  
+  /* Put the list in the right order and make it a constructor. */
+  list = nreverse (list);
+  ctor = build_constructor (assertion_table_type, list);
+
+  table_decl = build_decl (VAR_DECL, mangled_classname ("_type_assert_", class),
+                          assertion_table_type);
+
+  TREE_STATIC (table_decl) = 1;
+  TREE_READONLY (table_decl) = 1;
+  TREE_CONSTANT (table_decl) = 1;
+  DECL_IGNORED_P (table_decl) = 1;
+
+  DECL_INITIAL (table_decl) = ctor;
+  DECL_ARTIFICIAL (table_decl) = 1;
+  rest_of_decl_compilation (table_decl, 1, 0);
+
+  return table_decl;
+}
 
 void
 init_class_processing (void)