diff options
author | bryce <bryce@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-03-23 01:49:11 +0000 |
---|---|---|
committer | bryce <bryce@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-03-23 01:49:11 +0000 |
commit | 15672c9634de58077b260f0d24a526daba66b443 (patch) | |
tree | a8d88ecaa8d7079c04633b077af8f67b170c519a /gcc/cp/call.c | |
parent | 49604b5b4703e6a8851ad6b82ccd05597c1dd299 (diff) | |
download | gcc-15672c9634de58077b260f0d24a526daba66b443.tar.gz |
2001-03-23 Bryce McKinlay <bryce@albatross.co.nz>
* extend.texi: Document the "java_interface" attribute.
java/:
2001-03-21 Bryce McKinlay <bryce@albatross.co.nz>
* gjavah.c (process_file): Mark interface definitions with
"__attribute__ ((java_interface))".
cp/:
2001-03-22 Bryce McKinlay <bryce@albatross.co.nz>
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@40769 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/call.c')
-rw-r--r-- | gcc/cp/call.c | 72 |
1 files changed, 71 insertions, 1 deletions
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. */ |