[libcxx-commits] [libcxxabi] [libunwind] [llvm] [WebAssembly] Directly call EH personality function (PR #175202)
via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Jan 9 09:06:19 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libunwind
Author: Hugo Melder (hmelder)
<details>
<summary>Changes</summary>
Currently, the personality function is not called directly, but via the veneer function `_Unwind_CallPersonality`. This function resets the selector in the landing pad and calls `__gxx_personality_wasm0 `. The result is that other languages with EH, such as Objective-C, cannot provide their own personality function.
This PR removes `_Unwind_CallPersonality` and implements its functionality in codegen (`WasmEHPrepareImpl::prepareEHPad`) instead.
It turns out that there is a mismatch between the personality function name in LLVM and in libcxxabi/libunwind. In `CGException` and all other unit tests, the Wasm CXX personality function is called `__gxx_wasm_personality_v0 `. However it is defined as `__gxx_personality_wasm0 ` in `libcxxabi/src/cxa_personality.cpp`. This was never caught because the personality function was never called directly in codegen.
I have also fixed up the type definition of `_Unwind_LandingPadContext` in `WasmEHPrepare` for WASM64.
---
Patch is 22.75 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/175202.diff
11 Files Affected:
- (modified) libcxxabi/src/cxa_personality.cpp (+1-1)
- (modified) libunwind/src/Unwind-wasm.c (-23)
- (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (-4)
- (modified) llvm/lib/CodeGen/WasmEHPrepare.cpp (+67-46)
- (modified) llvm/test/CodeGen/WebAssembly/cfg-stackify-eh-legacy.ll (+6-6)
- (modified) llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll (+5-5)
- (modified) llvm/test/CodeGen/WebAssembly/eh-lsda.ll (+4-1)
- (modified) llvm/test/CodeGen/WebAssembly/exception-legacy.ll (+5-1)
- (modified) llvm/test/CodeGen/WebAssembly/exception.ll (+10-1)
- (modified) llvm/test/CodeGen/WebAssembly/wasm-eh-invalid-personality.ll (+1-1)
- (modified) llvm/test/CodeGen/WebAssembly/wasm-eh-prepare.ll (+6-3)
``````````diff
diff --git a/libcxxabi/src/cxa_personality.cpp b/libcxxabi/src/cxa_personality.cpp
index 77b2eb53af0e4..258e4d1f49444 100644
--- a/libcxxabi/src/cxa_personality.cpp
+++ b/libcxxabi/src/cxa_personality.cpp
@@ -1021,7 +1021,7 @@ static inline void get_landing_pad(__cxa_catch_temp_type &dest,
}
#ifdef __WASM_EXCEPTIONS__
-_Unwind_Reason_Code __gxx_personality_wasm0
+_Unwind_Reason_Code __gxx_wasm_personality_v0
#elif defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
static _Unwind_Reason_Code __gxx_personality_imp
#else
diff --git a/libunwind/src/Unwind-wasm.c b/libunwind/src/Unwind-wasm.c
index b8b7bc2779f17..4ffd74f34c238 100644
--- a/libunwind/src/Unwind-wasm.c
+++ b/libunwind/src/Unwind-wasm.c
@@ -37,29 +37,6 @@ struct _Unwind_LandingPadContext {
// function
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
-/// calls the personality function for each each frame it lands. On the other
-/// hand, WebAssembly stack unwinding process is performed by a VM, and the
-/// personality function cannot be called from there. So the compiler inserts
-/// a call to this function in landing pads in the user code, which in turn
-/// calls the personality function.
-_Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) {
- struct _Unwind_Exception *exception_object =
- (struct _Unwind_Exception *)exception_ptr;
- _LIBUNWIND_TRACE_API("_Unwind_CallPersonality(exception_object=%p)",
- (void *)exception_object);
-
- // Reset the selector.
- __wasm_lpad_context.selector = 0;
-
- // Call personality function. Wasm does not have two-phase unwinding, so we
- // only do the cleanup phase.
- return __gxx_personality_wasm0(
- 1, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object,
- (struct _Unwind_Context *)&__wasm_lpad_context);
-}
-
/// Called by __cxa_throw.
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_RaiseException(_Unwind_Exception *exception_object) {
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index b9e68247de94d..b6f5b8497b93a 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -1833,9 +1833,6 @@ defset list<RuntimeLibcallImpl> SjLjExceptionHandlingLibcalls = {
def _Unwind_SjLj_Unregister : RuntimeLibcallImpl<UNWIND_UNREGISTER>;
}
-// Only used on wasm?
-def _Unwind_CallPersonality : RuntimeLibcallImpl<UNWIND_CALL_PERSONALITY>;
-
// Used on OpenBSD
def __stack_smash_handler : RuntimeLibcallImpl<STACK_SMASH_HANDLER>;
@@ -3500,7 +3497,6 @@ def WasmSystemLibrary
(add DefaultRuntimeLibcallImpls, Int128RTLibcalls,
CompilerRTOnlyInt64Libcalls, CompilerRTOnlyInt128Libcalls,
exp10f, exp10,
- _Unwind_CallPersonality,
emscripten_return_address,
LibcallImpls<(add __small_printf,
__small_sprintf,
diff --git a/llvm/lib/CodeGen/WasmEHPrepare.cpp b/llvm/lib/CodeGen/WasmEHPrepare.cpp
index 2f54578da5113..cb97da33edef9 100644
--- a/llvm/lib/CodeGen/WasmEHPrepare.cpp
+++ b/llvm/lib/CodeGen/WasmEHPrepare.cpp
@@ -28,7 +28,9 @@
// wasm.landingpad.index(index);
// __wasm_lpad_context.lpad_index = index;
// __wasm_lpad_context.lsda = wasm.lsda();
-// _Unwind_CallPersonality(exn);
+// __wasm_lpad_context.selector = 0;
+// personality_fn(1, _UA_SEARCH_PHASE, exn->exception_class, exn,
+// (struct _Unwind_Context *)&__wasm_lpad_context);
// selector = __wasm_lpad_context.selector;
// ...
//
@@ -38,18 +40,13 @@
// exception is thrown. After the stack is unwound, the control flow is
// transfered to WebAssembly 'catch' instruction.
//
-// Unwinding the stack is not done by libunwind but the VM, so the personality
-// function in libcxxabi cannot be called from libunwind during the unwinding
-// process. So after a catch instruction, we insert a call to a wrapper function
-// in libunwind that in turn calls the real personality function.
-//
// In Itanium EH, if the personality function decides there is no matching catch
// clause in a call frame and no cleanup action to perform, the unwinder doesn't
// stop there and continues unwinding. But in Wasm EH, the unwinder stops at
// every call frame with a catch intruction, after which the personality
// function is called from the compiler-generated user code here.
//
-// In libunwind, we have this struct that serves as a communincation channel
+// In libunwind, we have this struct that serves as a communication channel
// between the compiler-generated user code and the personality function in
// libcxxabi.
//
@@ -60,20 +57,8 @@
// };
// struct _Unwind_LandingPadContext __wasm_lpad_context = ...;
//
-// And this wrapper in libunwind calls the personality function.
-//
-// _Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) {
-// struct _Unwind_Exception *exception_obj =
-// (struct _Unwind_Exception *)exception_ptr;
-// _Unwind_Reason_Code ret = __gxx_personality_v0(
-// 1, _UA_CLEANUP_PHASE, exception_obj->exception_class, exception_obj,
-// (struct _Unwind_Context *)__wasm_lpad_context);
-// return ret;
-// }
-//
// We pass a landing pad index, and the address of LSDA for the current function
-// to the wrapper function _Unwind_CallPersonality in libunwind, and we retrieve
-// the selector after it returns.
+// to the personality function, and we retrieve the selector after it returns.
//
//===----------------------------------------------------------------------===//
@@ -81,9 +66,12 @@
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/WasmEHFuncInfo.h"
+#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/EHPersonalities.h"
+#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/IntrinsicsWebAssembly.h"
+#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/RuntimeLibcalls.h"
#include "llvm/InitializePasses.h"
@@ -98,6 +86,7 @@ class WasmEHPrepareImpl {
friend class WasmEHPrepare;
Type *LPadContextTy = nullptr; // type of 'struct _Unwind_LandingPadContext'
+ Type *UnwindExceptionTy = nullptr; // type of 'struct _Unwind_Exception'
GlobalVariable *LPadContextGV = nullptr; // __wasm_lpad_context
// Field addresses of struct _Unwind_LandingPadContext
@@ -111,8 +100,12 @@ class WasmEHPrepareImpl {
Function *GetExnF = nullptr; // wasm.get.exception() intrinsic
Function *CatchF = nullptr; // wasm.catch() intrinsic
Function *GetSelectorF = nullptr; // wasm.get.ehselector() intrinsic
- FunctionCallee CallPersonalityF =
- nullptr; // _Unwind_CallPersonality() wrapper
+ FunctionCallee PersonalityF = nullptr;
+
+ IntegerType *Int32Ty = nullptr;
+ IntegerType *Int64Ty = nullptr;
+ PointerType *PtrTy = nullptr;
+ IntegerType *IntPtrTy = nullptr;
bool prepareThrows(Function &F);
bool prepareEHPads(Function &F);
@@ -120,7 +113,8 @@ class WasmEHPrepareImpl {
public:
WasmEHPrepareImpl() = default;
- WasmEHPrepareImpl(Type *LPadContextTy_) : LPadContextTy(LPadContextTy_) {}
+ WasmEHPrepareImpl(Type *LPadContextTy_, Type *UnwindExceptionTy_)
+ : LPadContextTy(LPadContextTy_), UnwindExceptionTy(UnwindExceptionTy_) {}
bool runOnFunction(Function &F);
};
@@ -144,11 +138,15 @@ class WasmEHPrepare : public FunctionPass {
PreservedAnalyses WasmEHPreparePass::run(Function &F,
FunctionAnalysisManager &) {
auto &Context = F.getContext();
- auto *I32Ty = Type::getInt32Ty(Context);
+ const DataLayout &DL = F.getParent()->getDataLayout();
+ auto *I64Ty = Type::getInt64Ty(Context);
auto *PtrTy = PointerType::get(Context, 0);
- auto *LPadContextTy =
- StructType::get(I32Ty /*lpad_index*/, PtrTy /*lsda*/, I32Ty /*selector*/);
- WasmEHPrepareImpl P(LPadContextTy);
+ auto *IntPtrTy = DL.getIntPtrType(Context, /*AddressSpace=*/0);
+ auto *LPadContextTy = StructType::get(IntPtrTy /*lpad_index*/, PtrTy /*lsda*/,
+ IntPtrTy /*selector*/);
+ auto *UnwindExceptionTy = StructType::get(I64Ty /* exception_class*/,
+ PtrTy /* exception_cleanup */);
+ WasmEHPrepareImpl P(LPadContextTy, UnwindExceptionTy);
bool Changed = P.runOnFunction(F);
return Changed ? PreservedAnalyses::none() : PreservedAnalyses ::all();
}
@@ -163,10 +161,16 @@ FunctionPass *llvm::createWasmEHPass() { return new WasmEHPrepare(); }
bool WasmEHPrepare::doInitialization(Module &M) {
IRBuilder<> IRB(M.getContext());
- P.LPadContextTy = StructType::get(IRB.getInt32Ty(), // lpad_index
- IRB.getPtrTy(), // lsda
- IRB.getInt32Ty() // selector
+ const DataLayout &DL = M.getDataLayout();
+ auto *I64Ty = IRB.getInt64Ty();
+ auto *PtrTy = IRB.getPtrTy();
+ auto *IntPtrTy = DL.getIntPtrType(M.getContext(), /*AddressSpace=*/0);
+ P.LPadContextTy = StructType::get(IntPtrTy, // lpad_index
+ PtrTy, // lsda
+ IntPtrTy // selector
);
+ P.UnwindExceptionTy = StructType::get(I64Ty /* exception_class*/,
+ PtrTy /* exception_cleanup */);
return false;
}
@@ -235,11 +239,14 @@ bool WasmEHPrepareImpl::prepareEHPads(Function &F) {
if (CatchPads.empty() && CleanupPads.empty())
return false;
- if (!F.hasPersonalityFn() ||
- !isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) {
+ if (!F.hasPersonalityFn())
+ return false;
+
+ auto Personality = classifyEHPersonality(F.getPersonalityFn());
+
+ if (!isScopedEHPersonality(Personality)) {
report_fatal_error("Function '" + F.getName() +
- "' does not have a correct Wasm personality function "
- "'__gxx_wasm_personality_v0'");
+ "' does not have a supported Wasm personality function");
}
assert(F.hasPersonalityFn() && "Personality function not found");
@@ -274,16 +281,17 @@ bool WasmEHPrepareImpl::prepareEHPads(Function &F) {
// instruction selection.
CatchF = Intrinsic::getOrInsertDeclaration(&M, Intrinsic::wasm_catch);
- // FIXME: Verify this is really supported for current module.
- StringRef UnwindCallPersonalityName =
- RTLIB::RuntimeLibcallsInfo::getLibcallImplName(
- RTLIB::impl__Unwind_CallPersonality);
+ auto DL = F.getParent()->getDataLayout();
+
+ Int32Ty = IRB.getInt32Ty();
+ Int64Ty = IRB.getInt64Ty();
+ PtrTy = IRB.getPtrTy();
+ IntPtrTy = DL.getIntPtrType(M.getContext(), /*AddressSpace=*/0);
- // _Unwind_CallPersonality() wrapper function, which calls the personality
- CallPersonalityF = M.getOrInsertFunction(UnwindCallPersonalityName,
- IRB.getInt32Ty(), IRB.getPtrTy());
- if (Function *F = dyn_cast<Function>(CallPersonalityF.getCallee()))
- F->setDoesNotThrow();
+ auto *PersPrototype = FunctionType::get(
+ Int32Ty, {Int32Ty, Int32Ty, Int64Ty, PtrTy, PtrTy}, false);
+ PersonalityF =
+ M.getOrInsertFunction(getEHPersonalityName(Personality), PersPrototype);
unsigned Index = 0;
for (auto *BB : CatchPads) {
@@ -367,9 +375,22 @@ void WasmEHPrepareImpl::prepareEHPad(BasicBlock *BB, bool NeedPersonality,
// Pseudocode: __wasm_lpad_context.lsda = wasm.lsda();
IRB.CreateStore(IRB.CreateCall(LSDAF), LSDAField);
- // Pseudocode: _Unwind_CallPersonality(exn);
- CallInst *PersCI = IRB.CreateCall(CallPersonalityF, CatchCI,
- OperandBundleDef("funclet", CPI));
+ // Pseudocode: __wasm_lpad_context.selector = 0;
+ IRB.CreateStore(ConstantInt::get(IntPtrTy, 0), SelectorField);
+
+ // Pseudocode: &exn->exception_class
+ auto *ExceptionClassPtr = IRB.CreateConstInBoundsGEP2_32(
+ UnwindExceptionTy, CatchCI, 0, 0, "exception_class_gep");
+ auto *ExceptionClass = IRB.CreateLoad(IRB.getInt64Ty(), ExceptionClassPtr);
+ auto *UASearchPhase = IRB.getInt32(1);
+
+ // Pseudocode:
+ // personality_fn(1, _UA_SEARCH_PHASE, exn->exception_class, exn,
+ // (struct _Unwind_Context *)&__wasm_lpad_context);
+ CallInst *PersCI = IRB.CreateCall(
+ PersonalityF,
+ {IRB.getInt32(1), UASearchPhase, ExceptionClass, CatchCI, LPadContextGV},
+ OperandBundleDef("funclet", CPI));
PersCI->setDoesNotThrow();
// Pseudocode: int selector = __wasm_lpad_context.selector;
diff --git a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh-legacy.ll b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh-legacy.ll
index f0a1d9805c806..b1156f07b1274 100644
--- a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh-legacy.ll
+++ b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh-legacy.ll
@@ -100,23 +100,23 @@ try.cont: ; preds = %catch, %catch2, %en
; CHECK: catch
; CHECK: block
; CHECK: block
-; CHECK: br_if 0, {{.*}} # 0: down to label[[L0:[0-9+]]]
+; CHECK: br_if 0, {{.*}} # 0: down to label[[L0:[0-9]+]]
; CHECK: call $drop=, __cxa_begin_catch, $0
; CHECK: try
; CHECK: try
; CHECK: call foo
-; CHECK: br 3 # 3: down to label[[L1:[0-9+]]]
+; CHECK: br 3 # 3: down to label[[L1:[0-9]+]]
; CHECK: catch
; CHECK: block
; CHECK: block
-; CHECK: br_if 0, {{.*}} # 0: down to label[[L2:[0-9+]]]
+; CHECK: br_if 0, {{.*}} # 0: down to label[[L2:[0-9]+]]
; CHECK: call $drop=, __cxa_begin_catch
; CHECK: try
; CHECK: call foo
-; CHECK: br 2 # 2: down to label[[L3:[0-9+]]]
+; CHECK: br 2 # 2: down to label[[L3:[0-9]+]]
; CHECK: catch_all
; CHECK: call __cxa_end_catch
-; CHECK: rethrow 0 # down to catch[[L4:[0-9+]]]
+; CHECK: rethrow 0 # down to catch[[L4:[0-9]+]]
; CHECK: end_try
; CHECK: end_block # label[[L2]]:
; CHECK: rethrow 1 # down to catch[[L4]]
@@ -1736,7 +1736,7 @@ unreachable: ; preds = %rethrow, %entry
}
; Check if the unwind destination mismatch stats are correct
-; NOSORT: 24 wasm-cfg-stackify - Number of call unwind mismatches found
+; NOSORT: 32 wasm-cfg-stackify - Number of call unwind mismatches found
; NOSORT: 5 wasm-cfg-stackify - Number of catch unwind mismatches found
declare void @foo()
diff --git a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll
index 98de9a267b95a..c89f88c67ac46 100644
--- a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll
+++ b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll
@@ -35,7 +35,7 @@ target triple = "wasm32-unknown-unknown"
; CHECK: local.set 2
; CHECK: local.set 1
; CHECK: local.get 0
-; CHECK: call _Unwind_CallPersonality
+; CHECK: call __gxx_wasm_personality_v0
; CHECK: block
; CHECK: br_if 0 # 0: down to label[[L2:[0-9]+]]
; CHECK: call __cxa_begin_catch
@@ -111,7 +111,7 @@ try.cont: ; preds = %catch, %catch2, %en
; CHECK: br 2 # 2: down to label[[L1:[0-9]+]]
; CHECK: end_try_table
; CHECK: end_block # label[[L0]]:
-; CHECK: call _Unwind_CallPersonality
+; CHECK: call __gxx_wasm_personality_v0
; CHECK: block
; CHECK: block
; CHECK: br_if 0 # 0: down to label[[L2:[0-9]+]]
@@ -124,7 +124,7 @@ try.cont: ; preds = %catch, %catch2, %en
; CHECK: br 5 # 5: down to label[[L5:[0-9]+]]
; CHECK: end_try_table
; CHECK: end_block # label[[L4]]:
-; CHECK: call _Unwind_CallPersonality
+; CHECK: call __gxx_wasm_personality_v0
; CHECK: block
; CHECK: block
; CHECK: br_if 0 # 0: down to label[[L6:[0-9]+]]
@@ -750,7 +750,7 @@ try.cont: ; preds = %catch.start0
; NOSORT: end_block # label[[L0]]:
; NOSORT: call __cxa_begin_catch
; NOSORT: call __cxa_end_catch
-; NOSORT: end_block # label74:
+; NOSORT: end_block
; NOSORT: return
; NOSORT: end_block # label[[L1]]:
; NOSORT: throw_ref
@@ -1507,7 +1507,7 @@ unreachable: ; preds = %rethrow, %entry
}
; Check if the unwind destination mismatch stats are correct
-; NOSORT: 23 wasm-cfg-stackify - Number of call unwind mismatches found
+; NOSORT: 30 wasm-cfg-stackify - Number of call unwind mismatches found
; NOSORT: 4 wasm-cfg-stackify - Number of catch unwind mismatches found
declare void @foo()
diff --git a/llvm/test/CodeGen/WebAssembly/eh-lsda.ll b/llvm/test/CodeGen/WebAssembly/eh-lsda.ll
index d5b28b279d419..f069f77147e57 100644
--- a/llvm/test/CodeGen/WebAssembly/eh-lsda.ll
+++ b/llvm/test/CodeGen/WebAssembly/eh-lsda.ll
@@ -66,7 +66,10 @@ try.cont: ; preds = %entry, %catch.start
; CHECK-LABEL: test1:
; In static linking, we load GCC_except_table as a constant directly.
-; NOPIC: i[[PTR]].const $push[[CONTEXT:.*]]=, {{[48]}}
+; NOPIC: i[[PTR]].const $push[[SELECTOR_OFF:.*]]=, {{(8|16)}}
+; NOPIC-NEXT: i[[PTR]].const $push[[SELECTOR:.*]]=, 0
+; NOPIC-NEXT: i[[PTR]].store __wasm_lpad_context($pop[[SELECTOR_OFF]]), $pop[[SELECTOR]]
+; NOPIC-NEXT: i[[PTR]].const $push[[CONTEXT:.*]]=, {{[48]}}
; NOPIC-NEXT: i[[PTR]].const $push[[EXCEPT_TABLE:.*]]=, GCC_except_table1
; NOPIC-NEXT: i[[PTR]].store __wasm_lpad_context($pop[[CONTEXT]]), $pop[[EXCEPT_TABLE]]
diff --git a/llvm/test/CodeGen/WebAssembly/exception-legacy.ll b/llvm/test/CodeGen/WebAssembly/exception-legacy.ll
index b96a664166f42..e638af4ad3bb2 100644
--- a/llvm/test/CodeGen/WebAssembly/exception-legacy.ll
+++ b/llvm/test/CodeGen/WebAssembly/exception-legacy.ll
@@ -35,7 +35,11 @@ define void @throw(ptr %p) {
; CHECK: catch $[[EXN:[0-9]+]]=, __cpp_exception
; CHECK: global.set __stack_pointer
; CHECK: i32.store __wasm_lpad_context
-; CHECK: call $drop=, _Unwind_CallPersonality, $[[EXN]]
+; CHECK: i32.const $push[[ACTION:[0-9]+]]=, 1
+; CHECK: i32.const $push[[PHASE:[0-9]+]]=, 1
+; CHECK: i64.load $push[[EH_CLASS:[0-9]+]]=, 0($[[EXN]])
+; CHECK: i32.const $push[[LPAD_CTX:[0-9]+]]=, __wasm_lpad_context
+; CHECK: call $drop=, __gxx_wasm_personality_v0, $pop[[ACTION]], $pop[[PHASE]], $pop[[EH_CLASS]], $0, $pop[[LPAD_CTX]]
; CHECK: block
; CHECK: br_if 0
; CHECK: call $drop=, __cxa_begin_catch
diff --git a/llvm/test/CodeGen/WebAssembly/exception.ll b/llvm/test/CodeGen/WebAssembly/exception.ll
index 873386b3dcc6d..f48ce2fc9d537 100644
--- a/llvm/test/CodeGen/WebAssembly/exception.ll
+++ b/llvm/test/CodeGen/WebAssembly/exception.ll
@@ -47,7 +47,16 @@ define void @throw(ptr %p) {
; CHECK: local.get 0
; CHECK: global.set __stack_pointer
; CHECK: i32.store __wasm_lpad_context
-; CHECK: call _Unwind_CallPersonality
+
+; CHECK: i32.const 1
+; CHECK: i32.const 1
+; CHECK: local.get 1
+; CHECK: i64.load 0
+; CHECK: local.get 1
+; CHECK: i32.const __wasm_lpad_context
+; CHECK: call __gxx_wasm_personality_v0
+; CHECK: drop
+
; CHECK: block
; CHECK: br_if 0
; CHECK: call __cxa_begin_catch
diff --git a/llvm/test/CodeGen/WebAssembly/wasm-eh-invalid-personality.ll b/llvm/test/...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/175202
More information about the libcxx-commits
mailing list