[cfe-commits] [libcxxabi] r149251 - in /libcxxabi/trunk/src: cxa_exception.cpp cxa_exception.hpp cxa_exception_storage.cpp cxa_handlers.cpp cxa_personality.cpp cxa_unexpected.cpp fallback_malloc.ipp

Howard Hinnant hhinnant at apple.com
Mon Jan 30 08:07:01 PST 2012


Author: hhinnant
Date: Mon Jan 30 10:07:00 2012
New Revision: 149251

URL: http://llvm.org/viewvc/llvm-project?rev=149251&view=rev
Log:
Add a descriptive name for a constant.  Also I'm at least temporarily waging war on throw specs, both old and new style.  Except where we have already publicly exposed the throw spec, I'm getting rid of them.  They may come back later.  But they seem somewhat prone to cyclic dependencies here.  The throw spec implies compiler generated code that this library has to jump to during stack unwinding.  I'd like to minimize the possiblity that the code used to properly make that jump is itself creating such jumps.

Modified:
    libcxxabi/trunk/src/cxa_exception.cpp
    libcxxabi/trunk/src/cxa_exception.hpp
    libcxxabi/trunk/src/cxa_exception_storage.cpp
    libcxxabi/trunk/src/cxa_handlers.cpp
    libcxxabi/trunk/src/cxa_personality.cpp
    libcxxabi/trunk/src/cxa_unexpected.cpp
    libcxxabi/trunk/src/fallback_malloc.ipp

Modified: libcxxabi/trunk/src/cxa_exception.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_exception.cpp?rev=149251&r1=149250&r2=149251&view=diff
==============================================================================
--- libcxxabi/trunk/src/cxa_exception.cpp (original)
+++ libcxxabi/trunk/src/cxa_exception.cpp Mon Jan 30 10:07:00 2012
@@ -21,6 +21,8 @@
 #include "cxa_exception.hpp"
 #include "cxa_handlers.hpp"
 
+#include <stdio.h>
+
 // +---------------------------+-----------------------------+---------------+
 // | __cxa_exception           | _Unwind_Exception CLNGC++\0 | thrown object |
 // +---------------------------+-----------------------------+---------------+
@@ -32,14 +34,13 @@
 // | __cxa_dependent_exception | _Unwind_Exception CLNGC++\1 |
 // +---------------------------+-----------------------------+
 
-
 namespace __cxxabiv1 {
 
 //  Utility routines
 static
 inline
 __cxa_exception*
-cxa_exception_from_thrown_object(void* thrown_object) noexcept
+cxa_exception_from_thrown_object(void* thrown_object)
 {
     return static_cast<__cxa_exception*>(thrown_object) - 1;
 }
@@ -49,7 +50,7 @@
 static
 inline
 void*
-thrown_object_from_cxa_exception(__cxa_exception* exception_header) noexcept
+thrown_object_from_cxa_exception(__cxa_exception* exception_header)
 {
     return static_cast<void*>(exception_header + 1);
 }
@@ -60,7 +61,7 @@
 static
 inline
 __cxa_exception*
-cxa_exception_from_exception_unwind_exception(_Unwind_Exception* unwind_exception) noexcept
+cxa_exception_from_exception_unwind_exception(_Unwind_Exception* unwind_exception)
 {
     return cxa_exception_from_thrown_object(unwind_exception + 1 );
 }
@@ -68,50 +69,50 @@
 static
 inline
 size_t
-cxa_exception_size_from_exception_thrown_size(size_t size) noexcept
+cxa_exception_size_from_exception_thrown_size(size_t size)
 {
     return size + sizeof (__cxa_exception);
 }
 
-static void setExceptionClass(_Unwind_Exception* unwind_exception) noexcept {
+static void setExceptionClass(_Unwind_Exception* unwind_exception) {
     unwind_exception->exception_class = kOurExceptionClass;
 }
 
-static void setDependentExceptionClass(_Unwind_Exception* unwind_exception) noexcept {
+static void setDependentExceptionClass(_Unwind_Exception* unwind_exception) {
     unwind_exception->exception_class = kOurDependentExceptionClass;
 }
 
 //  Is it one of ours?
-static bool isOurExceptionClass(_Unwind_Exception* unwind_exception) noexcept {
-    return(unwind_exception->exception_class == kOurExceptionClass)||
-               (unwind_exception->exception_class == kOurDependentExceptionClass);
+static bool isOurExceptionClass(const _Unwind_Exception* unwind_exception) {
+    return (unwind_exception->exception_class & get_language) == 
+           (kOurExceptionClass                & get_language);
 }
 
-static bool isDependentException(_Unwind_Exception* unwind_exception) noexcept {
+static bool isDependentException(_Unwind_Exception* unwind_exception) {
     return (unwind_exception->exception_class & 0xFF) == 0x01;
 }
 
 //  This does not need to be atomic
-static inline int incrementHandlerCount(__cxa_exception *exception) noexcept {
+static inline int incrementHandlerCount(__cxa_exception *exception) {
     return ++exception->handlerCount;
 }
 
 //  This does not need to be atomic
-static inline  int decrementHandlerCount(__cxa_exception *exception) noexcept {
+static inline  int decrementHandlerCount(__cxa_exception *exception) {
     return --exception->handlerCount;
 }
 
 #include "fallback_malloc.ipp"
 
 //  Allocate some memory from _somewhere_
-static void *do_malloc(size_t size) noexcept {
+static void *do_malloc(size_t size) {
     void *ptr = std::malloc(size);
     if (NULL == ptr) // if malloc fails, fall back to emergency stash
         ptr = fallback_malloc(size);
     return ptr;
 }
 
-static void do_free(void *ptr) noexcept {
+static void do_free(void *ptr) {
     is_fallback_ptr(ptr) ? fallback_free(ptr) : std::free(ptr);
 }
 
@@ -130,13 +131,14 @@
     if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason)
         std::__terminate(exception_header->terminateHandler);
 
+    // TODO: Shouldn't this check the reference count first?
     void * thrown_object = thrown_object_from_cxa_exception(exception_header);
     if (NULL != exception_header->exceptionDestructor)
         exception_header->exceptionDestructor(thrown_object);
     __cxa_free_exception(thrown_object);
 }
 
-static LIBCXXABI_NORETURN void failed_throw(__cxa_exception* exception_header) noexcept {
+static LIBCXXABI_NORETURN void failed_throw(__cxa_exception* exception_header) {
 //  Section 2.5.3 says:
 //      * For purposes of this ABI, several things are considered exception handlers:
 //      ** A terminate() call due to a throw.
@@ -155,7 +157,7 @@
 //  object. Zero-fill the object. If memory can't be allocated, call
 //  std::terminate. Return a pointer to the memory to be used for the
 //  user's exception object.
-void * __cxa_allocate_exception (size_t thrown_size) noexcept {
+void * __cxa_allocate_exception (size_t thrown_size) throw() {
     size_t actual_size = cxa_exception_size_from_exception_thrown_size(thrown_size);
     __cxa_exception* exception_header = static_cast<__cxa_exception*>(do_malloc(actual_size));
     if (NULL == exception_header)
@@ -166,7 +168,7 @@
 
 
 //  Free a __cxa_exception object allocated with __cxa_allocate_exception.
-void __cxa_free_exception (void * thrown_object) noexcept {
+void __cxa_free_exception (void * thrown_object) throw() {
     do_free(cxa_exception_from_thrown_object(thrown_object));
 }
 
@@ -174,7 +176,7 @@
 //  This function shall allocate a __cxa_dependent_exception and
 //  return a pointer to it. (Really to the object, not past its' end).
 //  Otherwise, it will work like __cxa_allocate_exception.
-void * __cxa_allocate_dependent_exception () noexcept {
+void * __cxa_allocate_dependent_exception () {
     size_t actual_size = sizeof(__cxa_dependent_exception);
     void *ptr = do_malloc(actual_size);
     if (NULL == ptr)
@@ -186,7 +188,7 @@
 
 //  This function shall free a dependent_exception.
 //  It does not affect the reference count of the primary exception.
-void __cxa_free_dependent_exception (void * dependent_exception) noexcept {
+void __cxa_free_dependent_exception (void * dependent_exception) {
     do_free(dependent_exception);
 }
 
@@ -249,9 +251,11 @@
 The adjusted pointer is computed by the personality routine during phase 1
   and saved in the exception header (either __cxa_exception or
   __cxa_dependent_exception).
+
+  Requires:  exception is native
 */
 void*
-__cxa_get_exception_ptr(void* unwind_exception) noexcept
+__cxa_get_exception_ptr(void* unwind_exception) throw()
 {
     return cxa_exception_from_exception_unwind_exception
            (
@@ -259,39 +263,75 @@
            )->adjustedPtr;
 }
     
-
 /*
-This routine:
+This routine can catch foreign or native exceptions.  If native, the exception
+can be a primary or dependent variety.  This routine may remain blissfully
+ignorant of whether the native exception is primary or dependent.
+
+If the exception is native:
 * Increment's the exception's handler count.
-* Places the exception on the stack of currently-caught exceptions if it is not 
-  already there, linking the exception to the previous top of the stack.
+* Push the exception on the stack of currently-caught exceptions if it is not 
+  already there (from a rethrow).
 * Decrements the uncaught_exception count.
-* Returns the adjusted pointer to the exception object.
+* Returns the adjusted pointer to the exception object, which is stored in
+  the __cxa_exception by the personality routine.
+
+If the exception is foreign, this means it did not originate from one of throw
+routines.  The foreign exception does not necessarily have a __cxa_exception
+header.  However we can catch it here with a catch (...), or with a call
+to terminate or unexpected during unwinding.
+* Do not try to increment the exception's handler count, we don't know where
+  it is.
+* Push the exception on the stack of currently-caught exceptions only if the
+  stack is empty.  The foreign exception has no way to link to the current
+  top of stack.  If the stack is not empty, call terminate.  Even with an
+  empty stack, this is hacked in by pushing a pointer to an imaginary
+  __cxa_exception block in front of the foreign exception.  It would be better
+  if the __cxa_eh_globals structure had a stack of _Unwind_Exception, but it
+  doesn't.  It has a stack of __cxa_exception (which has a next* in it).
+* Do not decrement the uncaught_exception count because we didn't increment it
+  in __cxa_throw (or one of our rethrow functions).
+* If we haven't terminated, assume the exception object is just past the 
+  _Unwind_Exception and return a pointer to that.
 */
 void*
-__cxa_begin_catch(void* unwind_exception) noexcept
+__cxa_begin_catch(void* unwind_arg) throw()
 {
-    __cxa_eh_globals *globals = __cxa_get_globals();
+printf("entering __cxa_begin_catch\n");
+    _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg);
+    bool native_exception = isOurExceptionClass(unwind_exception);
+    __cxa_eh_globals* globals = __cxa_get_globals();
+    // exception_header is a hackish offset from a foreign exception, but it
+    //   works as long as we're careful not to try to access any __cxa_exception
+    //   parts.
     __cxa_exception* exception_header =
             cxa_exception_from_exception_unwind_exception
             (
                 static_cast<_Unwind_Exception*>(unwind_exception)
             );
-
-// TODO:  Handle foreign exceptions?  How?
-
-//  Increment the handler count, removing the flag about being rethrown
-    exception_header->handlerCount = exception_header->handlerCount < 0 ?
-        -exception_header->handlerCount + 1 : exception_header->handlerCount + 1;
-
-//  place the exception on the top of the stack if it's not there.
-    if (exception_header != globals->caughtExceptions) {
-        exception_header->nextException = globals->caughtExceptions;
-        globals->caughtExceptions = exception_header;
+    if (native_exception)
+    {
+        // Increment the handler count, removing the flag about being rethrown
+        exception_header->handlerCount = exception_header->handlerCount < 0 ?
+            -exception_header->handlerCount + 1 : exception_header->handlerCount + 1;
+        //  place the exception on the top of the stack if it's not already
+        //    there by a previous rethrow
+        if (exception_header != globals->caughtExceptions)
+        {
+            exception_header->nextException = globals->caughtExceptions;
+            globals->caughtExceptions = exception_header;
+        }
+        globals->uncaughtExceptions -= 1;   // Not atomically, since globals are thread-local
+printf("leaving __cxa_begin_catch\n");
+        return exception_header->adjustedPtr;
     }
-        
-    globals->uncaughtExceptions -= 1;   // Not atomically, since globals are thread-local
-    return exception_header->adjustedPtr;
+    // Else this is a foreign exception
+    // If the caughtExceptions stack is not empty, terminate
+    if (globals->caughtExceptions != 0)
+        std::terminate();
+    // Push the foreign exception on to the stack
+    globals->caughtExceptions = exception_header;
+    return unwind_exception + 1;
 }
 
 
@@ -299,7 +339,8 @@
 Upon exit for any reason, a handler must call:
     void __cxa_end_catch ();
 
-This routine:
+This routine can be called for either a native or foreign exception.
+For a native exception:
 * Locates the most recently caught exception and decrements its handler count.
 * Removes the exception from the caught exception stack, if the handler count goes to zero.
 * If the handler count goes down to zero, and the exception was not re-thrown
@@ -307,45 +348,81 @@
   it's handling) and decrements its reference count. If that reference count
   goes to zero, the function destroys the exception. In any case, if the current
   exception is a dependent exception, it destroys that.
+
+For a foreign exception:
+* If it has been rethrown, there is nothing to do.
+* Otherwise delete the exception and pop the catch stack to empty.
 */
-void __cxa_end_catch() {
+void __cxa_end_catch()
+{
+printf("entering __cxa_end_catch\n");
     static_assert(sizeof(__cxa_exception) == sizeof(__cxa_dependent_exception),
                   "sizeof(__cxa_exception) must be equal to sizeof(__cxa_dependent_exception)");
-    __cxa_eh_globals *globals = __cxa_get_globals_fast(); // __cxa_get_globals called in __cxa_begin_catch
-    __cxa_exception *exception_header = globals->caughtExceptions;
-    
-    if (NULL != exception_header) {
-        // TODO:  Handle foreign exceptions?  How?
-        if (exception_header->handlerCount < 0) {
-        //  The exception has been rethrown
-            if (0 == incrementHandlerCount(exception_header)) {
-                //  Remove from the chain of uncaught exceptions
-                globals->caughtExceptions = exception_header->nextException;
-                // but don't destroy
+    __cxa_eh_globals* globals = __cxa_get_globals_fast(); // __cxa_get_globals called in __cxa_begin_catch
+    __cxa_exception* exception_header = globals->caughtExceptions;
+    // If we've rethrown a foreign exception, then globals->caughtExceptions
+    //    will have been made an empty stack by __cxa_rethrow() and there is
+    //    nothing more to be done.  Do nothing!
+    if (NULL != exception_header)
+    {
+        bool native_exception = isOurExceptionClass(&exception_header->unwindHeader);
+        if (native_exception)
+        {
+            // This is a native exception
+            if (exception_header->handlerCount < 0)
+            {
+                //  The exception has been rethrown by __cxa_rethrow, so don't delete it
+                if (0 == incrementHandlerCount(exception_header))
+                {
+                    //  Remove from the chain of uncaught exceptions
+                    globals->caughtExceptions = exception_header->nextException;
+                    // but don't destroy
+                }
+                // Keep handlerCount negative in case there are nested catch's
+                //   that need to be told that this exception is rethrown.  Don't
+                //   erase this rethrow flag until the exception is recaught.
             }
-        }
-        else {  // The exception has not been rethrown
-            if (0 == decrementHandlerCount(exception_header)) {
-                //  Remove from the chain of uncaught exceptions
-                globals->caughtExceptions = exception_header->nextException;
-                if (isDependentException(&exception_header->unwindHeader)) {
-                    // Reset exception_header to primaryException and deallocate the dependent exception
-                    __cxa_dependent_exception* dep_exception_header =
-                        reinterpret_cast<__cxa_dependent_exception*>(exception_header);
-                    exception_header =
-                        cxa_exception_from_thrown_object(dep_exception_header->primaryException);
-                    __cxa_free_dependent_exception(dep_exception_header);
+            else
+            {
+                // The native exception has not been rethrown
+                if (0 == decrementHandlerCount(exception_header))
+                {
+                    //  Remove from the chain of uncaught exceptions
+                    globals->caughtExceptions = exception_header->nextException;
+                    // Destroy this exception, being careful to distinguish
+                    //    between dependent and primary exceptions
+                    if (isDependentException(&exception_header->unwindHeader))
+                    {
+                        // Reset exception_header to primaryException and deallocate the dependent exception
+                        __cxa_dependent_exception* dep_exception_header =
+                            reinterpret_cast<__cxa_dependent_exception*>(exception_header);
+                        exception_header =
+                            cxa_exception_from_thrown_object(dep_exception_header->primaryException);
+                        __cxa_free_dependent_exception(dep_exception_header);
+                    }
+                    // Destroy the primary exception only if its referenceCount goes to 0
+                    //    (this decrement must be atomic)
+                    __cxa_decrement_exception_refcount(thrown_object_from_cxa_exception(exception_header));
                 }
-                // Destroy the primary exception only if its referenceCount goes to 0
-                //    (this decrement must be atomic)
-                __cxa_decrement_exception_refcount(thrown_object_from_cxa_exception(exception_header));
             }
         }       
+        else
+        {
+            // The foreign exception has not been rethrown.  Pop the stack
+            //    and delete it.  If there are nested catch's and they try
+            //    to touch a foreign exception in any way, that is undefined
+            //     behavior.  They likely can't since the only way to catch
+            //     a foreign exception is with catch (...)!
+            _Unwind_DeleteException(&globals->caughtExceptions->unwindHeader);
+            globals->caughtExceptions = 0;
+        }
     }
+printf("leaving __cxa_end_catch\n");
 }
 
 // Note:  exception_header may be masquerading as a __cxa_dependent_exception
 //        and that's ok.  exceptionType is there too.
+//        However watch out for foreign exceptions.  Return null for them.
 std::type_info * __cxa_current_exception_type() {
 //  get the current exception
     __cxa_eh_globals *globals = __cxa_get_globals_fast();
@@ -354,51 +431,76 @@
     __cxa_exception *exception_header = globals->caughtExceptions;
     if (NULL == exception_header)
         return NULL;        //  No current exception
+    if (!isOurExceptionClass(&exception_header->unwindHeader))
+        return NULL;
     return exception_header->exceptionType;
 }
 
 // 2.5.4 Rethrowing Exceptions
-/*  This routine 
+/*  This routine can rethrow native or foreign exceptions.
+If the exception is native:
 * marks the exception object on top of the caughtExceptions stack 
   (in an implementation-defined way) as being rethrown. 
 * If the caughtExceptions stack is empty, it calls terminate() 
   (see [C++FDIS] [except.throw], 15.1.8). 
-* It then calls _Unwind_Resume_or_Rethrow which should not return
+* It then calls _Unwind_RaiseException which should not return
    (terminate if it does).
   Note:  exception_header may be masquerading as a __cxa_dependent_exception
          and that's ok.
 */
-extern LIBCXXABI_NORETURN void __cxa_rethrow() {
-    __cxa_eh_globals *globals = __cxa_get_globals();
-    __cxa_exception *exception_header = globals->caughtExceptions;
-
-    if (NULL == exception_header)   // there's no current exception!
-        std::terminate ();
-
-// TODO:  Handle foreign exceptions?  How?
-//        Rethrow the foreign exception without touching anything!
-
-//  Mark the exception as being rethrown (reverse the effects of __cxa_begin_catch)
-    exception_header->handlerCount = -exception_header->handlerCount;
-    globals->uncaughtExceptions += 1;
-//  __cxa_end_catch will remove this exception from the caughtExceptions stack if necessary
-    
+LIBCXXABI_NORETURN
+void
+__cxa_rethrow()
+{
+    __cxa_eh_globals* globals = __cxa_get_globals();
+//printf("entering __cxa_rethrow\n");
+    __cxa_exception* exception_header = globals->caughtExceptions;
+    if (NULL == exception_header)
+        std::terminate();      // throw; called outside of a exception handler
+    bool native_exception = isOurExceptionClass(&exception_header->unwindHeader);
+    if (native_exception)
+    {
+//printf("__cxa_rethrow native branch\n");
+        //  Mark the exception as being rethrown (reverse the effects of __cxa_begin_catch)
+        exception_header->handlerCount = -exception_header->handlerCount;
+        globals->uncaughtExceptions += 1;
+        //  __cxa_end_catch will remove this exception from the caughtExceptions stack if necessary
+    }
+    else  // this is a foreign exception
+    {
+        // The only way to communicate to __cxa_end_catch that we've rethrown
+        //   a foreign exception, so don't delete us, is to pop the stack here
+        //   which must be empty afterwards.  Then __cxa_end_catch will do
+        //   nothing
+        globals->caughtExceptions = 0;
+    }
+//printf("leaving __cxa_rethrow, private_1 = %lu\n", exception_header->unwindHeader.private_1);
 #if __arm__
     (void) _Unwind_SjLj_Resume_or_Rethrow(&exception_header->unwindHeader);
 #else
-    (void) _Unwind_Resume_or_Rethrow     (&exception_header->unwindHeader);
+    (void)_Unwind_RaiseException(&exception_header->unwindHeader);
 #endif
 
-//  If we get here, some kind of unwinding error has occurred.
-    failed_throw(exception_header);
+    //  If we get here, some kind of unwinding error has occurred.
+    //  There is some weird code generation bug happening with 
+    //     Apple clang version 4.0 (tags/Apple/clang-418.0.2) (based on LLVM 3.1svn)
+    //     If we call failed_throw here.  Turns up with -O2 or higher, and -Os.
+    __cxa_begin_catch(&exception_header->unwindHeader);
+    if (native_exception)
+        std::__terminate(exception_header->terminateHandler);
+    // Foreign exception: can't get exception_header->terminateHandler
+    std::terminate();
 }
 
 /*
-    If p is not null, atomically increment the referenceCount field of the
-    __cxa_exception header associated with the thrown object referred to by p.
+    If thrown_object is not null, atomically increment the referenceCount field
+    of the __cxa_exception header associated with the thrown object referred to
+    by thrown_object.
+
+    Requires:  If thrown_object is not NULL, it is a native exception.
 */
 void
-__cxa_increment_exception_refcount(void* thrown_object) noexcept
+__cxa_increment_exception_refcount(void* thrown_object) throw()
 {
     if (thrown_object != NULL )
     {
@@ -408,12 +510,15 @@
 }
 
 /*
-    If p is not null, atomically decrement the referenceCount field of the
-    __cxa_exception header associated with the thrown object referred to by p.
-    If the referenceCount drops to zero, destroy and deallocate the exception.
+    If thrown_object is not null, atomically decrement the referenceCount field
+    of the __cxa_exception header associated with the thrown object referred to
+    by thrown_object.  If the referenceCount drops to zero, destroy and
+    deallocate the exception.
+
+    Requires:  If thrown_object is not NULL, it is a native exception.
 */
 void
-__cxa_decrement_exception_refcount(void* thrown_object) noexcept
+__cxa_decrement_exception_refcount(void* thrown_object) throw()
 {
     if (thrown_object != NULL )
     {
@@ -430,14 +535,15 @@
 /*
     Returns a pointer to the thrown object (if any) at the top of the
     caughtExceptions stack.  Atommically increment the exception's referenceCount.
-    If there is no such thrown object, returns null.
+    If there is no such thrown object or if the thrown object is foreign,
+    returns null.
 
     We can use __cxa_get_globals_fast here to get the globals because if there have
     been no exceptions thrown, ever, on this thread, we can return NULL without 
     the need to allocate the exception-handling globals.
 */
 void*
-__cxa_current_primary_exception() noexcept
+__cxa_current_primary_exception() throw()
 {
 //  get the current exception
     __cxa_eh_globals* globals = __cxa_get_globals_fast();
@@ -446,6 +552,8 @@
     __cxa_exception* exception_header = globals->caughtExceptions;
     if (NULL == exception_header)
         return NULL;        //  No current exception
+    if (!isOurExceptionClass(&exception_header->unwindHeader))
+        return NULL;        // Can't capture a foreign exception (no way to refcount it)
     if (isDependentException(&exception_header->unwindHeader)) {
         __cxa_dependent_exception* dep_exception_header =
             reinterpret_cast<__cxa_dependent_exception*>(exception_header);
@@ -483,6 +591,8 @@
 {
     if ( thrown_object != NULL )
     {
+        // thrown_object guaranteed to be native because
+        //   __cxa_current_primary_exception returns NULL for foreign exceptions
         __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
         __cxa_dependent_exception* dep_exception_header =
             static_cast<__cxa_dependent_exception*>(__cxa_allocate_dependent_exception());
@@ -506,8 +616,9 @@
 }
 
 bool
-__cxa_uncaught_exception() noexcept
+__cxa_uncaught_exception() throw()
 {
+    // This does not report foreign exceptions in flight
     __cxa_eh_globals* globals = __cxa_get_globals_fast();
     if (globals == 0)
         return false;

Modified: libcxxabi/trunk/src/cxa_exception.hpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_exception.hpp?rev=149251&r1=149250&r2=149251&view=diff
==============================================================================
--- libcxxabi/trunk/src/cxa_exception.hpp (original)
+++ libcxxabi/trunk/src/cxa_exception.hpp Mon Jan 30 10:07:00 2012
@@ -19,6 +19,7 @@
 
 static const uint64_t kOurExceptionClass          = 0x434C4E47432B2B00; // CLNGC++\0
 static const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1
+static const uint64_t get_language =                0x00000000FFFFFF00; // mask for C++
                                                     
     struct __cxa_exception { 
 #if __LP64__
@@ -102,10 +103,10 @@
 #endif
     };
 
-    extern "C" __cxa_eh_globals * __cxa_get_globals      () noexcept;
-    extern "C" __cxa_eh_globals * __cxa_get_globals_fast () noexcept;
+    extern "C" __cxa_eh_globals * __cxa_get_globals      ();
+    extern "C" __cxa_eh_globals * __cxa_get_globals_fast ();
 
-    extern "C" void * __cxa_allocate_dependent_exception () noexcept;
-    extern "C" void __cxa_free_dependent_exception (void * dependent_exception) noexcept;
+    extern "C" void * __cxa_allocate_dependent_exception ();
+    extern "C" void __cxa_free_dependent_exception (void * dependent_exception);
 
 }
\ No newline at end of file

Modified: libcxxabi/trunk/src/cxa_exception_storage.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_exception_storage.cpp?rev=149251&r1=149250&r2=149251&view=diff
==============================================================================
--- libcxxabi/trunk/src/cxa_exception_storage.cpp (original)
+++ libcxxabi/trunk/src/cxa_exception_storage.cpp Mon Jan 30 10:07:00 2012
@@ -18,15 +18,15 @@
 namespace __cxxabiv1 {
 
 namespace {
-    __cxa_eh_globals * __globals () noexcept {
+    __cxa_eh_globals * __globals () {
         static thread_local __cxa_eh_globals eh_globals;
         return &eh_globals;
         }
     }
 
 extern "C" {
-    __cxa_eh_globals * __cxa_get_globals      () noexcept { return __globals (); }
-    __cxa_eh_globals * __cxa_get_globals_fast () noexcept { return __globals (); }
+    __cxa_eh_globals * __cxa_get_globals      () { return __globals (); }
+    __cxa_eh_globals * __cxa_get_globals_fast () { return __globals (); }
     }
 }
 
@@ -43,23 +43,22 @@
 namespace __cxxabiv1 {
 namespace {
     pthread_key_t  key_;
+    pthread_once_t flag_ = PTHREAD_ONCE_INIT;
 
-    void destruct_ (void *p) noexcept {
+    void destruct_ (void *p) {
         std::free ( p );
         if ( 0 != ::pthread_setspecific ( key_, NULL ) ) 
             abort_message("cannot zero out thread value for __cxa_get_globals()");
         }
 
-    int construct_ () noexcept {
+    void construct_ () {
         if ( 0 != pthread_key_create ( &key_, destruct_ ) )
             abort_message("cannot create pthread key for __cxa_get_globals()");
-        return 0;
         }
 }   
 
 extern "C" {
-    __cxa_eh_globals * __cxa_get_globals () noexcept {
-
+    __cxa_eh_globals * __cxa_get_globals () {
     //  Try to get the globals for this thread
         __cxa_eh_globals* retVal = __cxa_get_globals_fast ();
     
@@ -79,9 +78,11 @@
     // preceeded by a call to __cxa_get_globals().  This is an extension
     // to the Itanium ABI and is taken advantage of in several places in
     // libc++abi.
-    __cxa_eh_globals * __cxa_get_globals_fast () noexcept {
+    __cxa_eh_globals * __cxa_get_globals_fast () {
     //  First time through, create the key.
-        static int init = construct_();
+        if (0 != pthread_once(&flag_, construct_))
+            abort_message("pthread_once failure in __cxa_get_globals_fast()");
+//        static int init = construct_();
         return static_cast<__cxa_eh_globals*>(::pthread_getspecific(key_));
         }
     

Modified: libcxxabi/trunk/src/cxa_handlers.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_handlers.cpp?rev=149251&r1=149250&r2=149251&view=diff
==============================================================================
--- libcxxabi/trunk/src/cxa_handlers.cpp (original)
+++ libcxxabi/trunk/src/cxa_handlers.cpp Mon Jan 30 10:07:00 2012
@@ -37,24 +37,34 @@
         {
             _Unwind_Exception* unwind_exception =
                 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1;
-            void* thrown_object =
-                unwind_exception->exception_class == kOurDependentExceptionClass ?
-                    ((__cxa_dependent_exception*)exception_header)->primaryException :
-                    exception_header + 1;
-            const __shim_type_info* thrown_type =
-                static_cast<const __shim_type_info*>(exception_header->exceptionType);
-            const __shim_type_info* catch_type =
-                static_cast<const __shim_type_info*>(&typeid(exception));
-            // If the uncaught exception can be caught with std::exception&
-            if (catch_type->can_catch(thrown_type, thrown_object))
+            bool native_exception = (unwind_exception->exception_class   & get_language) == 
+                                                     (kOurExceptionClass & get_language);
+            if (native_exception)
             {
-                // Include the what() message from the exception
-                const exception* e = static_cast<const exception*>(thrown_object);
-                abort_message("terminating with %s exception: %s", cause, e->what());
+                void* thrown_object =
+                    unwind_exception->exception_class == kOurDependentExceptionClass ?
+                        ((__cxa_dependent_exception*)exception_header)->primaryException :
+                        exception_header + 1;
+                const __shim_type_info* thrown_type =
+                    static_cast<const __shim_type_info*>(exception_header->exceptionType);
+                const __shim_type_info* catch_type =
+                    static_cast<const __shim_type_info*>(&typeid(exception));
+                // If the uncaught exception can be caught with std::exception&
+                if (catch_type->can_catch(thrown_type, thrown_object))
+                {
+                    // Include the what() message from the exception
+                    const exception* e = static_cast<const exception*>(thrown_object);
+                    abort_message("terminating with %s exception of type %s: %s",
+                                  cause, thrown_type->name(), e->what());
+                }
+                else
+                    // Else just note that we're terminating with an exception
+                    abort_message("terminating with %s exception of type %s",
+                                   cause, thrown_type->name());
             }
             else
-                // Else just note that we're terminating with an exception
-                abort_message("terminating with %s exception", cause);
+                // Else we're terminating with a foreign exception
+                abort_message("terminating with %s foreign exception", cause);
         }
     }
     // Else just note that we're terminating

Modified: libcxxabi/trunk/src/cxa_personality.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_personality.cpp?rev=149251&r1=149250&r2=149251&view=diff
==============================================================================
--- libcxxabi/trunk/src/cxa_personality.cpp (original)
+++ libcxxabi/trunk/src/cxa_personality.cpp Mon Jan 30 10:07:00 2012
@@ -14,13 +14,16 @@
 
 #include "unwind.h"
 #include "cxa_exception.hpp"
+#include "cxa_handlers.hpp"
 #include "private_typeinfo.h"
 #include <typeinfo>
 #include <stdlib.h>
 #include <assert.h>
 
+#include <stdio.h>
+
 /*
-Exception Header Layout:
+    Exception Header Layout:
 
 +---------------------------+-----------------------------+---------------+
 | __cxa_exception           | _Unwind_Exception CLNGC++\0 | thrown object |
@@ -47,19 +50,19 @@
 | callSiteEncoding | (char) | Encoding for Call Site Table |
 +------------------+--+-----+-----+------------------------+--------------------------+
 | callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table |
-+---------------------+-----------+--------------------------------------------------++
-| Beginning of Call Site Table              If the current ip lies within the        |
-| ...                                       (start, length) range of one of these    |
-|                                           call sites, there may be action needed.  |
-| +-------------+-----------------------------------+------------------------------+ |
-| | start       | (encoded with Call Site Encoding) | offset relative to funcStart | |
-| | length      | (encoded with Call Site Encoding) | lenght of code fragment      | |
-| | landingPad  | (encoded with Call Site Encoding) | offset relative to lpStart   | |
-| | actionEntry | (ULEB128)                         | Action Table Index 1-based   | |
-| |             |                                   | actionEntry == 0 -> clean up | |
-| +-------------+-----------------------------------+------------------------------+ |
-| ...                                                                                |
-+---------------------------------------------------------------------+--------------+
++---------------------+-----------+------------------------------------------------+--+
+| Beginning of Call Site Table            If the current ip lies within the        |
+| ...                                     (start, length) range of one of these    |
+|                                         call sites, there may be action needed.  |
+| +-------------+---------------------------------+------------------------------+ |
+| | start       | (encoded with callSiteEncoding) | offset relative to funcStart | |
+| | length      | (encoded with callSiteEncoding) | lenght of code fragment      | |
+| | landingPad  | (encoded with callSiteEncoding) | offset relative to lpStart   | |
+| | actionEntry | (ULEB128)                       | Action Table Index 1-based   | |
+| |             |                                 | actionEntry == 0 -> cleanup  | |
+| +-------------+---------------------------------+------------------------------+ |
+| ...                                                                              |
++---------------------------------------------------------------------+------------+
 | Beginning of Action Table       ttypeIndex == 0 : cleanup           |
 | ...                             ttypeIndex  > 0 : catch             |
 |                                 ttypeIndex  < 0 : exception spec    |
@@ -71,26 +74,47 @@
 +---------------------------------------------------------------------+-----------------+
 | type_info Table, but classInfoOffset does *not* point here!                           |
 | +----------------+------------------------------------------------+-----------------+ |
-| | Nth type_info* | Encoded with ttypeEncoding, 0 means every type | ttypeIndex == N | |
+| | Nth type_info* | Encoded with ttypeEncoding, 0 means catch(...) | ttypeIndex == N | |
 | +----------------+------------------------------------------------+-----------------+ |
 | ...                                                                                   |
 | +----------------+------------------------------------------------+-----------------+ |
-| | 1st type_info* | Encoded with ttypeEncoding, 0 means every type | ttypeIndex == 1 | |
+| | 1st type_info* | Encoded with ttypeEncoding, 0 means catch(...) | ttypeIndex == 1 | |
 | +----------------+------------------------------------------------+-----------------+ |
 | +---------------------------------------+-----------+------------------------------+  |
 | | 1st ttypeIndex for 1st exception spec | (ULEB128) | classInfoOffset points here! |  |
-| | 2nd ttypeIndex for 1st exception spec | (ULEB128) |                              |  |
-| | 3rd ttypeIndex for 1st exception spec | (ULEB128) |                              |  |
+| | ...                                   | (ULEB128) |                              |  |
+| | Mth ttypeIndex for 1st exception spec | (ULEB128) |                              |  |
 | | 0                                     | (ULEB128) |                              |  |
 | +---------------------------------------+------------------------------------------+  |
 | ...                                                                                   |
 | +---------------------------------------+------------------------------------------+  |
+| | 0                                     | (ULEB128) | throw()                      |  |
+| +---------------------------------------+------------------------------------------+  |
+| ...                                                                                   |
+| +---------------------------------------+------------------------------------------+  |
 | | 1st ttypeIndex for Nth exception spec | (ULEB128) |                              |  |
-| | 2nd ttypeIndex for Nth exception spec | (ULEB128) |                              |  |
-| | 3rd ttypeIndex for Nth exception spec | (ULEB128) |                              |  |
+| | ...                                   | (ULEB128) |                              |  |
+| | Mth ttypeIndex for Nth exception spec | (ULEB128) |                              |  |
 | | 0                                     | (ULEB128) |                              |  |
 | +---------------------------------------+------------------------------------------+  |
 +---------------------------------------------------------------------------------------+
+
+Notes:
+
+*  ttypeIndex in the Action Table, and in the exception spec table, is an index,
+     not a byte count, if positive.  It is a negative index offset of
+     classInfoOffset and the sizeof entry depends on ttypeEncoding.
+   But if ttypeIndex is negative, it is a positive 1-based byte offset into the
+     type_info Table.
+   And if ttypeIndex is zero, it refers to a catch (...).
+
+*  landingPad can be 0, this implies there is nothing to be done.
+
+*  landingPad != 0 and actionEntry == 0 implies a cleanup needs to be done
+     @landingPad.
+
+*  A cleanup can also be found under landingPad != 0 and actionEntry != 0 in
+     the Action Table with ttypeIndex == 0.
 */
 
 namespace __cxxabiv1
@@ -187,9 +211,9 @@
 // TODO:  Sometimes this is clearly not always reading an encoded pointer, for
 //        example a length in the call site table.  Needs new name?
     uintptr_t result = 0;
-    const uint8_t* p = *data;
     if (encoding == DW_EH_PE_omit) 
         return result;
+    const uint8_t* p = *data;
     // first get value 
     switch (encoding & 0x0F)
     {
@@ -259,6 +283,92 @@
 }
 
 static
+void
+call_terminate(bool native_exception, _Unwind_Exception* unwind_exception)
+{
+    __cxa_begin_catch(unwind_exception);
+    if (native_exception)
+    {
+        // Use the stored terminate_handler if possible
+        __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
+        std::__terminate(exception_header->terminateHandler);
+    }
+    std::terminate();
+}
+
+static
+const __shim_type_info*
+get_shim_type_info(int64_t ttypeIndex, const uint8_t* classInfo,
+                   uint8_t ttypeEncoding, bool native_exception,
+                   _Unwind_Exception* unwind_exception)
+{
+    // TODO:  Move this check sooner
+    if (classInfo == 0)
+    {
+        // this should not happen
+        call_terminate(native_exception, unwind_exception);
+    }
+    switch (ttypeEncoding & 0x0F)
+    {
+    case DW_EH_PE_absptr:
+        ttypeIndex *= sizeof(void*);
+        break;
+    case DW_EH_PE_udata2:
+    case DW_EH_PE_sdata2:
+        ttypeIndex *= 2;
+        break;
+    case DW_EH_PE_udata4:
+    case DW_EH_PE_sdata4:
+        ttypeIndex *= 4;
+        break;
+    case DW_EH_PE_udata8:
+    case DW_EH_PE_sdata8:
+        ttypeIndex *= 8;
+        break;
+    default:
+        // TODO:  Move this check sooner
+        // this should not happen
+        call_terminate(native_exception, unwind_exception);
+    }
+    classInfo -= ttypeIndex;
+    return (const __shim_type_info*)readEncodedPointer(&classInfo, ttypeEncoding);
+}
+
+static
+bool
+exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo,
+                         uint8_t ttypeEncoding, const __shim_type_info* excpType,
+                         void* adjustedPtr, _Unwind_Exception* unwind_exception)
+{
+    // TODO:  Move this check sooner
+    if (classInfo == 0)
+    {
+        // this should not happen
+        call_terminate(false, unwind_exception);
+    }
+    // specIndex is 1-based byte offset into classInfo;
+    --specIndex;
+    const uint8_t* temp = classInfo + specIndex;
+    // If any type in the spec list can catch excpType, return false, else return true
+    //    adjustments to adjustedPtr are ignored.
+    while (true)
+    {
+        uint64_t ttypeIndex = readULEB128(&temp);
+        if (ttypeIndex == 0)
+            break;
+        const __shim_type_info* catchType = get_shim_type_info(ttypeIndex,
+                                                               classInfo,
+                                                               ttypeEncoding,
+                                                               true,
+                                                               unwind_exception);
+        void* tempPtr = adjustedPtr;
+        if (catchType->can_catch(excpType, tempPtr))
+            return false;
+    }
+    return true;
+}
+
+static
 const uint8_t*
 getTTypeEntry(int64_t ttypeIndex, const uint8_t* classInfo, uint8_t ttypeEncoding)
 {
@@ -283,6 +393,33 @@
     return classInfo - ttypeIndex;
 }
 
+static
+void
+save_state(__cxa_exception* exception_header, int handlerSwitchValue,
+           const uint8_t* actionRecord, const uint8_t* languageSpecificData,
+           void* landingPad, void* adjustedPtr)
+{
+    exception_header->handlerSwitchValue = handlerSwitchValue;
+    exception_header->actionRecord = actionRecord;
+    exception_header->languageSpecificData = languageSpecificData;
+    exception_header->catchTemp = landingPad;
+    exception_header->adjustedPtr = adjustedPtr;
+}
+
+static
+void
+save_state_for_exception_spec(__cxa_exception* exception_header,
+                              int handlerSwitchValue,
+                              const void* classInfo,
+                              uint8_t ttypeEncoding,
+                              void* adjustedPtr)
+{
+    exception_header->handlerSwitchValue = handlerSwitchValue;
+    exception_header->languageSpecificData = static_cast<const uint8_t*>(classInfo);
+    exception_header->catchTemp = (void*)(uintptr_t)ttypeEncoding;
+    exception_header->adjustedPtr = adjustedPtr;
+}
+
 /// Deals with Dwarf actions matching our type infos 
 /// (OurExceptionType_t instances). Returns whether or not a dwarf emitted 
 /// action matches the supplied exception type. If such a match succeeds, 
@@ -293,7 +430,7 @@
 /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
 /// Also see @link http://refspecs.freestandards.org/abi-eh-1.21.html @unlink
 /// @param classInfo our array of type info pointers (to globals)
-/// @param actionEntry index into above type info array or 0 (clean up). 
+/// @param actionEntry index into above type info array or 0 (cleanup). 
 ///        We do not support filters.
 /// @param unwind_exception thrown _Unwind_Exception instance.
 /// @returns whether or not a type info was found. False is returned if only
@@ -341,7 +478,7 @@
         else if (ttypeIndex < 0)  // an exception spec
         {
         }
-        else  // ttypeIndex == 0  // a clean up
+        else  // ttypeIndex == 0  // a cleanup
         {
         }
         if (actionOffset == 0)
@@ -375,9 +512,9 @@
         //       dwarf emission
         // Parse LSDA header.
         uint8_t lpStartEncoding = *lsda++;
-        const uint8_t* lpStart = (const unit8_t*)readEncodedPointer(&lsda, lpStartEncoding);
+        const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
         if (lpStart == 0)
-            lpStart = funcStart;
+            lpStart = (const uint8_t*)funcStart;
         uint8_t ttypeEncoding = *lsda++;
         // TODO:  preflight ttypeEncoding here and return error if there's a problem
         if (ttypeEncoding != DW_EH_PE_omit)
@@ -415,9 +552,9 @@
                                              actionEntry, 
                                              unwind_exception,
                                              ttypeEncoding);
-                // Note: Only non-clean up handlers are marked as
-                //       found. Otherwise the clean up handlers will be 
-                //       re-found and executed during the clean up 
+                // Note: Only non-cleanup handlers are marked as
+                //       found. Otherwise the cleanup handlers will be 
+                //       re-found and executed during the cleanup 
                 //       phase.
                 return false;  // Won't find another call site in range of ipOffset
             }
@@ -465,10 +602,10 @@
 _UA_SEARCH_PHASE
 
     If _UA_CLEANUP_PHASE or _UA_HANDLER_FRAME or _UA_FORCE_UNWIND there's
-    an error from above, return _URC_FATAL_PHASE1_ERROR.
-    
+      an error from above, return _URC_FATAL_PHASE1_ERROR.
+
     Scan for anything that could stop unwinding:
-    
+
        1.  A catch clause that will catch this exception
            (will never catch foreign).
        2.  A catch (...) (will always catch foreign).
@@ -496,13 +633,695 @@
     
         Scan for anything that can not stop unwinding:
     
-            1.  A clean up.
+            1.  A cleanup.
         
-        If a clean up is found
+        If a cleanup is found
             transfer control to it. return _URC_INSTALL_CONTEXT
-    
-    Else a clean up is not found: return _URC_CONTINUE_UNWIND
+        Else a cleanup is not found: return _URC_CONTINUE_UNWIND
 */
+
+_Unwind_Reason_Code
+__gxx_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionClass,
+                     _Unwind_Exception* unwind_exception, _Unwind_Context* context)
+{
+printf("__gxx_personality_v0 start with unwind_exception = %p\n", unwind_exception);
+    if (version != 1 || unwind_exception == 0 || context == 0)
+        return _URC_FATAL_PHASE1_ERROR;
+    bool native_exception = (exceptionClass     & get_language) ==
+                            (kOurExceptionClass & get_language);
+    if (actions & _UA_SEARCH_PHASE)
+    {
+printf("__gxx_personality_v0 start phase 1\n");
+        // Do Phase 1
+        if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND))
+        {
+            // None of these flags should be set during Phase 1
+            return _URC_FATAL_PHASE1_ERROR;
+        }
+        // Scan for handlers
+        //   If a handler is found return _URC_HANDLER_FOUND else return _URC_CONTINUE_UNWIND
+        const uint8_t* lsda = (const uint8_t*)_Unwind_GetLanguageSpecificData(context);
+        if (lsda == 0)
+        {
+            // No LanguageSpecificData means no handlers
+printf("__gxx_personality_v0 phase 1 no lsda, returning _URC_CONTINUE_UNWIND\n");
+            return _URC_CONTINUE_UNWIND;
+        }
+        const uint8_t* languageSpecificData = lsda;
+        // Get the current instruction pointer and offset it before next
+        // instruction in the current frame which threw the exception.
+        uintptr_t ip = _Unwind_GetIP(context) - 1;
+        // Get beginning current frame's code (as defined by the 
+        // emitted dwarf code)
+        uintptr_t funcStart = _Unwind_GetRegionStart(context);
+        uintptr_t ipOffset = ip - funcStart;
+        const uint8_t* classInfo = NULL;
+        // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
+        //       dwarf emission
+        // Parse LSDA header.
+        uint8_t lpStartEncoding = *lsda++;
+        const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
+        if (lpStart == 0)
+            lpStart = (const uint8_t*)funcStart;
+        uint8_t ttypeEncoding = *lsda++;
+        if (ttypeEncoding != DW_EH_PE_omit)
+        {
+            // Calculate type info locations in emitted dwarf code which
+            // were flagged by type info arguments to llvm.eh.selector
+            // intrinsic
+            uintptr_t classInfoOffset = readULEB128(&lsda);
+            classInfo = lsda + classInfoOffset;
+        }
+        // Walk call-site table looking for range that 
+        // includes current PC. 
+        uint8_t callSiteEncoding = *lsda++;
+        uint32_t callSiteTableLength = readULEB128(&lsda);
+        const uint8_t* callSiteTableStart = lsda;
+        const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength;
+        const uint8_t* actionTableStart = callSiteTableEnd;
+        const uint8_t* callSitePtr = callSiteTableStart;
+        while (true)
+        {
+            // There is one entry per call site.
+            // The call sites are non-overlapping in [start, start+length)
+            // The call sites are ordered in increasing value of start
+            uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
+            uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding);
+            uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
+            uintptr_t actionEntry = readULEB128(&callSitePtr);
+            if ((start <= ipOffset) && (ipOffset < (start + length)))
+            {
+                // Found the call site containing ip.
+                if (landingPad == 0 || actionEntry == 0)
+                {
+                    // No handler here
+ printf("__gxx_personality_v0 phase 1 no landingPad or no actionEntry, returning _URC_CONTINUE_UNWIND\n");
+                   return _URC_CONTINUE_UNWIND;
+                }
+                // Convert 1-based byte offset into
+                const uint8_t* action = actionTableStart + (actionEntry - 1);
+                // Scan action entries until you find a matching handler, or they end
+                while (true)
+                {
+                    const uint8_t* actionRecord = action;
+                    int64_t ttypeIndex = readSLEB128(&action);
+                    const uint8_t* temp = action;
+                    int64_t actionOffset = readSLEB128(&temp);
+                    if (ttypeIndex > 0)
+                    {
+                        // Does this handler match?
+                        // First check for catch (...)
+                        const __shim_type_info* catchType =
+                            get_shim_type_info(ttypeIndex, classInfo,
+                                               ttypeEncoding, native_exception,
+                                               unwind_exception);
+                        if (catchType == 0)
+                        {
+                            // catch (...) catches everything, including foreign exceptions
+                            // If not foreign, safe state before returning
+                            if (native_exception)
+                            {
+                                __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
+                                void* adjustedPtr =
+                                    unwind_exception->exception_class == kOurDependentExceptionClass ?
+                                        ((__cxa_dependent_exception*)exception_header)->primaryException :
+                                        exception_header + 1;
+                                save_state(exception_header, static_cast<int>(ttypeIndex),
+                                           actionRecord, languageSpecificData,
+                                           const_cast<uint8_t*>(lpStart + landingPad),
+                                           adjustedPtr);
+                            }
+ printf("__gxx_personality_v0 phase 1 catch (...), returning _URC_HANDLER_FOUND\n");
+                            return _URC_HANDLER_FOUND;
+                        }
+                        // Else this is a catch (T) clause and will never
+                        //    catch a foreign exception
+                        if (native_exception)
+                        {
+                            __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
+                            void* adjustedPtr =
+                                unwind_exception->exception_class == kOurDependentExceptionClass ?
+                                    ((__cxa_dependent_exception*)exception_header)->primaryException :
+                                    exception_header + 1;
+                            const __shim_type_info* excpType =
+                                static_cast<const __shim_type_info*>(exception_header->exceptionType);
+                            if (adjustedPtr == 0 || excpType == 0)
+                            {
+                                // Something very bad happened
+                                call_terminate(native_exception, unwind_exception);
+                            }
+                            if (catchType->can_catch(excpType, adjustedPtr))
+                            {
+                                // Found a matching handler
+                                save_state(exception_header, static_cast<int>(ttypeIndex),
+                                           actionRecord, languageSpecificData,
+                                           const_cast<uint8_t*>(lpStart + landingPad),
+                                           adjustedPtr);
+ printf("__gxx_personality_v0 phase 1 catch (T), returning _URC_HANDLER_FOUND\n");
+                                return _URC_HANDLER_FOUND;
+                            }
+                        }
+                        // Scan next action ...
+                    }
+                    else if (ttypeIndex < 0)
+                    {
+                        // Found an exception spec.  If this is a foreign exception,
+                        //   it is always caught.
+                        if (!native_exception)
+                        {
+ printf("__gxx_personality_v0 phase 1 exception spec for foreign, returning _URC_HANDLER_FOUND\n");
+                            return _URC_HANDLER_FOUND;
+                        }
+                        __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
+                        void* adjustedPtr =
+                            unwind_exception->exception_class == kOurDependentExceptionClass ?
+                                ((__cxa_dependent_exception*)exception_header)->primaryException :
+                                exception_header + 1;
+                        const __shim_type_info* excpType =
+                            static_cast<const __shim_type_info*>(exception_header->exceptionType);
+                        if (adjustedPtr == 0 || excpType == 0)
+                        {
+                            // Something very bad happened
+                            call_terminate(native_exception, unwind_exception);
+                        }
+                        if (exception_spec_can_catch(ttypeIndex, classInfo,
+                                                     ttypeEncoding, excpType,
+                                                     adjustedPtr, unwind_exception))
+                        {
+                            // The state saved is a little different for exception specs
+                            save_state(exception_header,
+                                                          ttypeIndex,
+                                                          actionRecord,
+                                                          languageSpecificData,
+                                                          const_cast<uint8_t*>(lpStart + landingPad),
+                                                          adjustedPtr);
+ printf("__gxx_personality_v0 phase 1 exception spec for native, returning _URC_HANDLER_FOUND\n");
+                                return _URC_HANDLER_FOUND;
+                        }
+                        // Scan next action ...
+                    }
+                    if (actionOffset == 0)
+                    {
+                        // End of action list, no matching handler found
+ printf("__gxx_personality_v0 phase 1 no handler found, returning _URC_CONTINUE_UNWIND\n");
+                        return _URC_CONTINUE_UNWIND;
+                    }
+                    // Go to next action
+                    action += actionOffset;
+                }
+            }
+            else if (ipOffset < start)
+            {
+                // There is no call site for this ip
+                // Something bad has happened.  We should never get here.
+                // Possible stack corruption.
+                call_terminate(native_exception, unwind_exception);
+            }
+        }
+    }
+    if (actions & _UA_CLEANUP_PHASE)
+    {
+        if (actions & _UA_HANDLER_FRAME)
+        {
+printf("__gxx_personality_v0 start phase 2 handling\n");
+            // Search phase found a handler, now install it
+            if (actions & _UA_FORCE_UNWIND)
+            {
+                // This should never happen.  The search phase isn't executed
+                //   for forced unwinding, so no handler could have been found.
+                call_terminate(native_exception, unwind_exception);
+            }
+            // This is the state we need:
+            uintptr_t handlerSwitchValue;
+            uintptr_t landingPad;
+            if (native_exception)
+            {
+                // Just retrieve it from the exception_header
+                __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
+                handlerSwitchValue = static_cast<uintptr_t>(static_cast<intptr_t>(exception_header->handlerSwitchValue));
+                landingPad = reinterpret_cast<uintptr_t>(exception_header->catchTemp);
+            }
+            else
+            {
+                // Else a foreign exception, we need to find the handler that caught it
+                const uint8_t* lsda = (const uint8_t*)_Unwind_GetLanguageSpecificData(context);
+                if (lsda == 0)
+                {
+                    // If we don't find a handler, something bad happened
+                    call_terminate(native_exception, unwind_exception);
+                }
+                // Get the current instruction pointer and offset it before next
+                // instruction in the current frame which threw the exception.
+                uintptr_t ip = _Unwind_GetIP(context) - 1;
+                // Get beginning current frame's code (as defined by the 
+                // emitted dwarf code)
+                uintptr_t funcStart = _Unwind_GetRegionStart(context);
+                uintptr_t ipOffset = ip - funcStart;
+                const uint8_t* classInfo = NULL;
+                // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
+                //       dwarf emission
+                // Parse LSDA header.
+                uint8_t lpStartEncoding = *lsda++;
+                const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
+                if (lpStart == 0)
+                    lpStart = (const uint8_t*)funcStart;
+                uint8_t ttypeEncoding = *lsda++;
+                if (ttypeEncoding != DW_EH_PE_omit)
+                {
+                    // Calculate type info locations in emitted dwarf code which
+                    // were flagged by type info arguments to llvm.eh.selector
+                    // intrinsic
+                    uintptr_t classInfoOffset = readULEB128(&lsda);
+                    classInfo = lsda + classInfoOffset;
+                }
+                // Walk call-site table looking for range that 
+                // includes current PC. 
+                uint8_t callSiteEncoding = *lsda++;
+                uint32_t callSiteTableLength = readULEB128(&lsda);
+                const uint8_t* callSiteTableStart = lsda;
+                const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength;
+                const uint8_t* actionTableStart = callSiteTableEnd;
+                const uint8_t* callSitePtr = callSiteTableStart;
+                while (true)
+                {
+                    // There is one entry per call site.
+                    // The call sites are non-overlapping in [start, start+length)
+                    // The call sites are ordered in increasing value of start
+                    uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
+                    uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding);
+                    landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
+                    uintptr_t actionEntry = readULEB128(&callSitePtr);
+                    if ((start <= ipOffset) && (ipOffset < (start + length)))
+                    {
+                        // Found the call site containing ip.
+                        if (landingPad == 0 || actionEntry == 0)
+                        {
+                            // No handler here
+                            // If we don't find a handler, something bad happened
+                            call_terminate(native_exception, unwind_exception);
+                        }
+                        landingPad = (uintptr_t)lpStart + landingPad;
+                        // Convert 1-based byte offset into
+                        const uint8_t* action = actionTableStart + (actionEntry - 1);
+                        // Scan action entries until you find a matching handler, or they end
+                        while (true)
+                        {
+                            int64_t ttypeIndex = readSLEB128(&action);
+                            const uint8_t* temp = action;
+                            int64_t actionOffset = readSLEB128(&temp);
+                            if (ttypeIndex > 0)
+                            {
+                                // Does this handler match?
+                                // First check for catch (...)
+                                const __shim_type_info* catchType =
+                                    get_shim_type_info(ttypeIndex, classInfo,
+                                                       ttypeEncoding, native_exception,
+                                                       unwind_exception);
+                                if (catchType == 0)
+                                {
+                                    // catch (...) catches everything, including foreign exceptions
+                                    handlerSwitchValue = ttypeIndex;
+                                    goto install_handler;
+                                }
+                                // Else this is a catch (T) clause and will never
+                                //    catch a foreign exception
+                                // Scan next action ...
+                            }
+                            else if (ttypeIndex < 0)
+                            {
+                                // Found an exception spec.  This is a foreign exception,
+                                //   and thus is always caught.
+                                //   However the landing pad is going to call either
+                                //   __cxa_call_unexpected (for a throw spec) or
+                                //   std::terminate (for noexcept).  We
+                                //   don't know which.  And __cxa_call_unexpected
+                                //   lacks the API to recover ttypeIndex.  However
+                                //   if we were to call a variant of __cxa_call_unexpected
+                                //   from here, and if it throws an exception,
+                                //   that won't work either.  We can't propagate
+                                //   an exception out of here.  So just call
+                                //   the landing pad and let __cxa_call_unexpected
+                                //   force terminate.  There's nothing else we
+                                //   can do.
+                                handlerSwitchValue = ttypeIndex;
+                                goto install_handler;
+                            }
+                            if (actionOffset == 0)
+                            {
+                                // End of action list, no matching handler found
+                                // If we don't find a handler, something bad happened
+                                call_terminate(native_exception, unwind_exception);
+                            }
+                            // Go to next action
+                            action += actionOffset;
+                        }
+                    }
+                    else if (ipOffset < start)
+                    {
+                        // There is no call site for this ip
+                        // Something bad has happened.  We should never get here.
+                        // Possible stack corruption.
+                        call_terminate(native_exception, unwind_exception);
+                    }
+                }
+            }
+        install_handler:
+            _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), (uintptr_t)unwind_exception);
+            _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), handlerSwitchValue);
+            _Unwind_SetIP(context, landingPad);
+ printf("__gxx_personality_v0 phase 2 handler found, returning _URC_INSTALL_CONTEXT\n");
+            return _URC_INSTALL_CONTEXT;
+        }
+printf("__gxx_personality_v0 start phase 2 cleanup\n");
+        // Else scan for a cleanup.
+        //  If handler found and !_UA_FORCE_UNWIND, terminate.
+        //  If cleanup found, install it.
+        //  If nothing found return _URC_CONTINUE_UNWIND
+        const uint8_t* lsda = (const uint8_t*)_Unwind_GetLanguageSpecificData(context);
+        if (lsda == 0)
+        {
+            // No LanguageSpecificData means no handlers
+ printf("__gxx_personality_v0 phase 2 no lsda, returning _URC_CONTINUE_UNWIND\n");
+            return _URC_CONTINUE_UNWIND;
+        }
+        // Get the current instruction pointer and offset it before next
+        // instruction in the current frame which threw the exception.
+        uintptr_t ip = _Unwind_GetIP(context) - 1;
+        // Get beginning current frame's code (as defined by the 
+        // emitted dwarf code)
+        uintptr_t funcStart = _Unwind_GetRegionStart(context);
+        uintptr_t ipOffset = ip - funcStart;
+        const uint8_t* classInfo = NULL;
+        // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
+        //       dwarf emission
+        // Parse LSDA header.
+        uint8_t lpStartEncoding = *lsda++;
+        const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
+        if (lpStart == 0)
+            lpStart = (const uint8_t*)funcStart;
+        uint8_t ttypeEncoding = *lsda++;
+        if (ttypeEncoding != DW_EH_PE_omit)
+        {
+            // Calculate type info locations in emitted dwarf code which
+            // were flagged by type info arguments to llvm.eh.selector
+            // intrinsic
+            uintptr_t classInfoOffset = readULEB128(&lsda);
+            classInfo = lsda + classInfoOffset;
+        }
+        // Walk call-site table looking for range that 
+        // includes current PC. 
+        uint8_t callSiteEncoding = *lsda++;
+        uint32_t callSiteTableLength = readULEB128(&lsda);
+        const uint8_t* callSiteTableStart = lsda;
+        const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength;
+        const uint8_t* actionTableStart = callSiteTableEnd;
+        const uint8_t* callSitePtr = callSiteTableStart;
+        while (true)
+        {
+            // There is one entry per call site.
+            // The call sites are non-overlapping in [start, start+length)
+            // The call sites are ordered in increasing value of start
+            uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
+            uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding);
+            uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
+            uintptr_t actionEntry = readULEB128(&callSitePtr);
+            if ((start <= ipOffset) && (ipOffset < (start + length)))
+            {
+                // Found the call site containing ip.
+                if (landingPad == 0)
+                {
+                    // No handler here
+ printf("__gxx_personality_v0 phase 2 no landingPad, returning _URC_CONTINUE_UNWIND\n");
+                    return _URC_CONTINUE_UNWIND;
+                }
+                landingPad = (uintptr_t)lpStart + landingPad;
+                if (actionEntry == 0)
+                {
+                    // Found a cleanup, install it:
+                    _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), (uintptr_t)unwind_exception);
+                    _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0);
+                    _Unwind_SetIP(context, landingPad);
+ printf("__gxx_personality_v0 phase 2 found cleanup 1, returning _URC_INSTALL_CONTEXT\n");
+                    return _URC_INSTALL_CONTEXT;
+                }
+                // Convert 1-based byte offset into
+                const uint8_t* action = actionTableStart + (actionEntry - 1);
+                // Scan action entries until you find a matching handler, or they end
+                while (true)
+                {
+                    int64_t ttypeIndex = readSLEB128(&action);
+                    const uint8_t* temp = action;
+                    int64_t actionOffset = readSLEB128(&temp);
+                    if (ttypeIndex > 0)
+                    {
+                        // Does this handler match?
+                        // First check for catch (...)
+                        const __shim_type_info* catchType =
+                            get_shim_type_info(ttypeIndex, classInfo,
+                                               ttypeEncoding, native_exception,
+                                               unwind_exception);
+                        if (catchType == 0)
+                        {
+                            // catch (...) catches everything, including foreign exceptions
+                            if (!(actions & _UA_FORCE_UNWIND))
+                            {
+                                // Something bad has happened.  We should never get here.
+                                // We should have found this handler in phase 1
+                                // Possible stack corruption.
+                                call_terminate(native_exception, unwind_exception);
+                            }
+                            // Ignoring this handler because we are forced
+                        }
+                        else
+                        {
+                            // Else this is a catch (T) clause and will never
+                            //    catch a foreign exception
+                            if (native_exception)
+                            {
+                                __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
+                                void* adjustedPtr =
+                                    unwind_exception->exception_class == kOurDependentExceptionClass ?
+                                        ((__cxa_dependent_exception*)exception_header)->primaryException :
+                                        exception_header + 1;
+                                const __shim_type_info* excpType =
+                                    static_cast<const __shim_type_info*>(exception_header->exceptionType);
+                                if (adjustedPtr == 0 || excpType == 0)
+                                {
+                                    // Something very bad happened
+                                    call_terminate(native_exception, unwind_exception);
+                                }
+                                if (catchType->can_catch(excpType, adjustedPtr))
+                                {
+                                    // Found a matching handler
+                                    if (!(actions & _UA_FORCE_UNWIND))
+                                    {
+                                        // Something bad has happened.  We should never get here.
+                                        // We should have found this handler in phase 1
+                                        // Possible stack corruption.
+                                        call_terminate(native_exception, unwind_exception);
+                                    }
+                                    // Ignoring this handler because we are forced
+                                }
+                            }
+                        }
+                        // Scan next action ...
+                    }
+                    else if (ttypeIndex < 0)
+                    {
+                        // Found an exception spec.  If this is a foreign exception,
+                        //   it is always caught.
+                        if (!native_exception)
+                        {
+                            if (!(actions & _UA_FORCE_UNWIND))
+                            {
+                                // Something bad has happened.  We should never get here.
+                                // We should have found this handler in phase 1
+                                // Possible stack corruption.
+                                call_terminate(native_exception, unwind_exception);
+                            }
+                        }
+                        else
+                        {
+                            __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
+                            void* adjustedPtr =
+                                unwind_exception->exception_class == kOurDependentExceptionClass ?
+                                    ((__cxa_dependent_exception*)exception_header)->primaryException :
+                                    exception_header + 1;
+                            const __shim_type_info* excpType =
+                                static_cast<const __shim_type_info*>(exception_header->exceptionType);
+                            if (adjustedPtr == 0 || excpType == 0)
+                            {
+                                // Something very bad happened
+                                call_terminate(native_exception, unwind_exception);
+                            }
+                            if (exception_spec_can_catch(ttypeIndex, classInfo,
+                                                         ttypeEncoding, excpType,
+                                                         adjustedPtr, unwind_exception))
+                            {
+                                if (!(actions & _UA_FORCE_UNWIND))
+                                {
+                                    // Something bad has happened.  We should never get here.
+                                    // We should have found this handler in phase 1
+                                    // Possible stack corruption.
+                                    call_terminate(native_exception, unwind_exception);
+                                }
+                            }
+                        }
+                        // Scan next action ...
+                    }
+                    else  // ttypeIndex == 0
+                    {
+                        // Found a cleanup, install it:
+                        _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), (uintptr_t)unwind_exception);
+                        _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0);
+                        _Unwind_SetIP(context, landingPad);
+ printf("__gxx_personality_v0 phase 2 found cleanup 2, returning _URC_INSTALL_CONTEXT\n");
+                        return _URC_INSTALL_CONTEXT;
+                    }
+                    if (actionOffset == 0)
+                    {
+                        // End of action list, no matching handler or cleanup found
+ printf("__gxx_personality_v0 phase 2 found no cleanups, returning _URC_CONTINUE_UNWIND\n");
+                        return _URC_CONTINUE_UNWIND;
+                    }
+                    // Go to next action
+                    action += actionOffset;
+                }
+            }
+            else if (ipOffset < start)
+            {
+                // There is no call site for this ip
+                // Something bad has happened.  We should never get here.
+                // Possible stack corruption.
+                call_terminate(native_exception, unwind_exception);
+            }
+        }
+    }
+    // Neither _UA_SEARCH_PHASE nor _UA_CLEANUP_PHASE
+    return _URC_FATAL_PHASE1_ERROR;
+}
+
+__attribute__((noreturn))
+void
+__cxa_call_unexpected(void* arg)
+{
+printf("__cxa_call_unexpected A\n");
+    _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(arg);
+    if (unwind_exception == 0)
+        call_terminate(true, unwind_exception);
+    __cxa_begin_catch(unwind_exception);
+    bool native_old_exception = (unwind_exception->exception_class & get_language) ==
+                                (kOurExceptionClass                & get_language);
+    std::unexpected_handler u_handler;
+    std::terminate_handler t_handler;
+    __cxa_exception* old_exception_header = 0;
+    if (native_old_exception)
+    {
+        old_exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
+        t_handler = old_exception_header->terminateHandler;
+        u_handler = old_exception_header->unexpectedHandler;
+    }
+    else
+    {
+        t_handler = std::get_terminate();
+        u_handler = std::get_unexpected();
+    }
+    try
+    {
+        std::__unexpected(u_handler);
+    }
+    catch (...)
+    {
+        // If the old exception is foreign, then all we can do is terminate.
+        //   We have no way to recover the needed old exception spec.  There's
+        //   no way to pass that information here.  And the personality routine
+        //   can't call us directly and do anything but terminate() if we throw
+        //   from here.
+        if (native_old_exception)
+        {
+            int64_t ttypeIndex = old_exception_header->handlerSwitchValue;
+            // Have:
+            //   old_exception_header->languageSpecificData
+            //   old_exception_header->actionRecord
+            // Need
+            //   const uint8_t* classInfo
+            //   uint8_t ttypeEncoding
+            const uint8_t* lsda = old_exception_header->languageSpecificData;
+            uint8_t lpStartEncoding = *lsda++;
+            const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
+            uint8_t ttypeEncoding = *lsda++;
+            if (ttypeEncoding == DW_EH_PE_omit)
+                std::__terminate(t_handler);
+            uintptr_t classInfoOffset = readULEB128(&lsda);
+            const uint8_t* classInfo = lsda + classInfoOffset;
+            // Is this new exception catchable by the exception spec at ttypeIndex?
+            // The answer is obviously yes if the new and old exceptions are the same exception
+            // If no
+            //    throw;
+            __cxa_eh_globals* globals = __cxa_get_globals_fast();
+            __cxa_exception* new_exception_header = globals->caughtExceptions;
+            if (new_exception_header == 0)
+                // This shouldn't be able to happen!
+                std::__terminate(t_handler);
+            bool native_new_exception =
+                (new_exception_header->unwindHeader.exception_class & get_language) ==
+                                                (kOurExceptionClass & get_language);
+            void* adjustedPtr;
+            if (native_new_exception && new_exception_header != old_exception_header)
+            {
+                const __shim_type_info* excpType =
+                    static_cast<const __shim_type_info*>(new_exception_header->exceptionType);
+                adjustedPtr =
+                    new_exception_header->unwindHeader.exception_class == kOurDependentExceptionClass ?
+                        ((__cxa_dependent_exception*)new_exception_header)->primaryException :
+                        new_exception_header + 1;
+                if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,
+                                              excpType, adjustedPtr, unwind_exception))
+                {
+                    // We need to __cxa_end_catch, but for the old exception,
+                    //   not the new one.  This is a little tricky ...
+                    // Disguise new_exception_header as a rethrown exception, but
+                    //   don't actually rethrow it.  This means you can temporarily
+                    //   end the catch clause enclosing new_exception_header without
+                    //   __cxa_end_catch destroying new_exception_header.
+                    new_exception_header->handlerCount = -new_exception_header->handlerCount;
+                    globals->uncaughtExceptions += 1;
+                    // Call __cxa_end_catch for new_exception_header
+                    __cxa_end_catch();
+                    // Call __cxa_end_catch for old_exception_header
+                    __cxa_end_catch();
+                    // Renter this catch clause with new_exception_header
+                    __cxa_begin_catch(&new_exception_header->unwindHeader);
+                    // Rethrow new_exception_header
+                    throw;
+                }
+            }
+            // Will a std::bad_exception be catchable by the exception spec at
+            //   ttypeIndex?
+            // If no
+            //    throw std::bad_exception();
+            const __shim_type_info* excpType =
+                static_cast<const __shim_type_info*>(&typeid(std::bad_exception));
+            std::bad_exception be;
+            adjustedPtr = &be;
+            if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,
+                                          excpType, adjustedPtr, unwind_exception))
+            {
+                // We need to __cxa_end_catch for both the old exception and the
+                //   new exception.  Technically we should do it in that order.
+                //   But it is expedent to do it in the opposite order:
+                // Call __cxa_end_catch for new_exception_header
+                __cxa_end_catch();
+                // Throw std::bad_exception will __cxa_end_catch for
+                //   old_exception_header
+                throw be;
+            }
+        }
+    }
+    std::__terminate(t_handler);
+}
+
+/*
 _Unwind_Reason_Code
 __gxx_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionClass,
                      _Unwind_Exception* unwind_exception, _Unwind_Context* context)
@@ -551,7 +1370,7 @@
     }
     return _URC_FATAL_PHASE1_ERROR;
 }
-
+*/
 }  // extern "C"
 
 }  // __cxxabiv1

Modified: libcxxabi/trunk/src/cxa_unexpected.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_unexpected.cpp?rev=149251&r1=149250&r2=149251&view=diff
==============================================================================
--- libcxxabi/trunk/src/cxa_unexpected.cpp (original)
+++ libcxxabi/trunk/src/cxa_unexpected.cpp Mon Jan 30 10:07:00 2012
@@ -8,20 +8,20 @@
 //===----------------------------------------------------------------------===//
 
 #include <exception>
+#include <cxxabi.h>
+#include "cxa_exception.hpp"
+
+namespace __cxxabiv1
+{
 
 #pragma GCC visibility push(default)
 
 extern "C"
 {
 
-__attribute__((noreturn))
-void
-__cxa_call_unexpected (void*)
-{
-    // TODO:  Completely unfinished!
-    std::terminate();
-}
-
 }
 
 #pragma GCC visibility pop
+
+}  // namespace __cxxabiv1
+

Modified: libcxxabi/trunk/src/fallback_malloc.ipp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/fallback_malloc.ipp?rev=149251&r1=149250&r2=149251&view=diff
==============================================================================
--- libcxxabi/trunk/src/fallback_malloc.ipp (original)
+++ libcxxabi/trunk/src/fallback_malloc.ipp Mon Jan 30 10:07:00 2012
@@ -50,26 +50,26 @@
 static const heap_node *list_end = (heap_node *) ( &heap [ HEAP_SIZE ] );   // one past the end of the heap
 static heap_node *freelist = NULL;
 
-heap_node *node_from_offset ( const heap_offset offset ) noexcept
+heap_node *node_from_offset ( const heap_offset offset )
     { return (heap_node *) ( heap + ( offset * sizeof (heap_node))); }
 
-heap_offset offset_from_node ( const heap_node *ptr ) noexcept
+heap_offset offset_from_node ( const heap_node *ptr )
     { return (((char *) ptr ) - heap)  / sizeof (heap_node); }
  
-void init_heap () noexcept {
+void init_heap () {
     freelist = (heap_node *) heap;
     freelist->next_node = offset_from_node ( list_end );
     freelist->len = HEAP_SIZE / sizeof (heap_node);
     }
     
 //  How big a chunk we allocate
-size_t alloc_size (size_t len) noexcept
+size_t alloc_size (size_t len)
     { return (len + sizeof(heap_node) - 1) / sizeof(heap_node) + 1; }
 
-bool is_fallback_ptr ( void *ptr ) noexcept
+bool is_fallback_ptr ( void *ptr )
     { return ptr >= heap && ptr < ( heap + HEAP_SIZE ); }
 
-void *fallback_malloc(size_t len) noexcept {
+void *fallback_malloc(size_t len) {
     heap_node *p, *prev;
     const size_t nelems = alloc_size ( len );
     mutexor mtx ( &heap_mutex );
@@ -104,9 +104,9 @@
 }
 
 //  Return the start of the next block
-heap_node *after ( struct heap_node *p ) noexcept { return p + p->len; }
+heap_node *after ( struct heap_node *p ) { return p + p->len; }
 
-void fallback_free (void *ptr) noexcept {
+void fallback_free (void *ptr) {
     struct heap_node *cp = ((struct heap_node *) ptr) - 1;      // retrieve the chunk
     struct heap_node *p, *prev;
 





More information about the cfe-commits mailing list