summaryrefslogtreecommitdiff
path: root/recipes/gcc/gcc-4.3.3/arm-gcc-objective.patch
diff options
context:
space:
mode:
authorStefan Schmidt <stefan@datenfreihafen.org>2009-11-27 22:38:46 +0100
committerStefan Schmidt <stefan@datenfreihafen.org>2009-11-27 22:38:46 +0100
commit7b52c2df97ca766b03d0e0ecb346007d9d335105 (patch)
tree94fb6a245633c872898a185546fe351dbed59be4 /recipes/gcc/gcc-4.3.3/arm-gcc-objective.patch
parent7fcaef86af3dc262b4c315da1b5bb5a8e012b402 (diff)
parent0e0de60f4443c143fa92068932722f5d75b0999b (diff)
Merge branch 'org.openembedded.dev' of git.openembedded.org:openembedded into org.openembedded.dev
Diffstat (limited to 'recipes/gcc/gcc-4.3.3/arm-gcc-objective.patch')
-rw-r--r--recipes/gcc/gcc-4.3.3/arm-gcc-objective.patch342
1 files changed, 342 insertions, 0 deletions
diff --git a/recipes/gcc/gcc-4.3.3/arm-gcc-objective.patch b/recipes/gcc/gcc-4.3.3/arm-gcc-objective.patch
new file mode 100644
index 0000000000..36533b16d3
--- /dev/null
+++ b/recipes/gcc/gcc-4.3.3/arm-gcc-objective.patch
@@ -0,0 +1,342 @@
+Hi,
+
+This patch implements exception-handling support for Objective-C on ARM
+EABI Linux systems, using the ARM-defined EHABI. This patch gets things
+working fairly well, though at least one issue remains -- but this is a
+start, at least.
+
+Test results are clean, apart from the following:
+
+FAIL: objc/execute/exceptions/foward-1.m execution, -O3
+-fomit-frame-pointer -funroll-loops -fgnu-runtime
+
+FAIL: objc/execute/exceptions/foward-1.m execution, -O3
+-fomit-frame-pointer -funroll-all-loops -finline-functions
+-fgnu-runtime
+
+AFAICT, these seem to be caused by data-flow information being corrupted
+somehow: the failure happens during the regrename pass, but I don't
+think the underlying cause is there. On entry to the landing pad:
+
+ @catch (id error)
+ {
+ i++;
+ [error free];
+ }
+
+The "error" pointer gets scrambled, because the register it should be
+passed in, r0, is not marked as live-on-entry to the associated block,
+so register-renaming thinks it's safe to overwrite that register.
+
+On the 4.3 branch, defining the EH_USES macro in arm.h as follows fixed
+this issue:
+
+/* r0 may be used by catch handlers. Make sure it's marked live on
+ entry to those. */
+#define EH_USES(N) ((N) == 0)
+
+But, this solution doesn't seem to work on mainline. Does anyone know
+why that might be?
+
+Is the attached patch OK for mainline, despite the above shortcoming?
+(Tested with cross to ARM EABI Linux).
+
+Cheers,
+
+Julian
+
+ChangeLog
+
+ * 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.
+--MP_/JBpQpWs5CG=5JB9NzgrXUnG
+Content-Type: text/x-patch; name=libobjc-arm-eabi-support-1.diff
+Content-Transfer-Encoding: 7bit
+Content-Disposition: attachment; filename=libobjc-arm-eabi-support-1.diff
+
+--- a/libobjc/exception.c 2008-04-30 05:15:45.000000000 -0700
++++ b/libobjc/exception.c 2008-05-06 05:41:51.000000000 -0700
+@@ -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_Contex
+ 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
+ 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;
+
+
+--MP_/JBpQpWs5CG=5JB9NzgrXUnG--
+