This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[csl-arm] Fix __cxa{begin,end}_cleanup


I not must have been concentrating when I implemented 
__cxa_{begin,end}_cleanup because I got the interface wrong.
These should maintain a stack of propagating exceptions so that that caller 
does not need to pass the exception object to cxa_end_cleanup.
The attached patch rectifies this.

Tested with cross to arm-none-eabi and arm-unknown-elf.
Applied to csl-arm-branch.

Paul

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.
Index: libsupc++/eh_arm.cc
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/libstdc++-v3/libsupc++/Attic/eh_arm.cc,v
retrieving revision 1.1.2.3
diff -u -p -r1.1.2.3 eh_arm.cc
--- libsupc++/eh_arm.cc	17 Nov 2004 00:10:57 -0000	1.1.2.3
+++ libsupc++/eh_arm.cc	10 Dec 2004 12:56:50 -0000
@@ -83,16 +83,69 @@ __cxa_type_match(_Unwind_Exception* ue_h
   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
Index: libsupc++/unwind-cxx.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/libstdc++-v3/libsupc++/unwind-cxx.h,v
retrieving revision 1.6.8.3
diff -u -p -r1.6.8.3 unwind-cxx.h
--- libsupc++/unwind-cxx.h	17 Nov 2004 00:10:57 -0000	1.6.8.3
+++ libsupc++/unwind-cxx.h	17 Dec 2004 01:17:56 -0000
@@ -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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]