From 60c8748279c9a6b30aa8e370a8328ee8a9909792 Mon Sep 17 00:00:00 2001 From: Bryce McKinlay Date: Fri, 23 Mar 2001 01:49:11 +0000 Subject: [PATCH] [multiple changes] 2001-03-23 Bryce McKinlay * extend.texi: Document the "java_interface" attribute. java/: 2001-03-21 Bryce McKinlay * gjavah.c (process_file): Mark interface definitions with "__attribute__ ((java_interface))". cp/: 2001-03-22 Bryce McKinlay Add support for Java interface method calls. * cp-tree.h (struct lang_type): Add java_interface flag. (TYPE_JAVA_INTERFACE): New macro. * tree.c (cp_valid_lang_attribute): Handle "java_interface" attribute by setting TYPE_JAVA_INTERFACE. * call.c (java_iface_lookup_fn): New static. (build_over_call): If calling a method declared in a TYPE_JAVA_INTERFACE, call build_java_interface_fn_ref to generate the expression which resolves the function address. (build_java_interface_fn_ref): New function. From-SVN: r40769 --- gcc/ChangeLog | 4 +++ gcc/cp/ChangeLog | 13 +++++++++ gcc/cp/call.c | 72 +++++++++++++++++++++++++++++++++++++++++++++- gcc/cp/cp-tree.h | 7 ++++- gcc/cp/tree.c | 13 +++++++++ gcc/extend.texi | 8 ++++++ gcc/java/ChangeLog | 5 ++++ gcc/java/gjavah.c | 7 ++++- 8 files changed, 126 insertions(+), 3 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 07dcc2f4b51..e733bfd5e8c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2001-03-23 Bryce McKinlay + + * extend.texi: Document the "java_interface" attribute. + 2001-03-22 Zack Weinberg * mkconfig.sh: Use a subshell with redirected stdout, diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7eb92b2f097..e85d6b85290 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2001-03-22 Bryce McKinlay + + Add support for Java interface method calls. + * cp-tree.h (struct lang_type): Add java_interface flag. + (TYPE_JAVA_INTERFACE): New macro. + * tree.c (cp_valid_lang_attribute): Handle "java_interface" attribute + by setting TYPE_JAVA_INTERFACE. + * call.c (java_iface_lookup_fn): New static. + (build_over_call): If calling a method declared in a + TYPE_JAVA_INTERFACE, call build_java_interface_fn_ref to generate the + expression which resolves the function address. + (build_java_interface_fn_ref): New function. + 2001-03-22 Richard Henderson * Make-lang.in (cp/except.o): Don't depend on insn-flags.h. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 13827c9d1c4..0850f9b8048 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -45,6 +45,7 @@ static int equal_functions PARAMS ((tree, tree)); static int joust PARAMS ((struct z_candidate *, struct z_candidate *, int)); static int compare_ics PARAMS ((tree, tree)); static tree build_over_call PARAMS ((struct z_candidate *, tree, int)); +static tree build_java_interface_fn_ref PARAMS ((tree, tree)); #define convert_like(CONV, EXPR) convert_like_real (CONV, EXPR, NULL_TREE, 0, 0) #define convert_like_with_context(CONV, EXPR, FN, ARGNO) convert_like_real (CONV, EXPR, FN, ARGNO, 0) static tree convert_like_real PARAMS ((tree, tree, tree, int, int)); @@ -4271,7 +4272,10 @@ build_over_call (cand, args, flags) if (TREE_SIDE_EFFECTS (*p)) *p = save_expr (*p); t = build_pointer_type (TREE_TYPE (fn)); - fn = build_vfn_ref (p, build_indirect_ref (*p, 0), DECL_VINDEX (fn)); + if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn))) + fn = build_java_interface_fn_ref (fn, *p); + else + fn = build_vfn_ref (p, build_indirect_ref (*p, 0), DECL_VINDEX (fn)); TREE_TYPE (fn) = t; } else if (DECL_INLINE (fn)) @@ -4306,6 +4310,72 @@ build_over_call (cand, args, flags) return convert_from_reference (fn); } +static tree java_iface_lookup_fn; + +/* Make an expression which yields the address of the Java interface + method FN. This is achieved by generating a call to libjava's + _Jv_LookupInterfaceMethodIdx(). */ + +static tree +build_java_interface_fn_ref (fn, instance) + tree fn, instance; +{ + tree lookup_args, lookup_fn, method, idx; + tree klass_ref, iface, iface_ref; + int i; + + if (!java_iface_lookup_fn) + { + tree endlink = build_void_list_node (); + tree t = tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, java_int_type_node, + endlink))); + java_iface_lookup_fn + = builtin_function ("_Jv_LookupInterfaceMethodIdx", + build_function_type (ptr_type_node, t), + 0, NOT_BUILT_IN, NULL_PTR); + ggc_add_tree_root (&java_iface_lookup_fn, 1); + } + + /* Look up the pointer to the runtime java.lang.Class object for `instance'. + This is the first entry in the vtable. */ + klass_ref = build_vtbl_ref (build_indirect_ref (instance, 0), + integer_zero_node); + + /* Get the java.lang.Class pointer for the interface being called. */ + iface = DECL_CONTEXT (fn); + iface_ref = lookup_field (iface, get_identifier ("class$"), 0, 0); + if (!iface_ref || TREE_CODE (iface_ref) != VAR_DECL + || DECL_CONTEXT (iface_ref) != iface) + { + cp_error ("Could not find class$ field in java interface type `%T'", + iface); + return error_mark_node; + } + iface_ref = build1 (ADDR_EXPR, build_pointer_type (iface), iface_ref); + + /* Determine the itable index of FN. */ + i = 1; + for (method = TYPE_METHODS (iface); method; method = TREE_CHAIN (method)) + { + if (!DECL_VIRTUAL_P (method)) + continue; + if (fn == method) + break; + i++; + } + idx = build_int_2 (i, 0); + + lookup_args = tree_cons (NULL_TREE, klass_ref, + tree_cons (NULL_TREE, iface_ref, + build_tree_list (NULL_TREE, idx))); + lookup_fn = build1 (ADDR_EXPR, + build_pointer_type (TREE_TYPE (java_iface_lookup_fn)), + java_iface_lookup_fn); + return build (CALL_EXPR, ptr_type_node, lookup_fn, lookup_args, NULL_TREE); +} + /* Returns the value to use for the in-charge parameter when making a call to a function with the indicated NAME. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index de63fb1813a..f8dd6928f34 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1326,6 +1326,7 @@ struct lang_type unsigned has_abstract_assign_ref : 1; unsigned non_aggregate : 1; unsigned is_partial_instantiation : 1; + unsigned java_interface : 1; /* When adding a flag here, consider whether or not it ought to apply to a template instance if it applies to the template. If @@ -1334,7 +1335,7 @@ struct lang_type /* There are some bits left to fill out a 32-bit word. Keep track of this by updating the size of this bitfield whenever you add or remove a flag. */ - unsigned dummy : 9; + unsigned dummy : 8; int vsize; @@ -1556,6 +1557,10 @@ struct lang_type #define CLASSTYPE_ALIGN_UNIT(NODE) \ (CLASSTYPE_ALIGN (NODE) / BITS_PER_UNIT) +/* True if this a Java interface type, declared with + '__attribute__ ((java_interface))'. */ +#define TYPE_JAVA_INTERFACE(NODE) (TYPE_LANG_SPECIFIC(NODE)->java_interface) + /* A cons list of virtual functions which cannot be inherited by derived classes. When deriving from this type, the derived class must provide its own definition for each of these functions. */ diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 93e12beeaf5..3023e8fbf2f 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -2212,6 +2212,19 @@ cp_valid_lang_attribute (attr_name, attr_args, decl, type) tree decl ATTRIBUTE_UNUSED; tree type ATTRIBUTE_UNUSED; { + if (is_attribute_p ("java_interface", attr_name)) + { + if (attr_args != NULL_TREE + || decl != NULL_TREE + || ! CLASS_TYPE_P (type) + || ! TYPE_FOR_JAVA (type)) + { + error ("`java_interface' attribute can only be applied to Java class definitions"); + return 0; + } + TYPE_JAVA_INTERFACE (type) = 1; + return 1; + } if (is_attribute_p ("com_interface", attr_name)) { if (! flag_vtable_thunks) diff --git a/gcc/extend.texi b/gcc/extend.texi index 3319cca9235..49fe3192d52 100644 --- a/gcc/extend.texi +++ b/gcc/extend.texi @@ -4355,6 +4355,14 @@ changed to be COM-compliant. Also, all classes and structs derived from one marked with this attribute are implicitly marked with the same attribute; thus, only the base class in a COM hierarchy needs @code{com_interface}. +@item java_interface +@cindex java_interface attribute + +This type attribute informs C++ that the class is a Java interface. It may +only be applied to classes declared within an @code{extern "Java"} block. +Calls to methods declared in this interface will be dispatched using GCJ's +interface table mechanism, instead of regular virtual table dispatch. + @end table @node Deprecated Features diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 6a23f8e6b7e..d7d0e77a43c 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,8 @@ +2001-03-21 Bryce McKinlay + + * gjavah.c (process_file): Mark interface definitions with + "__attribute__ ((java_interface))". + 2001-03-21 Alexandre Petit-Bianco * class.c (layout_class): Fixed push_super_field's second diff --git a/gcc/java/gjavah.c b/gcc/java/gjavah.c index 809ccf4bd2a..7f6084955a1 100644 --- a/gcc/java/gjavah.c +++ b/gcc/java/gjavah.c @@ -1857,7 +1857,12 @@ DEFUN(process_file, (jcf, out), generate_access (out, ACC_PUBLIC); fprintf (out, "\n static ::java::lang::Class class$;\n"); - fputs ("};\n", out); + fputs ("}", out); + + if (jcf->access_flags & ACC_INTERFACE) + fputs (" __attribute__ ((java_interface))", out); + + fputs (";\n", out); if (append_count > 0) fputc ('\n', out); -- 2.30.2