aboutsummaryrefslogtreecommitdiff
path: root/libobjc
diff options
context:
space:
mode:
authorJulian Brown <julian@codesourcery.com>2008-05-30 18:21:31 +0000
committerJulian Brown <jules@gcc.gnu.org>2008-05-30 18:21:31 +0000
commit3f6383d38bc996a01dfa086a42b83c452386fa00 (patch)
treec1bdf9cb0cdd9e02e16dc55edb6e15883ce74f99 /libobjc
parentd750887f5f4273e10625e13d1bac1db9aeef849e (diff)
downloadgcc-3f6383d38bc996a01dfa086a42b83c452386fa00.zip
gcc-3f6383d38bc996a01dfa086a42b83c452386fa00.tar.gz
gcc-3f6383d38bc996a01dfa086a42b83c452386fa00.tar.bz2
configure.ac (arm*-*-linux-gnueabi): Don't disable building of libobjc for ARM EABI Linux.
* configure.ac (arm*-*-linux-gnueabi): Don't disable building of libobjc for ARM EABI Linux. * configure: Regenerate. libobjc/ * exception.c (__objc_exception_class): Initialise as constant array for ARM EABI. Change macro to static const for non-ARM EABI. (ObjcException): Add note about structure layout. Remove landingPad and handlerSwitchValue for ARM EABI. (get_ttype_entry): Add __ARM_EABI_UNWINDER__ version of function. (CONTINUE_UNWINDING): Define for ARM EABI/otherwise cases. (PERSONALITY_FUNCTION): Use ARM EABI-specific arguments, and add ARM EABI unwinding support. (objc_exception_throw): Use memcpy to initialise exception class. From-SVN: r136215
Diffstat (limited to 'libobjc')
-rw-r--r--libobjc/ChangeLog13
-rw-r--r--libobjc/exception.c154
2 files changed, 147 insertions, 20 deletions
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog
index df30eaa..fa0e059 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,3 +1,16 @@
+2008-05-30 Julian Brown <julian@codesourcery.com>
+
+ * exception.c (__objc_exception_class): Initialise as constant
+ array for ARM EABI. Change macro to static const for non-ARM EABI.
+ (ObjcException): Add note about structure layout. Remove landingPad
+ and handlerSwitchValue for ARM EABI.
+ (get_ttype_entry): Add __ARM_EABI_UNWINDER__ version
+ of function.
+ (CONTINUE_UNWINDING): Define for ARM EABI/otherwise cases.
+ (PERSONALITY_FUNCTION): Use ARM EABI-specific arguments, and add
+ ARM EABI unwinding support.
+ (objc_exception_throw): Use memcpy to initialise exception class.
+
2008-05-25 Alan Modra <amodra@bigpond.net.au>
* encoding.c (strip_array_types): Rename from get_inner_array_type.
diff --git a/libobjc/exception.c b/libobjc/exception.c
index 4777c3b..1a6b9da 100644
--- a/libobjc/exception.c
+++ b/libobjc/exception.c
@@ -31,16 +31,25 @@ Boston, MA 02110-1301, USA. */
#include "unwind-pe.h"
+#ifdef __ARM_EABI_UNWINDER__
+
+const _Unwind_Exception_Class __objc_exception_class
+ = {'G', 'N', 'U', 'C', 'O', 'B', 'J', 'C'};
+
+#else
+
/* This is the exception class we report -- "GNUCOBJC". */
-#define __objc_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) 'O') \
- << 8 | (_Unwind_Exception_Class) 'B') \
- << 8 | (_Unwind_Exception_Class) 'J') \
- << 8 | (_Unwind_Exception_Class) 'C')
+static const _Unwind_Exception_Class __objc_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) 'O')
+ << 8 | (_Unwind_Exception_Class) 'B')
+ << 8 | (_Unwind_Exception_Class) 'J')
+ << 8 | (_Unwind_Exception_Class) 'C');
+
+#endif
/* This is the object that is passed around by the Objective C runtime
to represent the exception in flight. */
@@ -50,12 +59,18 @@ struct ObjcException
/* This bit is needed in order to interact with the unwind runtime. */
struct _Unwind_Exception base;
- /* The actual object we want to throw. */
+ /* The actual object we want to throw. Note: must come immediately after
+ unwind header. */
id value;
+#ifdef __ARM_EABI_UNWINDER__
+ /* Note: we use the barrier cache defined in the unwind control block for
+ ARM EABI. */
+#else
/* Cache some internal unwind data between phase 1 and phase 2. */
_Unwind_Ptr landingPad;
int handlerSwitchValue;
+#endif
};
@@ -106,6 +121,24 @@ parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
return p;
}
+#ifdef __ARM_EABI_UNWINDER__
+
+static Class
+get_ttype_entry (struct lsda_header_info *info, _uleb128_t i)
+{
+ _Unwind_Ptr ptr;
+
+ ptr = (_Unwind_Ptr) (info->TType - (i * 4));
+ ptr = _Unwind_decode_target2 (ptr);
+
+ if (ptr)
+ return objc_get_class ((const char *) ptr);
+ else
+ return 0;
+}
+
+#else
+
static Class
get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i)
{
@@ -122,6 +155,8 @@ get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i)
return 0;
}
+#endif
+
/* Like unto the method of the same name on Object, but takes an id. */
/* ??? Does this bork the meta-type system? Can/should we look up an
isKindOf method on the id? */
@@ -150,12 +185,32 @@ isKindOf (id value, Class target)
#define PERSONALITY_FUNCTION __gnu_objc_personality_v0
#endif
+#ifdef __ARM_EABI_UNWINDER__
+
+#define CONTINUE_UNWINDING \
+ do \
+ { \
+ if (__gnu_unwind_frame(ue_header, context) != _URC_OK) \
+ return _URC_FAILURE; \
+ return _URC_CONTINUE_UNWIND; \
+ } \
+ while (0)
+
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (_Unwind_State state,
+ struct _Unwind_Exception *ue_header,
+ struct _Unwind_Context *context)
+#else
+
+#define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
+
_Unwind_Reason_Code
PERSONALITY_FUNCTION (int version,
_Unwind_Action actions,
_Unwind_Exception_Class exception_class,
struct _Unwind_Exception *ue_header,
struct _Unwind_Context *context)
+#endif
{
struct ObjcException *xh = (struct ObjcException *) ue_header;
@@ -165,19 +220,65 @@ PERSONALITY_FUNCTION (int version,
const unsigned char *p;
_Unwind_Ptr landing_pad, ip;
int handler_switch_value;
- int saw_cleanup = 0, saw_handler;
+ int saw_cleanup = 0, saw_handler, foreign_exception;
void *return_object;
+ int ip_before_insn = 0;
+
+#ifdef __ARM_EABI_UNWINDER__
+ _Unwind_Action actions;
+
+ switch (state & _US_ACTION_MASK)
+ {
+ case _US_VIRTUAL_UNWIND_FRAME:
+ actions = _UA_SEARCH_PHASE;
+ break;
+
+ case _US_UNWIND_FRAME_STARTING:
+ actions = _UA_CLEANUP_PHASE;
+ if (!(state & _US_FORCE_UNWIND)
+ && ue_header->barrier_cache.sp == _Unwind_GetGR (context, 13))
+ actions |= _UA_HANDLER_FRAME;
+ break;
+
+ case _US_UNWIND_FRAME_RESUME:
+ CONTINUE_UNWINDING;
+ break;
+
+ default:
+ abort();
+ }
+ actions |= state & _US_FORCE_UNWIND;
+
+ /* TODO: Foreign exceptions need some attention (e.g. rethrowing doesn't
+ work). */
+ foreign_exception = 0;
+ /* The dwarf unwinder assumes the context structure holds things like the
+ function and LSDA pointers. The ARM implementation caches these in
+ the exception header (UCB). To avoid rewriting everything we make the
+ virtual IP register point at the UCB. */
+ ip = (_Unwind_Ptr) ue_header;
+ _Unwind_SetGR (context, 12, ip);
+
+#else /* !__ARM_EABI_UNWINDER. */
/* Interface version check. */
if (version != 1)
return _URC_FATAL_PHASE1_ERROR;
+
+ foreign_exception = (exception_class != __objc_exception_class);
+#endif
/* Shortcut for phase 2 found handler for domestic exception. */
if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
- && exception_class == __objc_exception_class)
+ && !foreign_exception)
{
+#ifdef __ARM_EABI_UNWINDER__
+ handler_switch_value = (int) ue_header->barrier_cache.bitpattern[1];
+ landing_pad = (_Unwind_Ptr) ue_header->barrier_cache.bitpattern[3];
+#else
handler_switch_value = xh->handlerSwitchValue;
landing_pad = xh->landingPad;
+#endif
goto install_context;
}
@@ -186,12 +287,18 @@ PERSONALITY_FUNCTION (int version,
/* If no LSDA, then there are no handlers or cleanups. */
if (! language_specific_data)
- return _URC_CONTINUE_UNWIND;
+ CONTINUE_UNWINDING;
/* Parse the LSDA header. */
p = parse_lsda_header (context, language_specific_data, &info);
info.ttype_base = base_of_encoded_value (info.ttype_encoding, context);
+#ifdef HAVE_GETIPINFO
+ ip = _Unwind_GetIPInfo (context, &ip_before_insn);
+#else
ip = _Unwind_GetIP (context) - 1;
+#endif
+ if (!ip_before_insn)
+ --ip;
landing_pad = 0;
action_record = 0;
handler_switch_value = 0;
@@ -250,7 +357,7 @@ PERSONALITY_FUNCTION (int version,
/* If ip is not present in the table, C++ would call terminate. */
/* ??? As with Java, it's perhaps better to tweek the LSDA to
that no-action is mapped to no-entry. */
- return _URC_CONTINUE_UNWIND;
+ CONTINUE_UNWINDING;
found_something:
saw_cleanup = 0;
@@ -287,8 +394,7 @@ PERSONALITY_FUNCTION (int version,
/* 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 != __objc_exception_class)
+ else if ((actions & _UA_FORCE_UNWIND) || foreign_exception)
;
else if (ar_filter > 0)
@@ -318,18 +424,24 @@ PERSONALITY_FUNCTION (int version,
}
if (! saw_handler && ! saw_cleanup)
- return _URC_CONTINUE_UNWIND;
+ CONTINUE_UNWINDING;
if (actions & _UA_SEARCH_PHASE)
{
if (!saw_handler)
- return _URC_CONTINUE_UNWIND;
+ CONTINUE_UNWINDING;
/* For domestic exceptions, we cache data from phase 1 for phase 2. */
- if (exception_class == __objc_exception_class)
+ if (!foreign_exception)
{
+#ifdef __ARM_EABI_UNWINDER__
+ ue_header->barrier_cache.sp = _Unwind_GetGR (context, 13);
+ ue_header->barrier_cache.bitpattern[1] = (_uw) handler_switch_value;
+ ue_header->barrier_cache.bitpattern[3] = (_uw) landing_pad;
+#else
xh->handlerSwitchValue = handler_switch_value;
xh->landingPad = landing_pad;
+#endif
}
return _URC_HANDLER_FOUND;
}
@@ -361,7 +473,9 @@ void
objc_exception_throw (id value)
{
struct ObjcException *header = calloc (1, sizeof (*header));
- header->base.exception_class = __objc_exception_class;
+
+ memcpy (&header->base.exception_class, &__objc_exception_class,
+ sizeof (__objc_exception_class));
header->base.exception_cleanup = __objc_exception_cleanup;
header->value = value;