llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-llvm-ir 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
