Browse Source

YT-19142: Add emscripten patches to libcxxabi

dtorilov 1 year ago
parent
commit
f14549c83d

+ 42 - 0
contrib/libs/cxxsupp/libcxxabi/include/cxxabi.h

@@ -39,21 +39,44 @@ namespace __cxxabiv1 {
 extern "C"  {
 
 // 2.4.2 Allocating the Exception Object
+#ifndef __EMSCRIPTEN__
 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();
+#else
+extern _LIBCXXABI_FUNC_VIS void *
+__cxa_allocate_exception(size_t thrown_size) _NOEXCEPT;
+extern _LIBCXXABI_FUNC_VIS void
+__cxa_free_exception(void *thrown_exception) _NOEXCEPT;
+#endif
 
 // 2.4.3 Throwing the Exception Object
+#ifdef __USING_WASM_EXCEPTIONS__
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
+__cxa_throw(void *thrown_exception, std::type_info *tinfo,
+            void *(*dest)(void *));
+#else
 extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
 __cxa_throw(void *thrown_exception, std::type_info *tinfo,
             void (*dest)(void *));
+#endif
 
 // 2.5.3 Exception Handlers
+#ifndef __EMSCRIPTEN__
 extern _LIBCXXABI_FUNC_VIS void *
 __cxa_get_exception_ptr(void *exceptionObject) throw();
+#else
+extern _LIBCXXABI_FUNC_VIS void *
+__cxa_get_exception_ptr(void *exceptionObject) _NOEXCEPT;
+#endif
+#ifndef __EMSCRIPTEN__
 extern _LIBCXXABI_FUNC_VIS void *
 __cxa_begin_catch(void *exceptionObject) throw();
+#else
+extern _LIBCXXABI_FUNC_VIS void *
+__cxa_begin_catch(void *exceptionObject) _NOEXCEPT;
+#endif
 extern _LIBCXXABI_FUNC_VIS void __cxa_end_catch();
 #if defined(_LIBCXXABI_ARM_EHABI)
 extern _LIBCXXABI_FUNC_VIS bool
@@ -148,17 +171,36 @@ extern _LIBCXXABI_FUNC_VIS char *__cxa_demangle(const char *mangled_name,
 
 // Apple additions to support C++ 0x exception_ptr class
 // These are primitives to wrap a smart pointer around an exception object
+#ifndef __EMSCRIPTEN__
 extern _LIBCXXABI_FUNC_VIS void *__cxa_current_primary_exception() throw();
+#else
+extern _LIBCXXABI_FUNC_VIS void *__cxa_current_primary_exception() _NOEXCEPT;
+#endif
 extern _LIBCXXABI_FUNC_VIS void
 __cxa_rethrow_primary_exception(void *primary_exception);
+#ifndef __EMSCRIPTEN__
 extern _LIBCXXABI_FUNC_VIS void
 __cxa_increment_exception_refcount(void *primary_exception) throw();
+#else
+extern _LIBCXXABI_FUNC_VIS void
+__cxa_increment_exception_refcount(void *primary_exception) _NOEXCEPT;
+#endif
+#ifndef __EMSCRIPTEN__
 extern _LIBCXXABI_FUNC_VIS void
 __cxa_decrement_exception_refcount(void *primary_exception) throw();
+#else
+extern _LIBCXXABI_FUNC_VIS void
+__cxa_decrement_exception_refcount(void *primary_exception) _NOEXCEPT;
+#endif
 
 // Apple extension to support std::uncaught_exception()
+#ifndef __EMSCRIPTEN__
 extern _LIBCXXABI_FUNC_VIS bool __cxa_uncaught_exception() throw();
 extern _LIBCXXABI_FUNC_VIS unsigned int __cxa_uncaught_exceptions() throw();
+#else
+extern _LIBCXXABI_FUNC_VIS bool __cxa_uncaught_exception() _NOEXCEPT;
+extern _LIBCXXABI_FUNC_VIS unsigned int __cxa_uncaught_exceptions() _NOEXCEPT;
+#endif
 
 #if defined(__linux__) || defined(__Fuchsia__)
 // Linux and Fuchsia TLS support. Not yet an official part of the Itanium ABI.

+ 9 - 0
contrib/libs/cxxsupp/libcxxabi/src/abort_message.cpp

@@ -33,12 +33,21 @@ void abort_message(const char* format, ...)
     // formatting into the variable-sized buffer fails.
 #if !defined(NDEBUG) || !defined(LIBCXXABI_BAREMETAL)
     {
+#if defined(__EMSCRIPTEN__) && defined(NDEBUG)
+        // Just trap in a non-debug build. These internal libcxxabi assertions are
+        // very rare, and it's not worth linking in vfprintf stdio support or
+        // even minimal logging for them, as we'll have a proper call stack, which
+        // will show a call into "abort_message", and can help debugging. (In a
+        // debug build that won't be inlined.)
+        abort();
+#else
         fprintf(stderr, "libc++abi: ");
         va_list list;
         va_start(list, format);
         vfprintf(stderr, format, list);
         va_end(list);
         fprintf(stderr, "\n");
+#endif
     }
 #endif
 

+ 89 - 8
contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.cpp

@@ -180,7 +180,12 @@ 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() {
+#ifndef __EMSCRIPTEN__
+void *__cxa_allocate_exception(size_t thrown_size) throw()
+#else
+void *__cxa_allocate_exception(size_t thrown_size) _NOEXCEPT
+#endif
+{
     size_t actual_size = cxa_exception_size_from_exception_thrown_size(thrown_size);
 
     // Allocate extra space before the __cxa_exception header to ensure the
@@ -198,7 +203,12 @@ void *__cxa_allocate_exception(size_t thrown_size) throw() {
 
 
 //  Free a __cxa_exception object allocated with __cxa_allocate_exception.
-void __cxa_free_exception(void *thrown_object) throw() {
+#ifndef __EMSCRIPTEN__
+void __cxa_free_exception(void *thrown_object) throw()
+#else
+void __cxa_free_exception(void *thrown_object) _NOEXCEPT
+#endif
+{
     // Compute the size of the padding before the header.
     size_t header_offset = get_cxa_exception_offset();
     char *raw_buffer =
@@ -253,8 +263,21 @@ handler, _Unwind_RaiseException may return. In that case, __cxa_throw
 will call terminate, assuming that there was no handler for the
 exception.
 */
+
+#if defined(__USING_WASM_EXCEPTIONS__) && !defined(NDEBUG)
+extern "C" {
+void __throw_exception_with_stack_trace(_Unwind_Exception*);
+} // extern "C"
+#endif
+
 void
-__cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)) {
+#ifdef __USING_WASM_EXCEPTIONS__
+// In wasm, destructors return their 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 (*dest)(void *))
+#endif
+{
     __cxa_eh_globals *globals = __cxa_get_globals();
     __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
 
@@ -273,10 +296,26 @@ __cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)) {
     __asan_handle_no_return();
 #endif
 
+#ifdef __EMSCRIPTEN__
+#ifdef __USING_SJLJ_EXCEPTIONS__
+    _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
+#elif __USING_WASM_EXCEPTIONS__
+#ifdef NDEBUG
+    _Unwind_RaiseException(&exception_header->unwindHeader);
+#else
+    // In debug mode, call a JS library function to use WebAssembly.Exception JS
+    // API, which enables us to include stack traces
+    __throw_exception_with_stack_trace(&exception_header->unwindHeader);
+#endif
+#else
+    _Unwind_RaiseException(&exception_header->unwindHeader);
+#endif
+#else // !__EMSCRIPTEN__
 #ifdef __USING_SJLJ_EXCEPTIONS__
     _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
 #else
     _Unwind_RaiseException(&exception_header->unwindHeader);
+#endif
 #endif
     //  This only happens when there is no handler, or some unexpected unwinding
     //     error happens.
@@ -292,7 +331,12 @@ 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() {
+#ifndef __EMSCRIPTEN__
+void *__cxa_get_exception_ptr(void *unwind_exception) throw()
+#else
+void *__cxa_get_exception_ptr(void *unwind_exception) _NOEXCEPT
+#endif
+{
 #if defined(_LIBCXXABI_ARM_EHABI)
     return reinterpret_cast<void*>(
         static_cast<_Unwind_Control_Block*>(unwind_exception)->barrier_cache.bitpattern[0]);
@@ -307,7 +351,12 @@ 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() {
+#ifndef __EMSCRIPTEN__
+bool __cxa_begin_cleanup(void *unwind_arg) throw()
+#else
+bool __cxa_begin_cleanup(void *unwind_arg) _NOEXCEPT
+#endif
+{
     _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg);
     __cxa_eh_globals* globals = __cxa_get_globals();
     __cxa_exception* exception_header =
@@ -425,8 +474,13 @@ 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.
 */
+#ifndef __EMSCRIPTEN__
 void*
 __cxa_begin_catch(void* unwind_arg) throw()
+#else
+void*
+__cxa_begin_catch(void* unwind_arg) _NOEXCEPT
+#endif
 {
     _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg);
     bool native_exception = __isOurExceptionClass(unwind_exception);
@@ -633,8 +687,14 @@ void __cxa_rethrow() {
 
     Requires:  If thrown_object is not NULL, it is a native exception.
 */
+#ifndef __EMSCRIPTEN__
+void
+__cxa_increment_exception_refcount(void *thrown_object) throw()
+#else
 void
-__cxa_increment_exception_refcount(void *thrown_object) throw() {
+__cxa_increment_exception_refcount(void *thrown_object) _NOEXCEPT
+#endif
+{
     if (thrown_object != NULL )
     {
         __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
@@ -650,8 +710,14 @@ __cxa_increment_exception_refcount(void *thrown_object) throw() {
 
     Requires:  If thrown_object is not NULL, it is a native exception.
 */
+#ifndef __EMSCRIPTEN__
+_LIBCXXABI_NO_CFI
+void __cxa_decrement_exception_refcount(void *thrown_object) throw()
+#else
 _LIBCXXABI_NO_CFI
-void __cxa_decrement_exception_refcount(void *thrown_object) throw() {
+void __cxa_decrement_exception_refcount(void *thrown_object) _NOEXCEPT
+#endif
+{
     if (thrown_object != NULL )
     {
         __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
@@ -674,7 +740,12 @@ 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() {
+#ifndef __EMSCRIPTEN__
+void *__cxa_current_primary_exception() throw()
+#else
+void *__cxa_current_primary_exception() _NOEXCEPT
+#endif
+{
 //  get the current exception
     __cxa_eh_globals* globals = __cxa_get_globals_fast();
     if (NULL == globals)
@@ -745,11 +816,21 @@ __cxa_rethrow_primary_exception(void* thrown_object)
     // If we return client will call terminate()
 }
 
+#ifndef __EMSCRIPTEN__
 bool
 __cxa_uncaught_exception() throw() { return __cxa_uncaught_exceptions() != 0; }
+#else
+bool
+__cxa_uncaught_exception() _NOEXCEPT { return __cxa_uncaught_exceptions() != 0; }
+#endif
 
+#ifndef __EMSCRIPTEN__
 unsigned int
 __cxa_uncaught_exceptions() throw()
+#else
+unsigned int
+__cxa_uncaught_exceptions() _NOEXCEPT
+#endif
 {
     // This does not report foreign exceptions in flight
     __cxa_eh_globals* globals = __cxa_get_globals_fast();

+ 26 - 0
contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.h

@@ -19,6 +19,25 @@
 
 namespace __cxxabiv1 {
 
+#ifdef __USING_EMSCRIPTEN_EXCEPTIONS__
+
+struct _LIBCXXABI_HIDDEN __cxa_exception {
+  size_t referenceCount;
+  std::type_info *exceptionType;
+  void (*exceptionDestructor)(void *);
+  uint8_t caught;
+  uint8_t rethrown;
+  void *adjustedPtr;
+  // Add padding to ensure that the size of __cxa_exception is a multiple of
+  // the maximum useful alignment for the target machine.  This ensures that
+  // the thrown object that follows has that correct alignment.
+  void *padding;
+};
+
+static_assert(sizeof(__cxa_exception) % alignof(max_align_t) == 0, "__cxa_exception must have a size that is multipl of max alignment");
+
+#else
+
 static const uint64_t kOurExceptionClass          = 0x434C4E47432B2B00; // CLNGC++\0
 static const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1
 static const uint64_t get_vendor_and_language     = 0xFFFFFFFFFFFFFF00; // mask for CLNGC++
@@ -43,7 +62,12 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
 
     //  Manage the exception object itself.
     std::type_info *exceptionType;
+#ifdef __USING_WASM_EXCEPTIONS__
+    // In wasm, destructors return their argument
+    void *(*exceptionDestructor)(void *);
+#else
     void (*exceptionDestructor)(void *);
+#endif
     std::unexpected_handler unexpectedHandler;
     std::terminate_handler  terminateHandler;
 
@@ -159,6 +183,8 @@ extern "C" _LIBCXXABI_FUNC_VIS __cxa_eh_globals * __cxa_get_globals_fast ();
 extern "C" _LIBCXXABI_FUNC_VIS void * __cxa_allocate_dependent_exception ();
 extern "C" _LIBCXXABI_FUNC_VIS void __cxa_free_dependent_exception (void * dependent_exception);
 
+#endif // !__USING_EMSCRIPTEN_EXCEPTIONS__
+
 }  // namespace __cxxabiv1
 
 #endif // _CXA_EXCEPTION_H

+ 1 - 1
contrib/libs/cxxsupp/libcxxabi/src/cxa_handlers.cpp

@@ -73,7 +73,7 @@ __attribute__((noreturn))
 void
 terminate() noexcept
 {
-#ifndef _LIBCXXABI_NO_EXCEPTIONS
+#if !defined(_LIBCXXABI_NO_EXCEPTIONS) && !defined(__USING_EMSCRIPTEN_EXCEPTIONS__)
     // If there might be an uncaught exception
     using namespace __cxxabiv1;
     __cxa_eh_globals* globals = __cxa_get_globals_fast();

+ 26 - 17
contrib/libs/cxxsupp/libcxxabi/src/cxa_personality.cpp

@@ -32,6 +32,8 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
                                                        _Unwind_Personality_Fn);
 #endif
 
+#define __USING_SJLJ_OR_WASM_EXCEPTIONS__ (__USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__)
+
 /*
     Exception Header Layout:
 
@@ -61,7 +63,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
 +------------------+--+-----+-----+------------------------+--------------------------+
 | callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table |
 +---------------------+-----------+---------------------------------------------------+
-#ifndef __USING_SJLJ_EXCEPTIONS__
+#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__
 +---------------------+-----------+------------------------------------------------+
 | Beginning of Call Site Table            The current ip lies within the           |
 | ...                                     (start, length) range of one of these    |
@@ -75,7 +77,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
 | +-------------+---------------------------------+------------------------------+ |
 | ...                                                                              |
 +----------------------------------------------------------------------------------+
-#else  // __USING_SJLJ_EXCEPTIONS__
+#else  // !__USING_SJLJ_OR_WASM_EXCEPTIONS__
 +---------------------+-----------+------------------------------------------------+
 | Beginning of Call Site Table            The current ip is a 1-based index into   |
 | ...                                     this table.  Or it is -1 meaning no      |
@@ -88,7 +90,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
 | +-------------+---------------------------------+------------------------------+ |
 | ...                                                                              |
 +----------------------------------------------------------------------------------+
-#endif // __USING_SJLJ_EXCEPTIONS__
+#endif // __USING_SJLJ_OR_WASM_EXCEPTIONS__
 +---------------------------------------------------------------------+
 | Beginning of Action Table       ttypeIndex == 0 : cleanup           |
 | ...                             ttypeIndex  > 0 : catch             |
@@ -538,7 +540,7 @@ void
 set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
               const scan_results& results)
 {
-#if defined(__USING_SJLJ_EXCEPTIONS__)
+#ifdef __USING_SJLJ_OR_WASM_EXCEPTIONS__
 #define __builtin_eh_return_data_regno(regno) regno
 #elif defined(__ibmxl__)
 // IBM xlclang++ compiler does not support __builtin_eh_return_data_regno.
@@ -633,7 +635,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
     // Get beginning current frame's code (as defined by the
     // emitted dwarf code)
     uintptr_t funcStart = _Unwind_GetRegionStart(context);
-#ifdef __USING_SJLJ_EXCEPTIONS__
+#ifdef __USING_SJLJ_OR_WASM_EXCEPTIONS__
     if (ip == uintptr_t(-1))
     {
         // no action
@@ -643,9 +645,9 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
     else if (ip == 0)
         call_terminate(native_exception, unwind_exception);
     // ip is 1-based index into call site table
-#else  // !__USING_SJLJ_EXCEPTIONS__
+#else  // !__USING_SJLJ_OR_WASM_EXCEPTIONS__
     uintptr_t ipOffset = ip - funcStart;
-#endif // !defined(_USING_SLJL_EXCEPTIONS__)
+#endif // !defined(__USING_SJLJ_OR_WASM_EXCEPTIONS__)
     const uint8_t* classInfo = NULL;
     // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
     //       dwarf emission
@@ -667,7 +669,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
     // Walk call-site table looking for range that
     // includes current PC.
     uint8_t callSiteEncoding = *lsda++;
-#ifdef __USING_SJLJ_EXCEPTIONS__
+#ifdef __USING_SJLJ_OR_WASM_EXCEPTIONS__
     (void)callSiteEncoding;  // When using SjLj exceptions, callSiteEncoding is never used
 #endif
     uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda));
@@ -678,7 +680,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
     while (callSitePtr < callSiteTableEnd)
     {
         // There is one entry per call site.
-#ifndef __USING_SJLJ_EXCEPTIONS__
+#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__
         // The call sites are non-overlapping in [start, start+length)
         // The call sites are ordered in increasing value of start
         uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
@@ -686,15 +688,15 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
         uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
         uintptr_t actionEntry = readULEB128(&callSitePtr);
         if ((start <= ipOffset) && (ipOffset < (start + length)))
-#else  // __USING_SJLJ_EXCEPTIONS__
+#else  // __USING_SJLJ_OR_WASM_EXCEPTIONS__
         // ip is 1-based index into this table
         uintptr_t landingPad = readULEB128(&callSitePtr);
         uintptr_t actionEntry = readULEB128(&callSitePtr);
         if (--ip == 0)
-#endif // __USING_SJLJ_EXCEPTIONS__
+#endif // __USING_SJLJ_OR_WASM_EXCEPTIONS__
         {
             // Found the call site containing ip.
-#ifndef __USING_SJLJ_EXCEPTIONS__
+#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__
             if (landingPad == 0)
             {
                 // No handler here
@@ -702,9 +704,9 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
                 return;
             }
             landingPad = (uintptr_t)lpStart + landingPad;
-#else  // __USING_SJLJ_EXCEPTIONS__
+#else  // __USING_SJLJ_OR_WASM_EXCEPTIONS__
             ++landingPad;
-#endif // __USING_SJLJ_EXCEPTIONS__
+#endif // __USING_SJLJ_OR_WASM_EXCEPTIONS__
             results.landingPad = landingPad;
             if (actionEntry == 0)
             {
@@ -832,7 +834,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
                 action += actionOffset;
             }  // there is no break out of this loop, only return
         }
-#ifndef __USING_SJLJ_EXCEPTIONS__
+#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__
         else if (ipOffset < start)
         {
             // There is no call site for this ip
@@ -840,7 +842,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
             // Possible stack corruption.
             call_terminate(native_exception, unwind_exception);
         }
-#endif // !__USING_SJLJ_EXCEPTIONS__
+#endif // !__USING_SJLJ_OR_WASM_EXCEPTIONS__
     }  // there might be some tricky cases which break out of this loop
 
     // It is possible that no eh table entry specify how to handle
@@ -897,7 +899,9 @@ _UA_CLEANUP_PHASE
 */
 
 #if !defined(_LIBCXXABI_ARM_EHABI)
-#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
+#ifdef __USING_WASM_EXCEPTIONS__
+_Unwind_Reason_Code __gxx_personality_wasm0
+#elif defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
 static _Unwind_Reason_Code __gxx_personality_imp
 #else
 _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
@@ -962,6 +966,11 @@ __gxx_personality_v0
             exc->languageSpecificData = results.languageSpecificData;
             exc->catchTemp = reinterpret_cast<void*>(results.landingPad);
             exc->adjustedPtr = results.adjustedPtr;
+#ifdef __USING_WASM_EXCEPTIONS__
+            // Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the
+            // results here.
+            set_registers(unwind_exception, context, results);
+#endif
         }
         return _URC_HANDLER_FOUND;
     }

+ 6 - 1
contrib/libs/cxxsupp/libcxxabi/src/cxa_thread_atexit.cpp

@@ -112,9 +112,14 @@ extern "C" {
 #ifdef HAVE___CXA_THREAD_ATEXIT_IMPL
     return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
 #else
+#ifndef __EMSCRIPTEN__
+    // Emscripten doesn't implement __cxa_thread_atexit_impl, so we can simply
+    // avoid this check.
     if (__cxa_thread_atexit_impl) {
       return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
-    } else {
+    } else
+#endif
+    {
       // Initialize the dtors std::__libcpp_tls_key (uses __cxa_guard_*() for
       // one-time initialization and __cxa_atexit() for destruction)
       static DtorsManager manager;

+ 31 - 0
contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.cpp

@@ -1323,4 +1323,35 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info,
                                   use_strcmp);
 }
 
+// XXX EMSCRIPTEN
+
+#ifndef __USING_WASM_EXCEPTIONS__
+
+// These functions are used by the emscripten-style exception handling
+// mechanism.
+// Note that they need to be included even in the `-noexcept` build of
+// libc++abi to support the case where some parts of a project are built
+// with exception catching enabled, but at link time exception catching
+// is disabled.  In this case dependencies to these functions (and the JS
+// functions which call them) will still exist in the final build.
+extern "C" {
+
+int __cxa_can_catch(__shim_type_info* catchType, __shim_type_info* excpType, void **thrown) {
+  //std::type_info *t1 = static_cast<std::type_info*>(catchType);
+  //std::type_info *t2 = static_cast<std::type_info*>(excpType);
+  //printf("can %s catch %s (%p)?\n", t1->name(), t2->name(), thrown);
+
+  void *temp = *thrown;
+  int ret = catchType->can_catch(excpType, temp);
+  if (ret) *thrown = temp; // apply changes only if we are catching
+  return ret;
+}
+
+int __cxa_is_pointer_type(__shim_type_info* type) {
+  return !!dynamic_cast<__pointer_type_info*>(type);
+}
+
+}
+#endif // __USING_EMSCRIPTEN_EXCEPTIONS__
+
 }  // __cxxabiv1

+ 8 - 0
contrib/libs/cxxsupp/libcxxabi/src/stdlib_new_delete.cpp

@@ -37,8 +37,16 @@ operator new(std::size_t size) _THROW_BAD_ALLOC
         else
 #ifndef _LIBCXXABI_NO_EXCEPTIONS
             throw std::bad_alloc();
+#ifdef __EMSCRIPTEN__
+            // Abort here so that when exceptions are disabled, we do not just
+            // return 0 when malloc returns 0.
+            // We could also do this with set_new_handler, but that adds a
+            // global constructor and a table entry, overhead that we can avoid
+            // by doing it this way.
+            abort();
 #else
             break;
+#endif
 #endif
     }
     return p;