This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Re: PATCH: libffi vs. SPARC (again)
- From: Jeff Sturm <jsturm at one-point dot com>
- To: Bryce McKinlay <bryce at waitaki dot otago dot ac dot nz>
- Cc: tromey at redhat dot com, java-patches at gcc dot gnu dot org, green at redhat dot com
- Date: Fri, 16 Nov 2001 10:02:16 -0500 (EST)
- Subject: Re: PATCH: libffi vs. SPARC (again)
On Sat, 17 Nov 2001, Bryce McKinlay wrote:
> Okay, I misunderstood the problem. The only problem with libffi is that
> this behaviour isn't documented other than in the ffitest source. I
> agree its an inconsistency, but does make some sense, since it would
> presumably it would make the big-endian ports more complex and less
> efficient to not to promote the return value. And it isn't hard to deal
> with as long as you're aware of it.
I agree.
> I'm not sure I follow. The rule is that types that are smaller than int
> will get promoted to int.
Not exactly. I had assumed that too, before I realized the
declaration of "rint" isn't necessarily "int" (in ffitest.c):
#if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(MIPS)
&& (_MIPS_SIM == _ABIN32))
long long rint;
#else
int rint;
#endif
That's ugly, for a library that's intended to be portable. I think we
could declare the return value "long" instead and it should work almost
anywhere. It'd be better I guess if libffi supplied a typedef for this.
> Types that are equal/larger than int will be
> stored in the native way. As long as all 64-bit CPUs are little endian
> then there is no problem! Or am I missing something?
Hans pointed out that sparc64 is big-endian. (There may be others... does
anyone run ia64 in big-endian mode?)
> Anyway, here's my take on a fix. What do you think?
1) promoted return value may not be jint, e.g. sparc64
2) does this fix JNI, or just reflection?
Here's what I'm testing now:
2001-11-16 Jeff Sturm <jsturm@one-point.com>
* java/lang/reflect/natMethod.cc (_Jv_CallAnyMethodA):
Narrow subword return values to the proper type.
Index: natMethod.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/reflect/natMethod.cc,v
retrieving revision 1.24
diff -u -p -r1.24 natMethod.cc
--- natMethod.cc 2001/10/02 13:44:32 1.24
+++ natMethod.cc 2001/11/16 13:43:46
@@ -420,6 +420,7 @@ _Jv_CallAnyMethodA (jobject obj,
p += tsize;
}
+
// FIXME: initialize class here.
using namespace java::lang;
@@ -429,7 +430,69 @@ _Jv_CallAnyMethodA (jobject obj,
try
{
- ffi_call (&cif, (void (*)()) meth->ncode, result, values);
+ // Since ffi_call returns integer values promoted to a word, use
+ // a narrowing conversion for jbyte, jchar, etc. results.
+ // Note that boolean is handled either by the FFI_TYPE_SINT8 or
+ // FFI_TYPE_SINT32 case.
+ // FIXME - "long" may not be the same as a word.
+ switch (rtype->type)
+ {
+ case FFI_TYPE_VOID:
+ ffi_call (&cif, (void (*)()) meth->ncode, NULL, values);
+ break;
+ case FFI_TYPE_SINT8:
+ {
+ long result_word;
+ ffi_call (&cif, (void (*)()) meth->ncode, &result_word, values);
+ result->b = (jbyte)result_word;
+ }
+ break;
+ case FFI_TYPE_SINT16:
+ {
+ long result_word;
+ ffi_call (&cif, (void (*)()) meth->ncode, &result_word, values);
+ result->s = (jshort)result_word;
+ }
+ break;
+ case FFI_TYPE_UINT16:
+ {
+ long result_word;
+ ffi_call (&cif, (void (*)()) meth->ncode, &result_word, values);
+ result->c = (jchar)result_word;
+ }
+ break;
+ case FFI_TYPE_SINT32:
+ {
+ long result_word;
+ ffi_call (&cif, (void (*)()) meth->ncode, &result_word, values);
+ result->i = (jint)result_word;
+ }
+ break;
+ case FFI_TYPE_SINT64:
+ {
+ long result_word;
+ ffi_call (&cif, (void (*)()) meth->ncode, &result_word, values);
+ result->j = (jlong)result_word;
+ }
+ break;
+ case FFI_TYPE_FLOAT:
+ {
+ float float_result;
+ ffi_call (&cif, (void (*)()) meth->ncode, &float_result, values);
+ result->f = (jfloat)float_result;
+ }
+ break;
+ case FFI_TYPE_DOUBLE:
+ {
+ double double_result;
+ ffi_call (&cif, (void (*)()) meth->ncode, &double_result, values);
+ result->d = (jdouble)double_result;
+ }
+ break;
+ default:
+ JvFail ("Unknown ffi_call return type");
+ break;
+ }
}
catch (Throwable *ex2)
{