[libcxx-commits] [libcxxabi] e6cbba7 - [libc++abi][WebAssembly] Support Wasm EH

Heejin Ahn via libcxx-commits libcxx-commits at lists.llvm.org
Fri Sep 22 00:34:41 PDT 2023


Author: Heejin Ahn
Date: 2023-09-22T00:34:00-07:00
New Revision: e6cbba749490a20127359a3fbd05d8db7faef535

URL: https://github.com/llvm/llvm-project/commit/e6cbba749490a20127359a3fbd05d8db7faef535
DIFF: https://github.com/llvm/llvm-project/commit/e6cbba749490a20127359a3fbd05d8db7faef535.diff

LOG: [libc++abi][WebAssembly] Support Wasm EH

This adds Wasm-specific libc++abi changes to support Wasm exception
handling (https://github.com/WebAssembly/exception-handling).

Wasm EH requires `__USING_WASM_EXCEPTIONS__` to be defined. Wasm EH's
LSDA handling mostly shares that of SjLj EH.
Changes are:
- In Wasm, a destructor returns its argument.
- Wasm EH currently only has one phase (search) that does both search
  and cleanup. So added an additional `set_registers` to support that.

The bulk of these changes was added back in Mar 2020 in
https://github.com/emscripten-core/emscripten/pull/10577 to emscripten
repo and has been used ever since. Now we'd like to upstream this so
that other toolchains that don't use emscripten libraries, e.g., WASI,
can use this too.

Companion patch: D158919

Reviewed By: dschuff, #libc_abi, phosek

Differential Revision: https://reviews.llvm.org/D158918

Added: 
    

Modified: 
    libcxxabi/include/cxxabi.h
    libcxxabi/src/cxa_exception.cpp
    libcxxabi/src/cxa_exception.h
    libcxxabi/src/cxa_personality.cpp

Removed: 
    


################################################################################
diff  --git a/libcxxabi/include/cxxabi.h b/libcxxabi/include/cxxabi.h
index 85cb4b36b8119be..6f4f823bc273ff3 100644
--- a/libcxxabi/include/cxxabi.h
+++ b/libcxxabi/include/cxxabi.h
@@ -47,7 +47,12 @@ __cxa_free_exception(void *thrown_exception) 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 __USING_WASM_EXCEPTIONS__
+            // In Wasm, a destructor returns its argument
+            void *(_LIBCXXABI_DTOR_FUNC *dest)(void *));
+#else
             void (_LIBCXXABI_DTOR_FUNC *dest)(void *));
+#endif
 
 // 2.5.3 Exception Handlers
 extern _LIBCXXABI_FUNC_VIS void *

diff  --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp
index 5a347d8276ebba5..f723ececfe3327a 100644
--- a/libcxxabi/src/cxa_exception.cpp
+++ b/libcxxabi/src/cxa_exception.cpp
@@ -254,7 +254,12 @@ will call terminate, assuming that there was no handler for the
 exception.
 */
 void
+#ifdef __USING_WASM_EXCEPTIONS__
+// 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
     __cxa_eh_globals *globals = __cxa_get_globals();
     __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
 

diff  --git a/libcxxabi/src/cxa_exception.h b/libcxxabi/src/cxa_exception.h
index 49dde28b258f7c3..10712f6f47bb5f1 100644
--- a/libcxxabi/src/cxa_exception.h
+++ b/libcxxabi/src/cxa_exception.h
@@ -43,7 +43,12 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
 
     //  Manage the exception object itself.
     std::type_info *exceptionType;
+#ifdef __USING_WASM_EXCEPTIONS__
+    // In Wasm, a destructor returns its argument
+    void *(_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
+#else
     void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
+#endif
     std::unexpected_handler unexpectedHandler;
     std::terminate_handler  terminateHandler;
 

diff  --git a/libcxxabi/src/cxa_personality.cpp b/libcxxabi/src/cxa_personality.cpp
index 0bbb0c7d689ffeb..4570d0b5beb2e2e 100644
--- a/libcxxabi/src/cxa_personality.cpp
+++ b/libcxxabi/src/cxa_personality.cpp
@@ -70,7 +70,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__
+#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
 +---------------------+-----------+------------------------------------------------+
 | Beginning of Call Site Table            The current ip lies within the           |
 | ...                                     (start, length) range of one of these    |
@@ -84,7 +84,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
 | +-------------+---------------------------------+------------------------------+ |
 | ...                                                                              |
 +----------------------------------------------------------------------------------+
-#else  // __USING_SJLJ_EXCEPTIONS__
+#else  // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
 +---------------------+-----------+------------------------------------------------+
 | Beginning of Call Site Table            The current ip is a 1-based index into   |
 | ...                                     this table.  Or it is -1 meaning no      |
@@ -97,7 +97,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
 | +-------------+---------------------------------+------------------------------+ |
 | ...                                                                              |
 +----------------------------------------------------------------------------------+
-#endif // __USING_SJLJ_EXCEPTIONS__
+#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
 +---------------------------------------------------------------------+
 | Beginning of Action Table       ttypeIndex == 0 : cleanup           |
 | ...                             ttypeIndex  > 0 : catch             |
@@ -547,7 +547,7 @@ void
 set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
               const scan_results& results)
 {
-#if defined(__USING_SJLJ_EXCEPTIONS__)
+#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__)
 #define __builtin_eh_return_data_regno(regno) regno
 #elif defined(__ibmxl__)
 // IBM xlclang++ compiler does not support __builtin_eh_return_data_regno.
@@ -642,7 +642,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__
+#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__)
     if (ip == uintptr_t(-1))
     {
         // no action
@@ -652,9 +652,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_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__
     uintptr_t ipOffset = ip - funcStart;
-#endif // !defined(_USING_SLJL_EXCEPTIONS__)
+#endif // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__
     const uint8_t* classInfo = NULL;
     // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
     //       dwarf emission
@@ -676,8 +676,8 @@ 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__
-    (void)callSiteEncoding;  // When using SjLj exceptions, callSiteEncoding is never used
+#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__)
+    (void)callSiteEncoding;  // When using SjLj/Wasm exceptions, callSiteEncoding is never used
 #endif
     uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda));
     const uint8_t* callSiteTableStart = lsda;
@@ -687,7 +687,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__
+#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_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);
@@ -695,15 +695,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_EXCEPTIONS__ || __USING_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_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
         {
             // Found the call site containing ip.
-#ifndef __USING_SJLJ_EXCEPTIONS__
+#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
             if (landingPad == 0)
             {
                 // No handler here
@@ -711,9 +711,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_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
             ++landingPad;
-#endif // __USING_SJLJ_EXCEPTIONS__
+#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
             results.landingPad = landingPad;
             if (actionEntry == 0)
             {
@@ -841,7 +841,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__
+#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
         else if (ipOffset < start)
         {
             // There is no call site for this ip
@@ -849,7 +849,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_EXCEPTIONS__ && !__USING_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
@@ -906,7 +906,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
@@ -973,6 +975,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;
     }


        


More information about the libcxx-commits mailing list