aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2004-12-17 17:56:59 +0000
committerPaul Brook <paul@codesourcery.com>2004-12-17 17:56:59 +0000
commit9ae793df4972d8c7e1a0cac03889e4cbd09d2a23 (patch)
tree45f0b201e6dbf7d774860dcb8373f86365e7c702
parent4215937f2ae78c90bb7481911cb0163d70fa3b68 (diff)
2004-12-17 Paul Brook <paul@codesourcery.com>
* libsupc++/eh_arm.cc (__cxa_begin_cleanup): Add exception to list. (cxa_end_cleanup): Call __gnu_end_cleanup. (__gnu_end_cleanup): New function. * libsupc++/unwind-cxx.h (struct __cxa_exception): Add field for propagating exception stack. (struct __cxa_exception): Add propagatingExceptions. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/csl-arm-2004-q3-branch@92327 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--ChangeLog.csl-arm10
-rw-r--r--libstdc++-v3/libsupc++/eh_arm.cc65
-rw-r--r--libstdc++-v3/libsupc++/unwind-cxx.h13
3 files changed, 81 insertions, 7 deletions
diff --git a/ChangeLog.csl-arm b/ChangeLog.csl-arm
index a883e71e566..357019c0114 100644
--- a/ChangeLog.csl-arm
+++ b/ChangeLog.csl-arm
@@ -1,3 +1,13 @@
+2004-12-17 Paul Brook <paul@codesourcery.com>
+
+ * libstdc++/libsupc++/eh_arm.cc (__cxa_begin_cleanup): Add exception
+ to list.
+ (cxa_end_cleanup): Call __gnu_end_cleanup.
+ (__gnu_end_cleanup): New function.
+ * libstdc++/libsupc++/unwind-cxx.h (struct __cxa_exception): Add
+ field for propagating exception stack.
+ (struct __cxa_exception): Add propagatingExceptions.
+
2004-11-16 Paul Brook <paul@codesourcery.com>
* libstdc++/libsupc++/eh_arm.cc: Include cxxabi.h.
diff --git a/libstdc++-v3/libsupc++/eh_arm.cc b/libstdc++-v3/libsupc++/eh_arm.cc
index ecc86085dd0..1680ac7ae56 100644
--- a/libstdc++-v3/libsupc++/eh_arm.cc
+++ b/libstdc++-v3/libsupc++/eh_arm.cc
@@ -83,16 +83,69 @@ __cxa_type_match(_Unwind_Exception* ue_header,
return ctm_failed;
}
-extern "C" void
-__cxa_begin_cleanup(_Unwind_Exception* ue_header __attribute__((unused)))
+extern "C" bool
+__cxa_begin_cleanup(_Unwind_Exception* ue_header)
{
+ __cxa_eh_globals *globals = __cxa_get_globals();
+ __cxa_exception *header = __get_exception_header_from_ue(ue_header);
+
+ if (!__is_gxx_exception_class(header->unwindHeader.exception_class))
+ {
+ // TODO: cleanups with foreign exceptions.
+ return false;
+ }
+ header->propagationCount++;
+ // Add it to the chain if this is the first time we've seen this exception.
+ if (header->propagationCount == 1)
+ {
+ header->nextPropagatingException = globals->propagatingExceptions;
+ globals->propagatingExceptions = header;
+ }
+ return true;
+}
+
+/* Do the work for __cxa_end_cleanup. Returns the currently propagating
+ exception object. */
+extern "C" _Unwind_Exception *
+__gnu_end_cleanup(void)
+{
+ __cxa_exception *header;
+ __cxa_eh_globals *globals = __cxa_get_globals();
+
+ header = globals->propagatingExceptions;
+
+ // Check something hasn't gone horribly wrong.
+ if (!header)
+ std::terminate();
+
+ header->propagationCount--;
+ if (header->propagationCount == 0)
+ {
+ // Remove exception from chain.
+ globals->propagatingExceptions = header->nextPropagatingException;
+ header->nextPropagatingException = NULL;
+ }
+ return &header->unwindHeader;
}
-/* This needs to tailcall _Unwind_Resume without clobbering any registers,
- or altering the stack. */
+/* This needs to run the C++ semantics routine, then tailcall
+ _Unwind_Resume without clobbering any registers or altering the stack. */
extern "C" void __attribute__((naked))
-__cxa_end_cleanup (_Unwind_Exception* ue_header)
+__cxa_end_cleanup(void)
{
- _Unwind_Resume (ue_header);
+ /* We only need to save r1-r3. Push r4 to preserve stack alignment. */
+#ifdef __thumb__
+ asm volatile ("push\t{r1, r2, r3, r4}\n"
+ "bl\t__gnu_end_cleanup\n"
+ "pop\t{r1, r2, r3, r4}\n"
+ "bl\t_Unwind_Resume\n"
+ ::: "memory");
+#else
+ asm volatile ("stmfd\tsp!, {r1, r2, r3, r4}\n"
+ "bl\t__gnu_end_cleanup\n"
+ "ldmfd\tsp!, {r1, r2, r3, r4}\n"
+ "bl\t_Unwind_Resume\n"
+ ::: "memory");
+#endif
}
#endif
diff --git a/libstdc++-v3/libsupc++/unwind-cxx.h b/libstdc++-v3/libsupc++/unwind-cxx.h
index 373447a9ff5..f3db100f79f 100644
--- a/libstdc++-v3/libsupc++/unwind-cxx.h
+++ b/libstdc++-v3/libsupc++/unwind-cxx.h
@@ -67,6 +67,14 @@ struct __cxa_exception
// value is a signal that this object has been rethrown.
int handlerCount;
+#ifdef __ARM_EABI_UNWINDER__
+ // Stack of exceptions in cleanups.
+ __cxa_exception *nextPropagatingException;
+
+ // The nuber of active cleanup handlers for this exception.
+ int propagationCount;
+#endif
+
// Cache parsed handler data from the personality routine Phase 1
// for Phase 2 and __cxa_call_unexpected.
int handlerSwitchValue;
@@ -84,6 +92,9 @@ struct __cxa_eh_globals
{
__cxa_exception *caughtExceptions;
unsigned int uncaughtExceptions;
+#ifdef __ARM_EABI_UNWINDER__
+ __cxa_exception *propagatingExceptions;
+#endif
};
@@ -133,7 +144,7 @@ typedef enum {
extern "C" bool __cxa_type_match(_Unwind_Exception*, const std::type_info*,
bool, void**);
extern "C" void __cxa_begin_cleanup (_Unwind_Exception*);
-extern "C" void __cxa_end_cleanup (_Unwind_Exception*);
+extern "C" void __cxa_end_cleanup (void);
#endif
// Invokes given handler, dying appropriately if the user handler was