OSDN Git Service

PR java/12915:
[pf3gnuchains/gcc-fork.git] / gcc / java / class.c
index 1e0e83a..2aacbd4 100644 (file)
@@ -57,11 +57,11 @@ static tree get_dispatch_table (tree, tree);
 static int supers_all_compiled (tree type);
 static void add_interface_do (tree, tree, int);
 static tree maybe_layout_super_class (tree, tree);
+static void add_miranda_methods (tree, tree);
 static int assume_compiled (const char *);
-static tree build_method_symbols_entry (tree);
+static tree build_symbol_entry (tree);
 
 static GTY(()) rtx registerClass_libfunc;
-static GTY(()) rtx registerResource_libfunc;
 
 struct obstack temporary_obstack;
 
@@ -149,8 +149,7 @@ add_assume_compiled (const char *ident, int excludep)
 {
   int len;
   assume_compiled_node *parent;
-  assume_compiled_node *node = 
-    xmalloc (sizeof (assume_compiled_node));
+  assume_compiled_node *node = xmalloc (sizeof (assume_compiled_node));
 
   node->ident = xstrdup (ident);
   node->excludep = excludep;
@@ -276,7 +275,7 @@ make_class (void)
 {
   tree type;
   type = make_node (RECORD_TYPE);
-  TYPE_BINFO (type) = make_tree_vec (6);
+  TYPE_BINFO (type) = make_tree_vec (BINFO_ELTS);
   MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type);
 
   return type;
@@ -309,19 +308,17 @@ tree
 push_class (tree class_type, tree class_name)
 {
   tree decl, signature;
-  const char *save_input_filename = input_filename;
-  int save_lineno = lineno;
+  location_t saved_loc = input_location;
   tree source_name = identifier_subst (class_name, "", '.', '/', ".java");
   CLASS_P (class_type) = 1;
   input_filename = IDENTIFIER_POINTER (source_name);
-  lineno = 0;
+  input_line = 0;
   decl = build_decl (TYPE_DECL, class_name, class_type);
 
   /* dbxout needs a DECL_SIZE if in gstabs mode */
   DECL_SIZE (decl) = integer_zero_node;
 
-  input_filename = save_input_filename;
-  lineno = save_lineno;
+  input_location = saved_loc;
   signature = identifier_subst (class_name, "L", '.', '/', ";");
   IDENTIFIER_SIGNATURE_TYPE (signature) = build_pointer_type (class_type);
 
@@ -361,10 +358,9 @@ set_super_info (int access_flags, tree this_class,
   TYPE_BINFO_BASETYPES (this_class) = make_tree_vec (total_supers);
   if (super_class)
     {
-      tree super_binfo = make_tree_vec (6);
+      tree super_binfo = make_tree_vec (BINFO_ELTS);
       BINFO_TYPE (super_binfo) = super_class;
       BINFO_OFFSET (super_binfo) = integer_zero_node;
-      TREE_VIA_PUBLIC (super_binfo) = 1;
       TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (this_class)), 0)
        = super_binfo;
       CLASS_HAS_SUPER (this_class) = 1;
@@ -493,12 +489,11 @@ int common_enclosing_context_p (tree type1, tree type2)
 static void
 add_interface_do (tree basetype_vec, tree interface_class, int i)
 {
-  tree interface_binfo = make_tree_vec (6);
+  tree interface_binfo = make_tree_vec (BINFO_ELTS);
   BINFO_TYPE (interface_binfo) = interface_class;
   BINFO_OFFSET (interface_binfo) = integer_zero_node;
   BINFO_VPTR_FIELD (interface_binfo) = integer_zero_node;
   TREE_VIA_VIRTUAL (interface_binfo) = 1;
-  TREE_VIA_PUBLIC (interface_binfo) = 1;
   TREE_VEC_ELT (basetype_vec, i) = interface_binfo;
 }
 
@@ -623,7 +618,6 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
     METHOD_FINAL (fndecl) = DECL_INLINE (fndecl) = 1;
   if (access_flags & ACC_SYNCHRONIZED) METHOD_SYNCHRONIZED (fndecl) = 1;
   if (access_flags & ACC_ABSTRACT) METHOD_ABSTRACT (fndecl) = 1;
-  if (access_flags & ACC_TRANSIENT) METHOD_TRANSIENT (fndecl) = 1;
   if (access_flags & ACC_STRICT) METHOD_STRICTFP (fndecl) = 1;
   return fndecl;
 }
@@ -742,111 +736,7 @@ hashUtf8String (const char *str, int len)
   return hash;
 }
 
-/* Generate a byte array representing the contents of FILENAME.  The
-   array is assigned a unique local symbol.  The array represents a
-   compiled Java resource, which is accessed by the runtime using
-   NAME.  */
-void
-compile_resource_file (char *name, const char *filename)
-{
-  struct stat stat_buf;
-  int fd;
-  char *buffer;
-  char buf[60];
-  tree rtype, field = NULL_TREE, data_type, rinit, data, decl;
-  static int Jr_count = 0;
-
-  fd = open (filename, O_RDONLY | O_BINARY);
-  if (fd < 0)
-    {
-      perror ("Failed to read resource file");
-      return;
-    }
-  if (fstat (fd, &stat_buf) != 0
-      || ! S_ISREG (stat_buf.st_mode))
-    {
-      perror ("Could not figure length of resource file");
-      return;
-    }
-  buffer = xmalloc (strlen (name) + stat_buf.st_size);
-  strcpy (buffer, name);
-  read (fd, buffer + strlen (name), stat_buf.st_size);
-  close (fd);
-  data_type = build_prim_array_type (unsigned_byte_type_node,
-                                    strlen (name) + stat_buf.st_size);
-  rtype = make_node (RECORD_TYPE);
-  PUSH_FIELD (rtype, field, "name_length", unsigned_int_type_node);
-  PUSH_FIELD (rtype, field, "resource_length", unsigned_int_type_node);
-  PUSH_FIELD (rtype, field, "data", data_type);
-  FINISH_RECORD (rtype);
-  START_RECORD_CONSTRUCTOR (rinit, rtype);
-  PUSH_FIELD_VALUE (rinit, "name_length", 
-                   build_int_2 (strlen (name), 0));
-  PUSH_FIELD_VALUE (rinit, "resource_length", 
-                   build_int_2 (stat_buf.st_size, 0));
-  data = build_string (strlen(name) + stat_buf.st_size, buffer);
-  TREE_TYPE (data) = data_type;
-  PUSH_FIELD_VALUE (rinit, "data", data);
-  FINISH_RECORD_CONSTRUCTOR (rinit);
-  TREE_CONSTANT (rinit) = 1;
-
-  /* Generate a unique-enough identifier.  */
-  sprintf(buf, "_Jr%d", ++Jr_count);
-
-  decl = build_decl (VAR_DECL, get_identifier (buf), rtype);
-  TREE_STATIC (decl) = 1;
-  DECL_ARTIFICIAL (decl) = 1;
-  DECL_IGNORED_P (decl) = 1;
-  TREE_READONLY (decl) = 1;
-  TREE_THIS_VOLATILE (decl) = 0;
-  DECL_INITIAL (decl) = rinit;
-  layout_decl (decl, 0);
-  pushdecl (decl);
-  rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0);
-  make_decl_rtl (decl, (char*) 0);
-  assemble_variable (decl, 1, 0, 0);
-
-  {
-    tree init_name = get_file_function_name ('I');
-    tree init_type = build_function_type (void_type_node, end_params_node);
-    tree init_decl;
-    
-    init_decl = build_decl (FUNCTION_DECL, init_name, init_type);
-    SET_DECL_ASSEMBLER_NAME (init_decl, init_name);
-    TREE_STATIC (init_decl) = 1;
-    current_function_decl = init_decl;
-    DECL_RESULT (init_decl) = build_decl (RESULT_DECL, 
-                                         NULL_TREE, void_type_node);
-
-    /* It can be a static function as long as collect2 does not have
-       to scan the object file to find its ctor/dtor routine.  */
-    TREE_PUBLIC (init_decl) = ! targetm.have_ctors_dtors;
-
-    pushlevel (0);
-    make_decl_rtl (init_decl, NULL);
-    init_function_start (init_decl, input_filename, 0);
-    expand_function_start (init_decl, 0);
-    
-    emit_library_call (registerResource_libfunc, 0, VOIDmode, 1,
-                      gen_rtx (SYMBOL_REF, Pmode, buf), 
-                      Pmode);
-    
-    expand_function_end (input_filename, 0, 0);
-    poplevel (1, 0, 1);
-    { 
-      /* Force generation, even with -O3 or deeper. Gross hack. FIXME */
-      int saved_flag = flag_inline_functions;
-      flag_inline_functions = 0;       
-      rest_of_compilation (init_decl);
-      flag_inline_functions = saved_flag;
-    }
-    current_function_decl = NULL_TREE;
-    (* targetm.asm_out.constructor) (XEXP (DECL_RTL (init_decl), 0),
-                                    DEFAULT_INIT_PRIORITY);
-  }     
-}
-
-tree utf8_decl_list = NULL_TREE;
+static GTY(()) tree utf8_decl_list = NULL_TREE;
 
 tree
 build_utf8_ref (tree name)
@@ -889,23 +779,24 @@ build_utf8_ref (tree name)
   TREE_READONLY (decl) = 1;
   TREE_THIS_VOLATILE (decl) = 0;
   DECL_INITIAL (decl) = cinit;
-#ifdef HAVE_GAS_SHF_MERGE
-  {
-    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);
-    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);
-        DECL_SECTION_NAME (decl) = build_string (strlen (buf), buf);
-      }
-  }
-#endif
+
+  if (HAVE_GAS_SHF_MERGE)
+    {
+      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);
+      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);
+         DECL_SECTION_NAME (decl) = build_string (strlen (buf), buf);
+       }
+    }
+
   TREE_CHAIN (decl) = utf8_decl_list;
   layout_decl (decl, 0);
   pushdecl (decl);
@@ -917,6 +808,20 @@ build_utf8_ref (tree name)
   return ref;
 }
 
+/* Like build_class_ref, but instead of a direct reference generate a
+   pointer into the constant pool.  */
+
+static tree
+build_indirect_class_ref (tree type)
+{
+  int index;
+  tree cl;
+  index = alloc_class_constant (type);
+  cl = build_ref_from_constant_pool (index); 
+  TREE_TYPE (cl) = promote_type (class_ptr_type);
+  return cl;
+}
+
 /* Build a reference to the class TYPE.
    Also handles primitive types and array types. */
 
@@ -929,6 +834,12 @@ build_class_ref (tree type)
       tree ref, decl_name, decl;
       if (TREE_CODE (type) == POINTER_TYPE)
        type = TREE_TYPE (type);
+
+      if  (flag_indirect_dispatch 
+          && type != current_class
+          && TREE_CODE (type) == RECORD_TYPE)
+       return build_indirect_class_ref (type);
+
       if (TREE_CODE (type) == RECORD_TYPE)
        {
          if (TYPE_SIZE (type) == error_mark_node)
@@ -1011,14 +922,7 @@ build_class_ref (tree type)
       return ref;
     }
   else
-    {
-      int index;
-      tree cl;
-      index = alloc_class_constant (type);
-      cl = build_ref_from_constant_pool (index); 
-      TREE_TYPE (cl) = promote_type (class_ptr_type);
-      return cl;
-    }
+    return build_indirect_class_ref (type);
 }
 
 tree
@@ -1027,8 +931,19 @@ build_static_field_ref (tree fdecl)
   tree fclass = DECL_CONTEXT (fdecl);
   int is_compiled = is_compiled_class (fclass);
 
-  /* Allow static final fields to fold to a constant.  */
-  if (is_compiled || FIELD_FINAL (fdecl))
+  /* 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 || current_class == fclass))
+      || (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))
        {
@@ -1038,7 +953,18 @@ build_static_field_ref (tree fdecl)
        }
       return fdecl;
     }
-  else
+
+  if (flag_indirect_dispatch)
+    {
+      tree table_index 
+       = build_int_2 (get_symbol_table_index (fdecl, &atable_methods), 0);
+      tree field_address
+       = build (ARRAY_REF, build_pointer_type (TREE_TYPE (fdecl)), 
+                atable_decl, table_index);
+      return fold (build1 (INDIRECT_REF, TREE_TYPE (fdecl), 
+                          field_address));
+    }
+  else  
     {
       /* Compile as:
        * *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr */
@@ -1133,10 +1059,10 @@ get_access_flags_from_decl (tree decl)
        access_flags |= ACC_NATIVE;
       if (METHOD_ABSTRACT (decl))
        access_flags |= ACC_ABSTRACT;
-      if (METHOD_TRANSIENT (decl))
-       access_flags |= ACC_TRANSIENT;
       if (METHOD_STRICTFP (decl))
        access_flags |= ACC_STRICT;
+      if (METHOD_INVISIBLE (decl))
+       access_flags |= ACC_INVISIBLE;
       return access_flags;
     }
   abort ();
@@ -1148,7 +1074,7 @@ make_field_value (tree fdecl)
   tree finit;
   int flags;
   tree type = TREE_TYPE (fdecl);
-  int resolved = is_compiled_class (type);
+  int resolved = is_compiled_class (type) && ! flag_indirect_dispatch;
 
   START_RECORD_CONSTRUCTOR (finit, field_type_node);
   PUSH_FIELD_VALUE (finit, "name", build_utf8_ref (DECL_NAME (fdecl)));
@@ -1173,7 +1099,7 @@ make_field_value (tree fdecl)
 
   PUSH_FIELD_VALUE
     (finit, "info",
-     build (CONSTRUCTOR, field_info_union_node, NULL_TREE,
+     build_constructor (field_info_union_node,
            build_tree_list
            ((FIELD_STATIC (fdecl)
              ? TREE_CHAIN (TYPE_FIELDS (field_info_union_node))
@@ -1242,7 +1168,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, NULL_TREE, table);
+       table = build_constructor (type, table);
        /* Compute something unique enough.  */
        sprintf (buf, "_methods%d", method_name_count++);
        array = build_decl (VAR_DECL, get_identifier (buf), type);
@@ -1311,8 +1237,7 @@ get_dispatch_table (tree type, tree this_class_addr)
       if (METHOD_ABSTRACT (method))
        {
          if (! abstract_p)
-           warning_with_decl (method,
-                              "abstract method in non-abstract class");
+           warning ("%Jabstract method in non-abstract class", method);
 
          if (TARGET_VTABLE_USES_DESCRIPTORS)
            for (j = 0; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j)
@@ -1364,9 +1289,8 @@ 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),
-               NULL_TREE, list);
+  return build_constructor (build_prim_array_type (nativecode_ptr_type_node,
+                                                  arraysize), list);
 }
 
 static int
@@ -1449,8 +1373,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,
-                                         NULL_TREE, static_fields);
+      DECL_INITIAL (fields_decl) = build_constructor (field_array_type,
+                                                     static_fields);
       TREE_STATIC (fields_decl) = 1;
       DECL_ARTIFICIAL (fields_decl) = 1;
       DECL_IGNORED_P (fields_decl) = 1;
@@ -1475,8 +1399,8 @@ make_class_data (tree type)
   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,
-                                      NULL_TREE, nreverse (methods));
+  DECL_INITIAL (methods_decl) = build_constructor (method_array_type,
+                                                  nreverse (methods));
   TREE_STATIC (methods_decl) = 1;
   DECL_ARTIFICIAL (methods_decl) = 1;
   DECL_IGNORED_P (methods_decl) = 1;
@@ -1511,7 +1435,8 @@ make_class_data (tree type)
   super = CLASSTYPE_SUPER (type);
   if (super == NULL_TREE)
     super = null_pointer_node;
-  else if (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
@@ -1548,8 +1473,7 @@ make_class_data (tree type)
            }
          init = tree_cons (NULL_TREE, index, init); 
        }
-      DECL_INITIAL (idecl) = build (CONSTRUCTOR, interface_array_type,
-                                   NULL_TREE, init);
+      DECL_INITIAL (idecl) = build_constructor (interface_array_type, init);
       TREE_STATIC (idecl) = 1;
       DECL_ARTIFICIAL (idecl) = 1;
       DECL_IGNORED_P (idecl) = 1;
@@ -1582,7 +1506,7 @@ make_class_data (tree type)
   PUSH_FIELD_VALUE (cons, "method_count",  build_int_2 (method_count, 0));
 
   if (flag_indirect_dispatch)
-    PUSH_FIELD_VALUE (cons, "vtable_method_count", integer_minus_one_node)
+    PUSH_FIELD_VALUE (cons, "vtable_method_count", integer_minus_one_node);
   else
     PUSH_FIELD_VALUE (cons, "vtable_method_count", TYPE_NVIRTUALS (type));
     
@@ -1595,14 +1519,13 @@ make_class_data (tree type)
                    build_int_2 (static_field_count, 0));
 
   if (flag_indirect_dispatch)
-    PUSH_FIELD_VALUE (cons, "vtable", null_pointer_node)
+    PUSH_FIELD_VALUE (cons, "vtable", null_pointer_node);
   else
     PUSH_FIELD_VALUE (cons, "vtable",
                      dtable_decl == NULL_TREE ? null_pointer_node
                      : build (PLUS_EXPR, dtable_ptr_type,
                               build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl),
                               dtable_start_offset));
-  
   if (otable_methods == NULL_TREE)
     {
       PUSH_FIELD_VALUE (cons, "otable", null_pointer_node);
@@ -1613,9 +1536,27 @@ make_class_data (tree type)
       PUSH_FIELD_VALUE (cons, "otable",
                        build1 (ADDR_EXPR, otable_ptr_type, otable_decl));
       PUSH_FIELD_VALUE (cons, "otable_syms",
-                       build1 (ADDR_EXPR, method_symbols_array_ptr_type,
+                       build1 (ADDR_EXPR, symbols_array_ptr_type,
                                otable_syms_decl));
+      TREE_CONSTANT (otable_decl) = 1;
     }
+  if (atable_methods == 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, atable_decl));
+      PUSH_FIELD_VALUE (cons, "atable_syms",
+                       build1 (ADDR_EXPR, symbols_array_ptr_type,
+                               atable_syms_decl));
+      TREE_CONSTANT (atable_decl) = 1;
+    }
+  PUSH_FIELD_VALUE (cons, "catch_classes",
+                   build1 (ADDR_EXPR, ptr_type_node, ctable_decl)); 
   PUSH_FIELD_VALUE (cons, "interfaces", interfaces);
   PUSH_FIELD_VALUE (cons, "loader", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "interface_count", build_int_2 (interface_len, 0));
@@ -1627,6 +1568,7 @@ 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);
+  PUSH_FIELD_VALUE (cons, "signers", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "chain", null_pointer_node);
 
   FINISH_RECORD_CONSTRUCTOR (cons);
@@ -1823,8 +1765,19 @@ maybe_layout_super_class (tree super_class, tree this_class)
        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);
+             this_wrap = build_expr_wfl (this_class,
+                                         DECL_SOURCE_FILE (this_decl),
+                                         DECL_SOURCE_LINE (this_decl), 0);
+           }
          super_class = do_resolve_class (NULL_TREE, /* FIXME? */
-                                         super_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);
@@ -1841,14 +1794,14 @@ 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))
     {
       char buffer [1024];
       char *report;
       tree current;
-      
+
       sprintf (buffer, " with `%s'",
               IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))));
       obstack_grow (&temporary_obstack, buffer, strlen (buffer));
@@ -1902,8 +1855,9 @@ 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. */
+  /* 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))
     {
       tree basetype_vec = TYPE_BINFO_BASETYPES (this_class);
@@ -1931,14 +1885,63 @@ layout_class (tree this_class)
        }
     }
 
-  /* Convert the size back to an SI integer value */
-  TYPE_SIZE_UNIT (this_class) = 
+  /* Convert the size back to an SI integer value */
+  TYPE_SIZE_UNIT (this_class) =
     fold (convert (int_type_node, TYPE_SIZE_UNIT (this_class)));
 
   CLASS_BEING_LAIDOUT (this_class) = 0;
   class_list = TREE_CHAIN (class_list);
 }
 
+static void
+add_miranda_methods (tree base_class, tree search_class)
+{
+  tree basetype_vec = TYPE_BINFO_BASETYPES (search_class);
+  int i, n = TREE_VEC_LENGTH (basetype_vec);
+  for (i = 1; i < n; ++i)
+    {
+      tree method_decl;
+      tree elt = TREE_VEC_ELT (basetype_vec, i);
+      if (elt == NULL_TREE)
+       break;
+      elt = BINFO_TYPE (elt);
+
+      /* Ensure that interface methods are seen in declared order.  */
+      layout_class_methods (elt);
+
+      /* All base classes will have been laid out at this point, so the order 
+         will be correct.  This code must match similar layout code in the 
+         runtime.  */
+      for (method_decl = TYPE_METHODS (elt);
+          method_decl; method_decl = TREE_CHAIN (method_decl))
+       {
+         tree sig, override;
+
+         /* An interface can have <clinit>.  */
+         if (ID_CLINIT_P (DECL_NAME (method_decl)))
+           continue;
+
+         sig = build_java_argument_signature (TREE_TYPE (method_decl));
+         override = lookup_argument_method (base_class,
+                                            DECL_NAME (method_decl), sig);
+         if (override == NULL_TREE)
+           {
+             /* Found a Miranda method.  Add it.  */
+             tree new_method;
+             sig = build_java_signature (TREE_TYPE (method_decl));
+             new_method
+               = add_method (base_class,
+                             get_access_flags_from_decl (method_decl),
+                             DECL_NAME (method_decl), sig);
+             METHOD_INVISIBLE (new_method) = 1;
+           }
+       }
+
+      /* Try superinterfaces.  */
+      add_miranda_methods (base_class, elt);
+    }
+}
+
 void
 layout_class_methods (tree this_class)
 {
@@ -1960,11 +1963,20 @@ layout_class_methods (tree this_class)
   else
     dtable_count = integer_zero_node;
 
+  if (CLASS_ABSTRACT (TYPE_NAME (this_class)))
+    {
+      /* An abstract class can have methods which are declared only in
+        an implemented interface.  These are called "Miranda
+        methods".  We make a dummy method entry for such methods
+        here.  */
+      add_miranda_methods (this_class, this_class);
+    }
+
   TYPE_METHODS (this_class) = nreverse (TYPE_METHODS (this_class));
 
   for (method_decl = TYPE_METHODS (this_class);
        method_decl; method_decl = TREE_CHAIN (method_decl))
-    dtable_count = layout_class_method (this_class, super_class, 
+    dtable_count = layout_class_method (this_class, super_class,
                                        method_decl, dtable_count);
 
   TYPE_NVIRTUALS (this_class) = dtable_count;
@@ -1980,6 +1992,9 @@ 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,
@@ -2015,8 +2030,8 @@ layout_class_method (tree this_class, tree super_class,
          DECL_VINDEX (method_decl) = DECL_VINDEX (super_method);
          if (DECL_VINDEX (method_decl) == NULL_TREE 
              && !CLASS_FROM_SOURCE_P (this_class))
-           error_with_decl (method_decl,
-                            "non-static method '%s' overrides static method");
+           error ("%Jnon-static method '%D' overrides static method",
+                   method_decl, method_decl);
        }
       else if (! METHOD_FINAL (method_decl)
               && ! METHOD_PRIVATE (method_decl)
@@ -2085,9 +2100,11 @@ emit_register_classes (void)
       tree init_type = build_function_type (void_type_node, end_params_node);
       tree init_decl;
       tree t;
+      location_t saved_loc = input_location;
       
       init_decl = build_decl (FUNCTION_DECL, init_name, init_type);
       SET_DECL_ASSEMBLER_NAME (init_decl, init_name);
+      DECL_SOURCE_LINE (init_decl) = 0;
       TREE_STATIC (init_decl) = 1;
       current_function_decl = init_decl;
       DECL_RESULT (init_decl) = build_decl (RESULT_DECL, NULL_TREE,
@@ -2102,7 +2119,7 @@ emit_register_classes (void)
 
       pushlevel (0);
       make_decl_rtl (init_decl, NULL);
-      init_function_start (init_decl, input_filename, 0);
+      init_function_start (init_decl);
       expand_function_start (init_decl, 0);
 
       /* Do not allow the function to be deferred.  */
@@ -2112,8 +2129,8 @@ emit_register_classes (void)
       for ( t = registered_class; t; t = TREE_CHAIN (t))
        emit_library_call (registerClass_libfunc, 0, VOIDmode, 1,
                           XEXP (DECL_RTL (t), 0), Pmode);
-      
-      expand_function_end (input_filename, 0, 0);
+      input_location = DECL_SOURCE_LOCATION (init_decl);
+      expand_function_end ();
       poplevel (1, 0, 1);
       rest_of_compilation (init_decl);
       current_function_decl = NULL_TREE;
@@ -2121,61 +2138,63 @@ emit_register_classes (void)
       if (targetm.have_ctors_dtors)
        (* targetm.asm_out.constructor) (XEXP (DECL_RTL (init_decl), 0),
                                         DEFAULT_INIT_PRIORITY);
+      input_location = saved_loc;
     }
 }
 
-/* Make a method_symbol_type (_Jv_MethodSymbol) node for METHOD. */
+/* Make a symbol_type (_Jv_MethodSymbol) node for DECL. */
 
-tree
-build_method_symbols_entry (tree method)
+static tree
+build_symbol_entry (tree decl)
 {
-  tree clname, name, signature, method_symbol;
+  tree clname, name, signature, sym;
   
-  clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (method))));
-  name = build_utf8_ref (DECL_NAME (method));
-  signature = build_java_signature (TREE_TYPE (method));
+  clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
+  name = build_utf8_ref (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 (method_symbol, method_symbol_type);
-  PUSH_FIELD_VALUE (method_symbol, "clname", clname);
-  PUSH_FIELD_VALUE (method_symbol, "name", name);
-  PUSH_FIELD_VALUE (method_symbol, "signature", signature);
-  FINISH_RECORD_CONSTRUCTOR (method_symbol);
-  TREE_CONSTANT (method_symbol) = 1;
+  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;
 
-  return method_symbol;
+  return sym;
 } 
 
-/* Emit the offset symbols table for indirect virtual dispatch. */
+/* Emit a symbol table: used by -findirect-dispatch.  */
 
-void
-emit_offset_symbol_table (void)
+tree
+emit_symbol_table (tree name, tree the_table, tree decl_list, tree the_syms_decl, 
+                         tree the_array_element_type)
 {
   tree method_list, method, table, list, null_symbol;
-  tree otable_bound, otable_array_type;
+  tree table_size, the_array_type;
   int index;
   
-  /* Only emit an offset table if this translation unit actually made virtual 
-     calls. */
-  if (otable_methods == NULL_TREE)
-    return;
+  /* Only emit a table if this translation unit actually made any
+     references via it. */
+  if (decl_list == NULL_TREE)
+    return the_table;
 
   /* Build a list of _Jv_MethodSymbols for each entry in otable_methods. */
   index = 0;
-  method_list = otable_methods;
+  method_list = decl_list;
   list = NULL_TREE;  
   while (method_list != NULL_TREE)
     {
       method = TREE_VALUE (method_list);
-      list = tree_cons (NULL_TREE, build_method_symbols_entry (method), list);
+      list = tree_cons (NULL_TREE, build_symbol_entry (method), list);
       method_list = TREE_CHAIN (method_list);
       index++;
     }
 
   /* Terminate the list with a "null" entry. */
-  START_RECORD_CONSTRUCTOR (null_symbol, method_symbol_type);
+  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);
@@ -2185,32 +2204,73 @@ emit_offset_symbol_table (void)
 
   /* Put the list in the right order and make it a constructor. */
   list = nreverse (list);
-  table = build (CONSTRUCTOR, method_symbols_array_type, NULL_TREE, list);  
+  table = build_constructor (symbols_array_type, list);  
 
   /* Make it the initial value for otable_syms and emit the decl. */
-  DECL_INITIAL (otable_syms_decl) = table;
-  DECL_ARTIFICIAL (otable_syms_decl) = 1;
-  DECL_IGNORED_P (otable_syms_decl) = 1;
-  rest_of_decl_compilation (otable_syms_decl, NULL, 1, 0);
+  DECL_INITIAL (the_syms_decl) = table;
+  DECL_ARTIFICIAL (the_syms_decl) = 1;
+  DECL_IGNORED_P (the_syms_decl) = 1;
+  rest_of_decl_compilation (the_syms_decl, NULL, 1, 0);
   
-  /* Now that its size is known, redefine otable as an uninitialized static 
-     array of INDEX + 1 integers. The extra entry is used by the runtime 
-     to track whether the otable has been initialized. */
-  otable_bound = build_index_type (build_int_2 (index, 0));
-  otable_array_type = build_array_type (integer_type_node, otable_bound);
-  otable_decl = build_decl (VAR_DECL, get_identifier ("otable"), 
-                           otable_array_type);
-  TREE_STATIC (otable_decl) = 1;
-  TREE_READONLY (otable_decl) = 1;  
-  rest_of_decl_compilation (otable_decl, NULL, 1, 0);
+  /* Now that its size is known, redefine the table as an
+     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_2 (index, 0));
+  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;
+  TREE_READONLY (the_table) = 1;  
+  rest_of_decl_compilation (the_table, NULL, 1, 0);
+
+  return the_table;
+}
+
+/* make an entry for the catch_classes list.  */
+tree
+make_catch_class_record (tree catch_class, tree classname)
+{
+  tree entry;
+  tree type = TREE_TYPE (TREE_TYPE (ctable_decl));
+  START_RECORD_CONSTRUCTOR (entry, type);
+  PUSH_FIELD_VALUE (entry, "address", catch_class);
+  PUSH_FIELD_VALUE (entry, "classname", classname);
+  FINISH_RECORD_CONSTRUCTOR (entry);
+  return entry;
+}
+
+
+/* Generate the list of Throwable classes that are caught by exception
+   handlers in this compilation.  */
+void 
+emit_catch_table (void)
+{
+  tree table, table_size, array_type;
+  catch_classes 
+    = tree_cons (NULL, 
+                make_catch_class_record (null_pointer_node, null_pointer_node),
+                catch_classes);
+  catch_classes = nreverse (catch_classes);
+  catch_classes 
+    = tree_cons (NULL, 
+                make_catch_class_record (null_pointer_node, null_pointer_node),
+                catch_classes);
+  table_size = build_index_type (build_int_2 (list_length (catch_classes), 0));
+  array_type 
+    = build_array_type (TREE_TYPE (TREE_TYPE (ctable_decl)), table_size);
+  table = build_decl (VAR_DECL, DECL_NAME (ctable_decl), array_type);
+  DECL_INITIAL (table) = build_constructor (array_type, catch_classes);
+  TREE_STATIC (table) = 1;
+  TREE_READONLY (table) = 1;  
+  rest_of_decl_compilation (table, NULL, 1, 0);
+  ctable_decl = table;
 }
 
 void
 init_class_processing (void)
 {
   registerClass_libfunc = gen_rtx_SYMBOL_REF (Pmode, "_Jv_RegisterClass");
-  registerResource_libfunc = 
-    gen_rtx_SYMBOL_REF (Pmode, "_Jv_RegisterResource");
   fields_ident = get_identifier ("fields");
   info_ident = get_identifier ("info");
   gcc_obstack_init (&temporary_obstack);
@@ -2243,7 +2303,7 @@ java_treetreehash_find (htab_t ht, tree t)
 {
   struct treetreehash_entry *e;
   hashval_t hv = JAVA_TREEHASHHASH_H (t);
-  e = (struct treetreehash_entry *) htab_find_with_hash (ht, t, hv);
+  e = htab_find_with_hash (ht, t, hv);
   if (e == NULL)
     return NULL;
   else