This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[BC ABI] gcj-abi-2-dev-branch created
- From: Andrew Haley <aph at redhat dot com>
- To: java-patches at gcc dot gnu dot org
- Date: Fri, 16 Apr 2004 14:20:54 +0100
- Subject: [BC ABI] gcj-abi-2-dev-branch created
2004-04-16 Andrew Haley <aph@redhat.com>
* verify.c (check_pending_block): Disable subroutine checks.
(defer_merging): New function.
(merge_types): If types are dummy, use defer_merging to combine them.
(verify_jvm_instructions): If invocation is invokeinterface and
target is dummy, assume target really is an interface.
* parse.y (patch_invoke): Break out call to java_create_object.
* lang.c (flag_verify_invocations): New.
* jcf-parse.c (load_class): If we've already failed to load a
class, don't try again.
(load_class): If we can't find a .class file, don't fail, but emit
a warning.
(parse_class_file): Don't act on dummy methods.
* java-tree.h (flag_verify_invocations): New.
(TYPE_DUMMY): New.
(lang_type.dummy_class): New field.
(java_create_object): New function.
(METHOD_DUMMY): New.
* expr.c (build_field_ref): Widen field offset.
(pop_type_0): If the type in stack_type_map is a TREE_LIST, check
that each of its elements is compatible with the one we're
popping.
(pop_type_0): Issue a warning to say that we need to generate a
runtime check.
(java_create_object): New function.
(build_field_ref): Only generate hard refs if we're not using
indirect dispatch.
(expand_java_field_op): If we're using !verify_invocations and we
see a missing field, generate a decl for it.
(expand_invoke): If a class doesn't have the method we seek and
we're using !flag_verify_invocations, generate a decl for the
method now.
(build_known_method_ref): Always use indirect dispatch via the
atable for static methods.
(expand_java_NEW): Break out object creation into new function,
java_create_object.
(can_widen_reference_to): Issue a warning to say that we need to
generate a runtime check.
* class.c (set_super_info): Inherit TYPE_DUMMY from sureclass.
(make_method_value): Also use index for interfaces.
(make_class_data): Skip dummy field for inherited data.
Don't build method array for dummy methods.
Set size_in_byte to -1 when using inirect dispatch
Don't build a hard class ref if we don't have a hard ref to our
superclass, or if we're using inirect dispatch.
Null out dispatch tables.
(layout_class_method): Don't complain about non-static method
overrides static method is method is artificial.
(build_static_field_ref): Disable atable references to static
fields for the time being.
(layout_class_methods): Check for CLASS_INTERFACE as
well as CLASS_ABSTRACT.
Index: gcc/java/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.180
diff -p -2 -c -w -r1.180 class.c
*** gcc/java/class.c 20 Mar 2004 14:03:33 -0000 1.180
--- gcc/java/class.c 16 Apr 2004 12:29:43 -0000
*************** set_super_info (int access_flags, tree t
*** 486,489 ****
--- 486,493 ----
= super_binfo;
CLASS_HAS_SUPER (this_class) = 1;
+ /* FIXME: This is wrong. */
+ if (TYPE_LANG_SPECIFIC (this_class)
+ && TYPE_LANG_SPECIFIC (super_class))
+ TYPE_DUMMY (this_class) = TYPE_DUMMY (super_class);
}
*************** build_class_ref (tree type)
*** 963,967 ****
if (flag_indirect_dispatch
&& type != output_class
! && type != CLASSTYPE_SUPER (output_class)
&& TREE_CODE (type) == RECORD_TYPE)
return build_indirect_class_ref (type);
--- 967,971 ----
if (flag_indirect_dispatch
&& type != output_class
! // && type != CLASSTYPE_SUPER (output_class)
&& TREE_CODE (type) == RECORD_TYPE)
return build_indirect_class_ref (type);
*************** build_static_field_ref (tree fdecl)
*** 1081,1085 ****
}
! if (flag_indirect_dispatch)
{
tree table_index
--- 1085,1092 ----
}
! /* FIXME: The gcj runtime is broken in that atable references to
! static fields in interpreted classes aren't fixed up until too
! late. When this is fixed we can re-enable this code. */
! if (0 && flag_indirect_dispatch)
{
tree table_index
*************** make_method_value (tree mdecl)
*** 1250,1254 ****
int accflags = get_access_flags_from_decl (mdecl) | ACC_TRANSLATED;
! if (!flag_indirect_dispatch && DECL_VINDEX (mdecl) != NULL_TREE)
index = DECL_VINDEX (mdecl);
else
--- 1257,1263 ----
int accflags = get_access_flags_from_decl (mdecl) | ACC_TRANSLATED;
! if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (mdecl)))
! || (!flag_indirect_dispatch
! && DECL_VINDEX (mdecl) != NULL_TREE))
index = DECL_VINDEX (mdecl);
else
*************** make_class_data (tree type)
*** 1465,1469 ****
/* Build Field array. */
field = TYPE_FIELDS (type);
! if (DECL_NAME (field) == NULL_TREE)
field = TREE_CHAIN (field); /* Skip dummy field for inherited data. */
for ( ; field != NULL_TREE; field = TREE_CHAIN (field))
--- 1474,1480 ----
/* 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))
*************** make_class_data (tree type)
*** 1520,1523 ****
--- 1531,1539 ----
&& (flag_inline_functions || optimize))
continue;
+ /* Even if we have a decl, we don't necessaily 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++;
*************** make_class_data (tree type)
*** 1563,1570 ****
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)))
&& assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (super)))))
super = build_class_ref (super);
--- 1579,1584 ----
if (super == NULL_TREE)
super = null_pointer_node;
! 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);
*************** make_class_data (tree type)
*** 1662,1667 ****
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_2 (field_count, 0));
PUSH_FIELD_VALUE (cons, "static_field_count",
build_int_2 (static_field_count, 0));
--- 1676,1687 ----
fields_decl == NULL_TREE ? null_pointer_node
: build1 (ADDR_EXPR, field_ptr_type_node, fields_decl));
! /* If we're using the binary compatibility ABI we don't know the
! size until load time. */
! PUSH_FIELD_VALUE (cons, "size_in_bytes",
! (flag_indirect_dispatch
! ? integer_minus_one_node
! : size_in_bytes (type)));
! PUSH_FIELD_VALUE (cons, "field_count",
! build_int_2 (field_count, 0));
PUSH_FIELD_VALUE (cons, "static_field_count",
build_int_2 (static_field_count, 0));
*************** make_class_data (tree type)
*** 1729,1732 ****
--- 1749,1756 ----
rest_of_decl_compilation (decl, (char*) 0, 1, 0);
+
+ TYPE_OTABLE_DECL (type) = NULL_TREE;
+ TYPE_ATABLE_DECL (type) = NULL_TREE;
+ TYPE_CTABLE_DECL (type) = NULL_TREE;
}
*************** layout_class_method (tree this_class, tr
*** 2177,2181 ****
tree super_method = lookup_argument_method (super_class, method_name,
method_sig);
! if (super_method != NULL_TREE && ! METHOD_PRIVATE (super_method))
{
DECL_VINDEX (method_decl) = DECL_VINDEX (super_method);
--- 2201,2206 ----
tree super_method = lookup_argument_method (super_class, method_name,
method_sig);
! if (super_method != NULL_TREE && ! METHOD_PRIVATE (super_method)
! && ! DECL_ARTIFICIAL (super_method))
{
DECL_VINDEX (method_decl) = DECL_VINDEX (super_method);
Index: gcc/java/except.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/except.c,v
retrieving revision 1.42
diff -p -2 -c -w -r1.42 except.c
Index: gcc/java/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.185
diff -p -2 -c -w -r1.185 expr.c
*** gcc/java/expr.c 30 Mar 2004 19:19:06 -0000 1.185
--- gcc/java/expr.c 16 Apr 2004 12:29:44 -0000
*************** pop_type_0 (tree type, char **messagep)
*** 314,317 ****
--- 314,332 ----
if (type == NULL_TREE || t == type)
return t;
+ if (TREE_CODE (t) == TREE_LIST)
+ {
+ do
+ {
+ tree tt = TREE_PURPOSE (t);
+ if (! can_widen_reference_to (tt, type))
+ {
+ t = tt;
+ goto fail;
+ }
+ t = TREE_CHAIN (t);
+ }
+ while (t);
+ return t;
+ }
if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (t)
&& TYPE_PRECISION (type) <= 32 && TYPE_PRECISION (t) <= 32)
*************** pop_type_0 (tree type, char **messagep)
*** 332,337 ****
--- 347,362 ----
}
+ if (! flag_verify_invocations && flag_indirect_dispatch
+ && t == object_ptr_type_node)
+ {
+ if (type != ptr_type_node)
+ warning ("need to insert runtime check for %s",
+ xstrdup (lang_printable_name (type, 0)));
+ return type;
+ }
+
/* lang_printable_name uses a static buffer, so we must save the result
from calling it the first time. */
+ fail:
{
char *temp = xstrdup (lang_printable_name (type, 0));
*************** can_widen_reference_to (tree source_type
*** 378,381 ****
--- 403,414 ----
if (source_type == target_type)
return 1;
+
+ if (TYPE_DUMMY (source_type) || TYPE_DUMMY (target_type))
+ {
+ warning ("assert: %s is assign compatible with %s",
+ xstrdup (lang_printable_name (target_type, 0)),
+ xstrdup (lang_printable_name (source_type, 0)));
+ return 1;
+ }
else
{
*************** can_widen_reference_to (tree source_type
*** 411,414 ****
--- 444,454 ----
int target_depth = class_depth (target_type);
+ if (TYPE_DUMMY (source_type) || TYPE_DUMMY (target_type))
+ {
+ warning ("assert: %s is assign compatible with %s",
+ xstrdup (lang_printable_name (target_type, 0)),
+ xstrdup (lang_printable_name (source_type, 0)));
+ return 1;
+ }
/* class_depth can return a negative depth if an error occurred */
if (source_depth < 0 || target_depth < 0)
*************** bool class_has_finalize_method (tree typ
*** 1139,1158 ****
}
static void
expand_java_NEW (tree type)
{
- tree alloc_node;
-
- alloc_node = (class_has_finalize_method (type) ? alloc_object_node
- : alloc_no_finalizer_node);
if (! CLASS_LOADED_P (type))
load_class (type, 1);
safe_layout_class (type);
! push_value (build (CALL_EXPR, promote_type (type),
! build_address_of (alloc_node),
! tree_cons (NULL_TREE, build_class_ref (type),
! build_tree_list (NULL_TREE,
! size_in_bytes (type))),
! NULL_TREE));
}
--- 1179,1204 ----
}
+ tree
+ java_create_object (tree type)
+ {
+ tree alloc_node = (class_has_finalize_method (type)
+ ? alloc_object_node
+ : alloc_no_finalizer_node);
+ tree size = flag_indirect_dispatch ? integer_zero_node : size_in_bytes (type);
+
+ return build (CALL_EXPR, promote_type (type),
+ build_address_of (alloc_node),
+ tree_cons (NULL_TREE, build_class_ref (type),
+ build_tree_list (NULL_TREE, size)),
+ NULL_TREE);
+ }
+
static void
expand_java_NEW (tree type)
{
if (! CLASS_LOADED_P (type))
load_class (type, 1);
safe_layout_class (type);
! push_value (java_create_object (type));
}
*************** build_field_ref (tree self_value, tree s
*** 1512,1521 ****
if (base_type != TREE_TYPE (self_value))
self_value = fold (build1 (NOP_EXPR, base_type, self_value));
! if (flag_indirect_dispatch
! && output_class != self_class)
! /* FIXME: output_class != self_class is not exactly the right
! test. What we really want to know is whether self_class is
! in the same translation unit as output_class. If it is,
! we can make a direct reference. */
{
tree otable_index =
--- 1558,1568 ----
if (base_type != TREE_TYPE (self_value))
self_value = fold (build1 (NOP_EXPR, base_type, self_value));
! if (! flag_syntax_only
! && (flag_indirect_dispatch
! /* DECL_FIELD_OFFSET == 0 if we have no reference for
! the field, perhaps because we couldn't find the class
! in which the field is defined.
! FIXME: We should investigate this. */
! || DECL_FIELD_OFFSET (field_decl) == 0))
{
tree otable_index =
*************** build_known_method_ref (tree method, tre
*** 1768,1773 ****
if (is_compiled_class (self_type))
{
! if (!flag_indirect_dispatch
! || (!TREE_PUBLIC (method) && DECL_CONTEXT (method)))
{
make_decl_rtl (method, NULL);
--- 1815,1828 ----
if (is_compiled_class (self_type))
{
! /* At one point I used
!
! (!TREE_PUBLIC (method) && DECL_CONTEXT (method)))
!
! here, meaning that we would make a direct call to methods that
! are in the current compilation unit and not public. That ought
! to work, right? Wrong. Unfortunately, for some reason we still
! generate a PLT jump for such methods, and they can end up being
! resolved in some other library. Sigh. */
! if (!flag_indirect_dispatch)
{
make_decl_rtl (method, NULL);
*************** expand_invoke (int opcode, int method_re
*** 2029,2032 ****
--- 2084,2089 ----
if (method == NULL_TREE)
{
+ if (flag_verify_invocations || ! flag_indirect_dispatch)
+ {
error ("class '%s' has no method named '%s' matching signature '%s'",
self_name,
*************** expand_invoke (int opcode, int method_re
*** 2034,2039 ****
IDENTIFIER_POINTER (method_signature));
}
/* Invoke static can't invoke static/abstract method */
! else if (opcode == OPCODE_invokestatic)
{
if (!METHOD_STATIC (method))
--- 2091,2116 ----
IDENTIFIER_POINTER (method_signature));
}
+ else
+ {
+ int flags = ACC_PUBLIC;
+ if (opcode == OPCODE_invokestatic)
+ flags |= ACC_STATIC;
+ if (opcode == OPCODE_invokeinterface)
+ {
+ flags |= ACC_INTERFACE;
+ CLASS_INTERFACE (TYPE_NAME (self_type)) = 1;
+ }
+ method = add_method (self_type, flags, method_name, method_signature);
+ DECL_ARTIFICIAL (method) = 1;
+ METHOD_DUMMY (method) = 1;
+ layout_class_method (self_type, NULL,
+ method, NULL);
+ }
+ }
+
/* Invoke static can't invoke static/abstract method */
! if (method != NULL_TREE)
! {
! if (opcode == OPCODE_invokestatic)
{
if (!METHOD_STATIC (method))
*************** expand_invoke (int opcode, int method_re
*** 2056,2059 ****
--- 2133,2137 ----
}
}
+ }
if (method == NULL_TREE)
*************** expand_java_field_op (int is_static, int
*** 2336,2340 ****
COMPONENT_REF_CLASS_INDEX (¤t_jcf->cpool,
field_ref_index));
! const char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
tree field_name = COMPONENT_REF_NAME (¤t_jcf->cpool, field_ref_index);
tree field_signature = COMPONENT_REF_SIGNATURE (¤t_jcf->cpool,
--- 2414,2419 ----
COMPONENT_REF_CLASS_INDEX (¤t_jcf->cpool,
field_ref_index));
! const char *self_name =
! IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
tree field_name = COMPONENT_REF_NAME (¤t_jcf->cpool, field_ref_index);
tree field_signature = COMPONENT_REF_SIGNATURE (¤t_jcf->cpool,
*************** expand_java_field_op (int is_static, int
*** 2344,2347 ****
--- 2423,2427 ----
tree field_ref;
int is_error = 0;
+ tree original_self_type = self_type;
tree field_decl = lookup_field (&self_type, field_name);
if (field_decl == error_mark_node)
*************** expand_java_field_op (int is_static, int
*** 2351,2357 ****
--- 2431,2451 ----
else if (field_decl == NULL_TREE)
{
+ if (! flag_verify_invocations)
+ {
+ int flags = ACC_PUBLIC;
+ if (is_static)
+ flags |= ACC_STATIC;
+ self_type = original_self_type;
+ field_decl = add_field (original_self_type, field_name,
+ field_type, flags);
+ DECL_ARTIFICIAL (field_decl) = 1;
+ DECL_IGNORED_P (field_decl) = 1;
+ }
+ else
+ {
error ("missing field '%s' in '%s'",
IDENTIFIER_POINTER (field_name), self_name);
is_error = 1;
+ }
}
else if (build_java_signature (TREE_TYPE (field_decl)) != field_signature)
Index: gcc/java/java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.197
diff -p -2 -c -w -r1.197 java-tree.h
*** gcc/java/java-tree.h 19 Mar 2004 23:10:55 -0000 1.197
--- gcc/java/java-tree.h 16 Apr 2004 12:29:45 -0000
*************** extern GTY(()) struct JCF * current_jcf;
*** 245,248 ****
--- 245,250 ----
extern int always_initialize_class_p;
+ extern int flag_verify_invocations;
+
typedef struct CPool constant_pool;
*************** struct lang_decl_func GTY(())
*** 990,993 ****
--- 992,996 ----
internally but which shouldn't be
written to the .class file. */
+ unsigned int dummy:1;
};
*************** struct lang_decl GTY(())
*** 1048,1051 ****
--- 1051,1057 ----
/* The decl of the synthetic method `class$' used to handle `.class'
for non primitive types when compiling to bytecode. */
+
+ #define TYPE_DUMMY(T) (TYPE_LANG_SPECIFIC(T)->dummy_class)
+
#define TYPE_DOT_CLASS(T) (TYPE_LANG_SPECIFIC (T)->dot_class)
#define TYPE_PACKAGE_LIST(T) (TYPE_LANG_SPECIFIC (T)->package_list)
*************** struct lang_type GTY(())
*** 1109,1112 ****
--- 1115,1119 ----
unsigned strictfp:1; /* `strictfp' class. */
unsigned assertions:1; /* Any method uses `assert'. */
+ unsigned dummy_class:1; /* Not a real class, just a placeholder. */
};
*************** extern void load_type_state (tree);
*** 1272,1275 ****
--- 1279,1283 ----
extern void add_interface (tree, tree);
extern tree force_evaluation_order (tree);
+ extern tree java_create_object (tree);
extern int verify_constant_pool (struct JCF *);
extern void start_java_method (tree);
*************** extern void gen_indirect_dispatch_tables
*** 1353,1356 ****
--- 1361,1366 ----
/* Access flags etc for a method (a FUNCTION_DECL): */
+
+ #define METHOD_DUMMY(DECL) (DECL_LANG_SPECIFIC (DECL)->u.f.dummy)
#define METHOD_PUBLIC(DECL) DECL_LANG_FLAG_1 (FUNCTION_DECL_CHECK (DECL))
Index: gcc/java/jcf-parse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-parse.c,v
retrieving revision 1.158
diff -p -2 -c -w -r1.158 jcf-parse.c
*** gcc/java/jcf-parse.c 29 Feb 2004 14:09:58 -0000 1.158
--- gcc/java/jcf-parse.c 16 Apr 2004 12:29:45 -0000
*************** load_class (tree class_or_name, int verb
*** 567,570 ****
--- 567,575 ----
int class_loaded;
+ /* We've already failed, don't try again. */
+ if (TREE_CODE (class_or_name) == RECORD_TYPE
+ && TYPE_DUMMY (class_or_name))
+ return;
+
/* class_or_name can be the name of the class we want to load */
if (TREE_CODE (class_or_name) == IDENTIFIER_NODE)
*************** load_class (tree class_or_name, int verb
*** 601,607 ****
}
! if (!class_loaded && verbose)
error ("cannot find file for class %s", IDENTIFIER_POINTER (saved));
}
/* Parse the .class file JCF. */
--- 606,634 ----
}
! if (!class_loaded)
! {
! if (flag_verify_invocations || ! flag_indirect_dispatch
! || flag_emit_class_files)
! {
! if (verbose)
error ("cannot find file for class %s", IDENTIFIER_POINTER (saved));
}
+ else if (verbose)
+ {
+ /* This is just a diagnostic during testing, not a real problem. */
+ warning("cannot find file for class %s",
+ IDENTIFIER_POINTER (saved));
+
+ /* Fake it. */
+ if (TREE_CODE (class_or_name) == RECORD_TYPE)
+ {
+ set_super_info (0, class_or_name, object_type_node, 0);
+ TYPE_DUMMY (class_or_name) = 1;
+ /* We won't be able to output any debug info for this class. */
+ DECL_IGNORED_P (TYPE_NAME (class_or_name)) = 1;
+ }
+ }
+ }
+ }
/* Parse the .class file JCF. */
*************** parse_class_file (void)
*** 717,721 ****
JCF *jcf = current_jcf;
! if (METHOD_ABSTRACT (method))
continue;
--- 744,748 ----
JCF *jcf = current_jcf;
! if (METHOD_ABSTRACT (method) || METHOD_DUMMY (method))
continue;
Index: gcc/java/lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/lang.c,v
retrieving revision 1.151
diff -p -2 -c -w -r1.151 lang.c
*** gcc/java/lang.c 20 Mar 2004 14:03:34 -0000 1.151
--- gcc/java/lang.c 16 Apr 2004 12:29:45 -0000
*************** int flag_optimize_sci = 1;
*** 181,184 ****
--- 181,187 ----
int flag_indirect_dispatch = 0;
+ /* Don't attempt to verify invocations. */
+ int flag_verify_invocations = 0;
+
/* When zero, don't generate runtime array store checks. */
int flag_store_check = 1;
*************** java_get_callee_fndecl (tree call_expr)
*** 1252,1255 ****
--- 1255,1262 ----
HOST_WIDE_INT index;
+
+ /* FIXME: This is disabled because we end up passing calls through
+ the PLT, and we do NOT want to do that. */
+ return NULL;
if (TREE_CODE (call_expr) != CALL_EXPR)
Index: gcc/java/parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.474
diff -p -2 -c -w -r1.474 parse.y
*** gcc/java/parse.y 19 Mar 2004 23:10:55 -0000 1.474
--- gcc/java/parse.y 16 Apr 2004 12:29:50 -0000
*************** patch_invoke (tree patch, tree method, t
*** 10859,10872 ****
if (!TYPE_SIZE (class))
safe_layout_class (class);
! size = size_in_bytes (class);
! alloc_node =
! (class_has_finalize_method (class) ? alloc_object_node
! : alloc_no_finalizer_node);
! new = build (CALL_EXPR, promote_type (class),
! build_address_of (alloc_node),
! tree_cons (NULL_TREE, build_class_ref (class),
! build_tree_list (NULL_TREE,
! size_in_bytes (class))),
! NULL_TREE);
saved_new = save_expr (new);
c1 = build_tree_list (NULL_TREE, saved_new);
--- 10859,10863 ----
if (!TYPE_SIZE (class))
safe_layout_class (class);
! new = java_create_object (class);
saved_new = save_expr (new);
c1 = build_tree_list (NULL_TREE, saved_new);
Index: gcc/java/verify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/verify.c,v
retrieving revision 1.59
diff -p -2 -c -w -r1.59 verify.c
*** gcc/java/verify.c 20 Dec 2003 15:38:28 -0000 1.59
--- gcc/java/verify.c 16 Apr 2004 12:29:50 -0000
*************** check_pending_block (tree target_label)
*** 85,90 ****
if (current_subr == NULL)
{
! if (LABEL_IN_SUBR (target_label))
! return "might transfer control into subroutine";
}
else
--- 85,90 ----
if (current_subr == NULL)
{
! /* if (LABEL_IN_SUBR (target_label)) */
! /* return "might transfer control into subroutine"; */
}
else
*************** check_pending_block (tree target_label)
*** 92,97 ****
if (LABEL_IN_SUBR (target_label))
{
! if (LABEL_SUBR_START (target_label) != current_subr)
! return "transfer out of subroutine";
}
else if (! LABEL_VERIFIED (target_label))
--- 92,97 ----
if (LABEL_IN_SUBR (target_label))
{
! /* if (LABEL_SUBR_START (target_label) != current_subr) */
! /* return "transfer out of subroutine"; */
}
else if (! LABEL_VERIFIED (target_label))
*************** check_pending_block (tree target_label)
*** 100,105 ****
LABEL_SUBR_START (target_label) = current_subr;
}
! else
! return "transfer out of subroutine";
}
return NULL;
--- 100,105 ----
LABEL_SUBR_START (target_label) = current_subr;
}
! /* else */
! /* return "transfer out of subroutine"; */
}
return NULL;
*************** subroutine_nesting (tree label)
*** 122,125 ****
--- 122,177 ----
}
+ static tree
+ defer_merging (tree type1, tree type2)
+ {
+ if (TYPE_DUMMY (type1) || TYPE_DUMMY (type2))
+ {
+ warning ("assert: cannot merge types %s and %s",
+ xstrdup (lang_printable_name (type1, 0)),
+ xstrdup (lang_printable_name (type2, 0)));
+ }
+
+ return object_ptr_type_node;
+
+ if (TREE_CODE (type1) == POINTER_TYPE)
+ type1 = TREE_TYPE (type1);
+ if (TREE_CODE (type2) == POINTER_TYPE)
+ type2 = TREE_TYPE (type2);
+
+ if (TREE_CODE (type1) == RECORD_TYPE && TREE_CODE (type2) == RECORD_TYPE)
+ {
+ tree list = build_tree_list (type1, NULL_TREE);
+ list = tree_cons (type2, NULL_TREE, list);
+ return list;
+ }
+
+ if (TREE_CODE (type1) == TREE_LIST && TREE_CODE (type2) == TREE_LIST)
+ {
+ return chainon (copy_list (type1), copy_list (type2));
+ }
+
+ if (TREE_CODE (type1) == TREE_LIST && TREE_CODE (type2) == RECORD_TYPE)
+ {
+ tree tmp = type1;
+ do
+ {
+ if (TREE_PURPOSE (tmp) == type2)
+ return type1;
+ tmp = TREE_CHAIN (tmp);
+ }
+ while (tmp);
+
+ return tree_cons (type2, NULL_TREE, copy_list (type1));
+ }
+
+ if (TREE_CODE (type2) == TREE_LIST && TREE_CODE (type1) == RECORD_TYPE)
+ {
+ return defer_merging (type2, type1);
+ }
+
+ abort ();
+ }
+
+
/* Return the "merged" types of TYPE1 and TYPE2.
If either is primitive, the other must match (after promotion to int).
*************** merge_types (tree type1, tree type2)
*** 135,138 ****
--- 187,194 ----
|| type1 == TYPE_RETURN_ADDR || type2 == TYPE_RETURN_ADDR)
return TYPE_UNKNOWN;
+
+ if (TREE_CODE (type1) == TREE_LIST || TREE_CODE (type2) == TREE_LIST)
+ return defer_merging (type1, type2);
+
if (TREE_CODE (type1) == POINTER_TYPE && TREE_CODE (type2) == POINTER_TYPE)
{
*************** merge_types (tree type1, tree type2)
*** 149,152 ****
--- 205,211 ----
tt2 = TREE_TYPE (type2);
+ if (TYPE_DUMMY (tt1) || TYPE_DUMMY (tt2))
+ return defer_merging (tt1, tt2);
+
/* If tt{1,2} haven't been properly loaded, now is a good time
to do it. */
*************** verify_jvm_instructions (JCF* jcf, const
*** 651,654 ****
--- 710,715 ----
("invalid local variable index %d in load");
tmp = type_map[index];
+ if (TREE_CODE (tmp) != TREE_LIST)
+ {
if (tmp == TYPE_UNKNOWN)
VERIFICATION_ERROR_WITH_INDEX
*************** verify_jvm_instructions (JCF* jcf, const
*** 664,667 ****
--- 725,729 ----
VERIFICATION_ERROR_WITH_INDEX
("loading local variable %d which has invalid type");
+ }
PUSH_TYPE (tmp);
goto note_used;
*************** verify_jvm_instructions (JCF* jcf, const
*** 1024,1027 ****
--- 1086,1094 ----
if (! CLASS_LOADED_P (self_type))
load_class (self_type, 1);
+
+ if (TYPE_DUMMY (self_type) && op_code == OPCODE_invokeinterface)
+ /* Assume we are an interface. */
+ CLASS_INTERFACE (TYPE_NAME (self_type)) = 1;
+
self_is_interface = CLASS_INTERFACE (TYPE_NAME (self_type));
method_name = COMPONENT_REF_NAME (¤t_jcf->cpool, index);
*************** verify_jvm_instructions (JCF* jcf, const
*** 1058,1061 ****
--- 1125,1129 ----
VERIFICATION_ERROR
("invalid argument number in invokeinterface");
+
/* If we verify/resolve the constant pool, as we should,
this test (and the one just following) are redundant. */