[libcxx-commits] [compiler-rt] [libcxx] [libcxxabi] [libunwind] [libunwind][libcxx][libcxxabi][compiler-rt-builtins] Fix Exception Handling build for wasm (PR #79667)

via libcxx-commits libcxx-commits at lists.llvm.org
Wed Aug 28 14:38:28 PDT 2024


https://github.com/trcrsired updated https://github.com/llvm/llvm-project/pull/79667

>From 4f1ce895254dd9505150c1f5f5cb77454b9aca68 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 1/2] [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                   | 179 ++---
 libcxxabi/src/cxa_exception.cpp              | 712 ++++++++-----------
 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, 423 insertions(+), 543 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 0a8337fa39de39..01f340a587ec37 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 0e3969084e04fd..4162fd7ec2ba77 100644
--- a/libcxxabi/include/cxxabi.h
+++ b/libcxxabi/include/cxxabi.h
@@ -20,62 +20,51 @@
 #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) throw();
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_free_exception(void *thrown_exception) throw();
+extern _LIBCXXABI_FUNC_VIS void* __cxa_allocate_exception(size_t thrown_size) throw();
+extern _LIBCXXABI_FUNC_VIS void __cxa_free_exception(void* thrown_exception) throw();
 // 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*)) throw();
-#else
-__cxa_init_primary_exception(void* object, std::type_info* tinfo, void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw();
-#endif
+extern _LIBCXXABI_FUNC_VIS __cxa_exception* __cxa_init_primary_exception(void* object, std::type_info* tinfo,
+                                                                         __libcxxabi_exception_destructor_func) throw();
 
 // 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 *
-__cxa_get_exception_ptr(void *exceptionObject) throw();
-extern _LIBCXXABI_FUNC_VIS void *
-__cxa_begin_catch(void *exceptionObject) throw();
+extern _LIBCXXABI_FUNC_VIS void* __cxa_get_exception_ptr(void* exceptionObject) throw();
+extern _LIBCXXABI_FUNC_VIS void* __cxa_begin_catch(void* exceptionObject) throw();
 extern _LIBCXXABI_FUNC_VIS void __cxa_end_catch();
-#if defined(_LIBCXXABI_ARM_EHABI)
-extern _LIBCXXABI_FUNC_VIS bool
-__cxa_begin_cleanup(void *exceptionObject) throw();
+#  if defined(_LIBCXXABI_ARM_EHABI)
+extern _LIBCXXABI_FUNC_VIS bool __cxa_begin_cleanup(void* exceptionObject) throw();
 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();
 
 // 2.5.4 Rethrowing Exceptions
 extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_rethrow();
@@ -83,8 +72,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);
@@ -93,63 +81,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_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_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_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_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_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_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_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_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_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_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*));
 
 // 3.3.5.3 Runtime API
 // These functions are part of the C++ ABI, but they are not defined in libc++abi:
@@ -157,30 +131,25 @@ __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
-extern _LIBCXXABI_FUNC_VIS void *__cxa_current_primary_exception() throw();
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_rethrow_primary_exception(void *primary_exception);
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_increment_exception_refcount(void *primary_exception) throw();
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_decrement_exception_refcount(void *primary_exception) throw();
+extern _LIBCXXABI_FUNC_VIS void* __cxa_current_primary_exception() throw();
+extern _LIBCXXABI_FUNC_VIS void __cxa_rethrow_primary_exception(void* primary_exception);
+extern _LIBCXXABI_FUNC_VIS void __cxa_increment_exception_refcount(void* primary_exception) throw();
+extern _LIBCXXABI_FUNC_VIS void __cxa_decrement_exception_refcount(void* primary_exception) throw();
 
 // Apple extension to support std::uncaught_exception()
 extern _LIBCXXABI_FUNC_VIS bool __cxa_uncaught_exception() throw();
 extern _LIBCXXABI_FUNC_VIS unsigned int __cxa_uncaught_exceptions() throw();
 
-#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 *,
-                                                   void *) throw();
-#endif
+extern _LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*)(void*), void*, void*) throw();
+#  endif
 
 } // extern "C"
 } // namespace __cxxabiv1
diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp
index ff69a4c65e465e..10d209fc5ceb41 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,89 +452,77 @@ 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;
     }
+  }
 }
 
 // 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
@@ -618,41 +538,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();
 }
 
 /*
@@ -662,13 +580,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));
+  }
 }
 
 /*
@@ -680,17 +596,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);
     }
+  }
 }
 
 /*
@@ -703,24 +617,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;
 }
 
 /*
@@ -729,64 +642,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; }
-
-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;
+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;
 }
 
 } // 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 67d9e05711898d..955246db46cf7f 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
@@ -1235,4 +1236,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 5bf6055fe4147f..4397295e5929d9 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
@@ -1180,3 +1181,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 fb07d04071af3d..2c76e4b8a06b86 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
@@ -284,5 +285,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 c364ed3e12feb3..7be3cc10a7fd71 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.
@@ -39,3 +40,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__

>From d105b0c1435cb5a8cc31eadd8a92f774b440f507 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 2/2] [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                   | 179 ++---
 libcxxabi/src/cxa_exception.cpp              | 712 ++++++++-----------
 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, 423 insertions(+), 543 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 0a8337fa39de39..01f340a587ec37 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 0e3969084e04fd..4162fd7ec2ba77 100644
--- a/libcxxabi/include/cxxabi.h
+++ b/libcxxabi/include/cxxabi.h
@@ -20,62 +20,51 @@
 #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) throw();
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_free_exception(void *thrown_exception) throw();
+extern _LIBCXXABI_FUNC_VIS void* __cxa_allocate_exception(size_t thrown_size) throw();
+extern _LIBCXXABI_FUNC_VIS void __cxa_free_exception(void* thrown_exception) throw();
 // 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*)) throw();
-#else
-__cxa_init_primary_exception(void* object, std::type_info* tinfo, void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw();
-#endif
+extern _LIBCXXABI_FUNC_VIS __cxa_exception* __cxa_init_primary_exception(void* object, std::type_info* tinfo,
+                                                                         __libcxxabi_exception_destructor_func) throw();
 
 // 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 *
-__cxa_get_exception_ptr(void *exceptionObject) throw();
-extern _LIBCXXABI_FUNC_VIS void *
-__cxa_begin_catch(void *exceptionObject) throw();
+extern _LIBCXXABI_FUNC_VIS void* __cxa_get_exception_ptr(void* exceptionObject) throw();
+extern _LIBCXXABI_FUNC_VIS void* __cxa_begin_catch(void* exceptionObject) throw();
 extern _LIBCXXABI_FUNC_VIS void __cxa_end_catch();
-#if defined(_LIBCXXABI_ARM_EHABI)
-extern _LIBCXXABI_FUNC_VIS bool
-__cxa_begin_cleanup(void *exceptionObject) throw();
+#  if defined(_LIBCXXABI_ARM_EHABI)
+extern _LIBCXXABI_FUNC_VIS bool __cxa_begin_cleanup(void* exceptionObject) throw();
 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();
 
 // 2.5.4 Rethrowing Exceptions
 extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_rethrow();
@@ -83,8 +72,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);
@@ -93,63 +81,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_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_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_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_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_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_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_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_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_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_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*));
 
 // 3.3.5.3 Runtime API
 // These functions are part of the C++ ABI, but they are not defined in libc++abi:
@@ -157,30 +131,25 @@ __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
-extern _LIBCXXABI_FUNC_VIS void *__cxa_current_primary_exception() throw();
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_rethrow_primary_exception(void *primary_exception);
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_increment_exception_refcount(void *primary_exception) throw();
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_decrement_exception_refcount(void *primary_exception) throw();
+extern _LIBCXXABI_FUNC_VIS void* __cxa_current_primary_exception() throw();
+extern _LIBCXXABI_FUNC_VIS void __cxa_rethrow_primary_exception(void* primary_exception);
+extern _LIBCXXABI_FUNC_VIS void __cxa_increment_exception_refcount(void* primary_exception) throw();
+extern _LIBCXXABI_FUNC_VIS void __cxa_decrement_exception_refcount(void* primary_exception) throw();
 
 // Apple extension to support std::uncaught_exception()
 extern _LIBCXXABI_FUNC_VIS bool __cxa_uncaught_exception() throw();
 extern _LIBCXXABI_FUNC_VIS unsigned int __cxa_uncaught_exceptions() throw();
 
-#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 *,
-                                                   void *) throw();
-#endif
+extern _LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*)(void*), void*, void*) throw();
+#  endif
 
 } // extern "C"
 } // namespace __cxxabiv1
diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp
index ff69a4c65e465e..10d209fc5ceb41 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,89 +452,77 @@ 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;
     }
+  }
 }
 
 // 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
@@ -618,41 +538,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();
 }
 
 /*
@@ -662,13 +580,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));
+  }
 }
 
 /*
@@ -680,17 +596,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);
     }
+  }
 }
 
 /*
@@ -703,24 +617,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;
 }
 
 /*
@@ -729,64 +642,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; }
-
-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;
+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;
 }
 
 } // 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 67d9e05711898d..955246db46cf7f 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
@@ -1235,4 +1236,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 5bf6055fe4147f..4397295e5929d9 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
@@ -1180,3 +1181,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 fb07d04071af3d..2c76e4b8a06b86 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
@@ -284,5 +285,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 c364ed3e12feb3..7be3cc10a7fd71 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.
@@ -39,3 +40,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 libcxx-commits mailing list