Split exception.cpp and new.cpp implementation into different files for different runtimes.

exception.cpp is a bloody mess. It's full of confusing #ifdef branches for
each different ABI library we support, and it's getting unmaintainable.

This patch breaks down exception.cpp into multiple different header files,
roughly one per implementation. Additionally it moves the definitions of
exceptions in new.cpp into the correct implementation header.

This patch also removes an unmaintained libc++abi configuration.
This configuration may still be used by Apple internally but there
are no other possible users. If it turns out that Apple still uses
this configuration internally I will re-add it in a later commit.
See http://llvm.org/PR31904.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@294707 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Fiselier
2017-02-10 04:25:33 +00:00
parent e7bee0d9c6
commit d60b66ad4f
16 changed files with 725 additions and 506 deletions

View File

@@ -6,328 +6,30 @@
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <stdlib.h>
#include <stdio.h>
#include "exception"
#include "new"
#if defined(_LIBCPP_ABI_MICROSOFT)
#include <eh.h>
#include <corecrt_terminate.h>
#elif defined(__APPLE__) && !defined(LIBCXXRT) && \
!defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY)
#if defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI) || \
(defined(__APPLE__) && !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY))
#include <cxxabi.h>
using namespace __cxxabiv1;
#define HAVE_DEPENDENT_EH_ABI 1
#ifndef _LIBCPPABI_VERSION
using namespace __cxxabiapple;
// On Darwin, there are two STL shared libraries and a lower level ABI
// shared library. The globals holding the current terminate handler and
// current unexpected handler are in the ABI library.
#define __terminate_handler __cxxabiapple::__cxa_terminate_handler
#define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
#endif // _LIBCPPABI_VERSION
#elif defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI)
#include <cxxabi.h>
using namespace __cxxabiv1;
#if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
#define HAVE_DEPENDENT_EH_ABI 1
#endif
#elif !defined(__GLIBCXX__) // defined(LIBCXX_BUILDING_LIBCXXABI)
_LIBCPP_SAFE_STATIC static std::terminate_handler __terminate_handler;
_LIBCPP_SAFE_STATIC static std::unexpected_handler __unexpected_handler;
#endif // defined(LIBCXX_BUILDING_LIBCXXABI)
#endif
namespace std
{
#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
// libcxxrt provides implementations of these functions itself.
unexpected_handler
set_unexpected(unexpected_handler func) _NOEXCEPT
{
#if defined(_LIBCPP_ABI_MICROSOFT)
return ::set_unexpected(func);
#else
return __sync_lock_test_and_set(&__unexpected_handler, func);
#endif
}
unexpected_handler
get_unexpected() _NOEXCEPT
{
#if defined(_LIBCPP_ABI_MICROSOFT)
return ::_get_unexpected();
#else
return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
#endif
}
_LIBCPP_NORETURN
void
unexpected()
{
(*get_unexpected())();
// unexpected handler should not return
terminate();
}
terminate_handler
set_terminate(terminate_handler func) _NOEXCEPT
{
#if defined(_LIBCPP_ABI_MICROSOFT)
return ::set_terminate(func);
#else
return __sync_lock_test_and_set(&__terminate_handler, func);
#endif
}
terminate_handler
get_terminate() _NOEXCEPT
{
#if defined(_LIBCPP_ABI_MICROSOFT)
return ::_get_terminate();
#else
return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
#endif
}
#ifndef __EMSCRIPTEN__ // We provide this in JS
_LIBCPP_NORETURN
void
terminate() _NOEXCEPT
{
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
#endif // _LIBCPP_NO_EXCEPTIONS
(*get_terminate())();
// handler should not return
fprintf(stderr, "terminate_handler unexpectedly returned\n");
::abort();
#ifndef _LIBCPP_NO_EXCEPTIONS
}
catch (...)
{
// handler should not throw exception
fprintf(stderr, "terminate_handler unexpectedly threw an exception\n");
::abort();
}
#endif // _LIBCPP_NO_EXCEPTIONS
}
#endif // !__EMSCRIPTEN__
#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
#if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(__EMSCRIPTEN__)
bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; }
int uncaught_exceptions() _NOEXCEPT
{
#if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \
(defined(__APPLE__) || defined(_LIBCPPABI_VERSION))
// on Darwin, there is a helper function so __cxa_get_globals is private
# if _LIBCPPABI_VERSION > 1101
return __cxa_uncaught_exceptions();
# else
return __cxa_uncaught_exception() ? 1 : 0;
# endif
#elif defined(_LIBCPP_ABI_MICROSOFT)
return __uncaught_exceptions();
#else
# if defined(_LIBCPP_MSVC)
_LIBCPP_WARNING("uncaught_exceptions not yet implemented")
# else
# warning uncaught_exception not yet implemented
# endif
fprintf(stderr, "uncaught_exceptions not yet implemented\n");
::abort();
#endif // __APPLE__
}
#ifndef _LIBCPPABI_VERSION
exception::~exception() _NOEXCEPT
{
}
const char* exception::what() const _NOEXCEPT
{
return "std::exception";
}
#endif // _LIBCPPABI_VERSION
#endif //LIBCXXRT
#if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
bad_exception::~bad_exception() _NOEXCEPT
{
}
const char* bad_exception::what() const _NOEXCEPT
{
return "std::bad_exception";
}
#endif
#if defined(__GLIBCXX__)
// libsupc++ does not implement the dependent EH ABI and the functionality
// it uses to implement std::exception_ptr (which it declares as an alias of
// std::__exception_ptr::exception_ptr) is not directly exported to clients. So
// we have little choice but to hijack std::__exception_ptr::exception_ptr's
// (which fortunately has the same layout as our std::exception_ptr) copy
// constructor, assignment operator and destructor (which are part of its
// stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr)
// function.
namespace __exception_ptr
{
struct exception_ptr
{
void* __ptr_;
exception_ptr(const exception_ptr&) _NOEXCEPT;
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
~exception_ptr() _NOEXCEPT;
};
}
_LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr);
#endif
exception_ptr::~exception_ptr() _NOEXCEPT
{
#if HAVE_DEPENDENT_EH_ABI
__cxa_decrement_exception_refcount(__ptr_);
#include "support/runtime/exception_msvc.ipp"
#include "support/runtime/exception_pointer_unimplemented.ipp"
#elif defined(_LIBCPPABI_VERSION)
#include "support/runtime/exception_libcxxabi.ipp"
#include "support/runtime/exception_pointer_cxxabi.ipp"
#elif defined(LIBCXXRT)
#include "support/runtime/exception_libcxxrt.ipp"
#include "support/runtime/exception_pointer_cxxabi.ipp"
#elif defined(__GLIBCXX__)
reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr();
#include "support/runtime/exception_glibcxx.ipp"
#include "support/runtime/exception_pointer_glibcxx.ipp"
#else
# if defined(_LIBCPP_MSVC)
_LIBCPP_WARNING("exception_ptr not yet implemented")
# else
# warning exception_ptr not yet implemented
# endif
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
#include "support/runtime/exception_fallback.ipp"
#include "support/runtime/exception_pointer_unimplemented.ipp"
#endif
}
exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
: __ptr_(other.__ptr_)
{
#if HAVE_DEPENDENT_EH_ABI
__cxa_increment_exception_refcount(__ptr_);
#elif defined(__GLIBCXX__)
new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr(
reinterpret_cast<const __exception_ptr::exception_ptr&>(other));
#else
# if defined(_LIBCPP_MSVC)
_LIBCPP_WARNING("exception_ptr not yet implemented")
# else
# warning exception_ptr not yet implemented
# endif
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
#endif
}
exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
{
#if HAVE_DEPENDENT_EH_ABI
if (__ptr_ != other.__ptr_)
{
__cxa_increment_exception_refcount(other.__ptr_);
__cxa_decrement_exception_refcount(__ptr_);
__ptr_ = other.__ptr_;
}
return *this;
#elif defined(__GLIBCXX__)
*reinterpret_cast<__exception_ptr::exception_ptr*>(this) =
reinterpret_cast<const __exception_ptr::exception_ptr&>(other);
return *this;
#else
# if defined(_LIBCPP_MSVC)
_LIBCPP_WARNING("exception_ptr not yet implemented")
# else
# warning exception_ptr not yet implemented
# endif
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
#endif
}
nested_exception::nested_exception() _NOEXCEPT
: __ptr_(current_exception())
{
}
#if !defined(__GLIBCXX__)
nested_exception::~nested_exception() _NOEXCEPT
{
}
#endif
_LIBCPP_NORETURN
void
nested_exception::rethrow_nested() const
{
if (__ptr_ == nullptr)
terminate();
rethrow_exception(__ptr_);
}
#if !defined(__GLIBCXX__)
exception_ptr current_exception() _NOEXCEPT
{
#if HAVE_DEPENDENT_EH_ABI
// be nicer if there was a constructor that took a ptr, then
// this whole function would be just:
// return exception_ptr(__cxa_current_primary_exception());
exception_ptr ptr;
ptr.__ptr_ = __cxa_current_primary_exception();
return ptr;
#else
# if defined(_LIBCPP_MSVC)
_LIBCPP_WARNING( "exception_ptr not yet implemented" )
# else
# warning exception_ptr not yet implemented
# endif
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
#endif
}
#endif // !__GLIBCXX__
_LIBCPP_NORETURN
void rethrow_exception(exception_ptr p)
{
#if HAVE_DEPENDENT_EH_ABI
__cxa_rethrow_primary_exception(p.__ptr_);
// if p.__ptr_ is NULL, above returns so we terminate
terminate();
#elif defined(__GLIBCXX__)
rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p));
#else
# if defined(_LIBCPP_MSVC)
_LIBCPP_WARNING("exception_ptr not yet implemented")
# else
# warning exception_ptr not yet implemented
# endif
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
#endif
}
} // std