diff options
Diffstat (limited to 'runtime/GCCLibraries')
-rw-r--r-- | runtime/GCCLibraries/crtend/C++-Exception.cpp | 362 | ||||
-rw-r--r-- | runtime/GCCLibraries/crtend/C++-Exception.h | 89 | ||||
-rw-r--r-- | runtime/GCCLibraries/crtend/Exception.h | 10 |
3 files changed, 10 insertions, 451 deletions
diff --git a/runtime/GCCLibraries/crtend/C++-Exception.cpp b/runtime/GCCLibraries/crtend/C++-Exception.cpp deleted file mode 100644 index ce7f0d4fd0..0000000000 --- a/runtime/GCCLibraries/crtend/C++-Exception.cpp +++ /dev/null @@ -1,362 +0,0 @@ -//===- C++-Exception.cpp - Exception handling support for C++ exceptions --===// -// -// This file defines the methods used to implement C++ exception handling in -// terms of the invoke and %llvm.unwind intrinsic. These primitives implement -// an exception handling ABI similar (but simpler and more efficient than) the -// Itanium C++ ABI exception handling standard. -// -//===----------------------------------------------------------------------===// - -#include "C++-Exception.h" -#include <cstdlib> -#include <cstdarg> - -//#define DEBUG - -#ifdef DEBUG -#include <cstdio> -#endif - -// LastCaughtException - The last exception caught by this handler. This is for -// implementation of _rethrow and _get_last_caught. -// -// FIXME: This should be thread-local! -// -static llvm_exception *LastCaughtException = 0; - - -using namespace __cxxabiv1; - -// __llvm_cxxeh_allocate_exception - This function allocates space for the -// specified number of bytes, plus a C++ exception object header. -// -void *__llvm_cxxeh_allocate_exception(unsigned NumBytes) throw() { - // FIXME: This should eventually have back-up buffers for out-of-memory - // situations. - // - llvm_cxx_exception *E = - (llvm_cxx_exception *)malloc(NumBytes+sizeof(llvm_cxx_exception)); - E->BaseException.ExceptionType = 0; // initialize to invalid - - return E+1; // return the pointer after the header -} - -// __llvm_cxxeh_free_exception - Low-level function to free an exception. This -// is called directly from generated C++ code if evaluating the exception value -// into the exception location throws. Otherwise it is called from the C++ -// exception object destructor. -// -void __llvm_cxxeh_free_exception(void *ObjectPtr) throw() { - llvm_cxx_exception *E = (llvm_cxx_exception *)ObjectPtr - 1; - free(E); -} - -// cxx_destructor - This function is called through the generic -// exception->ExceptionDestructor function pointer to destroy a caught -// exception. -// -static void cxx_destructor(llvm_exception *LE) /* might throw */{ - assert(LE->Next == 0 && "On the uncaught stack??"); - llvm_cxx_exception *E = get_cxx_exception(LE); - - struct ExceptionFreer { - void *Ptr; - ExceptionFreer(void *P) : Ptr(P) {} - ~ExceptionFreer() { - // Free the memory for the exception, when the function is left, even if - // the exception object dtor throws its own exception! - __llvm_cxxeh_free_exception(Ptr); - } - } EF(E+1); - - // Run the exception object dtor if it exists. */ - if (E->ExceptionObjectDestructor) - E->ExceptionObjectDestructor(E+1); -} - -// __llvm_cxxeh_throw - Given a pointer to memory which has an exception object -// evaluated into it, this sets up all of the fields of the exception allowing -// it to be thrown. After calling this, the code should call %llvm.unwind -// -void __llvm_cxxeh_throw(void *ObjectPtr, void *TypeInfoPtr, - void (*DtorPtr)(void*)) throw() { - llvm_cxx_exception *E = (llvm_cxx_exception *)ObjectPtr - 1; - E->BaseException.ExceptionDestructor = cxx_destructor; - E->BaseException.ExceptionType = CXXException; - E->BaseException.HandlerCount = 0; - E->BaseException.isRethrown = 0; - - E->TypeInfo = (const std::type_info*)TypeInfoPtr; - E->ExceptionObjectDestructor = DtorPtr; - E->UnexpectedHandler = __unexpected_handler; - E->TerminateHandler = __terminate_handler; - - __llvm_eh_add_uncaught_exception(&E->BaseException); -} - - -// CXXExceptionISA - use the type info object stored in the exception to see if -// TypeID matches and, if so, to adjust the exception object pointer. -// -static void *CXXExceptionISA(llvm_cxx_exception *E, - const std::type_info *Type) throw() { - // ThrownPtr is a pointer to the object being thrown... - void *ThrownPtr = E+1; - const std::type_info *ThrownType = E->TypeInfo; - -#if 0 - // FIXME: this code exists in the GCC exception handling library: I haven't - // thought about this yet, so it should be verified at some point! - - // Pointer types need to adjust the actual pointer, not - // the pointer to pointer that is the exception object. - // This also has the effect of passing pointer types - // "by value" through the __cxa_begin_catch return value. - if (ThrownType->__is_pointer_p()) - ThrownPtr = *(void **)ThrownPtr; -#endif - - if (Type->__do_catch(ThrownType, &ThrownPtr, 1)) { -#ifdef DEBUG - printf("isa<%s>(%s): 0x%p -> 0x%p\n", Type->name(), ThrownType->name(), - E+1, ThrownPtr); -#endif - return ThrownPtr; - } - - return 0; -} - -// __llvm_cxxeh_current_uncaught_exception_isa - This function checks to see if -// the current uncaught exception is a C++ exception, and if it is of the -// specified type id. If so, it returns a pointer to the object adjusted as -// appropriate, otherwise it returns null. -// -void *__llvm_cxxeh_current_uncaught_exception_isa(void *CatchType) throw() { - void *EPtr = __llvm_eh_current_uncaught_exception_type(CXXException); - if (EPtr == 0) return 0; // If it's not a c++ exception, it doesn't match! - - // If it is a C++ exception, use the type info object stored in the exception - // to see if TypeID matches and, if so, to adjust the exception object - // pointer. - // - const std::type_info *Info = (const std::type_info *)CatchType; - return CXXExceptionISA((llvm_cxx_exception*)EPtr - 1, Info); -} - - -// __llvm_cxxeh_begin_catch - This function is called by "exception handlers", -// which transition an exception from being uncaught to being caught. It -// returns a pointer to the exception object portion of the exception. This -// function must work with foreign exceptions. -// -void *__llvm_cxxeh_begin_catch() throw() { - llvm_exception *E = __llvm_eh_pop_from_uncaught_stack(); - - // The exception is now caught. - LastCaughtException = E; - E->Next = 0; - E->isRethrown = 0; - - // Increment the handler count for this exception. - E->HandlerCount++; - -#ifdef DEBUG - printf("Exiting begin_catch Ex=0x%p HandlerCount=%d!\n", E+1, - E->HandlerCount); -#endif - - // Return a pointer to the raw exception object. - return E+1; -} - -// __llvm_cxxeh_begin_catch_if_isa - This function checks to see if the current -// uncaught exception is of the specified type. If not, it returns a null -// pointer, otherwise it 'catches' the exception and returns a pointer to the -// object of the specified type. This function does never succeeds with foreign -// exceptions (because they can never be of type CatchType). -// -void *__llvm_cxxeh_begin_catch_if_isa(void *CatchType) throw() { - void *ObjPtr = __llvm_cxxeh_current_uncaught_exception_isa(CatchType); - if (!ObjPtr) return 0; - - // begin_catch, meaning that the object is now "caught", not "uncaught" - __llvm_cxxeh_begin_catch(); - return ObjPtr; -} - -// __llvm_cxxeh_get_last_caught - Return the last exception that was caught by -// ...begin_catch. -// -void *__llvm_cxxeh_get_last_caught() throw() { - assert(LastCaughtException && "No exception caught!!"); - return LastCaughtException+1; -} - -// __llvm_cxxeh_end_catch - This function decrements the HandlerCount of the -// top-level caught exception, destroying it if this is the last handler for the -// exception. -// -void __llvm_cxxeh_end_catch(void *Ex) /* might throw */ { - llvm_exception *E = (llvm_exception*)Ex - 1; - assert(E && "There are no caught exceptions!"); - - // If this is the last handler using the exception, destroy it now! - if (--E->HandlerCount == 0 && !E->isRethrown) { -#ifdef DEBUG - printf("Destroying exception!\n"); -#endif - E->ExceptionDestructor(E); // Release memory for the exception - } -#ifdef DEBUG - printf("Exiting end_catch Ex=0x%p HandlerCount=%d!\n", Ex, E->HandlerCount); -#endif -} - -// __llvm_cxxeh_call_terminate - This function is called when the dtor for an -// object being destroyed due to an exception throw throws an exception. This -// is illegal because it would cause multiple exceptions to be active at one -// time. -void __llvm_cxxeh_call_terminate() throw() { - void (*Handler)(void) = __terminate_handler; - if (__llvm_eh_has_uncaught_exception()) - if (void *EPtr = __llvm_eh_current_uncaught_exception_type(CXXException)) - Handler = ((llvm_cxx_exception*)EPtr - 1)->TerminateHandler; - __terminate(Handler); -} - - -// __llvm_cxxeh_rethrow - This function turns the top-level caught exception -// into an uncaught exception, in preparation for an llvm.unwind, which should -// follow immediately after the call to this function. This function must be -// prepared to deal with foreign exceptions. -// -void __llvm_cxxeh_rethrow() throw() { - llvm_exception *E = LastCaughtException; - if (E == 0) - // 15.1.8 - If there are no exceptions being thrown, 'throw;' should call - // terminate. - // - __terminate(__terminate_handler); - - // Otherwise we have an exception to rethrow. Mark the exception as such. - E->isRethrown = 1; - - // Add the exception to the top of the uncaught stack, to preserve the - // invariant that the top of the uncaught stack is the current exception. - __llvm_eh_add_uncaught_exception(E); - - // Return to the caller, which should perform the unwind now. -} - -static bool ExceptionSpecificationPermitsException(llvm_exception *E, - const std::type_info *Info, - va_list Args) { - // The only way it could match one of the types is if it is a C++ exception. - if (E->ExceptionType != CXXException) return false; - - llvm_cxx_exception *Ex = get_cxx_exception(E); - - // Scan the list of accepted types, checking to see if the uncaught - // exception is any of them. - do { - // Check to see if the exception matches one of the types allowed by the - // exception specification. If so, return to the caller to have the - // exception rethrown. - if (CXXExceptionISA(Ex, Info)) - return true; - - Info = va_arg(Args, std::type_info *); - } while (Info); - return false; -} - - -// __llvm_cxxeh_check_eh_spec - If a function with an exception specification is -// throwing an exception, this function gets called with the list of type_info -// objects that it is allowing to propagate. Check to see if the current -// uncaught exception is one of these types, and if so, allow it to be thrown by -// returning to the caller, which should immediately follow this call with -// llvm.unwind. -// -// Note that this function does not throw any exceptions, but we can't put an -// exception specification on it or else we'll get infinite loops! -// -void __llvm_cxxeh_check_eh_spec(void *Info, ...) { - const std::type_info *TypeInfo = (const std::type_info *)Info; - - if (TypeInfo == 0) { // Empty exception specification - // Whatever exception this is, it is not allowed by the (empty) spec, call - // unexpected, according to 15.4.8. - try { - void *Ex = __llvm_cxxeh_begin_catch(); // Start the catch - __llvm_cxxeh_end_catch(Ex); // Free the exception - __unexpected(__unexpected_handler); - } catch (...) { - // Any exception thrown by unexpected cannot match the ehspec. Call - // terminate, according to 15.4.9. - __terminate(__terminate_handler); - } - } - - llvm_exception *E = __llvm_eh_get_uncaught_exception(); - assert(E && "No uncaught exceptions!"); - - // Check to see if the exception matches one of the types allowed by the - // exception specification. If so, return to the caller to have the - // exception rethrown. - - va_list Args; - va_start(Args, Info); - bool Ok = ExceptionSpecificationPermitsException(E, TypeInfo, Args); - va_end(Args); - if (Ok) return; - - // Ok, now we know that the exception is either not a C++ exception (thus not - // permitted to pass through) or not a C++ exception that is allowed. Kill - // the exception and call the unexpected handler. - try { - void *Ex = __llvm_cxxeh_begin_catch(); // Start the catch - __llvm_cxxeh_end_catch(Ex); // Free the exception - } catch (...) { - __terminate(__terminate_handler); // Exception dtor threw - } - - try { - __unexpected(__unexpected_handler); - } catch (...) { - // If the unexpected handler threw an exception, we will get here. Since - // entering the try block calls ..._begin_catch, we need to "rethrow" the - // exception to make it uncaught again. Exiting the catch will then leave - // it in the uncaught state. - __llvm_cxxeh_rethrow(); - } - - // Grab the newly caught exception. If this exception is permitted by the - // specification, allow it to be thrown. - E = __llvm_eh_get_uncaught_exception(); - - va_start(Args, Info); - Ok = ExceptionSpecificationPermitsException(E, TypeInfo, Args); - va_end(Args); - if (Ok) return; - - // Final case, check to see if we can throw an std::bad_exception. - try { - throw std::bad_exception(); - } catch (...) { - __llvm_cxxeh_rethrow(); - } - - // Grab the new bad_exception... - E = __llvm_eh_get_uncaught_exception(); - - // If it's permitted, allow it to be thrown instead. - va_start(Args, Info); - Ok = ExceptionSpecificationPermitsException(E, TypeInfo, Args); - va_end(Args); - if (Ok) return; - - // Otherwise, we are out of options, terminate, according to 15.5.2.2. - __terminate(__terminate_handler); -} diff --git a/runtime/GCCLibraries/crtend/C++-Exception.h b/runtime/GCCLibraries/crtend/C++-Exception.h deleted file mode 100644 index d66b8acd7c..0000000000 --- a/runtime/GCCLibraries/crtend/C++-Exception.h +++ /dev/null @@ -1,89 +0,0 @@ -//===- C++-Exception.h - C++ Specific Exception Handling --------*- C++ -*-===// -// -// This file defines the data structures and API used by the C++ exception -// handling runtime library. -// -//===----------------------------------------------------------------------===// - -#ifndef CXX_EXCEPTION_H -#define CXX_EXCEPTION_H - -#include "Exception.h" -#include <typeinfo> -#include <cassert> - -// Assert should only be used for debugging the runtime library. Enabling it in -// CVS will break some platforms! -#undef assert -#define assert(X) - -struct llvm_cxx_exception { - // TypeInfo - A pointer to the C++ std::type_info object for this exception - // class. This is required because the class may not be polymorphic. - // - const std::type_info *TypeInfo; - - // ExceptionObjectDestructor - A pointer to the function which destroys the - // object represented by this exception. This is required because the class - // may not be polymorphic. This may be null if there is no cleanup required. - // - void (*ExceptionObjectDestructor)(void *); - - // UnexpectedHandler - This contains a pointer to the "unexpected" handler - // which may be registered by the user program with set_unexpected. Calls to - // unexpected which are a result of an exception throw are supposed to use the - // value of the handler at the time of the throw, not the currently set value. - // - void (*UnexpectedHandler)(); - - // TerminateHandler - This contains a pointer to the "terminate" handler which - // may be registered by the user program with set_terminate. Calls to - // unexpected which are a result of an exception throw are supposed to use the - // value of the handler at the time of the throw, not the currently set value. - // - void (*TerminateHandler)(); - - // BaseException - The language independent portion of the exception state. - // This is at the end of the record so that we can add additional members to - // this structure without breaking binary compatibility. - // - llvm_exception BaseException; -}; - -inline llvm_cxx_exception *get_cxx_exception(llvm_exception *E) throw() { - assert(E->ExceptionType == CXXException && "Not a C++ exception?"); - return (llvm_cxx_exception*)(E+1)-1; -} - -// Interface to the C++ standard library to get to the terminate and unexpected -// handler stuff. -namespace __cxxabiv1 { - // Invokes given handler, dying appropriately if the user handler was - // so inconsiderate as to return. - extern void __terminate(std::terminate_handler) throw() __attribute__((noreturn)); - extern void __unexpected(std::unexpected_handler) __attribute__((noreturn)); - - // The current installed user handlers. - extern std::terminate_handler __terminate_handler; - extern std::unexpected_handler __unexpected_handler; -} - -extern "C" { - void *__llvm_cxxeh_allocate_exception(unsigned NumBytes) throw(); - void __llvm_cxxeh_free_exception(void *ObjectPtr) throw(); - void __llvm_cxxeh_throw(void *ObjectPtr, void *TypeInfoPtr, - void (*DtorPtr)(void*)) throw(); - - void __llvm_cxxeh_call_terminate() throw() __attribute__((noreturn)); - void * __llvm_cxxeh_current_uncaught_exception_isa(void *Ty) - throw(); - void *__llvm_cxxeh_begin_catch() throw(); - void *__llvm_cxxeh_begin_catch_if_isa(void *CatchType) throw(); - void __llvm_cxxeh_end_catch(void *Exception) /* might throw */; - void __llvm_cxxeh_rethrow() throw(); - void *__llvm_cxxeh_get_last_caught() throw(); - - void __llvm_cxxeh_check_eh_spec(void *Info, ...); -} - -#endif diff --git a/runtime/GCCLibraries/crtend/Exception.h b/runtime/GCCLibraries/crtend/Exception.h index d3f95e77b0..1e515196e8 100644 --- a/runtime/GCCLibraries/crtend/Exception.h +++ b/runtime/GCCLibraries/crtend/Exception.h @@ -1,8 +1,18 @@ //===- Exception.h - Generic language-independent exceptions ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// // // This file defines the the shared data structures used by all language // specific exception handling runtime libraries. // +// NOTE NOTE NOTE: A copy of this file lives in llvmgcc/libstdc++-v3/libsupc++/ +// Any modifications to this file must keep it in sync! +// //===----------------------------------------------------------------------===// #ifndef EXCEPTION_H |