diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp index 2e5b71ac597489..e9cad5e0567818 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp @@ -434,15 +434,6 @@ Value *WebAssemblyLowerEmscriptenEHSjLj::wrapInvoke(CallBase *CI) { Module *M = CI->getModule(); LLVMContext &C = M->getContext(); - // If we are calling a function that is noreturn, we must remove that - // attribute. The code we insert here does expect it to return, after we - // catch the exception. - if (CI->doesNotReturn()) { - if (auto *F = CI->getCalledFunction()) - F->removeFnAttr(Attribute::NoReturn); - CI->removeFnAttr(Attribute::NoReturn); - } - IRBuilder<> IRB(C); IRB.SetInsertPoint(CI); @@ -760,6 +751,7 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) { FunctionType *ResumeFTy = FunctionType::get(IRB.getVoidTy(), IRB.getInt8PtrTy(), false); ResumeF = getEmscriptenFunction(ResumeFTy, "__resumeException", &M); + ResumeF->addFnAttr(Attribute::NoReturn); // Register llvm_eh_typeid_for function FunctionType *EHTypeIDTy = @@ -790,6 +782,7 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) { FunctionType *FTy = FunctionType::get( IRB.getVoidTy(), {getAddrIntType(&M), IRB.getInt32Ty()}, false); EmLongjmpF = getEmscriptenFunction(FTy, "emscripten_longjmp", &M); + EmLongjmpF->addFnAttr(Attribute::NoReturn); if (SetjmpF) { // Register saveSetjmp function @@ -1152,11 +1145,16 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) { Instruction *TI = BB.getTerminator(); if (isa(TI)) ExitingInsts.push_back(TI); + // Any 'call' instruction with 'noreturn' attribute exits the function at + // this point. If this throws but unwinds to another EH pad within this + // function instead of exiting, this would have been an 'invoke', which + // happens if we use Wasm EH or Wasm SjLJ. for (auto &I : BB) { - if (auto *CB = dyn_cast(&I)) { - StringRef CalleeName = CB->getCalledOperand()->getName(); - if (CalleeName == "__resumeException" || - CalleeName == "emscripten_longjmp" || CalleeName == "__cxa_throw") + if (auto *CI = dyn_cast(&I)) { + bool IsNoReturn = CI->hasFnAttr(Attribute::NoReturn); + if (auto *CalleeF = dyn_cast(CI->getCalledOperand())) + IsNoReturn |= CalleeF->hasFnAttribute(Attribute::NoReturn); + if (IsNoReturn) ExitingInsts.push_back(&I); } } diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll index 85ea09ef538b45..5615901316b628 100644 --- a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll @@ -311,7 +311,7 @@ attributes #3 = { allocsize(0) } ; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="__invoke_void" } ; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="saveSetjmp" } ; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="testSetjmp" } -; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="emscripten_longjmp" } +; CHECK-DAG: attributes #{{[0-9]+}} = { noreturn "wasm-import-module"="env" "wasm-import-name"="emscripten_longjmp" } ; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="__invoke_i8*_i32_%struct.__jmp_buf_tag*" } ; CHECK-DAG: attributes #[[ALLOCSIZE_ATTR]] = { allocsize(1) }