This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Re: how do I stop gcjh from generating function bodies?
[Get raw message]
Works like a charm; commit it!
- a
Tom Tromey <tromey@redhat.com> writes:
> >>>>> "Adam" == Adam Megacz <gcj@lists.megacz.com> writes:
>
> Adam> public class C implements I {
> Adam> public I returnSelfAsI() { return this; }
> Adam> }
>
> Adam> ...but gcjh generates a body for it in the .h file, except that
> Adam> CNI doesn't grok interfaces, so the generated .h doesn't compile
>
> Thanks again for finding this.
> I wrote a patch to gcjh which should fix this bug.
> Could you try it out?
> It is appended. If it works for you I will check it in.
>
> Tom
>
> 2001-11-12 Tom Tromey <tromey@redhat.com>
>
> * gjavah.c (method_signature): New global.
> (HANDLE_METHOD): Set it.
> (decompile_return_statement): New function.
> (decompile_method): Use it.
> (print_method_info): Removed `synth' argument.
>
> Index: gjavah.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/java/gjavah.c,v
> retrieving revision 1.74
> diff -u -r1.74 gjavah.c
> --- gjavah.c 2001/10/22 03:58:19 1.74
> +++ gjavah.c 2001/11/12 21:05:30
> @@ -120,7 +120,7 @@
> static void print_field_info PARAMS ((FILE*, JCF*, int, int, JCF_u2));
> static void print_mangled_classname PARAMS ((FILE*, JCF*, const char*, int));
> static int print_cxx_classname PARAMS ((FILE*, const char*, JCF*, int));
> -static void print_method_info PARAMS ((FILE*, JCF*, int, int, JCF_u2, int));
> +static void print_method_info PARAMS ((FILE*, JCF*, int, int, JCF_u2));
> static void print_c_decl PARAMS ((FILE*, JCF*, int, int, int, const char *,
> int));
> static void print_stub_or_jni PARAMS ((FILE*, JCF*, int, int, int,
> @@ -151,6 +151,7 @@
> static int overloaded_jni_method_exists_p PARAMS ((const unsigned char *, int,
> const char *, int));
> static void jni_print_char PARAMS ((FILE *, int));
> +static void decompile_return_statement PARAMS ((FILE *, JCF *, int, int, int));
>
> JCF_u2 current_field_name;
> JCF_u2 current_field_value;
> @@ -187,9 +188,12 @@
> static int method_access = 0;
> static int method_printed = 0;
> static int method_synthetic = 0;
> +static int method_signature = 0;
> +
> #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
> { \
> method_synthetic = 0; \
> + method_signature = SIGNATURE; \
> if (ATTRIBUTE_COUNT) \
> method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
> (const char *)"Synthetic", 9); \
> @@ -207,12 +211,12 @@
> decompiled = 0; method_printed = 0; \
> if (out) \
> print_method_info (out, jcf, NAME, SIGNATURE, \
> - ACCESS_FLAGS, method_synthetic); \
> + ACCESS_FLAGS); \
> } \
> else if (!method_synthetic) \
> { \
> print_method_info (NULL, jcf, NAME, SIGNATURE, \
> - ACCESS_FLAGS, method_synthetic); \
> + ACCESS_FLAGS); \
> if (! stubs && ! flag_jni) \
> add_class_decl (out, jcf, SIGNATURE); \
> } \
> @@ -784,9 +788,9 @@
>
>
> static void
> -DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags, synth),
> +DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
> FILE *stream AND JCF* jcf
> - AND int name_index AND int sig_index AND JCF_u2 flags AND int synth)
> + AND int name_index AND int sig_index AND JCF_u2 flags)
> {
> const unsigned char *str;
> int length, is_init = 0;
> @@ -799,10 +803,6 @@
> str = JPOOL_UTF_DATA (jcf, name_index);
> length = JPOOL_UTF_LENGTH (jcf, name_index);
>
> - /* Ignore synthetic methods. */
> - if (synth)
> - return;
> -
> if (str[0] == '<')
> {
> /* Ignore the internally generated method <clinit>. However,
> @@ -892,6 +892,132 @@
> free (override);
> }
>
> +/* A helper for the decompiler which prints a `return' statement where
> + the type is a reference type. If METHODTYPE and OBJECTTYPE are not
> + identical, we emit a cast. We do this because the C++ compiler
> + doesn't know that a reference can be cast to the type of an
> + interface it implements. METHODTYPE is the index of the method's
> + signature. NAMEINDEX is the index of the field name; -1 for
> + `this'. OBJECTTYPE is the index of the object's type. */
> +static void
> +decompile_return_statement (out, jcf, methodtype, nameindex, objecttype)
> + FILE *out;
> + JCF *jcf;
> + int methodtype, nameindex, objecttype;
> +{
> + int cast = 0;
> + int obj_name_len, method_name_len;
> + const unsigned char *obj_data, *method_data;
> +
> + obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
> + obj_data = JPOOL_UTF_DATA (jcf, objecttype);
> +
> + method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
> + method_data = JPOOL_UTF_DATA (jcf, methodtype);
> +
> + /* Skip forward to return type part of method. */
> + while (*method_data != ')')
> + {
> + ++method_data;
> + --method_name_len;
> + }
> + /* Skip past `)'. */
> + ++method_data;
> + --method_name_len;
> +
> + /* If we see an `L', skip it and the trailing `;'. */
> + if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
> + {
> + ++method_data;
> + method_name_len -= 2;
> + }
> + if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
> + {
> + ++obj_data;
> + obj_name_len -= 2;
> + }
> +
> + /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
> + need a cast. Right now there is no way to determine if this is
> + the case. */
> + if (method_name_len != obj_name_len)
> + cast = 1;
> + else
> + {
> + int i;
> + for (i = 0; i < method_name_len; ++i)
> + {
> + if (method_data[i] != obj_data[i])
> + {
> + cast = 1;
> + break;
> + }
> + }
> + }
> +
> + fputs (" { return ", out);
> +
> + if (cast)
> + {
> + int array_depth = 0;
> + const unsigned char *limit;
> +
> + fputs ("reinterpret_cast<", out);
> +
> + while (*method_data == '[')
> + {
> + ++method_data;
> + ++array_depth;
> + --method_name_len;
> + fputs ("JArray<", out);
> + }
> +
> + fputs ("::", out);
> +
> + /* If we see an `L', skip it and the trailing `;'. Only do this
> + if we've seen an array specification. If we don't have an
> + array then the `L' was stripped earlier. */
> + if (array_depth && method_data[0] == 'L'
> + && method_data[method_name_len - 1] == ';')
> + {
> + ++method_data;
> + method_name_len -= 2;
> + }
> +
> + limit = method_data + method_name_len;
> + while (method_data < limit)
> + {
> + int ch = UTF8_GET (method_data, limit);
> + if (ch == '/')
> + fputs ("::", out);
> + else
> + jcf_print_char (out, ch);
> + }
> + fputs (" *", out);
> +
> + /* Close each array. */
> + while (array_depth > 0)
> + {
> + fputs ("> *", out);
> + --array_depth;
> + }
> +
> + /* Close the cast. */
> + fputs ("> (", out);
> + }
> +
> + if (nameindex == -1)
> + fputs ("this", out);
> + else
> + print_field_name (out, jcf, nameindex, 0);
> +
> + if (cast)
> + fputs (")", out);
> +
> + fputs ("; }", out);
> +}
> +
> +
> /* Try to decompile a method body. Right now we just try to handle a
> simple case that we can do. Expand as desired. */
> static void
> @@ -918,24 +1044,29 @@
> || codes[4] == OPCODE_lreturn))
> {
> /* Found code like `return FIELD'. */
> - fputs (" { return ", out);
> index = (codes[2] << 8) | codes[3];
> /* FIXME: ensure that tag is CONSTANT_Fieldref. */
> - /* FIXME: ensure that the field's class is this class. */
> name_and_type = JPOOL_USHORT2 (jcf, index);
> /* FIXME: ensure that tag is CONSTANT_NameAndType. */
> name = JPOOL_USHORT1 (jcf, name_and_type);
> - /* FIXME: flags. */
> - print_field_name (out, jcf, name, 0);
> - fputs ("; }", out);
> + if (codes[4] == OPCODE_areturn)
> + decompile_return_statement (out, jcf, method_signature,
> + name, JPOOL_USHORT2 (jcf, name_and_type));
> + else
> + {
> + fputs (" { return ", out);
> + /* FIXME: flags. */
> + print_field_name (out, jcf, name, 0);
> + fputs ("; }", out);
> + }
> decompiled = 1;
> }
> else if (code_len == 2
> && codes[0] == OPCODE_aload_0
> && codes[1] == OPCODE_areturn)
> {
> - /* Found `return this'. */
> - fputs (" { return this; }", out);
> + decompile_return_statement (out, jcf, method_signature, -1,
> + JPOOL_USHORT1 (jcf, jcf->this_class));
> decompiled = 1;
> }
> else if (code_len == 1 && codes[0] == OPCODE_return)
>
>
--