[compiler-rt] [libcxx] [libcxxabi] [libunwind] [libunwind][libcxx][libcxxabi] Fix Exception Handling build for wasm (PR #140365)
via cfe-commits
cfe-commits at lists.llvm.org
Sat May 17 01:59:41 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxxabi
Author: cqwrteur (trcrsired)
<details>
<summary>Changes</summary>
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.
---
Patch is 63.80 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/140365.diff
14 Files Affected:
- (modified) compiler-rt/lib/builtins/fp_compare_impl.inc (+1-1)
- (modified) libcxx/include/__exception/exception_ptr.h (+10-11)
- (modified) libcxxabi/include/cxxabi.h (+55-79)
- (modified) libcxxabi/src/cxa_exception.cpp (+307-403)
- (modified) libcxxabi/src/cxa_exception.h (+1-6)
- (modified) libunwind/include/libunwind.h (+2)
- (modified) libunwind/src/Unwind-wasm.c (+5-8)
- (modified) libunwind/src/UnwindRegistersRestore.S (+2-1)
- (modified) libunwind/src/UnwindRegistersSave.S (+3)
- (modified) libunwind/src/assembly.h (+2)
- (modified) libunwind/src/config.h (+8-7)
- (modified) libunwind/src/libunwind.cpp (+2)
- (modified) libunwind/src/libunwind_ext.h (+2)
- (modified) libunwind/src/shadow_stack_unwind.h (+3)
``````````diff
diff --git a/compiler-rt/lib/builtins/fp_compare_impl.inc b/compiler-rt/lib/builtins/fp_compare_impl.inc
index f883338c471d3..fa1629fc1a07a 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).
-#if defined(__aarch64__) || defined(__arm64ec__)
+#if defined(__aarch64__) || defined(__arm64ec__) || 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 b1fe9a1299ec7..6b1e9f09c95d2 100644
--- a/libcxx/include/__exception/exception_ptr.h
+++ b/libcxx/include/__exception/exception_ptr.h
@@ -28,22 +28,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 9ea93680f62e0..cf0cc40ff42b9 100644
--- a/libcxxabi/include/cxxabi.h
+++ b/libcxxabi/include/cxxabi.h
@@ -20,49 +20,41 @@
#include <__cxxabi_config.h>
#define _LIBCPPABI_VERSION 15000
-#define _LIBCXXABI_NORETURN __attribute__((noreturn))
+#define _LIBCXXABI_NORETURN __attribute__((noreturn))
#define _LIBCXXABI_ALWAYS_COLD __attribute__((cold))
#ifdef __cplusplus
namespace std {
-#if defined(_WIN32)
+# if defined(_WIN32)
class _LIBCXXABI_TYPE_VIS type_info; // forward declaration
-#else
+# else
class type_info; // forward declaration
-#endif
-}
-
+# endif
+} // namespace std
// runtime routines use C calling conventions, but are in __cxxabiv1 namespace
namespace __cxxabiv1 {
struct __cxa_exception;
+# if defined(__wasm__)
+typedef void* (*__libcxxabi_exception_destructor_func)(void*);
+# else
+typedef void(_LIBCXXABI_DTOR_FUNC* __libcxxabi_exception_destructor_func)(void*);
+# endif
-extern "C" {
+extern "C" {
// 2.4.2 Allocating the Exception Object
-extern _LIBCXXABI_FUNC_VIS void *
-__cxa_allocate_exception(size_t thrown_size) _LIBCXXABI_NOEXCEPT;
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_free_exception(void *thrown_exception) _LIBCXXABI_NOEXCEPT;
+extern _LIBCXXABI_FUNC_VIS void* __cxa_allocate_exception(size_t thrown_size) _LIBCXXABI_NOEXCEPT;
+extern _LIBCXXABI_FUNC_VIS void __cxa_free_exception(void* thrown_exception) _LIBCXXABI_NOEXCEPT;
// This function is an LLVM extension, which mirrors the same extension in libsupc++ and libcxxrt
-extern _LIBCXXABI_FUNC_VIS __cxa_exception*
-#ifdef __wasm__
-// In Wasm, a destructor returns its argument
-__cxa_init_primary_exception(void* object, std::type_info* tinfo, void*(_LIBCXXABI_DTOR_FUNC* dest)(void*)) _LIBCXXABI_NOEXCEPT;
-#else
-__cxa_init_primary_exception(void* object, std::type_info* tinfo, void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) _LIBCXXABI_NOEXCEPT;
-#endif
+extern _LIBCXXABI_FUNC_VIS __cxa_exception* __cxa_init_primary_exception(void* object, std::type_info* tinfo,
+ __libcxxabi_exception_destructor_func) _LIBCXXABI_NOEXCEPT;
// 2.4.3 Throwing the Exception Object
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
-__cxa_throw(void *thrown_exception, std::type_info *tinfo,
-#ifdef __wasm__
- void *(_LIBCXXABI_DTOR_FUNC *dest)(void *));
-#else
- void (_LIBCXXABI_DTOR_FUNC *dest)(void *));
-#endif
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_throw(void* thrown_exception, std::type_info* tinfo,
+ __libcxxabi_exception_destructor_func);
// 2.5.3 Exception Handlers
extern _LIBCXXABI_FUNC_VIS void *
@@ -74,8 +66,8 @@ extern _LIBCXXABI_FUNC_VIS void __cxa_end_catch();
extern _LIBCXXABI_FUNC_VIS bool
__cxa_begin_cleanup(void *exceptionObject) _LIBCXXABI_NOEXCEPT;
extern _LIBCXXABI_FUNC_VIS void __cxa_end_cleanup();
-#endif
-extern _LIBCXXABI_FUNC_VIS std::type_info *__cxa_current_exception_type();
+# endif
+extern _LIBCXXABI_FUNC_VIS std::type_info* __cxa_current_exception_type();
// GNU extension
// Calls `terminate` with the current exception being caught. This function is used by GCC when a `noexcept` function
@@ -88,8 +80,7 @@ extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_rethrow();
// 2.6 Auxiliary Runtime APIs
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_bad_cast(void);
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_bad_typeid(void);
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
-__cxa_throw_bad_array_new_length(void);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_throw_bad_array_new_length(void);
// 3.2.6 Pure Virtual Function API
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_pure_virtual(void);
@@ -98,63 +89,49 @@ extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_pure_virtual(void);
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_deleted_virtual(void);
// 3.3.2 One-time Construction API
-#if defined(_LIBCXXABI_GUARD_ABI_ARM)
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint32_t *);
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint32_t *);
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint32_t *);
-#else
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint64_t *);
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint64_t *);
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint64_t *);
-#endif
+# if defined(_LIBCXXABI_GUARD_ABI_ARM)
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint32_t*);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint32_t*);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint32_t*);
+# else
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint64_t*);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint64_t*);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint64_t*);
+# endif
// 3.3.3 Array Construction and Destruction API
-extern _LIBCXXABI_FUNC_VIS void *
-__cxa_vec_new(size_t element_count, size_t element_size, size_t padding_size,
- void (*constructor)(void *), void (*destructor)(void *));
+extern _LIBCXXABI_FUNC_VIS void* __cxa_vec_new(size_t element_count, size_t element_size, size_t padding_size,
+ void (*constructor)(void*), void (*destructor)(void*));
-extern _LIBCXXABI_FUNC_VIS void *
-__cxa_vec_new2(size_t element_count, size_t element_size, size_t padding_size,
- void (*constructor)(void *), void (*destructor)(void *),
- void *(*alloc)(size_t), void (*dealloc)(void *));
+extern _LIBCXXABI_FUNC_VIS void* __cxa_vec_new2(size_t element_count, size_t element_size, size_t padding_size,
+ void (*constructor)(void*), void (*destructor)(void*),
+ void* (*alloc)(size_t), void (*dealloc)(void*));
-extern _LIBCXXABI_FUNC_VIS void *
-__cxa_vec_new3(size_t element_count, size_t element_size, size_t padding_size,
- void (*constructor)(void *), void (*destructor)(void *),
- void *(*alloc)(size_t), void (*dealloc)(void *, size_t));
+extern _LIBCXXABI_FUNC_VIS void* __cxa_vec_new3(size_t element_count, size_t element_size, size_t padding_size,
+ void (*constructor)(void*), void (*destructor)(void*),
+ void* (*alloc)(size_t), void (*dealloc)(void*, size_t));
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_vec_ctor(void *array_address, size_t element_count, size_t element_size,
- void (*constructor)(void *), void (*destructor)(void *));
+extern _LIBCXXABI_FUNC_VIS void __cxa_vec_ctor(void* array_address, size_t element_count, size_t element_size,
+ void (*constructor)(void*), void (*destructor)(void*));
-extern _LIBCXXABI_FUNC_VIS void __cxa_vec_dtor(void *array_address,
- size_t element_count,
- size_t element_size,
- void (*destructor)(void *));
+extern _LIBCXXABI_FUNC_VIS void __cxa_vec_dtor(void* array_address, size_t element_count, size_t element_size,
+ void (*destructor)(void*));
-extern _LIBCXXABI_FUNC_VIS void __cxa_vec_cleanup(void *array_address,
- size_t element_count,
- size_t element_size,
- void (*destructor)(void *));
+extern _LIBCXXABI_FUNC_VIS void __cxa_vec_cleanup(void* array_address, size_t element_count, size_t element_size,
+ void (*destructor)(void*));
-extern _LIBCXXABI_FUNC_VIS void __cxa_vec_delete(void *array_address,
- size_t element_size,
- size_t padding_size,
- void (*destructor)(void *));
+extern _LIBCXXABI_FUNC_VIS void __cxa_vec_delete(void* array_address, size_t element_size, size_t padding_size,
+ void (*destructor)(void*));
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_vec_delete2(void *array_address, size_t element_size, size_t padding_size,
- void (*destructor)(void *), void (*dealloc)(void *));
+extern _LIBCXXABI_FUNC_VIS void __cxa_vec_delete2(void* array_address, size_t element_size, size_t padding_size,
+ void (*destructor)(void*), void (*dealloc)(void*));
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_vec_delete3(void *__array_address, size_t element_size,
- size_t padding_size, void (*destructor)(void *),
- void (*dealloc)(void *, size_t));
+extern _LIBCXXABI_FUNC_VIS void __cxa_vec_delete3(void* __array_address, size_t element_size, size_t padding_size,
+ void (*destructor)(void*), void (*dealloc)(void*, size_t));
-extern _LIBCXXABI_FUNC_VIS void
-__cxa_vec_cctor(void *dest_array, void *src_array, size_t element_count,
- size_t element_size, void (*constructor)(void *, void *),
- void (*destructor)(void *));
+extern _LIBCXXABI_FUNC_VIS void __cxa_vec_cctor(void* dest_array, void* src_array, size_t element_count,
+ size_t element_size, void (*constructor)(void*, void*),
+ void (*destructor)(void*));
// 3.3.5.3 Runtime API
// These functions are part of the C++ ABI, but they are not defined in libc++abi:
@@ -162,9 +139,8 @@ __cxa_vec_cctor(void *dest_array, void *src_array, size_t element_count,
// void __cxa_finalize(void *);
// 3.4 Demangler API
-extern _LIBCXXABI_FUNC_VIS char *__cxa_demangle(const char *mangled_name,
- char *output_buffer,
- size_t *length, int *status);
+extern _LIBCXXABI_FUNC_VIS char* __cxa_demangle(const char* mangled_name, char* output_buffer, size_t* length,
+ int* status);
// Apple additions to support C++ 0x exception_ptr class
// These are primitives to wrap a smart pointer around an exception object
@@ -180,7 +156,7 @@ __cxa_decrement_exception_refcount(void *primary_exception) _LIBCXXABI_NOEXCEPT;
extern _LIBCXXABI_FUNC_VIS bool __cxa_uncaught_exception() _LIBCXXABI_NOEXCEPT;
extern _LIBCXXABI_FUNC_VIS unsigned int __cxa_uncaught_exceptions() _LIBCXXABI_NOEXCEPT;
-#if defined(__linux__) || defined(__Fuchsia__)
+# if defined(__linux__) || defined(__Fuchsia__)
// Linux and Fuchsia TLS support. Not yet an official part of the Itanium ABI.
// https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables
extern _LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*)(void *), void *,
diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp
index 92901a83bfd03..7eae8bbccf092 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...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/140365
More information about the cfe-commits
mailing list