[compiler-rt] [libcxx] [libcxxabi] [libunwind] [libunwind][libcxx][libcxxabi][compiler-rt-builtins] Fix Exception Handling build for wasm (PR #79667)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 5 12:55:50 PST 2024
https://github.com/trcrsired updated https://github.com/llvm/llvm-project/pull/79667
>From 2b526821d4e70f3ea83f95d25f804d9fbcf82612 Mon Sep 17 00:00:00 2001
From: cqwrteur <100043421+trcrsired at users.noreply.github.com>
Date: Sat, 1 Jun 2024 02:55:50 -0400
Subject: [PATCH] [libunwind][libcxx][libcxxabi] Fix Exception Handling build
for wasm
The wasm unwind build appears to be dysfunctional, likely because the author has only supplied a customized LLVM build on request, rather than a fully functional patch.
This patch fixes the build
Apply formatting patch proposed by github bot
use "" to prevent CMAKE_SYSTEM_PROCESSOR not defined
[libunwind] logAPI functions should also be built
[libcxxabi] Fix function signatures for wasm
wasm does not define the function signatures correctly for cxxabi
Fix them
Fix formatting issues for libcxxabi's wasm eh change
Merge remote-tracking branch 'parent/main' into wasmlibunwindfix
remove unwanted changes in unwind-wasm.c
Make Unwind-wasm.c compile correctly without workaround in
CMakeLists.txt
using __wasm__ macro to guard against all wasm eh build
fix UnwindLevel.c's formatting issue
ISO C requires a translation unit to contain at least one declaration [-Werror,-Wempty-translation-unit]
compiler-rt does not define CMP_RESULT correct on wasm64
Fixed
Merge code
---
compiler-rt/lib/builtins/fp_compare_impl.inc | 2 +-
libcxx/include/__exception/exception_ptr.h | 21 +-
libcxxabi/include/cxxabi.h | 134 ++--
libcxxabi/src/cxa_exception.cpp | 710 ++++++++-----------
libcxxabi/src/cxa_exception.h | 7 +-
libunwind/include/libunwind.h | 2 +
libunwind/src/Unwind-wasm.c | 13 +-
libunwind/src/UnwindRegistersRestore.S | 3 +-
libunwind/src/UnwindRegistersSave.S | 3 +
libunwind/src/assembly.h | 2 +
libunwind/src/cet_unwind.h | 3 +
libunwind/src/config.h | 15 +-
libunwind/src/libunwind.cpp | 2 +
libunwind/src/libunwind_ext.h | 2 +
14 files changed, 403 insertions(+), 516 deletions(-)
diff --git a/compiler-rt/lib/builtins/fp_compare_impl.inc b/compiler-rt/lib/builtins/fp_compare_impl.inc
index a9a4f6fbf5dfe4..83bdea46a45da4 100644
--- a/compiler-rt/lib/builtins/fp_compare_impl.inc
+++ b/compiler-rt/lib/builtins/fp_compare_impl.inc
@@ -12,7 +12,7 @@
// functions. We need to ensure that the return value is sign-extended in the
// same way as GCC expects (since otherwise GCC-generated __builtin_isinf
// returns true for finite 128-bit floating-point numbers).
-#ifdef __aarch64__
+#if defined(__aarch64__) || defined(__wasm__)
// AArch64 GCC overrides libgcc_cmp_return to use int instead of long.
typedef int CMP_RESULT;
#elif __SIZEOF_POINTER__ == 8 && __SIZEOF_LONG__ == 4
diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h
index 9e5351f534a1c1..84a78d378cc19f 100644
--- a/libcxx/include/__exception/exception_ptr.h
+++ b/libcxx/include/__exception/exception_ptr.h
@@ -29,22 +29,21 @@
namespace __cxxabiv1 {
+# if defined(__wasm__)
+typedef void* (*__libcpp_exception_destructor_func)(void*);
+# elif defined(_WIN32)
+typedef void(__thiscall* __libcpp_exception_destructor_func)(void*);
+# else
+typedef void (*__libcpp_exception_destructor_func)(void*);
+# endif
+
extern "C" {
_LIBCPP_OVERRIDABLE_FUNC_VIS void* __cxa_allocate_exception(size_t) throw();
_LIBCPP_OVERRIDABLE_FUNC_VIS void __cxa_free_exception(void*) throw();
struct __cxa_exception;
-_LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception* __cxa_init_primary_exception(
- void*,
- std::type_info*,
-# if defined(_WIN32)
- void(__thiscall*)(void*)) throw();
-# elif defined(__wasm__)
- // In Wasm, a destructor returns its argument
- void* (*)(void*)) throw();
-# else
- void (*)(void*)) throw();
-# endif
+_LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception*
+__cxa_init_primary_exception(void*, std::type_info*, __libcpp_exception_destructor_func) throw();
}
} // namespace __cxxabiv1
diff --git a/libcxxabi/include/cxxabi.h b/libcxxabi/include/cxxabi.h
index 9ea93680f62e06..cf0cc40ff42b9e 100644
--- a/libcxxabi/include/cxxabi.h
+++ b/libcxxabi/include/cxxabi.h
@@ -20,49 +20,41 @@
#include <__cxxabi_config.h>
#define _LIBCPPABI_VERSION 15000
-#define _LIBCXXABI_NORETURN __attribute__((noreturn))
+#define _LIBCXXABI_NORETURN __attribute__((noreturn))
#define _LIBCXXABI_ALWAYS_COLD __attribute__((cold))
#ifdef __cplusplus
namespace std {
-#if defined(_WIN32)
+# if defined(_WIN32)
class _LIBCXXABI_TYPE_VIS type_info; // forward declaration
-#else
+# else
class type_info; // forward declaration
-#endif
-}
-
+# endif
+} // namespace std
// runtime routines use C calling conventions, but are in __cxxabiv1 namespace
namespace __cxxabiv1 {
struct __cxa_exception;
+# if defined(__wasm__)
+typedef void* (*__libcxxabi_exception_destructor_func)(void*);
+# else
+typedef void(_LIBCXXABI_DTOR_FUNC* __libcxxabi_exception_destructor_func)(void*);
+# endif
-extern "C" {
+extern "C" {
// 2.4.2 Allocating the Exception Object
-extern _LIBCXXABI_FUNC_VIS void *
-__cxa_allocate_exception(size_t thrown_size) _LIBCXXABI_NOEXCEPT;
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_free_exception(void *thrown_exception) _LIBCXXABI_NOEXCEPT;
+extern _LIBCXXABI_FUNC_VIS void* __cxa_allocate_exception(size_t thrown_size) _LIBCXXABI_NOEXCEPT;
+extern _LIBCXXABI_FUNC_VIS void __cxa_free_exception(void* thrown_exception) _LIBCXXABI_NOEXCEPT;
// This function is an LLVM extension, which mirrors the same extension in libsupc++ and libcxxrt
-extern _LIBCXXABI_FUNC_VIS __cxa_exception*
-#ifdef __wasm__
-// In Wasm, a destructor returns its argument
-__cxa_init_primary_exception(void* object, std::type_info* tinfo, void*(_LIBCXXABI_DTOR_FUNC* dest)(void*)) _LIBCXXABI_NOEXCEPT;
-#else
-__cxa_init_primary_exception(void* object, std::type_info* tinfo, void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) _LIBCXXABI_NOEXCEPT;
-#endif
+extern _LIBCXXABI_FUNC_VIS __cxa_exception* __cxa_init_primary_exception(void* object, std::type_info* tinfo,
+ __libcxxabi_exception_destructor_func) _LIBCXXABI_NOEXCEPT;
// 2.4.3 Throwing the Exception Object
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
-__cxa_throw(void *thrown_exception, std::type_info *tinfo,
-#ifdef __wasm__
- void *(_LIBCXXABI_DTOR_FUNC *dest)(void *));
-#else
- void (_LIBCXXABI_DTOR_FUNC *dest)(void *));
-#endif
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_throw(void* thrown_exception, std::type_info* tinfo,
+ __libcxxabi_exception_destructor_func);
// 2.5.3 Exception Handlers
extern _LIBCXXABI_FUNC_VIS void *
@@ -74,8 +66,8 @@ extern _LIBCXXABI_FUNC_VIS void __cxa_end_catch();
extern _LIBCXXABI_FUNC_VIS bool
__cxa_begin_cleanup(void *exceptionObject) _LIBCXXABI_NOEXCEPT;
extern _LIBCXXABI_FUNC_VIS void __cxa_end_cleanup();
-#endif
-extern _LIBCXXABI_FUNC_VIS std::type_info *__cxa_current_exception_type();
+# endif
+extern _LIBCXXABI_FUNC_VIS std::type_info* __cxa_current_exception_type();
// GNU extension
// Calls `terminate` with the current exception being caught. This function is used by GCC when a `noexcept` function
@@ -88,8 +80,7 @@ extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_rethrow();
// 2.6 Auxiliary Runtime APIs
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_bad_cast(void);
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_bad_typeid(void);
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
-__cxa_throw_bad_array_new_length(void);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_throw_bad_array_new_length(void);
// 3.2.6 Pure Virtual Function API
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_pure_virtual(void);
@@ -98,63 +89,49 @@ extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_pure_virtual(void);
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_deleted_virtual(void);
// 3.3.2 One-time Construction API
-#if defined(_LIBCXXABI_GUARD_ABI_ARM)
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint32_t *);
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint32_t *);
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint32_t *);
-#else
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint64_t *);
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint64_t *);
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint64_t *);
-#endif
+# if defined(_LIBCXXABI_GUARD_ABI_ARM)
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint32_t*);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint32_t*);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint32_t*);
+# else
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint64_t*);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint64_t*);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint64_t*);
+# endif
// 3.3.3 Array Construction and Destruction API
-extern _LIBCXXABI_FUNC_VIS void *
-__cxa_vec_new(size_t element_count, size_t element_size, size_t padding_size,
- void (*constructor)(void *), void (*destructor)(void *));
+extern _LIBCXXABI_FUNC_VIS void* __cxa_vec_new(size_t element_count, size_t element_size, size_t padding_size,
+ void (*constructor)(void*), void (*destructor)(void*));
-extern _LIBCXXABI_FUNC_VIS void *
-__cxa_vec_new2(size_t element_count, size_t element_size, size_t padding_size,
- void (*constructor)(void *), void (*destructor)(void *),
- void *(*alloc)(size_t), void (*dealloc)(void *));
+extern _LIBCXXABI_FUNC_VIS void* __cxa_vec_new2(size_t element_count, size_t element_size, size_t padding_size,
+ void (*constructor)(void*), void (*destructor)(void*),
+ void* (*alloc)(size_t), void (*dealloc)(void*));
-extern _LIBCXXABI_FUNC_VIS void *
-__cxa_vec_new3(size_t element_count, size_t element_size, size_t padding_size,
- void (*constructor)(void *), void (*destructor)(void *),
- void *(*alloc)(size_t), void (*dealloc)(void *, size_t));
+extern _LIBCXXABI_FUNC_VIS void* __cxa_vec_new3(size_t element_count, size_t element_size, size_t padding_size,
+ void (*constructor)(void*), void (*destructor)(void*),
+ void* (*alloc)(size_t), void (*dealloc)(void*, size_t));
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_vec_ctor(void *array_address, size_t element_count, size_t element_size,
- void (*constructor)(void *), void (*destructor)(void *));
+extern _LIBCXXABI_FUNC_VIS void __cxa_vec_ctor(void* array_address, size_t element_count, size_t element_size,
+ void (*constructor)(void*), void (*destructor)(void*));
-extern _LIBCXXABI_FUNC_VIS void __cxa_vec_dtor(void *array_address,
- size_t element_count,
- size_t element_size,
- void (*destructor)(void *));
+extern _LIBCXXABI_FUNC_VIS void __cxa_vec_dtor(void* array_address, size_t element_count, size_t element_size,
+ void (*destructor)(void*));
-extern _LIBCXXABI_FUNC_VIS void __cxa_vec_cleanup(void *array_address,
- size_t element_count,
- size_t element_size,
- void (*destructor)(void *));
+extern _LIBCXXABI_FUNC_VIS void __cxa_vec_cleanup(void* array_address, size_t element_count, size_t element_size,
+ void (*destructor)(void*));
-extern _LIBCXXABI_FUNC_VIS void __cxa_vec_delete(void *array_address,
- size_t element_size,
- size_t padding_size,
- void (*destructor)(void *));
+extern _LIBCXXABI_FUNC_VIS void __cxa_vec_delete(void* array_address, size_t element_size, size_t padding_size,
+ void (*destructor)(void*));
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_vec_delete2(void *array_address, size_t element_size, size_t padding_size,
- void (*destructor)(void *), void (*dealloc)(void *));
+extern _LIBCXXABI_FUNC_VIS void __cxa_vec_delete2(void* array_address, size_t element_size, size_t padding_size,
+ void (*destructor)(void*), void (*dealloc)(void*));
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_vec_delete3(void *__array_address, size_t element_size,
- size_t padding_size, void (*destructor)(void *),
- void (*dealloc)(void *, size_t));
+extern _LIBCXXABI_FUNC_VIS void __cxa_vec_delete3(void* __array_address, size_t element_size, size_t padding_size,
+ void (*destructor)(void*), void (*dealloc)(void*, size_t));
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_vec_cctor(void *dest_array, void *src_array, size_t element_count,
- size_t element_size, void (*constructor)(void *, void *),
- void (*destructor)(void *));
+extern _LIBCXXABI_FUNC_VIS void __cxa_vec_cctor(void* dest_array, void* src_array, size_t element_count,
+ size_t element_size, void (*constructor)(void*, void*),
+ void (*destructor)(void*));
// 3.3.5.3 Runtime API
// These functions are part of the C++ ABI, but they are not defined in libc++abi:
@@ -162,9 +139,8 @@ __cxa_vec_cctor(void *dest_array, void *src_array, size_t element_count,
// void __cxa_finalize(void *);
// 3.4 Demangler API
-extern _LIBCXXABI_FUNC_VIS char *__cxa_demangle(const char *mangled_name,
- char *output_buffer,
- size_t *length, int *status);
+extern _LIBCXXABI_FUNC_VIS char* __cxa_demangle(const char* mangled_name, char* output_buffer, size_t* length,
+ int* status);
// Apple additions to support C++ 0x exception_ptr class
// These are primitives to wrap a smart pointer around an exception object
@@ -180,7 +156,7 @@ __cxa_decrement_exception_refcount(void *primary_exception) _LIBCXXABI_NOEXCEPT;
extern _LIBCXXABI_FUNC_VIS bool __cxa_uncaught_exception() _LIBCXXABI_NOEXCEPT;
extern _LIBCXXABI_FUNC_VIS unsigned int __cxa_uncaught_exceptions() _LIBCXXABI_NOEXCEPT;
-#if defined(__linux__) || defined(__Fuchsia__)
+# if defined(__linux__) || defined(__Fuchsia__)
// Linux and Fuchsia TLS support. Not yet an official part of the Itanium ABI.
// https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables
extern _LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*)(void *), void *,
diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp
index 92901a83bfd039..7eae8bbccf092e 100644
--- a/libcxxabi/src/cxa_exception.cpp
+++ b/libcxxabi/src/cxa_exception.cpp
@@ -12,15 +12,15 @@
#include "cxxabi.h"
-#include <exception> // for std::terminate
-#include <string.h> // for memset
+#include <exception> // for std::terminate
+#include <string.h> // for memset
#include "cxa_exception.h"
#include "cxa_handlers.h"
#include "fallback_malloc.h"
#include "include/atomic_support.h" // from libc++
#if __has_feature(address_sanitizer)
-#include <sanitizer/asan_interface.h>
+# include <sanitizer/asan_interface.h>
#endif
// +---------------------------+-----------------------------+---------------+
@@ -37,89 +37,67 @@
namespace __cxxabiv1 {
// Utility routines
-static
-inline
-__cxa_exception*
-cxa_exception_from_thrown_object(void* thrown_object)
-{
- return static_cast<__cxa_exception*>(thrown_object) - 1;
+static inline __cxa_exception* cxa_exception_from_thrown_object(void* thrown_object) {
+ return static_cast<__cxa_exception*>(thrown_object) - 1;
}
// Note: This is never called when exception_header is masquerading as a
// __cxa_dependent_exception.
-static
-inline
-void*
-thrown_object_from_cxa_exception(__cxa_exception* exception_header)
-{
- return static_cast<void*>(exception_header + 1);
+static inline void* thrown_object_from_cxa_exception(__cxa_exception* exception_header) {
+ return static_cast<void*>(exception_header + 1);
}
// Get the exception object from the unwind pointer.
// Relies on the structure layout, where the unwind pointer is right in
// front of the user's exception object
-static
-inline
-__cxa_exception*
-cxa_exception_from_exception_unwind_exception(_Unwind_Exception* unwind_exception)
-{
- return cxa_exception_from_thrown_object(unwind_exception + 1 );
+static inline __cxa_exception* cxa_exception_from_exception_unwind_exception(_Unwind_Exception* unwind_exception) {
+ return cxa_exception_from_thrown_object(unwind_exception + 1);
}
// Round s up to next multiple of a.
-static inline
-size_t aligned_allocation_size(size_t s, size_t a) {
- return (s + a - 1) & ~(a - 1);
-}
+static inline size_t aligned_allocation_size(size_t s, size_t a) { return (s + a - 1) & ~(a - 1); }
-static inline
-size_t cxa_exception_size_from_exception_thrown_size(size_t size) {
- return aligned_allocation_size(size + sizeof (__cxa_exception),
- alignof(__cxa_exception));
+static inline size_t cxa_exception_size_from_exception_thrown_size(size_t size) {
+ return aligned_allocation_size(size + sizeof(__cxa_exception), alignof(__cxa_exception));
}
void __setExceptionClass(_Unwind_Exception* unwind_exception, uint64_t newValue) {
- ::memcpy(&unwind_exception->exception_class, &newValue, sizeof(newValue));
+ ::memcpy(&unwind_exception->exception_class, &newValue, sizeof(newValue));
}
-
static void setOurExceptionClass(_Unwind_Exception* unwind_exception) {
- __setExceptionClass(unwind_exception, kOurExceptionClass);
+ __setExceptionClass(unwind_exception, kOurExceptionClass);
}
static void setDependentExceptionClass(_Unwind_Exception* unwind_exception) {
- __setExceptionClass(unwind_exception, kOurDependentExceptionClass);
+ __setExceptionClass(unwind_exception, kOurDependentExceptionClass);
}
// Is it one of ours?
uint64_t __getExceptionClass(const _Unwind_Exception* unwind_exception) {
- // On x86 and some ARM unwinders, unwind_exception->exception_class is
- // a uint64_t. On other ARM unwinders, it is a char[8].
- // See: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
- // So we just copy it into a uint64_t to be sure.
- uint64_t exClass;
- ::memcpy(&exClass, &unwind_exception->exception_class, sizeof(exClass));
- return exClass;
+ // On x86 and some ARM unwinders, unwind_exception->exception_class is
+ // a uint64_t. On other ARM unwinders, it is a char[8].
+ // See: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
+ // So we just copy it into a uint64_t to be sure.
+ uint64_t exClass;
+ ::memcpy(&exClass, &unwind_exception->exception_class, sizeof(exClass));
+ return exClass;
}
bool __isOurExceptionClass(const _Unwind_Exception* unwind_exception) {
- return (__getExceptionClass(unwind_exception) & get_vendor_and_language) ==
- (kOurExceptionClass & get_vendor_and_language);
+ return (__getExceptionClass(unwind_exception) & get_vendor_and_language) ==
+ (kOurExceptionClass & get_vendor_and_language);
}
static bool isDependentException(_Unwind_Exception* unwind_exception) {
- return (__getExceptionClass(unwind_exception) & 0xFF) == 0x01;
+ return (__getExceptionClass(unwind_exception) & 0xFF) == 0x01;
}
// This does not need to be atomic
-static inline int incrementHandlerCount(__cxa_exception *exception) {
- return ++exception->handlerCount;
-}
+static inline int incrementHandlerCount(__cxa_exception* exception) { return ++exception->handlerCount; }
// This does not need to be atomic
-static inline int decrementHandlerCount(__cxa_exception *exception) {
- return --exception->handlerCount;
-}
+static inline int decrementHandlerCount(__cxa_exception* exception) { return --exception->handlerCount; }
/*
If reason isn't _URC_FOREIGN_EXCEPTION_CAUGHT, then the terminateHandler
@@ -128,28 +106,25 @@ static inline int decrementHandlerCount(__cxa_exception *exception) {
This is never called for a __cxa_dependent_exception.
*/
-static
-void
-exception_cleanup_func(_Unwind_Reason_Code reason, _Unwind_Exception* unwind_exception)
-{
- __cxa_exception* exception_header = cxa_exception_from_exception_unwind_exception(unwind_exception);
- if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason)
- std::__terminate(exception_header->terminateHandler);
- // Just in case there exists a dependent exception that is pointing to this,
- // check the reference count and only destroy this if that count goes to zero.
- __cxa_decrement_exception_refcount(unwind_exception + 1);
+static void exception_cleanup_func(_Unwind_Reason_Code reason, _Unwind_Exception* unwind_exception) {
+ __cxa_exception* exception_header = cxa_exception_from_exception_unwind_exception(unwind_exception);
+ if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason)
+ std::__terminate(exception_header->terminateHandler);
+ // Just in case there exists a dependent exception that is pointing to this,
+ // check the reference count and only destroy this if that count goes to zero.
+ __cxa_decrement_exception_refcount(unwind_exception + 1);
}
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.
-// and
-// * Upon entry, Following initialization of the catch parameter,
-// a handler must call:
-// * void *__cxa_begin_catch(void *exceptionObject );
- (void) __cxa_begin_catch(&exception_header->unwindHeader);
- std::__terminate(exception_header->terminateHandler);
+ // Section 2.5.3 says:
+ // * For purposes of this ABI, several things are considered exception handlers:
+ // ** A terminate() call due to a throw.
+ // and
+ // * Upon entry, Following initialization of the catch parameter,
+ // a handler must call:
+ // * void *__cxa_begin_catch(void *exceptionObject );
+ (void)__cxa_begin_catch(&exception_header->unwindHeader);
+ std::__terminate(exception_header->terminateHandler);
}
// Return the offset of the __cxa_exception header from the start of the
@@ -165,8 +140,7 @@ static size_t get_cxa_exception_offset() {
// Compute the maximum alignment for the target machine.
constexpr size_t alignment = alignof(S);
constexpr size_t excp_size = sizeof(__cxa_exception);
- constexpr size_t aligned_size =
- (excp_size + alignment - 1) / alignment * alignment;
+ constexpr size_t aligned_size = (excp_size + alignment - 1) / alignment * alignment;
constexpr size_t offset = aligned_size - excp_size;
static_assert((offset == 0 || alignof(_Unwind_Exception) < alignment),
"offset is non-zero only if _Unwind_Exception isn't aligned");
@@ -180,39 +154,30 @@ extern "C" {
// 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) throw() {
- size_t actual_size = cxa_exception_size_from_exception_thrown_size(thrown_size);
-
- // Allocate extra space before the __cxa_exception header to ensure the
- // start of the thrown object is sufficiently aligned.
- size_t header_offset = get_cxa_exception_offset();
- char *raw_buffer =
- (char *)__aligned_malloc_with_fallback(header_offset + actual_size);
- if (NULL == raw_buffer)
- std::terminate();
- __cxa_exception *exception_header =
- static_cast<__cxa_exception *>((void *)(raw_buffer + header_offset));
- ::memset(exception_header, 0, actual_size);
- return thrown_object_from_cxa_exception(exception_header);
+void* __cxa_allocate_exception(size_t thrown_size) throw() {
+ size_t actual_size = cxa_exception_size_from_exception_thrown_size(thrown_size);
+
+ // Allocate extra space before the __cxa_exception header to ensure the
+ // start of the thrown object is sufficiently aligned.
+ size_t header_offset = get_cxa_exception_offset();
+ char* raw_buffer = (char*)__aligned_malloc_with_fallback(header_offset + actual_size);
+ if (NULL == raw_buffer)
+ std::terminate();
+ __cxa_exception* exception_header = static_cast<__cxa_exception*>((void*)(raw_buffer + header_offset));
+ ::memset(exception_header, 0, actual_size);
+ return thrown_object_from_cxa_exception(exception_header);
}
-
// Free a __cxa_exception object allocated with __cxa_allocate_exception.
-void __cxa_free_exception(void *thrown_object) throw() {
- // Compute the size of the padding before the header.
- size_t header_offset = get_cxa_exception_offset();
- char *raw_buffer =
- ((char *)cxa_exception_from_thrown_object(thrown_object)) - header_offset;
- __aligned_free_with_fallback((void *)raw_buffer);
+void __cxa_free_exception(void* thrown_object) throw() {
+ // Compute the size of the padding before the header.
+ size_t header_offset = get_cxa_exception_offset();
+ char* raw_buffer = ((char*)cxa_exception_from_thrown_object(thrown_object)) - header_offset;
+ __aligned_free_with_fallback((void*)raw_buffer);
}
__cxa_exception* __cxa_init_primary_exception(void* object, std::type_info* tinfo,
-#ifdef __wasm__
-// In Wasm, a destructor returns its argument
- void *(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw() {
-#else
- void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw() {
-#endif
+ __libcxxabi_exception_destructor_func dest) throw() {
__cxa_exception* exception_header = cxa_exception_from_thrown_object(object);
exception_header->referenceCount = 0;
exception_header->unexpectedHandler = std::get_unexpected();
@@ -228,22 +193,18 @@ __cxa_exception* __cxa_init_primary_exception(void* object, std::type_info* tinf
// 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 () {
- size_t actual_size = sizeof(__cxa_dependent_exception);
- void *ptr = __aligned_malloc_with_fallback(actual_size);
- if (NULL == ptr)
- std::terminate();
- ::memset(ptr, 0, actual_size);
- return ptr;
+void* __cxa_allocate_dependent_exception() {
+ size_t actual_size = sizeof(__cxa_dependent_exception);
+ void* ptr = __aligned_malloc_with_fallback(actual_size);
+ if (NULL == ptr)
+ std::terminate();
+ ::memset(ptr, 0, actual_size);
+ return ptr;
}
-
// 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) {
- __aligned_free_with_fallback(dependent_exception);
-}
-
+void __cxa_free_dependent_exception(void* dependent_exception) { __aligned_free_with_fallback(dependent_exception); }
// 2.4.3 Throwing the Exception Object
/*
@@ -271,13 +232,7 @@ handler, _Unwind_RaiseException may return. In that case, __cxa_throw
will call terminate, assuming that there was no handler for the
exception.
*/
-void
-#ifdef __wasm__
-// In Wasm, a destructor returns its argument
-__cxa_throw(void *thrown_object, std::type_info *tinfo, void *(_LIBCXXABI_DTOR_FUNC *dest)(void *)) {
-#else
-__cxa_throw(void *thrown_object, std::type_info *tinfo, void (_LIBCXXABI_DTOR_FUNC *dest)(void *)) {
-#endif
+void __cxa_throw(void* thrown_object, std::type_info* tinfo, __libcxxabi_exception_destructor_func dest) {
__cxa_eh_globals* globals = __cxa_get_globals();
globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local
@@ -290,16 +245,15 @@ __cxa_throw(void *thrown_object, std::type_info *tinfo, void (_LIBCXXABI_DTOR_FU
#endif
#ifdef __USING_SJLJ_EXCEPTIONS__
- _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
+ _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
#else
- _Unwind_RaiseException(&exception_header->unwindHeader);
+ _Unwind_RaiseException(&exception_header->unwindHeader);
#endif
- // This only happens when there is no handler, or some unexpected unwinding
- // error happens.
- failed_throw(exception_header);
+ // This only happens when there is no handler, or some unexpected unwinding
+ // error happens.
+ failed_throw(exception_header);
}
-
// 2.5.3 Exception Handlers
/*
The adjusted pointer is computed by the personality routine during phase 1
@@ -308,13 +262,11 @@ The adjusted pointer is computed by the personality routine during phase 1
Requires: exception is native
*/
-void *__cxa_get_exception_ptr(void *unwind_exception) throw() {
+void* __cxa_get_exception_ptr(void* unwind_exception) throw() {
#if defined(_LIBCXXABI_ARM_EHABI)
- return reinterpret_cast<void*>(
- static_cast<_Unwind_Control_Block*>(unwind_exception)->barrier_cache.bitpattern[0]);
+ return reinterpret_cast<void*>(static_cast<_Unwind_Control_Block*>(unwind_exception)->barrier_cache.bitpattern[0]);
#else
- return cxa_exception_from_exception_unwind_exception(
- static_cast<_Unwind_Exception*>(unwind_exception))->adjustedPtr;
+ return cxa_exception_from_exception_unwind_exception(static_cast<_Unwind_Exception*>(unwind_exception))->adjustedPtr;
#endif
}
@@ -323,30 +275,25 @@ void *__cxa_get_exception_ptr(void *unwind_exception) throw() {
The routine to be called before the cleanup. This will save __cxa_exception in
__cxa_eh_globals, so that __cxa_end_cleanup() can recover later.
*/
-bool __cxa_begin_cleanup(void *unwind_arg) throw() {
- _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg);
- __cxa_eh_globals* globals = __cxa_get_globals();
- __cxa_exception* exception_header =
- cxa_exception_from_exception_unwind_exception(unwind_exception);
-
- if (__isOurExceptionClass(unwind_exception))
- {
- if (0 == exception_header->propagationCount)
- {
- exception_header->nextPropagatingException = globals->propagatingExceptions;
- globals->propagatingExceptions = exception_header;
- }
- ++exception_header->propagationCount;
- }
- else
- {
- // If the propagatingExceptions stack is not empty, since we can't
- // chain the foreign exception, terminate it.
- if (NULL != globals->propagatingExceptions)
- std::terminate();
- globals->propagatingExceptions = exception_header;
+bool __cxa_begin_cleanup(void* unwind_arg) throw() {
+ _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg);
+ __cxa_eh_globals* globals = __cxa_get_globals();
+ __cxa_exception* exception_header = cxa_exception_from_exception_unwind_exception(unwind_exception);
+
+ if (__isOurExceptionClass(unwind_exception)) {
+ if (0 == exception_header->propagationCount) {
+ exception_header->nextPropagatingException = globals->propagatingExceptions;
+ globals->propagatingExceptions = exception_header;
}
- return true;
+ ++exception_header->propagationCount;
+ } else {
+ // If the propagatingExceptions stack is not empty, since we can't
+ // chain the foreign exception, terminate it.
+ if (NULL != globals->propagatingExceptions)
+ std::terminate();
+ globals->propagatingExceptions = exception_header;
+ }
+ return true;
}
/*
@@ -363,55 +310,48 @@ returns and we need to keep the original lr so just branch to it. When
targeting bare metal, the function also clobbers ip/r12 to hold the address of
_Unwind_Resume, which may be too far away for an ordinary branch.
*/
-__attribute__((used)) static _Unwind_Exception *
-__cxa_end_cleanup_impl()
-{
- __cxa_eh_globals* globals = __cxa_get_globals();
- __cxa_exception* exception_header = globals->propagatingExceptions;
- if (NULL == exception_header)
- {
- // It seems that __cxa_begin_cleanup() is not called properly.
- // We have no choice but terminate the program now.
- std::terminate();
- }
+__attribute__((used)) static _Unwind_Exception* __cxa_end_cleanup_impl() {
+ __cxa_eh_globals* globals = __cxa_get_globals();
+ __cxa_exception* exception_header = globals->propagatingExceptions;
+ if (NULL == exception_header) {
+ // It seems that __cxa_begin_cleanup() is not called properly.
+ // We have no choice but terminate the program now.
+ std::terminate();
+ }
- if (__isOurExceptionClass(&exception_header->unwindHeader))
- {
- --exception_header->propagationCount;
- if (0 == exception_header->propagationCount)
- {
- globals->propagatingExceptions = exception_header->nextPropagatingException;
- exception_header->nextPropagatingException = NULL;
- }
- }
- else
- {
- globals->propagatingExceptions = NULL;
+ if (__isOurExceptionClass(&exception_header->unwindHeader)) {
+ --exception_header->propagationCount;
+ if (0 == exception_header->propagationCount) {
+ globals->propagatingExceptions = exception_header->nextPropagatingException;
+ exception_header->nextPropagatingException = NULL;
}
- return &exception_header->unwindHeader;
+ } else {
+ globals->propagatingExceptions = NULL;
+ }
+ return &exception_header->unwindHeader;
}
asm(" .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n"
" .globl __cxa_end_cleanup\n"
" .type __cxa_end_cleanup,%function\n"
"__cxa_end_cleanup:\n"
-#if defined(__ARM_FEATURE_BTI_DEFAULT)
+# if defined(__ARM_FEATURE_BTI_DEFAULT)
" bti\n"
-#endif
+# endif
" push {r1, r2, r3, r4}\n"
" mov r4, lr\n"
" bl __cxa_end_cleanup_impl\n"
" mov lr, r4\n"
-#if defined(LIBCXXABI_BAREMETAL)
+# if defined(LIBCXXABI_BAREMETAL)
" ldr r4, =_Unwind_Resume\n"
" mov ip, r4\n"
-#endif
+# endif
" pop {r1, r2, r3, r4}\n"
-#if defined(LIBCXXABI_BAREMETAL)
+# if defined(LIBCXXABI_BAREMETAL)
" bx ip\n"
-#else
+# else
" b _Unwind_Resume\n"
-#endif
+# endif
" .popsection");
#endif // defined(_LIBCXXABI_ARM_EHABI)
@@ -446,57 +386,49 @@ to terminate or unexpected during unwinding.
* 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_arg) throw()
-{
- _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)
- );
+void* __cxa_begin_catch(void* unwind_arg) throw() {
+ _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));
#if defined(__MVS__)
- // Remove the exception object from the linked list of exceptions that the z/OS unwinder
- // maintains before adding it to the libc++abi list of caught exceptions.
- // The libc++abi will manage the lifetime of the exception from this point forward.
- _UnwindZOS_PopException();
+ // Remove the exception object from the linked list of exceptions that the z/OS unwinder
+ // maintains before adding it to the libc++abi list of caught exceptions.
+ // The libc++abi will manage the lifetime of the exception from this point forward.
+ _UnwindZOS_PopException();
#endif
- 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
+ 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
#if defined(_LIBCXXABI_ARM_EHABI)
- return reinterpret_cast<void*>(exception_header->unwindHeader.barrier_cache.bitpattern[0]);
+ return reinterpret_cast<void*>(exception_header->unwindHeader.barrier_cache.bitpattern[0]);
#else
- return exception_header->adjustedPtr;
+ return exception_header->adjustedPtr;
#endif
- }
- // 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;
+ }
+ // 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;
}
-
/*
Upon exit for any reason, a handler must call:
void __cxa_end_catch ();
@@ -520,73 +452,61 @@ void __cxa_end_catch() {
"sizeof(__cxa_exception) must be equal to "
"sizeof(__cxa_dependent_exception)");
static_assert(__builtin_offsetof(__cxa_exception, referenceCount) ==
- __builtin_offsetof(__cxa_dependent_exception,
- primaryException),
+ __builtin_offsetof(__cxa_dependent_exception, primaryException),
"the layout of __cxa_exception must match the layout of "
"__cxa_dependent_exception");
static_assert(__builtin_offsetof(__cxa_exception, handlerCount) ==
__builtin_offsetof(__cxa_dependent_exception, handlerCount),
"the layout of __cxa_exception must match the layout of "
"__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 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 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));
- }
- }
+ __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
}
- 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;
+ // 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 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));
}
+ }
+ } 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;
}
+ }
}
void __cxa_call_terminate(void* unwind_arg) throw() {
@@ -597,17 +517,17 @@ void __cxa_call_terminate(void* unwind_arg) throw() {
// 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();
- if (NULL == globals)
- return NULL; // If there have never been any exceptions, there are none now.
- __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;
+std::type_info* __cxa_current_exception_type() {
+ // get the current exception
+ __cxa_eh_globals* globals = __cxa_get_globals_fast();
+ if (NULL == globals)
+ return NULL; // If there have never been any exceptions, there are none now.
+ __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
@@ -623,41 +543,39 @@ If the exception is native:
and that's ok.
*/
void __cxa_rethrow() {
- __cxa_eh_globals* globals = __cxa_get_globals();
- __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)
- {
- // 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;
- }
+ __cxa_eh_globals* globals = __cxa_get_globals();
+ __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) {
+ // 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;
+ }
#ifdef __USING_SJLJ_EXCEPTIONS__
- _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
+ _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
#else
- _Unwind_RaiseException(&exception_header->unwindHeader);
+ _Unwind_RaiseException(&exception_header->unwindHeader);
#endif
- // 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 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();
}
/*
@@ -667,13 +585,11 @@ void __cxa_rethrow() {
Requires: If thrown_object is not NULL, it is a native exception.
*/
-void
-__cxa_increment_exception_refcount(void *thrown_object) throw() {
- if (thrown_object != NULL )
- {
- __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
- std::__libcpp_atomic_add(&exception_header->referenceCount, size_t(1));
- }
+void __cxa_increment_exception_refcount(void* thrown_object) throw() {
+ if (thrown_object != NULL) {
+ __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
+ std::__libcpp_atomic_add(&exception_header->referenceCount, size_t(1));
+ }
}
/*
@@ -685,17 +601,15 @@ __cxa_increment_exception_refcount(void *thrown_object) throw() {
Requires: If thrown_object is not NULL, it is a native exception.
*/
_LIBCXXABI_NO_CFI
-void __cxa_decrement_exception_refcount(void *thrown_object) throw() {
- if (thrown_object != NULL )
- {
- __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
- if (std::__libcpp_atomic_add(&exception_header->referenceCount, size_t(-1)) == 0)
- {
- if (NULL != exception_header->exceptionDestructor)
- exception_header->exceptionDestructor(thrown_object);
- __cxa_free_exception(thrown_object);
- }
+void __cxa_decrement_exception_refcount(void* thrown_object) throw() {
+ if (thrown_object != NULL) {
+ __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
+ if (std::__libcpp_atomic_add(&exception_header->referenceCount, size_t(-1)) == 0) {
+ if (NULL != exception_header->exceptionDestructor)
+ exception_header->exceptionDestructor(thrown_object);
+ __cxa_free_exception(thrown_object);
}
+ }
}
/*
@@ -708,24 +622,23 @@ void __cxa_decrement_exception_refcount(void *thrown_object) throw() {
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() throw() {
-// get the current exception
- __cxa_eh_globals* globals = __cxa_get_globals_fast();
- if (NULL == globals)
- return NULL; // If there are no globals, there is no exception
- __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);
- exception_header = cxa_exception_from_thrown_object(dep_exception_header->primaryException);
- }
- void* thrown_object = thrown_object_from_cxa_exception(exception_header);
- __cxa_increment_exception_refcount(thrown_object);
- return thrown_object;
+void* __cxa_current_primary_exception() throw() {
+ // get the current exception
+ __cxa_eh_globals* globals = __cxa_get_globals_fast();
+ if (NULL == globals)
+ return NULL; // If there are no globals, there is no exception
+ __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);
+ exception_header = cxa_exception_from_thrown_object(dep_exception_header->primaryException);
+ }
+ void* thrown_object = thrown_object_from_cxa_exception(exception_header);
+ __cxa_increment_exception_refcount(thrown_object);
+ return thrown_object;
}
/*
@@ -734,64 +647,55 @@ void *__cxa_current_primary_exception() throw() {
primary exception is decremented, destroying the primary if necessary.
Finally the dependent exception is destroyed.
*/
-static
-void
-dependent_exception_cleanup(_Unwind_Reason_Code reason, _Unwind_Exception* unwind_exception)
-{
- __cxa_dependent_exception* dep_exception_header =
- reinterpret_cast<__cxa_dependent_exception*>(unwind_exception + 1) - 1;
- if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason)
- std::__terminate(dep_exception_header->terminateHandler);
- __cxa_decrement_exception_refcount(dep_exception_header->primaryException);
- __cxa_free_dependent_exception(dep_exception_header);
+static void dependent_exception_cleanup(_Unwind_Reason_Code reason, _Unwind_Exception* unwind_exception) {
+ __cxa_dependent_exception* dep_exception_header =
+ reinterpret_cast<__cxa_dependent_exception*>(unwind_exception + 1) - 1;
+ if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason)
+ std::__terminate(dep_exception_header->terminateHandler);
+ __cxa_decrement_exception_refcount(dep_exception_header->primaryException);
+ __cxa_free_dependent_exception(dep_exception_header);
}
/*
If thrown_object is not null, allocate, initialize and throw a dependent
exception.
*/
-void
-__cxa_rethrow_primary_exception(void* thrown_object)
-{
- 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());
- dep_exception_header->primaryException = thrown_object;
- __cxa_increment_exception_refcount(thrown_object);
- dep_exception_header->exceptionType = exception_header->exceptionType;
- dep_exception_header->unexpectedHandler = std::get_unexpected();
- dep_exception_header->terminateHandler = std::get_terminate();
- setDependentExceptionClass(&dep_exception_header->unwindHeader);
- __cxa_get_globals()->uncaughtExceptions += 1;
- dep_exception_header->unwindHeader.exception_cleanup = dependent_exception_cleanup;
+void __cxa_rethrow_primary_exception(void* thrown_object) {
+ 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());
+ dep_exception_header->primaryException = thrown_object;
+ __cxa_increment_exception_refcount(thrown_object);
+ dep_exception_header->exceptionType = exception_header->exceptionType;
+ dep_exception_header->unexpectedHandler = std::get_unexpected();
+ dep_exception_header->terminateHandler = std::get_terminate();
+ setDependentExceptionClass(&dep_exception_header->unwindHeader);
+ __cxa_get_globals()->uncaughtExceptions += 1;
+ dep_exception_header->unwindHeader.exception_cleanup = dependent_exception_cleanup;
#ifdef __USING_SJLJ_EXCEPTIONS__
- _Unwind_SjLj_RaiseException(&dep_exception_header->unwindHeader);
+ _Unwind_SjLj_RaiseException(&dep_exception_header->unwindHeader);
#else
- _Unwind_RaiseException(&dep_exception_header->unwindHeader);
+ _Unwind_RaiseException(&dep_exception_header->unwindHeader);
#endif
- // Some sort of unwinding error. Note that terminate is a handler.
- __cxa_begin_catch(&dep_exception_header->unwindHeader);
- }
- // If we return client will call terminate()
+ // Some sort of unwinding error. Note that terminate is a handler.
+ __cxa_begin_catch(&dep_exception_header->unwindHeader);
+ }
+ // If we return client will call terminate()
}
-bool
-__cxa_uncaught_exception() throw() { return __cxa_uncaught_exceptions() != 0; }
+bool __cxa_uncaught_exception() throw() { return __cxa_uncaught_exceptions() != 0; }
-unsigned int
-__cxa_uncaught_exceptions() throw()
-{
- // This does not report foreign exceptions in flight
- __cxa_eh_globals* globals = __cxa_get_globals_fast();
- if (globals == 0)
- return 0;
- return globals->uncaughtExceptions;
+unsigned int __cxa_uncaught_exceptions() throw() {
+ // This does not report foreign exceptions in flight
+ __cxa_eh_globals* globals = __cxa_get_globals_fast();
+ if (globals == 0)
+ return 0;
+ return globals->uncaughtExceptions;
}
} // extern "C"
-} // abi
+} // namespace __cxxabiv1
diff --git a/libcxxabi/src/cxa_exception.h b/libcxxabi/src/cxa_exception.h
index aba08f2992103e..4476cec9738f35 100644
--- a/libcxxabi/src/cxa_exception.h
+++ b/libcxxabi/src/cxa_exception.h
@@ -43,12 +43,7 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
// Manage the exception object itself.
std::type_info *exceptionType;
-#ifdef __wasm__
- // In Wasm, a destructor returns its argument
- void *(_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
-#else
- void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
-#endif
+ __libcxxabi_exception_destructor_func exceptionDestructor;
std::unexpected_handler unexpectedHandler;
std::terminate_handler terminateHandler;
diff --git a/libunwind/include/libunwind.h b/libunwind/include/libunwind.h
index b2dae8feed9a3b..63e147ae2423e2 100644
--- a/libunwind/include/libunwind.h
+++ b/libunwind/include/libunwind.h
@@ -15,6 +15,7 @@
#include <__libunwind_config.h>
+#ifndef __wasm__
#include <stdint.h>
#include <stddef.h>
@@ -1299,5 +1300,6 @@ enum {
UNW_LOONGARCH_F30 = 62,
UNW_LOONGARCH_F31 = 63,
};
+#endif
#endif
diff --git a/libunwind/src/Unwind-wasm.c b/libunwind/src/Unwind-wasm.c
index b18b32c5d17847..808940c3a26d2e 100644
--- a/libunwind/src/Unwind-wasm.c
+++ b/libunwind/src/Unwind-wasm.c
@@ -10,15 +10,13 @@
//
//===----------------------------------------------------------------------===//
+// clang-format off
#include <stdbool.h>
-
+// clang-format on
#include "config.h"
-
-#ifdef __WASM_EXCEPTIONS__
-
#include "unwind.h"
-#include <threads.h>
+#ifdef __wasm__
_Unwind_Reason_Code __gxx_personality_wasm0(int version, _Unwind_Action actions,
uint64_t exceptionClass,
_Unwind_Exception *unwind_exception,
@@ -35,7 +33,7 @@ struct _Unwind_LandingPadContext {
// Communication channel between compiler-generated user code and personality
// function
-thread_local struct _Unwind_LandingPadContext __wasm_lpad_context;
+_Thread_local struct _Unwind_LandingPadContext __wasm_lpad_context;
/// Calls to this function is in landing pads in compiler-generated user code.
/// In other EH schemes, stack unwinding is done by libunwind library, which
@@ -119,5 +117,4 @@ _LIBUNWIND_EXPORT uintptr_t
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
return 0;
}
-
-#endif // defined(__WASM_EXCEPTIONS__)
+#endif
diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S
index 180a66582f41b5..5b7ed4ac921296 100644
--- a/libunwind/src/UnwindRegistersRestore.S
+++ b/libunwind/src/UnwindRegistersRestore.S
@@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
+#if !defined(__wasm__)
#include "assembly.h"
#define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
@@ -1253,4 +1254,4 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv)
#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */
NO_EXEC_STACK_DIRECTIVE
-
+#endif
diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S
index fab234fcd6f318..7f35689af5f799 100644
--- a/libunwind/src/UnwindRegistersSave.S
+++ b/libunwind/src/UnwindRegistersSave.S
@@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
+#ifndef __wasm__
#include "assembly.h"
#define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
@@ -1184,3 +1185,5 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */
NO_EXEC_STACK_DIRECTIVE
+
+#endif
diff --git a/libunwind/src/assembly.h b/libunwind/src/assembly.h
index f8e83e138eff50..21b20a8caf2cbf 100644
--- a/libunwind/src/assembly.h
+++ b/libunwind/src/assembly.h
@@ -15,6 +15,7 @@
#ifndef UNWIND_ASSEMBLY_H
#define UNWIND_ASSEMBLY_H
+#ifndef __wasm__
#if defined(__linux__) && defined(__CET__)
#include <cet.h>
#define _LIBUNWIND_CET_ENDBR _CET_ENDBR
@@ -299,5 +300,6 @@ aliasname: \
#if defined(__powerpc__)
#define PPC_LEFT_SHIFT(index) << (index)
#endif
+#endif
#endif /* UNWIND_ASSEMBLY_H */
diff --git a/libunwind/src/cet_unwind.h b/libunwind/src/cet_unwind.h
index 47d7616a7322c3..670abe37561bc4 100644
--- a/libunwind/src/cet_unwind.h
+++ b/libunwind/src/cet_unwind.h
@@ -10,6 +10,7 @@
#ifndef LIBUNWIND_CET_UNWIND_H
#define LIBUNWIND_CET_UNWIND_H
+#ifndef __wasm__
#include "libunwind.h"
// Currently, CET is implemented on Linux x86 platforms.
@@ -61,3 +62,5 @@ extern void *__libunwind_cet_get_registers(unw_cursor_t *);
extern void *__libunwind_cet_get_jump_target(void);
#endif
+
+#endif
diff --git a/libunwind/src/config.h b/libunwind/src/config.h
index deb5a4d4d73d46..2a57df41acca9f 100644
--- a/libunwind/src/config.h
+++ b/libunwind/src/config.h
@@ -66,13 +66,14 @@
#define _LIBUNWIND_EXPORT
#define _LIBUNWIND_HIDDEN
#else
- #if !defined(__ELF__) && !defined(__MACH__) && !defined(_AIX)
- #define _LIBUNWIND_EXPORT __declspec(dllexport)
- #define _LIBUNWIND_HIDDEN
- #else
- #define _LIBUNWIND_EXPORT __attribute__((visibility("default")))
- #define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden")))
- #endif
+#if !defined(__ELF__) && !defined(__MACH__) && !defined(_AIX) && \
+ !defined(__wasm__)
+#define _LIBUNWIND_EXPORT __declspec(dllexport)
+#define _LIBUNWIND_HIDDEN
+#else
+#define _LIBUNWIND_EXPORT __attribute__((visibility("default")))
+#define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden")))
+#endif
#endif
#define STR(a) #a
diff --git a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp
index cf39ec5f7dbdf9..7d5855102a0e53 100644
--- a/libunwind/src/libunwind.cpp
+++ b/libunwind/src/libunwind.cpp
@@ -12,6 +12,7 @@
#include <libunwind.h>
#include "config.h"
+#ifndef __wasm__
#include "libunwind_ext.h"
#include <stdlib.h>
@@ -430,6 +431,7 @@ int __unw_remove_find_dynamic_unwind_sections(
}
#endif // __APPLE__
+#endif
// Add logging hooks in Debug builds only
#ifndef NDEBUG
diff --git a/libunwind/src/libunwind_ext.h b/libunwind/src/libunwind_ext.h
index 28db43a4f6eef2..3a7ca7c337e008 100644
--- a/libunwind/src/libunwind_ext.h
+++ b/libunwind/src/libunwind_ext.h
@@ -12,6 +12,7 @@
#ifndef __LIBUNWIND_EXT__
#define __LIBUNWIND_EXT__
+#ifndef __wasm__
#include "config.h"
#include <libunwind.h>
#include <unwind.h>
@@ -133,5 +134,6 @@ extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context,
#ifdef __cplusplus
}
#endif
+#endif
#endif // __LIBUNWIND_EXT__
More information about the cfe-commits
mailing list