cxa_exception.cpp revision 57d64cd19aee4b6cf4acf6184a3f5d454bb69e9d
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===------------------------- cxa_exception.cpp --------------------------===//
25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//                     The LLVM Compiler Infrastructure
45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is dual licensed under the MIT and the University of Illinois Open
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// Source Licenses. See LICENSE.TXT for details.
75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  This file implements the "Exception Handling APIs"
105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  http://www.codesourcery.com/public/cxx-abi/abi-eh.html
115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "cxxabi.h"
152eadfb638eb1bb6ccfd6fd0453e764d47e27eed9Chris Lattner
165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <exception>        // for std::terminate
17c7229c338c21ef26b01ef3ecf9eec4fd373fa9ecChris Lattner#include <cstdlib>          // for malloc, free
18da5a6b6d9fd52899499d5b7b46273ec844dcaa6eChris Lattner#include <string>           // for memset
198a99764f9b778a54e7440b1ee06a1e48f25d76d8Nate Begeman#include <pthread.h>
208a99764f9b778a54e7440b1ee06a1e48f25d76d8Nate Begeman
215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "cxa_exception.hpp"
225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "cxa_handlers.hpp"
235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencernamespace __cxxabiv1 {
255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic const uint64_t kOurExceptionClass          = 0x434C4E47432B2B00; // CLNGC++\0
265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1
275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  Utility routines
295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic inline __cxa_exception *exception_from_thrown_object(void *p) throw() {
305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return ((__cxa_exception *) p) - 1;
315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic inline void * thrown_object_from_exception(void *p) throw() {
345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return (void *) (((__cxa_exception *) p) + 1 );
355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic inline size_t object_size_from_exception_size(size_t size) throw() {
385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return size + sizeof (__cxa_exception);
395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  Get the exception object from the unwind pointer.
425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  Relies on the structure layout, where the unwind pointer is right in
435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  front of the user's exception object
445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic __cxa_exception *
455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerexception_from_exception_object(void *ptr) throw() {
465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    _Unwind_Exception *p = reinterpret_cast<_Unwind_Exception *>(ptr);
475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return exception_from_thrown_object(p + 1 );
485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void setExceptionClass(_Unwind_Exception *unwind) throw() {
515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    unwind->exception_class = kOurExceptionClass;
525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void setDependentExceptionClass(_Unwind_Exception *unwind) throw() {
555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    unwind->exception_class = kOurDependentExceptionClass;
565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  Is it one of ours?
595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic bool isOurExceptionClass(_Unwind_Exception *unwind) throw() {
605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return(unwind->exception_class == kOurExceptionClass)||
615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer               (unwind->exception_class == kOurDependentExceptionClass);
625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic bool isDependentException(_Unwind_Exception *unwind) throw() {
655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return (unwind->exception_class & 0xFF) == 0x01;
665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  This does not need to be atomic
695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic inline int incrementHandlerCount(__cxa_exception *exception) throw() {
705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return ++exception->handlerCount;
715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  This does not need to be atomic
745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic inline  int decrementHandlerCount(__cxa_exception *exception) throw() {
7573d0d4fac161ed12926e010dcf8b448a8de6a2ecChris Lattner    return --exception->handlerCount;
765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "fallback_malloc.cpp"
795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  Allocate some memory from _somewhere_
815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void *do_malloc(size_t size) throw() {
825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    void *ptr = std::malloc(size);
83e2ce1d9440186cf3332368291cd884a6e3ae8946Nate Begeman    if (NULL == ptr) // if malloc fails, fall back to emergency stash
845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        ptr = fallback_malloc(size);
855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return ptr;
8677ed8e4edf6ed78c53fb20ec3210aff2a59c9d87Ted Kremenek}
8777ed8e4edf6ed78c53fb20ec3210aff2a59c9d87Ted Kremenek
8877ed8e4edf6ed78c53fb20ec3210aff2a59c9d87Ted Kremenek//  Didn't know you could "return <expression>" from a void function, did you?
895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  Well, you can, if the type of the expression is "void" also.
9077ed8e4edf6ed78c53fb20ec3210aff2a59c9d87Ted Kremenekstatic void do_free(void *ptr) throw() {
915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return is_fallback_ptr(ptr) ? fallback_free(ptr) : std::free(ptr);
925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
94d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner/*
95d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner    If reason isn't _URC_FOREIGN_EXCEPTION_CAUGHT, then the terminateHandler
96d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner    stored in exc is called.  Otherwise the exceptionDestructor stored in
97d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner    exc is called, and then the memory for the exception is deallocated.
98d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner*/
99d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattnerstatic void exception_cleanup_func(_Unwind_Reason_Code reason, struct _Unwind_Exception* exc) {
100d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner    __cxa_exception *exception = exception_from_exception_object(exc);
101d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner    if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason)
102d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner        std::__terminate(exception->terminateHandler);
103d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner
104d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner    void * thrown_object = thrown_object_from_exception(exception);
105d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner    if (NULL != exception->exceptionDestructor)
106d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner        exception->exceptionDestructor(thrown_object);
107d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner    __cxa_free_exception(thrown_object);
108d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner}
109d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner
110d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattnerstatic LIBCXXABI_NORETURN void failed_throw(__cxa_exception *exception) throw() {
111d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner//  Section 2.5.3 says:
112d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner//      * For purposes of this ABI, several things are considered exception handlers:
113d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner//      ** A terminate() call due to a throw.
114d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner//  and
115d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner//      * Upon entry, Following initialization of the catch parameter,
116d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner//          a handler must call:
117d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner//      * void *__cxa_begin_catch(void *exceptionObject );
118d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner    (void) __cxa_begin_catch(&exception->unwindHeader);
119d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner    std::__terminate(exception->terminateHandler);
120d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner}
121d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner
122d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattnerextern "C" {
123c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff
124c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff//  Allocate a __cxa_exception object, and zero-fill it.
125c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff//  Reserve "thrown_size" bytes on the end for the user's exception
126c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff//  object. Zero-fill the object. If memory can't be allocated, call
127c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff//  std::terminate. Return a pointer to the memory to be used for the
128c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff//  user's exception object.
129c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroffvoid * __cxa_allocate_exception (size_t thrown_size) throw() {
130c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff    size_t actual_size = object_size_from_exception_size(thrown_size);
131c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff    void *ptr = do_malloc(actual_size);
132c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff    if (NULL == ptr)
133c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff        std::terminate();
134c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff    std::memset(ptr, 0, actual_size);
135bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson    return thrown_object_from_exception(ptr);
136bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson}
137bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson
138bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson
139bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson//  Free a __cxa_exception object allocated with __cxa_allocate_exception.
140bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlssonvoid __cxa_free_exception (void * thrown_exception) throw() {
141bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson    do_free(exception_from_thrown_object(thrown_exception));
142bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson}
143bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson
144861dc46e3c53d64d8685fd9a0f95faac710b61c6Eli Friedman
145861dc46e3c53d64d8685fd9a0f95faac710b61c6Eli Friedman//  This function shall allocate a __cxa_dependent_exception and
146c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff//  return a pointer to it. (Really to the object, not past its' end).
147d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner//  Otherwise, it will work like __cxa_allocate_exception.
14813b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffvoid * __cxa_allocate_dependent_exception () throw() {
14913b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    size_t actual_size = sizeof(__cxa_dependent_exception);
15013b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    void *ptr = do_malloc(actual_size);
15113b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    if (NULL == ptr)
15213b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff        std::terminate();
15313b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    std::memset(ptr, 0, actual_size);
15413b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    return ptr;
15513b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff}
15613b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff
15713b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff
15813b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff//  This function shall free a dependent_exception.
15913b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff//  It does not affect the reference count of the primary exception.
16013b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffvoid __cxa_free_dependent_exception (void * dependent_exception) throw() {
16113b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    do_free(dependent_exception);
16213b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff}
16313b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff
16413b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff
16513b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff// 2.4.3 Throwing the Exception Object
16613b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff/*
16713b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve NaroffAfter constructing the exception object with the throw argument value,
16813b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffthe generated code calls the __cxa_throw runtime library routine. This
16913b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffroutine never returns.
17013b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff
17113b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve NaroffThe __cxa_throw routine will do the following:
17213b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff
17313b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff* Obtain the __cxa_exception header from the thrown exception object address,
17413b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffwhich can be computed as follows:
17513b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff __cxa_exception *header = ((__cxa_exception *) thrown_exception - 1);
17613b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff* Save the current unexpected_handler and terminate_handler in the __cxa_exception header.
17713b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff* Save the tinfo and dest arguments in the __cxa_exception header.
17813b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff* Set the exception_class field in the unwind header. This is a 64-bit value
17913b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffrepresenting the ASCII string "XXXXC++\0", where "XXXX" is a
18013b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffvendor-dependent string. That is, for implementations conforming to this
18113b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve NaroffABI, the low-order 4 bytes of this 64-bit value will be "C++\0".
18213b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff* Increment the uncaught_exception flag.
18313b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff* Call _Unwind_RaiseException in the system unwind library, Its argument is the
18413b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffpointer to the thrown exception, which __cxa_throw itself received as an argument.
18513b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff__Unwind_RaiseException begins the process of stack unwinding, described
18613b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffin Section 2.5. In special cases, such as an inability to find a
18713b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffhandler, _Unwind_RaiseException may return. In that case, __cxa_throw
18813b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffwill call terminate, assuming that there was no handler for the
18913b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffexception.
19013b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff*/
19113b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve NaroffLIBCXXABI_NORETURN void
19213b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff__cxa_throw(void * thrown_exception, std::type_info * tinfo, void (*dest)(void *)) {
19313b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    __cxa_eh_globals *globals = __cxa_get_globals();
19413b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    __cxa_exception *exception = exception_from_thrown_object(thrown_exception);
19513b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff
19613b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    exception->unexpectedHandler = std::get_unexpected();
19713b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    exception->terminateHandler  = std::get_terminate();
19813b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    exception->exceptionType = tinfo;
19913b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    exception->exceptionDestructor = dest;
20013b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    setExceptionClass(&exception->unwindHeader);
20113b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    exception->referenceCount = 1;  // This is a newly allocated exception, no need for thread safety.
20213b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    globals->uncaughtExceptions += 1;   // Not atomically, since globals are thread-local
20313b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff
20413b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    exception->unwindHeader.exception_cleanup = exception_cleanup_func;
20513b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff#if __arm__
20613b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    _Unwind_SjLj_RaiseException(&exception->unwindHeader);
20713b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff#else
20813b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    _Unwind_RaiseException(&exception->unwindHeader);
20913b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff#endif
2103ef5bc03d0bfc05fd76fc83beeb1b7ddbbb463daChris Lattner//  If we get here, some kind of unwinding error has occurred.
21113b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff    failed_throw(exception);
21213b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff}
21313b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff
21413b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff
21513b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff// 2.5.3 Exception Handlers
21613b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffextern void * __cxa_get_exception_ptr(void * exceptionObject) throw() {
2175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return exception_from_exception_object(exceptionObject);
2185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
2195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/*
2225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerThis routine:
2235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer* Increment's the exception's handler count.
2245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer* Places the exception on the stack of currently-caught exceptions if it is not
2255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  already there, linking the exception to the previous top of the stack.
2265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer* Decrements the uncaught_exception count.
2275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer* Returns the adjusted pointer to the exception object.
2285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer*/
2295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid * __cxa_begin_catch(void * exceptionObject) throw() {
2305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    __cxa_eh_globals *globals = __cxa_get_globals();
2315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    __cxa_exception *exception = exception_from_exception_object(exceptionObject);
2325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// TODO:  Handle foreign exceptions?  How?
2345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  Increment the handler count, removing the flag about being rethrown
2365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    exception->handlerCount = exception->handlerCount < 0 ?
2375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        -exception->handlerCount + 1 : exception->handlerCount + 1;
2385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  place the exception on the top of the stack if it's not there.
2405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    if (exception != globals->caughtExceptions) {
2415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        exception->nextException = globals->caughtExceptions;
2425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        globals->caughtExceptions = exception;
2435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
2445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    globals->uncaughtExceptions -= 1;   // Not atomically, since globals are thread-local
2465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return thrown_object_from_exception(exception);
2475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
2485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/*
2515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerUpon exit for any reason, a handler must call:
2525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    void __cxa_end_catch ();
2535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerThis routine:
25566b5a8a39088598c01a9fa6f032dc908612dc8ecAnders Carlsson* Locates the most recently caught exception and decrements its handler count.
25666b5a8a39088598c01a9fa6f032dc908612dc8ecAnders Carlsson* Removes the exception from the caught exception stack, if the handler count goes to zero.
25766b5a8a39088598c01a9fa6f032dc908612dc8ecAnders Carlsson* If the handler count goes down to zero, and the exception was not re-thrown
258c5ae899b4bbf65488445316c63168079177db0edSteve Naroff  by throw, it locates the primary exception (which may be the same as the one
259c5ae899b4bbf65488445316c63168079177db0edSteve Naroff  it's handling) and decrements its reference count. If that reference count
26066b5a8a39088598c01a9fa6f032dc908612dc8ecAnders Carlsson  goes to zero, the function destroys the exception. In any case, if the current
26166b5a8a39088598c01a9fa6f032dc908612dc8ecAnders Carlsson  exception is a dependent exception, it destroys that.
262c5ae899b4bbf65488445316c63168079177db0edSteve Naroff*/
26366b5a8a39088598c01a9fa6f032dc908612dc8ecAnders Carlssonvoid __cxa_end_catch() {
2645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    __cxa_eh_globals *globals = __cxa_get_globals_fast(); // __cxa_get_globals called in __cxa_begin_catch
2655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    __cxa_exception *current_exception = globals->caughtExceptions;
2665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    if (NULL != current_exception) {
2685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        // TODO:  Handle foreign exceptions?  How?
2695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        if (current_exception->handlerCount < 0) {
2705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        //  The exception has been rethrown
2715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            if (0 == incrementHandlerCount(current_exception)) {
2725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                //  Remove from the chain of uncaught exceptions
2735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                globals->caughtExceptions = current_exception->nextException;
2745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                // but don't destroy
2755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            }
2765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        }
2775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        else {  // The exception has not been rethrown
2785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            if (0 == decrementHandlerCount(current_exception)) {
2795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                //  Remove from the chain of uncaught exceptions
2805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                globals->caughtExceptions = current_exception->nextException;
2815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                if (isDependentException(&current_exception->unwindHeader)) {
2825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                    // Reset current_exception to primaryException and deallocate the dependent exception
2835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                    __cxa_dependent_exception* deh =
2845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                        reinterpret_cast<__cxa_dependent_exception*>(current_exception + 1) - 1;
2855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                    current_exception = static_cast<__cxa_exception*>(deh->primaryException) - 1;
2865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                    __cxa_free_dependent_exception(deh);
2875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                }
2885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                // Destroy the primary exception only if its referenceCount goes to 0
2895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                //    (this decrement must be atomic)
2905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                __cxa_decrement_exception_refcount(thrown_object_from_exception(current_exception));
2915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            }
2925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        }
2935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
2945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
2955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstd::type_info * __cxa_current_exception_type() {
2985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  get the current exception
2995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    __cxa_eh_globals *globals = __cxa_get_globals_fast();
300e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner    if (NULL == globals)
301e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner        return NULL;     //  If there have never been any exceptions, there are none now.
302e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner    __cxa_exception *current_exception = globals->caughtExceptions;
303e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner    if (NULL == current_exception)
304e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner        return NULL;        //  No current exception
305e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner    if (isDependentException(&current_exception->unwindHeader)) {
306e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner        __cxa_dependent_exception* deh =
307e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner            reinterpret_cast<__cxa_dependent_exception*>(current_exception + 1) - 1;
308e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner        current_exception = static_cast<__cxa_exception*>(deh->primaryException) - 1;
309eb14fe839ec24c2ca14e5f094be147a34e3d3339Chris Lattner    }
3101f683e9cf2e855b32d3fb4b142aa121cd3cf1088Chris Lattner    return current_exception->exceptionType;
3115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
312ab38e4b50268633f037a10841fdfb612513f8d33Fariborz Jahanian
313ab38e4b50268633f037a10841fdfb612513f8d33Fariborz Jahanian// 2.5.4 Rethrowing Exceptions
314ab38e4b50268633f037a10841fdfb612513f8d33Fariborz Jahanian/*  This routine
315ab38e4b50268633f037a10841fdfb612513f8d33Fariborz Jahanian* marks the exception object on top of the caughtExceptions stack
316ab38e4b50268633f037a10841fdfb612513f8d33Fariborz Jahanian  (in an implementation-defined way) as being rethrown.
317ab38e4b50268633f037a10841fdfb612513f8d33Fariborz Jahanian* If the caughtExceptions stack is empty, it calls terminate()
318ab38e4b50268633f037a10841fdfb612513f8d33Fariborz Jahanian  (see [C++FDIS] [except.throw], 15.1.8).
3195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer* It then calls _Unwind_Resume_or_Rethrow which should not return
3205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer   (terminate if it does).
3215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer*/
3225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerextern LIBCXXABI_NORETURN void __cxa_rethrow() {
3235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    __cxa_eh_globals *globals = __cxa_get_globals();
3245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    __cxa_exception *exception = globals->caughtExceptions;
3255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    if (NULL == exception)   // there's no current exception!
3275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        std::terminate ();
3285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
329a9c01021724b9b546d282b8609cbe559734812ecChris Lattner// TODO:  Handle foreign exceptions?  How?
330a9c01021724b9b546d282b8609cbe559734812ecChris Lattner
3315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  Mark the exception as being rethrown (reverse the effects of __cxa_begin_catch)
3325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    exception->handlerCount = -exception->handlerCount;
3335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    globals->uncaughtExceptions += 1;
3345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  __cxa_end_catch will remove this exception from the caughtExceptions stack if necessary
3355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#if __arm__
3375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    (void) _Unwind_SjLj_Resume_or_Rethrow(&exception->unwindHeader);
33804421087832a031c90bd58f128c7c0e741db8dd2Chris Lattner#else
3394be1f47de20525ad90f02ba8682a7e2cbd3205d1Eli Friedman    (void) _Unwind_Resume_or_Rethrow     (&exception->unwindHeader);
3404be1f47de20525ad90f02ba8682a7e2cbd3205d1Eli Friedman#endif
3414be1f47de20525ad90f02ba8682a7e2cbd3205d1Eli Friedman
3424be1f47de20525ad90f02ba8682a7e2cbd3205d1Eli Friedman//  If we get here, some kind of unwinding error has occurred.
34304421087832a031c90bd58f128c7c0e741db8dd2Chris Lattner    failed_throw(exception);
34404421087832a031c90bd58f128c7c0e741db8dd2Chris Lattner}
3455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/*
3475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    If p is not null, atomically increment the referenceCount field of the
3485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    __cxa_exception header associated with the thrown object referred to by p.
3495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer*/
3505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid
3515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer__cxa_increment_exception_refcount(void* p) throw()
3525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
3535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    if (p != NULL )
3545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    {
3555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        __cxa_exception* header = exception_from_thrown_object(p);
3565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        __sync_add_and_fetch(&header->referenceCount, 1);
3577da36f642e907ff5a5ba4b18b5bfebfabf36ecc7Chris Lattner    }
35808ad47cbd1f81fcb31dbc731c13b885a07e12704Bill Wendling}
3595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
360ca51c97fbb10b9d48e1857e01c532493f87cd5f0Bill Wendling/*
3615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    If p is not null, atomically decrement the referenceCount field of the
362cb4f9a6d0be445d84af35ba81323be6127816f9eChris Lattner    __cxa_exception header associated with the thrown object referred to by p.
3635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    If the referenceCount drops to zero, destroy and deallocate the exception.
3645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer*/
365acb818a4f7d9b608826171094d6b5a555a8fe694Steve Naroffvoid
366f46699ce225811d8d9dbab9d00189a0e54469457Chris Lattner__cxa_decrement_exception_refcount(void* thrown_object) throw()
367acb818a4f7d9b608826171094d6b5a555a8fe694Steve Naroff{
368acb818a4f7d9b608826171094d6b5a555a8fe694Steve Naroff    if (thrown_object != NULL )
369cb4f9a6d0be445d84af35ba81323be6127816f9eChris Lattner    {
37008ad47cbd1f81fcb31dbc731c13b885a07e12704Bill Wendling        __cxa_exception* header = exception_from_thrown_object(thrown_object);
37108ad47cbd1f81fcb31dbc731c13b885a07e12704Bill Wendling        if (__sync_sub_and_fetch(&header->referenceCount, size_t(1)) == 0)
3725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        {
3735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            if (NULL != header->exceptionDestructor)
3745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                header->exceptionDestructor(thrown_object);
3757323a6297edad643c202594dcf3d9a174de96ca6Anders Carlsson            __cxa_free_exception(thrown_object);
3765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        }
3775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
3785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
3795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/*
3815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Returns a pointer to the thrown object (if any) at the top of the
3825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    caughtExceptions stack.  Atommically increment the exception's referenceCount.
3835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    If there is no such thrown object, returns null.
3845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer*/
385fdd75663fffeb2058a7847975e50837e61200593Anton Korobeynikovvoid*
3865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer__cxa_current_primary_exception() throw()
3875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
388fdd75663fffeb2058a7847975e50837e61200593Anton Korobeynikov//  get the current exception
3897da36f642e907ff5a5ba4b18b5bfebfabf36ecc7Chris Lattner    __cxa_eh_globals* globals = __cxa_get_globals();
3905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    __cxa_exception* current_exception = globals->caughtExceptions;
3917da36f642e907ff5a5ba4b18b5bfebfabf36ecc7Chris Lattner    if (NULL == current_exception)
3927da36f642e907ff5a5ba4b18b5bfebfabf36ecc7Chris Lattner        return NULL;        //  No current exception
3937da36f642e907ff5a5ba4b18b5bfebfabf36ecc7Chris Lattner    if (isDependentException(&current_exception->unwindHeader)) {
3947da36f642e907ff5a5ba4b18b5bfebfabf36ecc7Chris Lattner        __cxa_dependent_exception* deh =
3957da36f642e907ff5a5ba4b18b5bfebfabf36ecc7Chris Lattner            reinterpret_cast<__cxa_dependent_exception*>(current_exception + 1) - 1;
3965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        current_exception = static_cast<__cxa_exception*>(deh->primaryException) - 1;
3975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
3985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    void* thrown_object = thrown_object_from_exception(current_exception);
399e6386394677ed4f77b20e2e3d5446a3a2f628e53Steve Naroff    __cxa_increment_exception_refcount(thrown_object);
400e6386394677ed4f77b20e2e3d5446a3a2f628e53Steve Naroff    return thrown_object;
401213541a68a3e137d11d2cefb612c6cdb410d7e8eNate Begeman}
402213541a68a3e137d11d2cefb612c6cdb410d7e8eNate Begeman
403fec0b49c3fa621fbf63e420f3d54a5bb3a0265d2Steve Naroff/*
404fec0b49c3fa621fbf63e420f3d54a5bb3a0265d2Steve Naroff    If reason isn't _URC_FOREIGN_EXCEPTION_CAUGHT, then the terminateHandler
405027282d1c1ac151aa7b1b3b45babc918b8ad456aSteve Naroff    stored in exc is called.  Otherwise the referenceCount stored in the
406027282d1c1ac151aa7b1b3b45babc918b8ad456aSteve Naroff    primary exception is decremented, destroying the primary if necessary.
407fa28b30d5a1e93e5263be33e343532b900d2c643Chris Lattner    Finally the dependent exception is destroyed.
408fa28b30d5a1e93e5263be33e343532b900d2c643Chris Lattner*/
40904421087832a031c90bd58f128c7c0e741db8dd2Chris Lattnerstatic
41004421087832a031c90bd58f128c7c0e741db8dd2Chris Lattnervoid
4115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdependent_exception_cleanup(_Unwind_Reason_Code reason, struct _Unwind_Exception* exc)
4125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
4135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    __cxa_dependent_exception* deh =
4145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                      reinterpret_cast<__cxa_dependent_exception*>(exc + 1) - 1;
4155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason)
4165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        std::__terminate(deh->terminateHandler);
4175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    __cxa_decrement_exception_refcount(deh->primaryException);
4185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    __cxa_free_dependent_exception(deh);
4195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
4205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/*
422ca51c97fbb10b9d48e1857e01c532493f87cd5f0Bill Wendling    If thrown_object is not null, allocate, initialize and thow a dependent
4235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    exception.
4245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer*/
4255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid
4265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer__cxa_rethrow_primary_exception(void* thrown_object)
4275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
4285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    if ( thrown_object != NULL )
429fec0b49c3fa621fbf63e420f3d54a5bb3a0265d2Steve Naroff    {
4305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        __cxa_exception* header = exception_from_thrown_object(thrown_object);
4315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        __cxa_dependent_exception* deh =
4325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            (__cxa_dependent_exception*)__cxa_allocate_dependent_exception();
4335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        deh->primaryException = thrown_object;
4345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        __cxa_increment_exception_refcount(thrown_object);
4355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        deh->exceptionType = header->exceptionType;
4365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        deh->unexpectedHandler = std::get_unexpected();
4375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        deh->terminateHandler = std::get_terminate();
4385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        setDependentExceptionClass(&deh->unwindHeader);
4395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        __cxa_get_globals()->uncaughtExceptions += 1;
4405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        deh->unwindHeader.exception_cleanup = dependent_exception_cleanup;
4415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#if __arm__
4425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        _Unwind_SjLj_RaiseException(&deh->unwindHeader);
4435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#else
4445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        _Unwind_RaiseException(&deh->unwindHeader);
4455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#endif
4462e5f54aa1dd15a62c34a9d1d24a5a0692f43934aTed Kremenek        // Some sort of unwinding error.  Note that terminate is a handler.
4474cc627111453b75519d5130b57e06256da7b00e8Chris Lattner        __cxa_begin_catch(&deh->unwindHeader);
4484cc627111453b75519d5130b57e06256da7b00e8Chris Lattner    }
4492e5f54aa1dd15a62c34a9d1d24a5a0692f43934aTed Kremenek    // If we return client will call terminate()
4501d09ecca892185ba067e47ba879f424de59950efChris Lattner}
4511d09ecca892185ba067e47ba879f424de59950efChris Lattner
4521d09ecca892185ba067e47ba879f424de59950efChris Lattner_Unwind_Reason_Code
4534cc627111453b75519d5130b57e06256da7b00e8Chris Lattner__gxx_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionClass,
4542e5f54aa1dd15a62c34a9d1d24a5a0692f43934aTed Kremenek                     _Unwind_Exception* exceptionObject, _Unwind_Context* context)
4554cc627111453b75519d5130b57e06256da7b00e8Chris Lattner{
4562e5f54aa1dd15a62c34a9d1d24a5a0692f43934aTed Kremenek}
457e9b12198c4cc7f5687960100351b4af006c14469Steve Naroff
458e9b12198c4cc7f5687960100351b4af006c14469Steve Naroff}  // extern "C"
4591d09ecca892185ba067e47ba879f424de59950efChris Lattner
4601d09ecca892185ba067e47ba879f424de59950efChris Lattner}  // abi
4611d09ecca892185ba067e47ba879f424de59950efChris Lattner