This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
ia64 eh, part 20d [libjava]
- To: gcc-patches at gcc dot gnu dot org, java-patches at gcc dot gnu dot org
- Subject: ia64 eh, part 20d [libjava]
- From: Richard Henderson <rth at redhat dot com>
- Date: Wed, 28 Mar 2001 02:24:55 -0800
This is the libjava change. Except for removing the option frobbing,
it follows from the libstdc++ changes relatively directly.
r~
IA-64 ABI Exception Handling:
* Makefile.am (GCC_UNWIND_INCLUDE): Rename from EH_COMMON_INCLUDE.
(AM_CXXFLAGS): -fnon-call-exceptions not -fasynchronous-exceptions.
Remove EXCEPTIONSPEC.
* configure.host (libgcj_sjlj): Remove.
* configure.in (EXCEPTIONSPEC): Remove.
(enable-sjlj-exceptions): Detect if not specified.
(GCC_UNWIND_INCLUDE): Rename from EH_COMMON_INCLUDE; change
what header we're looking for.
* libgcj.spec.in (jc1): Remove EXCEPTIONSPEC.
* Makefile.in, configure: Regenerate.
* exception.cc: Don't declare libgcc2 stuff.
(java_eh_info, _Jv_type_matcher, _Jv_exception_info): Remove.
(_Jv_eh_alloc, _Jv_eh_free, _Jv_setup_eh_info): Remove.
(win32_get_restart_frame): Remove.
(struct java_exception_header): New.
(__gcj_exception_class): New.
(get_exception_header_from_ue): New.
(_Jv_Throw): Rewrite for IA-64 ABI unwind routines.
(size_of_encoded_value, read_encoded_value): New.
(read_uleb128, read_sleb128, parse_lsda_header): New.
(get_ttype_entry, __gcj_personality_sj0): New.
* gcj/javaprims.h (_Jv_Sjlj_Throw): Remove.
Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.135
diff -c -p -d -r1.135 Makefile.am
*** Makefile.am 2001/03/27 00:18:30 1.135
--- Makefile.am 2001/03/28 10:15:29
*************** LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mo
*** 87,104 ****
JAVAC = $(GCJ_WITH_FLAGS) -C
! EH_COMMON_INCLUDE = @EH_COMMON_INCLUDE@
WARNINGS = -W -Wall
## We need _GNU_SOURCE defined for some Linux builds. It doesn't hurt
## to always define it.
! ## Note that we need -fasynchronous-exceptions because gcc is
! ## currently broken with respect to exception handling in leaf
! ## functions.
! AM_CXXFLAGS = -fno-rtti -fvtable-thunks -fasynchronous-exceptions \
## Some systems don't allow `$' in identifiers by default, so we force it.
-fdollars-in-identifiers \
! @LIBGCJ_CXXFLAGS@ @EXCEPTIONSPEC@ @X_CFLAGS@ $(WARNINGS) -D_GNU_SOURCE
if USING_GCC
AM_CFLAGS = @LIBGCJ_CFLAGS@ $(WARNINGS)
else
--- 87,101 ----
JAVAC = $(GCJ_WITH_FLAGS) -C
! GCC_UNWIND_INCLUDE = @GCC_UNWIND_INCLUDE@
WARNINGS = -W -Wall
## We need _GNU_SOURCE defined for some Linux builds. It doesn't hurt
## to always define it.
! AM_CXXFLAGS = -fno-rtti -fvtable-thunks -fnon-call-exceptions \
## Some systems don't allow `$' in identifiers by default, so we force it.
-fdollars-in-identifiers \
! @LIBGCJ_CXXFLAGS@ @X_CFLAGS@ $(WARNINGS) -D_GNU_SOURCE
if USING_GCC
AM_CFLAGS = @LIBGCJ_CFLAGS@ $(WARNINGS)
else
*************** LIBFFIINCS = -I$(top_srcdir)/../libffi/i
*** 112,118 ****
INCLUDES = -I$(top_srcdir) -Iinclude -I$(top_srcdir)/include \
$(GCINCS) $(THREADINCS) $(INCLTDL) \
! $(EH_COMMON_INCLUDE) $(ZINCS) $(LIBFFIINCS)
## ################################################################
--- 109,115 ----
INCLUDES = -I$(top_srcdir) -Iinclude -I$(top_srcdir)/include \
$(GCINCS) $(THREADINCS) $(INCLTDL) \
! $(GCC_UNWIND_INCLUDE) $(ZINCS) $(LIBFFIINCS)
## ################################################################
Index: configure.host
===================================================================
RCS file: /cvs/gcc/gcc/libjava/configure.host,v
retrieving revision 1.15
diff -c -p -d -r1.15 configure.host
*** configure.host 2001/02/05 05:49:44 1.15
--- configure.host 2001/03/28 10:15:29
*************** libgcj_flags=
*** 23,29 ****
libgcj_cflags=
libgcj_cxxflags=
libgcj_javaflags=
- libgcj_sjlj=
libgcj_interpreter=
case "${target_optspace}:${host}" in
--- 23,28 ----
*************** case "${host}" in
*** 67,83 ****
alpha*-*)
libgcj_flags="${libgcj_flags} -mieee"
libgcj_interpreter=yes
- libgcj_sjlj=yes
;;
sparc-*)
;;
ia64-*)
libgcj_flags="${libgcj_flags} -funwind-tables"
- libgcj_sjlj=yes
libgcj_interpreter=yes
- ;;
- *)
- libgcj_sjlj=yes
;;
esac
--- 66,77 ----
Index: configure.in
===================================================================
RCS file: /cvs/gcc/gcc/libjava/configure.in,v
retrieving revision 1.75
diff -c -p -d -r1.75 configure.in
*** configure.in 2001/03/21 18:43:03 1.75
--- configure.in 2001/03/28 10:15:29
*************** if test "$libgcj_interpreter" = yes; the
*** 88,106 ****
AC_DEFINE(INTERPRETER)
fi
! EXCEPTIONSPEC=
! dnl See if we should use setjmp/longjmp exceptions
AC_ARG_ENABLE(sjlj-exceptions,
! [ --enable-sjlj-exceptions use setjmp/longjmp exceptions],
! if test "$enable_sjlj_exceptions" = yes; then
! # This can be set in configure.host.
! libgcj_sjlj=yes
! fi)
!
! if test "$libgcj_sjlj" = yes; then
! EXCEPTIONSPEC="-fsjlj-exceptions"
! AC_DEFINE(SJLJ_EXCEPTIONS)
fi
AC_MSG_CHECKING([for data_start])
LIBDATASTARTSPEC=
--- 88,138 ----
AC_DEFINE(INTERPRETER)
fi
! AC_MSG_CHECKING([for exception model to use])
! AC_LANG_SAVE
! AC_LANG_CPLUSPLUS
AC_ARG_ENABLE(sjlj-exceptions,
! [ --enable-sjlj-exceptions force use of builtin_setjmp for exceptions],
! [:],
! [dnl Botheration. Now we've got to detect the exception model.
! dnl Link tests against libgcc.a are problematic since -- at least
! dnl as of this writing -- we've not been given proper -L bits for
! dnl single-tree newlib and libgloss.
! dnl
! dnl This is what AC_TRY_COMPILE would do if it didn't delete the
! dnl conftest files before we got a change to grep them first.
! cat > conftest.$ac_ext << EOF
! [#]line __oline__ "configure"
! struct S { ~S(); };
! void bar();
! void foo()
! {
! S s;
! bar();
! }
! EOF
! old_CXXFLAGS="$CXXFLAGS"
! CXXFLAGS=-S
! if AC_TRY_EVAL(ac_compile); then
! if grep _Unwind_Sjlj_Resume conftest.s >/dev/null 2>&1 ; then
! enable_sjlj_exceptions=yes
! elif grep _Unwind_Resume conftest.s >/dev/null 2>&1 ; then
! enable_sjlj_exceptions=no
! fi
! fi
! CXXFLAGS="$old_CXXFLAGS"
! rm -f conftest*])
! if test x$enable_sjlj_exceptions = xyes; then
! AC_DEFINE(SJLJ_EXCEPTIONS, 1,
! [Define if the compiler is configured for setjmp/longjmp exceptions.])
! ac_exception_model_name=sjlj
! elif test x$enable_sjlj_exceptions = xno; then
! ac_exception_model_name="call frame"
! else
! AC_MSG_ERROR([unable to detect exception model])
fi
+ AC_LANG_RESTORE
+ AC_MSG_RESULT($ac_exception_model_name)
AC_MSG_CHECKING([for data_start])
LIBDATASTARTSPEC=
*************** CANADIAN=no
*** 349,364 ****
NULL_TARGET=no
NATIVE=yes
! # Find eh-common.h and support headers. If we're in the tree with
# gcc, then look there. Otherwise look in compat-include. If all else
# fails, just hope the user has set things up somehow.
! if test -r $srcdir/../gcc/eh-common.h; then
! EH_COMMON_INCLUDE='-I$(top_srcdir)/../gcc -I$(top_srcdir)/../include'
else
if test -d $srcdir/../compat-include; then
! EH_COMMON_INCLUDE='-I$(top_srcdir)/../compat-include'
else
! EH_COMMON_INCLUDE=
fi
fi
--- 381,397 ----
NULL_TARGET=no
NATIVE=yes
! # Find unwind.h and support headers. If we're in the tree with
# gcc, then look there. Otherwise look in compat-include. If all else
# fails, just hope the user has set things up somehow.
! echo "probing $srcdir/../gcc/unwind.h"
! if test -r $srcdir/../gcc/unwind.h; then
! GCC_UNWIND_INCLUDE='-I$(top_srcdir)/../gcc'
else
if test -d $srcdir/../compat-include; then
! GCC_UNWIND_INCLUDE='-I$(top_srcdir)/../compat-include'
else
! GCC_UNWIND_INCLUDE=
fi
fi
*************** if test -n "${with_cross_host}"; then
*** 389,395 ****
# directory.
if test "$build" != "$with_cross_host"; then
CANADIAN=yes
! EH_COMMON_INCLUDE=
GCJ="${target_alias}-gcj"
else
GCJ=
--- 422,428 ----
# directory.
if test "$build" != "$with_cross_host"; then
CANADIAN=yes
! GCC_UNWIND_INCLUDE=
GCJ="${target_alias}-gcj"
else
GCJ=
*************** AC_SUBST(ZLIBS)
*** 623,636 ****
AC_SUBST(ZDEPS)
AC_SUBST(ZINCS)
AC_SUBST(DIVIDESPEC)
- AC_SUBST(EXCEPTIONSPEC)
AM_CONDITIONAL(CANADIAN, test "$CANADIAN" = yes)
AM_CONDITIONAL(NULL_TARGET, test "$NULL_TARGET" = yes)
AM_CONDITIONAL(NATIVE, test "$NATIVE" = yes || test "$NULL_TARGET" = yes)
AM_CONDITIONAL(USE_LIBDIR, test -z "$with_cross_host")
AM_CONDITIONAL(NEEDS_DATA_START, test "$NEEDS_DATA_START" = yes && test "$NATIVE" = yes)
! AC_SUBST(EH_COMMON_INCLUDE)
# Determine gcj version number.
changequote(<<,>>)
--- 656,668 ----
AC_SUBST(ZDEPS)
AC_SUBST(ZINCS)
AC_SUBST(DIVIDESPEC)
AM_CONDITIONAL(CANADIAN, test "$CANADIAN" = yes)
AM_CONDITIONAL(NULL_TARGET, test "$NULL_TARGET" = yes)
AM_CONDITIONAL(NATIVE, test "$NATIVE" = yes || test "$NULL_TARGET" = yes)
AM_CONDITIONAL(USE_LIBDIR, test -z "$with_cross_host")
AM_CONDITIONAL(NEEDS_DATA_START, test "$NEEDS_DATA_START" = yes && test "$NATIVE" = yes)
! AC_SUBST(GCC_UNWIND_INCLUDE)
# Determine gcj version number.
changequote(<<,>>)
Index: exception.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/exception.cc,v
retrieving revision 1.11
diff -c -p -d -r1.11 exception.cc
*** exception.cc 2001/03/26 07:05:31 1.11
--- exception.cc 2001/03/28 10:15:29
***************
*** 1,6 ****
// Functions for Exception Support for Java.
! /* Copyright (C) 1998, 1999 Free Software Foundation
This file is part of libgcj.
--- 1,6 ----
// Functions for Exception Support for Java.
! /* Copyright (C) 1998, 1999, 2001 Free Software Foundation
This file is part of libgcj.
*************** details. */
*** 18,199 ****
#include <gcj/cni.h>
#include <jvm.h>
! // eh-common.h needs gansidecl.h.
! #include "gansidecl.h"
! #include "eh-common.h"
! typedef struct {
! __eh_info eh_info;
jthrowable value;
- } java_eh_info;
! /* Language-specific EH info pointer, throw routine, and language/version
! info routines. All defined in libgcc2. */
- extern "C" java_eh_info **__get_eh_info ();
- extern "C" void __throw () __attribute__ ((__noreturn__));
- extern "C" void __sjthrow () __attribute__ ((__noreturn__));
- extern "C" short __get_eh_table_version (void *table);
- extern "C" short __get_eh_table_language (void *table);
- extern "C" void *__get_eh_context ();
! extern "C" void *
! _Jv_type_matcher (java_eh_info *info, void* match_info,
! void *exception_table)
{
! #ifndef SJLJ_EXCEPTIONS
! /* No exception table implies the old style mechanism, so don't check. */
! if (exception_table != NULL
! && __get_eh_table_language (exception_table) != EH_LANG_Java)
! return NULL;
#endif
! /* we don't worry about version info yet, there is only one version! */
!
! if (match_info != NULL)
! {
! // The match_info is either a (java::lang::Class*) or
! // match_info is one more than a (Utf8Const*).
! if (sizeof(void*) != sizeof(size_t))
! abort();
! size_t mi = (size_t) match_info;
! if ((mi & 1) != 0)
! match_info = _Jv_FindClass ((Utf8Const*) (mi - 1), NULL);
! if (! _Jv_IsInstanceOf (info->value, (jclass) match_info))
! return NULL;
! }
! return info->value;
}
! /* Compiler hook to return a pointer to java exception object. The value
! is cleared, so if the exception needs to be rethrown, it should be set
! again */
! extern "C" void *
! _Jv_exception_info (void)
{
! java_eh_info *info = *(__get_eh_info ());
! void *ptr;
! if (info == NULL)
! abort ();
! ptr = info->value;
! /* clear the value so another throw is an error */
! info->value = NULL;
! return ptr;
! }
! /* Allocate an exception info structure for java. Called the first time
! an exception is thrown. */
! extern "C" void
! _Jv_eh_alloc ()
! {
! /* FIXME: we should use _Jv_AllocBytes here. However, libgcc2
! apparently can sometimes free() this value itself. */
! java_eh_info *p = (java_eh_info *) malloc (sizeof (java_eh_info));
! if (p == 0)
! abort ();
! p->value = 0;
! java_eh_info ** info_ptr = __get_eh_info ();
! /* There should NOT be an exception info pointer already. */
! if (*info_ptr != NULL)
! abort ();
! *info_ptr = p;
}
! /* Deallocate the current exception info structure. Called at shutdown time. */
! extern "C" void
! _Jv_eh_free ()
{
! java_eh_info ** info_ptr = __get_eh_info ();
! if (*info_ptr == NULL)
! abort ();
!
! /* FIXME: ideally we should just let the GC handle this. */
! free (*info_ptr);
! *info_ptr = NULL;
}
! /* Initialize an __eh_info structure with this libraries matching info. */
! extern "C" void
! _Jv_setup_eh_info (__eh_info *)
{
}
! /* Perform a throw, Java style. Throw will unwind through this call,
! so there better not be any handlers or exception thrown here. */
#ifdef SJLJ_EXCEPTIONS
! #define _Jv_Throw _Jv_Sjlj_Throw
#endif
! extern "C" void
! _Jv_Throw (jthrowable value)
{
! if (value == NULL)
! value = new java::lang::NullPointerException;
! java_eh_info *ehinfo = *(__get_eh_info ());
! if (ehinfo == NULL)
{
! _Jv_eh_alloc ();
! ehinfo = *(__get_eh_info ());
}
- ehinfo->eh_info.match_function = (__eh_matcher) _Jv_type_matcher;
- ehinfo->eh_info.language = EH_LANG_Java;
- ehinfo->eh_info.version = 1;
- ehinfo->value = value;
! /* We're happy with setjmp/longjmp exceptions or region-based
! exception handlers: entry points are provided here for both. */
#ifdef SJLJ_EXCEPTIONS
! __sjthrow ();
#else
! __throw ();
! #endif
! }
! #ifdef USE_WIN32_SIGNALLING
! // This is a mangled version of _Jv_Throw and __sjthrow except
! // rather than calling longjmp, it returns a pointer to the jmp buffer
! extern "C" int *
! win32_get_restart_frame (void *value)
! {
! struct eh_context *eh = (struct eh_context *)__get_eh_context ();
! void ***dhc = &eh->dynamic_handler_chain;
!
! java_eh_info *ehinfo = *(__get_eh_info ());
! if (ehinfo == NULL)
{
! _Jv_eh_alloc ();
! ehinfo = *(__get_eh_info ());
}
! ehinfo->eh_info.match_function = (__eh_matcher) _Jv_type_matcher;
! ehinfo->eh_info.language = EH_LANG_Java;
! ehinfo->eh_info.version = 1;
! ehinfo->value = value;
! // FIXME: Run clean ups?
! int *jmpbuf = (int*)&(*dhc)[2];
! *dhc = (void**)(*dhc)[0];
! return jmpbuf;
! }
! #endif /* USE_WIN32_SIGNALLING */
--- 18,563 ----
#include <gcj/cni.h>
#include <jvm.h>
! #include "unwind.h"
!
! // More nastiness: the GC wants to define TRUE and FALSE. We don't
! // need the Java definitions (themselves a hack), so we undefine them.
! #undef TRUE
! #undef FALSE
!
! extern "C"
! {
! #include <gc_priv.h>
! #include <gc_mark.h>
! #include <include/gc_gcj.h>
! };
!
!
! struct alignment_test_struct
! {
! char space;
! char end[0] __attribute__((aligned));
! };
!
! struct java_exception_header
! {
! /* Cache handler details between Phase 1 and Phase 2. */
! _Unwind_Ptr landingPad;
! int handlerSwitchValue;
!
! /* The object being thrown. Compiled code expects this to be immediately
! before the generic exception header. Which is complicated by the fact
! that _Unwind_Exception is ((aligned)). */
!
! char pad[sizeof(jthrowable) < sizeof(alignment_test_struct)
! ? sizeof(alignment_test_struct) - sizeof(jthrowable) : 0]
! __attribute__((aligned));
!
jthrowable value;
+ /* The generic exception header. */
+ _Unwind_Exception unwindHeader;
+ };
! // This is the exception class we report -- "GNUCJAVA".
! const _Unwind_Exception_Class __gcj_exception_class
! = ((((((((_Unwind_Exception_Class) 'G'
! << 8 | (_Unwind_Exception_Class) 'N')
! << 8 | (_Unwind_Exception_Class) 'U')
! << 8 | (_Unwind_Exception_Class) 'C')
! << 8 | (_Unwind_Exception_Class) 'J')
! << 8 | (_Unwind_Exception_Class) 'A')
! << 8 | (_Unwind_Exception_Class) 'V')
! << 8 | (_Unwind_Exception_Class) 'A');
! static inline java_exception_header *
! get_exception_header_from_ue (_Unwind_Exception *exc)
{
! return reinterpret_cast<java_exception_header *>(exc + 1) - 1;
! }
!
! /* Perform a throw, Java style. Throw will unwind through this call,
! so there better not be any handlers or exception thrown here. */
!
! extern "C" void
! _Jv_Throw (jthrowable value)
! {
! /* FIXME: Use the proper API to the collector. */
! java_exception_header *xh
! = static_cast<java_exception_header *>(GC_malloc (sizeof (*xh)));
!
! if (value == NULL)
! value = new java::lang::NullPointerException ();
! xh->value = value;
!
! xh->unwindHeader.exception_class = __gcj_exception_class;
! xh->unwindHeader.exception_cleanup = NULL;
!
! /* We're happy with setjmp/longjmp exceptions or region-based
! exception handlers: entry points are provided here for both. */
! _Unwind_Reason_Code code;
! #ifdef SJLJ_EXCEPTIONS
! code = _Unwind_SjLj_RaiseException (&xh->unwindHeader);
! #else
! code = _Unwind_RaiseException (&xh->unwindHeader);
#endif
! /* FIXME: If code == _URC_END_OF_STACK, then we reached top of
! stack without finding a handler for the exception. I seem to
! recall that Java has specific rules to handle this.
! If code is something else, we encountered some sort of heinous
! lossage, from which we could not recover. As is the way of such
! things we'll almost certainly have crashed before now, rather
! than actually being able to diagnose the problem. */
! abort ();
}
!
! // ??? These ought to go somewhere else dwarf2 or dwarf2eh related.
! // Pointer encodings.
! #define DW_EH_PE_absptr 0x00
! #define DW_EH_PE_omit 0xff
!
! #define DW_EH_PE_uleb128 0x01
! #define DW_EH_PE_udata2 0x02
! #define DW_EH_PE_udata4 0x03
! #define DW_EH_PE_udata8 0x04
! #define DW_EH_PE_sleb128 0x09
! #define DW_EH_PE_sdata2 0x0A
! #define DW_EH_PE_sdata4 0x0B
! #define DW_EH_PE_sdata8 0x0C
! #define DW_EH_PE_signed 0x08
!
! #define DW_EH_PE_pcrel 0x10
! #define DW_EH_PE_textrel 0x20
! #define DW_EH_PE_datarel 0x30
! #define DW_EH_PE_funcrel 0x40
!
! static unsigned int
! size_of_encoded_value (unsigned char encoding)
{
! switch (encoding & 0x07)
! {
! case DW_EH_PE_absptr:
! return sizeof (void *);
! case DW_EH_PE_udata2:
! return 2;
! case DW_EH_PE_udata4:
! return 4;
! case DW_EH_PE_udata8:
! return 8;
! }
! abort ();
! }
! static const unsigned char *
! read_encoded_value (_Unwind_Context *context, unsigned char encoding,
! const unsigned char *p, _Unwind_Ptr *val)
! {
! union unaligned
! {
! void *ptr;
! unsigned u2 __attribute__ ((mode (HI)));
! unsigned u4 __attribute__ ((mode (SI)));
! unsigned u8 __attribute__ ((mode (DI)));
! signed s2 __attribute__ ((mode (HI)));
! signed s4 __attribute__ ((mode (SI)));
! signed s8 __attribute__ ((mode (DI)));
! } __attribute__((__packed__));
! union unaligned *u = (union unaligned *) p;
! _Unwind_Ptr result;
! switch (encoding & 0x0f)
! {
! case DW_EH_PE_absptr:
! result = (_Unwind_Ptr) u->ptr;
! p += sizeof (void *);
! break;
! case DW_EH_PE_uleb128:
! {
! unsigned int shift = 0;
! unsigned char byte;
+ result = 0;
+ do
+ {
+ byte = *p++;
+ result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
+ shift += 7;
+ }
+ while (byte & 0x80);
+ }
+ break;
+ case DW_EH_PE_sleb128:
+ {
+ unsigned int shift = 0;
+ unsigned char byte;
! result = 0;
! do
! {
! byte = *p++;
! result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
! shift += 7;
! }
! while (byte & 0x80);
! if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
! result |= -(1L << shift);
! }
! break;
! case DW_EH_PE_udata2:
! result = u->u2;
! p += 2;
! break;
! case DW_EH_PE_udata4:
! result = u->u4;
! p += 4;
! break;
! case DW_EH_PE_udata8:
! result = u->u8;
! p += 8;
! break;
! case DW_EH_PE_sdata2:
! result = u->s2;
! p += 2;
! break;
! case DW_EH_PE_sdata4:
! result = u->s4;
! p += 4;
! break;
! case DW_EH_PE_sdata8:
! result = u->s8;
! p += 8;
! break;
! default:
! abort ();
! }
!
! if (result != 0)
! switch (encoding & 0xf0)
! {
! case DW_EH_PE_absptr:
! break;
!
! case DW_EH_PE_pcrel:
! // Define as relative to the beginning of the pointer.
! result += (_Unwind_Ptr) u;
! break;
!
! case DW_EH_PE_textrel:
! case DW_EH_PE_datarel:
! // FIXME.
! abort ();
!
! case DW_EH_PE_funcrel:
! result += _Unwind_GetRegionStart (context);
! break;
!
! default:
! abort ();
! }
!
! *val = result;
! return p;
}
! static inline const unsigned char *
! read_uleb128 (const unsigned char *p, _Unwind_Ptr *val)
! {
! return read_encoded_value (0, DW_EH_PE_uleb128, p, val);
! }
! static inline const unsigned char *
! read_sleb128 (const unsigned char *p, _Unwind_Ptr *val)
{
! return read_encoded_value (0, DW_EH_PE_sleb128, p, val);
}
!
! struct lsda_header_info
! {
! _Unwind_Ptr Start;
! _Unwind_Ptr LPStart;
! const unsigned char *TType;
! const unsigned char *action_table;
! unsigned char ttype_encoding;
! unsigned char call_site_encoding;
! };
! static const unsigned char *
! parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
! lsda_header_info *info)
{
+ _Unwind_Ptr tmp;
+ unsigned char lpstart_encoding;
+
+ info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
+
+ // Find @LPStart, the base to which landing pad offsets are relative.
+ lpstart_encoding = *p++;
+ if (lpstart_encoding != DW_EH_PE_omit)
+ p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
+ else
+ info->LPStart = info->Start;
+
+ // Find @TType, the base of the handler and exception spec type data.
+ info->ttype_encoding = *p++;
+ if (info->ttype_encoding != DW_EH_PE_omit)
+ {
+ p = read_uleb128 (p, &tmp);
+ info->TType = p + tmp;
+ }
+ else
+ info->TType = 0;
+
+ // The encoding and length of the call-site table; the action table
+ // immediately follows.
+ info->call_site_encoding = *p++;
+ p = read_uleb128 (p, &tmp);
+ info->action_table = p + tmp;
+
+ return p;
}
! static jclass
! get_ttype_entry (_Unwind_Context *context, lsda_header_info *info, long i)
! {
! _Unwind_Ptr ptr;
+ i *= size_of_encoded_value (info->ttype_encoding);
+ read_encoded_value (context, info->ttype_encoding, info->TType - i, &ptr);
+
+ return reinterpret_cast<jclass>(ptr);
+ }
+
+
+ // Using a different personality function name causes link failures
+ // when trying to mix code using different exception handling models.
#ifdef SJLJ_EXCEPTIONS
! #define PERSONALITY_FUNCTION __gcj_personality_sj0
! #define __builtin_eh_return_data_regno(x) x
! #else
! #define PERSONALITY_FUNCTION __gcj_personality_v0
#endif
! extern "C" _Unwind_Reason_Code
! PERSONALITY_FUNCTION (int version,
! _Unwind_Action actions,
! _Unwind_Exception_Class exception_class,
! struct _Unwind_Exception *ue_header,
! struct _Unwind_Context *context)
{
! java_exception_header *xh = get_exception_header_from_ue (ue_header);
!
! lsda_header_info info;
! const unsigned char *language_specific_data;
! const unsigned char *action_record;
! const unsigned char *p;
! _Unwind_Ptr landing_pad, ip;
! int handler_switch_value;
! bool saw_cleanup;
! bool saw_handler;
!
!
! // Interface version check.
! if (version != 1)
! return _URC_FATAL_PHASE1_ERROR;
!
! // Shortcut for phase 2 found handler for domestic exception.
! if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
! && exception_class == __gcj_exception_class)
{
! handler_switch_value = xh->handlerSwitchValue;
! landing_pad = xh->landingPad;
! goto install_context;
}
! // FIXME: In Phase 1, record _Unwind_GetIP in xh->obj as a part of
! // the stack trace for this exception. This will only collect Java
! // frames, but perhaps that is acceptable.
! // FIXME2: _Unwind_GetIP is nonsensical for SJLJ, being a call-site
! // index instead of a PC value. We could perhaps arrange for
! // _Unwind_GetRegionStart to return context->fc->jbuf[1], which
! // is the address of the handler label for __builtin_longjmp, but
! // there is no solution for DONT_USE_BUILTIN_SETJMP.
!
! language_specific_data = (const unsigned char *)
! _Unwind_GetLanguageSpecificData (context);
!
! // If no LSDA, then there are no handlers or cleanups.
! if (! language_specific_data)
! return _URC_CONTINUE_UNWIND;
!
! // Parse the LSDA header.
! p = parse_lsda_header (context, language_specific_data, &info);
! ip = _Unwind_GetIP (context) - 1;
! landing_pad = 0;
! action_record = 0;
! handler_switch_value = 0;
!
#ifdef SJLJ_EXCEPTIONS
! // The given "IP" is an index into the call-site table, with two
! // exceptions -- -1 means no-action, and 0 means terminate. But
! // since we're using uleb128 values, we've not got random access
! // to the array.
! if ((int) ip <= 0)
! return _URC_CONTINUE_UNWIND;
! else
! {
! _Unwind_Ptr cs_lp, cs_action;
! do
! {
! p = read_uleb128 (p, &cs_lp);
! p = read_uleb128 (p, &cs_action);
! }
! while (--ip);
!
! // Can never have null landing pad for sjlj -- that would have
! // been indicated by a -1 call site index.
! landing_pad = cs_lp + 1;
! if (cs_action)
! action_record = info.action_table + cs_action - 1;
! goto found_something;
! }
#else
! // Search the call-site table for the action associated with this IP.
! while (p < info.action_table)
! {
! _Unwind_Ptr cs_start, cs_len, cs_lp, cs_action;
! // Note that all call-site encodings are "absolute" displacements.
! p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
! p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
! p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
! p = read_uleb128 (p, &cs_action);
! // The table is sorted, so if we've passed the ip, stop.
! if (ip < info.Start + cs_start)
! p = info.action_table;
! else if (ip < info.Start + cs_start + cs_len)
! {
! if (cs_lp)
! landing_pad = info.LPStart + cs_lp;
! if (cs_action)
! action_record = info.action_table + cs_action - 1;
! goto found_something;
! }
! }
! #endif // SJLJ_EXCEPTIONS
! // If ip is not present in the table, C++ would call terminate.
! // ??? It is perhaps better to tweek the LSDA so that no-action
! // is mapped to no-entry for Java.
! return _URC_CONTINUE_UNWIND;
!
! found_something:
! saw_cleanup = false;
! saw_handler = false;
!
! if (landing_pad == 0)
{
! // If ip is present, and has a null landing pad, there are
! // no cleanups or handlers to be run.
}
! else if (action_record == 0)
! {
! // If ip is present, has a non-null landing pad, and a null
! // action table offset, then there are only cleanups present.
! // Cleanups use a zero switch value, as set above.
! saw_cleanup = true;
! }
! else
! {
! // Otherwise we have a catch handler.
! signed long ar_filter, ar_disp;
! while (1)
! {
! _Unwind_Ptr tmp;
! p = action_record;
! p = read_sleb128 (p, &tmp); ar_filter = tmp;
! read_sleb128 (p, &tmp); ar_disp = tmp;
! if (ar_filter == 0)
! {
! // Zero filter values are cleanups.
! saw_cleanup = true;
! }
! // During forced unwinding, we only run cleanups. With a
! // foreign exception class, we have no class info to match.
! else if ((actions & _UA_FORCE_UNWIND)
! || exception_class != __gcj_exception_class)
! ;
! else if (ar_filter > 0)
! {
! // Positive filter values are handlers.
!
! jclass catch_type = get_ttype_entry (context, &info, ar_filter);
!
! // The catch_type is either a (java::lang::Class*) or
! // is one more than a (Utf8Const*).
! if ((size_t)catch_type & 1)
! catch_type = _Jv_FindClass ((Utf8Const*)catch_type - 1, NULL);
!
! if (_Jv_IsInstanceOf (xh->value, catch_type))
! {
! handler_switch_value = ar_filter;
! saw_handler = true;
! break;
! }
! }
! else
! {
! // Negative filter values are exception specifications,
! // which Java does not use.
! // ??? Perhaps better to make them an index into a table
! // of null-terminated strings instead of playing games
! // with Utf8Const+1 as above.
! abort ();
! }
!
! if (ar_disp == 0)
! break;
! action_record = p + ar_disp;
! }
! }
!
! if (! saw_handler && ! saw_cleanup)
! return _URC_CONTINUE_UNWIND;
!
! if (actions & _UA_SEARCH_PHASE)
! {
! if (! saw_handler)
! return _URC_CONTINUE_UNWIND;
!
! // For domestic exceptions, we cache data from phase 1 for phase 2.
! if (exception_class == __gcj_exception_class)
! {
! xh->handlerSwitchValue = handler_switch_value;
! xh->landingPad = landing_pad;
! }
! return _URC_HANDLER_FOUND;
! }
!
! install_context:
! _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
! (_Unwind_Ptr) &xh->unwindHeader);
! _Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
! handler_switch_value);
! _Unwind_SetIP (context, landing_pad);
! return _URC_INSTALL_CONTEXT;
! }
Index: libgcj.spec.in
===================================================================
RCS file: /cvs/gcc/gcc/libjava/libgcj.spec.in,v
retrieving revision 1.14
diff -c -p -d -r1.14 libgcj.spec.in
*** libgcj.spec.in 2001/02/27 09:41:21 1.14
--- libgcj.spec.in 2001/03/28 10:15:29
***************
*** 6,12 ****
%rename lib liborig
*lib: -lgcj -lm @GCSPEC@ @THREADSPEC@ @ZLIBSPEC@ @SYSTEMSPEC@ %(libgcc) %(liborig)
! *jc1: @DIVIDESPEC@ @EXCEPTIONSPEC@ @JC1GCSPEC@ -fasynchronous-exceptions
#
# On some systems we force in a data_start symbol so that the GC will work
--- 6,12 ----
%rename lib liborig
*lib: -lgcj -lm @GCSPEC@ @THREADSPEC@ @ZLIBSPEC@ @SYSTEMSPEC@ %(libgcc) %(liborig)
! *jc1: @DIVIDESPEC@ @JC1GCSPEC@
#
# On some systems we force in a data_start symbol so that the GC will work
Index: gcj/javaprims.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gcj/javaprims.h,v
retrieving revision 1.16
diff -c -p -d -r1.16 javaprims.h
*** javaprims.h 2001/03/26 07:05:31 1.16
--- javaprims.h 2001/03/28 10:15:29
*************** extern "C" jsize _Jv_GetStringUTFLength
*** 369,375 ****
extern "C" jsize _Jv_GetStringUTFRegion (jstring, jsize, jsize, char *);
extern "C" void _Jv_Throw (jthrowable) __attribute__ ((__noreturn__));
- extern "C" void _Jv_Sjlj_Throw (jthrowable) __attribute__ ((__noreturn__));
extern "C" void* _Jv_Malloc (jsize) __attribute__((__malloc__));
extern "C" void* _Jv_Realloc (void *, jsize);
extern "C" void _Jv_Free (void*);
--- 369,374 ----