123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- diff --git a/src/support/runtime/exception_pointer_msvc.ipp b/src/support/runtime/exception_pointer_msvc.ipp
- index 9e7f392..c88c68c 100644
- --- a/src/support/runtime/exception_pointer_msvc.ipp
- +++ b/src/support/runtime/exception_pointer_msvc.ipp
- @@ -7,70 +7,242 @@
- //
- //===----------------------------------------------------------------------===//
-
- -#include <stdio.h>
- -#include <stdlib.h>
- -
- -_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrCreate(void*);
- -_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrDestroy(void*);
- -_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrCopy(void*, const void*);
- -_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrAssign(void*, const void*);
- -_LIBCPP_CRT_FUNC bool __cdecl __ExceptionPtrCompare(const void*, const void*);
- -_LIBCPP_CRT_FUNC bool __cdecl __ExceptionPtrToBool(const void*);
- -_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrSwap(void*, void*);
- -_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrCurrentException(void*);
- -[[noreturn]] _LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrRethrow(const void*);
- -_LIBCPP_CRT_FUNC void __cdecl
- -__ExceptionPtrCopyException(void*, const void*, const void*);
- +#include <atomic>
- +#include <cstdint>
- +#include <cstring>
- +#include <malloc.h>
- +#include <windows.h> // For RtlPcToFileHeader function
-
- -namespace std {
- +struct EHCatchableType {
- + uint32_t properties;
- + int32_t type_info;
- + uint32_t non_virtual_adjustment;
- + uint32_t offset_to_virtual_base_ptr;
- + uint32_t virtual_base_table_index;
- + uint32_t size;
- + int32_t copy_function;
- +};
-
- -exception_ptr::exception_ptr() noexcept { __ExceptionPtrCreate(this); }
- -exception_ptr::exception_ptr(nullptr_t) noexcept { __ExceptionPtrCreate(this); }
- +struct EHCatchableTypeArray {
- + uint32_t catchable_types;
- + // It is variable size but we only need the first element of this array
- + int32_t array_of_catchable_types[1];
- +};
-
- -exception_ptr::exception_ptr(const exception_ptr& __other) noexcept {
- - __ExceptionPtrCopy(this, &__other);
- -}
- -exception_ptr& exception_ptr::operator=(const exception_ptr& __other) noexcept {
- - __ExceptionPtrAssign(this, &__other);
- - return *this;
- -}
- +struct EHThrowInfo {
- + uint32_t attributes;
- + int32_t unwind;
- + int32_t forward_compat;
- + int32_t catchable_type_array;
- +};
-
- -exception_ptr& exception_ptr::operator=(nullptr_t) noexcept {
- - exception_ptr dummy;
- - __ExceptionPtrAssign(this, &dummy);
- - return *this;
- -}
- +struct EHParameters {
- + uint32_t magic_number;
- + void* exception_object;
- + EHThrowInfo* throw_info;
- +#ifdef _M_AMD64
- + uintptr_t throw_image_base;
- +#endif
- +};
-
- -exception_ptr::~exception_ptr() noexcept { __ExceptionPtrDestroy(this); }
- +struct EHExceptionRecord {
- + uint32_t exception_code;
- + uint32_t exception_flags;
- + void* exception_record;
- + void* exception_address;
- + uint32_t number_of_parameters;
- + EHParameters parameters;
- +};
-
- -exception_ptr::operator bool() const noexcept {
- - return __ExceptionPtrToBool(this);
- -}
- +// defined in vcruntime<ver>.dll
- +extern "C" EHExceptionRecord** __current_exception();
- +
- +// This is internal compiler definition for MSVC but not for clang.
- +// We use our own EHThrowInfo because _ThrowInfo doesn't match actual
- +// compiler-generated structures in 64-bit mode.
- +#ifdef __clang__
- +struct _ThrowInfo;
- +// defined in vcruntime<ver>.dll
- +extern "C" _LIBCPP_NORETURN void __stdcall _CxxThrowException(
- + void* __exc, _ThrowInfo* __throw_info);
- +#endif
- +
- +namespace {
- +struct ExceptionPtr {
- + void* exception_object;
- + const EHThrowInfo* throw_info;
- + std::atomic<size_t> counter;
- +#ifdef _M_AMD64
- + PVOID image_base;
- +#endif
- + template <class T>
- + T convert(int32_t offset) {
- +#ifdef _M_AMD64
- + uintptr_t value = reinterpret_cast<uintptr_t>(image_base) +
- + static_cast<uintptr_t>(offset);
- +#else
- + uintptr_t value = static_cast<uintptr_t>(offset);
- +#endif
- + T res;
- + static_assert(
- + sizeof(value) == sizeof(res),
- + "Can only convert to pointers or pointers to member functions");
- + memcpy(&res, &value, sizeof(value));
- + return res;
- + }
- +
- + void copy(void* dst, const void* src, const EHCatchableType* exc_type) {
- + struct Temp {};
- + constexpr uint32_t virtual_base = 4;
- + if (exc_type->copy_function == 0) {
- + memcpy(dst, src, exc_type->size);
- + } else if (exc_type->properties & virtual_base) {
- + auto copy_constructor =
- + convert<void (Temp::*)(const void*, int)>(exc_type->copy_function);
- + ((Temp*)dst->*copy_constructor)(src, 1);
- + } else {
- + auto copy_constructor =
- + convert<void (Temp::*)(const void*)>(exc_type->copy_function);
- + ((Temp*)dst->*copy_constructor)(src);
- + }
- + }
- +
- + EHCatchableType* exception_type() {
- + return convert<EHCatchableType*>(
- + convert<EHCatchableTypeArray*>(throw_info->catchable_type_array)
- + ->array_of_catchable_types[0]);
- + }
- +
- + ExceptionPtr(const void* exception_object_, const EHThrowInfo* throw_info_)
- + : exception_object(nullptr), throw_info(throw_info_), counter(1) {
- +#ifdef _M_AMD64
- + RtlPcToFileHeader(
- + reinterpret_cast<PVOID>(const_cast<EHThrowInfo*>(throw_info)),
- + &image_base);
- +#endif
- + EHCatchableType* exc_type = exception_type();
- + this->exception_object = malloc(exc_type->size);
- + if (this->exception_object == nullptr) {
- + throw std::bad_alloc();
- + }
- + copy(exception_object, exception_object_, exc_type);
- + }
- +
- + ~ExceptionPtr() {
- + if (throw_info->unwind && exception_object) {
- + struct Temp {};
- + auto destructor = convert<void (Temp::*)()>(throw_info->unwind);
- + ((Temp*)exception_object->*destructor)();
- + }
- + free(exception_object);
- + }
-
- -bool operator==(const exception_ptr& __x, const exception_ptr& __y) noexcept {
- - return __ExceptionPtrCompare(&__x, &__y);
- + // _bad_alloc_storage must be initialized before bad_alloc, so we declare and define it first.
- + static std::bad_alloc _bad_alloc_storage;
- + static ExceptionPtr bad_alloc;
- + //static ExceptionPtr bad_exception;
- +};
- +
- +#ifdef __clang__
- +#pragma clang diagnostic push
- +#pragma clang diagnostic ignored "-Waddress-of-temporary"
- +#endif
- +
- +std::bad_alloc ExceptionPtr::_bad_alloc_storage;
- +
- +ExceptionPtr ExceptionPtr::bad_alloc(
- + &ExceptionPtr::_bad_alloc_storage,
- + reinterpret_cast<const EHThrowInfo*>(__GetExceptionInfo(ExceptionPtr::_bad_alloc_storage)));
- +
- +/* ExceptionPtr
- +ExceptionPtr::bad_exception(&std::bad_exception(),
- + reinterpret_cast<const EHThrowInfo*>(
- + __GetExceptionInfo(std::bad_exception()))); */
- +
- +#ifdef __clang__
- +#pragma clang diagnostic pop
- +#endif
- +
- +} // namespace
- +
- +namespace std {
- +
- +exception_ptr::exception_ptr(const exception_ptr& __other) noexcept
- + : __ptr_(__other.__ptr_) {
- + if (__ptr_) {
- + reinterpret_cast<ExceptionPtr*>(__ptr_)->counter.fetch_add(1);
- + }
- }
-
- +exception_ptr& exception_ptr::
- +operator=(const exception_ptr& __other) noexcept {
- + auto before = __ptr_;
- + __ptr_ = __other.__ptr_;
- + if (__ptr_) {
- + reinterpret_cast<ExceptionPtr*>(__ptr_)->counter.fetch_add(1);
- + }
- + if (before) {
- + if (reinterpret_cast<ExceptionPtr*>(before)->counter.fetch_sub(1) == 1) {
- + delete reinterpret_cast<ExceptionPtr*>(before);
- + }
- + }
- + return *this;
- +}
-
- -void swap(exception_ptr& lhs, exception_ptr& rhs) noexcept {
- - __ExceptionPtrSwap(&rhs, &lhs);
- +exception_ptr::~exception_ptr() noexcept {
- + if (__ptr_) {
- + if (reinterpret_cast<ExceptionPtr*>(__ptr_)->counter.fetch_sub(1) == 1) {
- + delete reinterpret_cast<ExceptionPtr*>(__ptr_);
- + }
- + }
- }
-
- -exception_ptr __copy_exception_ptr(void* __except, const void* __ptr) {
- - exception_ptr __ret = nullptr;
- - if (__ptr)
- - __ExceptionPtrCopyException(&__ret, __except, __ptr);
- - return __ret;
- +exception_ptr __copy_exception_ptr(void* exception_object,
- + const void* throw_info) {
- + ExceptionPtr* ptr;
- + try {
- + ptr = new ExceptionPtr(exception_object,
- + reinterpret_cast<const EHThrowInfo*>(throw_info));
- + } catch (const std::bad_alloc&) {
- + ptr = &ExceptionPtr::bad_alloc;
- + ptr->counter.fetch_add(1);
- + } catch (...) {
- + //ptr = &ExceptionPtr::bad_exception;
- + //ptr->counter.fetch_add(1);
- + std::terminate();
- + }
- + exception_ptr res;
- + memcpy(&res, &ptr, sizeof(ptr));
- + return res;
- }
-
- exception_ptr current_exception() noexcept {
- - exception_ptr __ret;
- - __ExceptionPtrCurrentException(&__ret);
- - return __ret;
- + EHExceptionRecord** record = __current_exception();
- + if (*record && !std::uncaught_exception()) {
- + return __copy_exception_ptr((*record)->parameters.exception_object,
- + (*record)->parameters.throw_info);
- + }
- + return exception_ptr();
- }
-
- _LIBCPP_NORETURN
- -void rethrow_exception(exception_ptr p) { __ExceptionPtrRethrow(&p); }
- +void rethrow_exception(exception_ptr p) {
- + if (!p) {
- + throw std::bad_exception();
- + }
- + ExceptionPtr* exc_ptr = reinterpret_cast<ExceptionPtr*>(p.__ptr_);
- + EHCatchableType* exc_type = exc_ptr->exception_type();
- + // _CxxThrowException doesn't call free on exception object so we must
- + // allocate it on the stack.
- + void* dst = _alloca(exc_type->size);
- + exc_ptr->copy(dst, exc_ptr->exception_object, exc_type);
- + auto throw_info = reinterpret_cast<_ThrowInfo*>(
- + const_cast<EHThrowInfo*>(exc_ptr->throw_info));
- + // For some reason clang doesn't call p destructor during unwinding.
- + // So we must clear it ourselves.
- + p = nullptr;
- + _CxxThrowException(dst, throw_info);
- +}
-
- nested_exception::nested_exception() noexcept : __ptr_(current_exception()) {}
-
|