diff --git a/patches/llvm/11.0.0/001-hardware-exception-handling.patch b/patches/llvm/11.0.0/001-hardware-exception-handling.patch deleted file mode 100644 index 3b0d37c..0000000 --- a/patches/llvm/11.0.0/001-hardware-exception-handling.patch +++ /dev/null @@ -1,1044 +0,0 @@ -diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h -index d3fad58fcf5..77153f85a93 100644 ---- a/clang/include/clang/AST/Stmt.h -+++ b/clang/include/clang/AST/Stmt.h -@@ -1764,6 +1764,7 @@ public: - class LabelStmt : public ValueStmt { - LabelDecl *TheDecl; - Stmt *SubStmt; -+ bool SideEntry = false; - - public: - /// Build a label statement. -@@ -1799,6 +1800,9 @@ public: - static bool classof(const Stmt *T) { - return T->getStmtClass() == LabelStmtClass; - } -+ -+ bool isSideEntry() const { return SideEntry; } -+ void setSideEntry(bool SE) { SideEntry = SE; } - }; - - /// Represents an attribute applied to a statement. -diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def -index 70f68d664bb..1e87b455db8 100644 ---- a/clang/include/clang/Basic/LangOptions.def -+++ b/clang/include/clang/Basic/LangOptions.def -@@ -128,6 +128,7 @@ LANGOPT(ZVector , 1, 0, "System z vector extensions") - LANGOPT(Exceptions , 1, 0, "exception handling") - LANGOPT(ObjCExceptions , 1, 0, "Objective-C exceptions") - LANGOPT(CXXExceptions , 1, 0, "C++ exceptions") -+LANGOPT(EHAsynch , 1, 0, "C/C++ EH Asynch exceptions") - LANGOPT(DWARFExceptions , 1, 0, "dwarf exception handling") - LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling") - LANGOPT(SEHExceptions , 1, 0, "SEH .xdata exception handling") -diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td -index 966cb907b7e..dc7b38c254f 100644 ---- a/clang/include/clang/Driver/Options.td -+++ b/clang/include/clang/Driver/Options.td -@@ -889,6 +889,8 @@ def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group, Group; - defm cxx_exceptions: OptInFFlag<"cxx-exceptions", "Enable C++ exceptions">; -+def feh_asynch: Flag<["-"], "feh-asynch">, Group, -+ HelpText<"Enable EH Asynchronous exceptions">, Flags<[CC1Option]>; - def fcxx_modules : Flag <["-"], "fcxx-modules">, Group, - Flags<[DriverOption]>; - def fdebug_pass_arguments : Flag<["-"], "fdebug-pass-arguments">, Group; -@@ -1505,6 +1507,7 @@ def fno_common : Flag<["-"], "fno-common">, Group, Flags<[CC1Option]>, - def fno_constant_cfstrings : Flag<["-"], "fno-constant-cfstrings">, Group, - Flags<[CC1Option]>, - HelpText<"Disable creation of CodeFoundation-type constant strings">; -+def fno_eh_asynch: Flag<["-"], "fno-eh-asynch">, Group; - def fno_cxx_modules : Flag <["-"], "fno-cxx-modules">, Group, - Flags<[DriverOption]>; - def fno_diagnostics_fixit_info : Flag<["-"], "fno-diagnostics-fixit-info">, Group, -diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp -index 4bd00ece86a..7cc6089b711 100644 ---- a/clang/lib/AST/JSONNodeDumper.cpp -+++ b/clang/lib/AST/JSONNodeDumper.cpp -@@ -1444,6 +1444,7 @@ void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) { - void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) { - JOS.attribute("name", LS->getName()); - JOS.attribute("declId", createPointerRepresentation(LS->getDecl())); -+ attributeOnlyIfTrue("sideEntry", LS->isSideEntry()); - } - void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) { - JOS.attribute("targetLabelDeclId", -diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp -index 5b0a0ac392c..0d5e9418fb7 100644 ---- a/clang/lib/AST/TextNodeDumper.cpp -+++ b/clang/lib/AST/TextNodeDumper.cpp -@@ -916,6 +916,8 @@ void TextNodeDumper::VisitWhileStmt(const WhileStmt *Node) { - - void TextNodeDumper::VisitLabelStmt(const LabelStmt *Node) { - OS << " '" << Node->getName() << "'"; -+ if (Node->isSideEntry()) -+ OS << " side_entry"; - } - - void TextNodeDumper::VisitGotoStmt(const GotoStmt *Node) { -diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp -index ad543ef86c1..3b69bb20b06 100644 ---- a/clang/lib/CodeGen/CGCleanup.cpp -+++ b/clang/lib/CodeGen/CGCleanup.cpp -@@ -194,6 +194,11 @@ void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) { - if (IsLifetimeMarker) - Scope->setLifetimeMarker(); - -+ // With Windows -EHa, Invoke llvm.seh.scope.begin() for EHCleanup -+ if (CGF->getLangOpts().EHAsynch && IsEHCleanup && -+ CGF->getTarget().getCXXABI().isMicrosoft()) -+ CGF->EmitSehCppScopeBegin(); -+ - return Scope->getCleanupBuffer(); - } - -@@ -759,14 +764,31 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { - if (Scope.isEHCleanup()) - cleanupFlags.setIsEHCleanupKind(); - -+ // Under -EHa, invoke seh.scope.end() to mark scope end before dtor -+ bool IsEHa = getLangOpts().EHAsynch && !Scope.isLifetimeMarker(); -+ const EHPersonality& Personality = EHPersonality::get(*this); - if (!RequiresNormalCleanup) { -+ // Mark CPP scope end for passed-by-value Arg temp -+ // per Windows ABI which is "normally" Cleanup in callee -+ if (IsEHa && getInvokeDest()) { -+ if (Personality.isMSVCXXPersonality()) -+ EmitSehCppScopeEnd(); -+ } - destroyOptimisticNormalEntry(*this, Scope); - EHStack.popCleanup(); - } else { - // If we have a fallthrough and no other need for the cleanup, - // emit it directly. -- if (HasFallthrough && !HasPrebranchedFallthrough && -- !HasFixups && !HasExistingBranches) { -+ if (HasFallthrough && !HasPrebranchedFallthrough && !HasFixups && -+ !HasExistingBranches) { -+ -+ // mark SEH scope end for fall-through flow -+ if (IsEHa && getInvokeDest()) { -+ if (Personality.isMSVCXXPersonality()) -+ EmitSehCppScopeEnd(); -+ else -+ EmitSehTryScopeEnd(); -+ } - - destroyOptimisticNormalEntry(*this, Scope); - EHStack.popCleanup(); -@@ -801,6 +823,14 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { - // should already be branched to it. - EmitBlock(NormalEntry); - -+ // intercept normal cleanup to mark SEH scope end -+ if (IsEHa) { -+ if (Personality.isMSVCXXPersonality()) -+ EmitSehCppScopeEnd(); -+ else -+ EmitSehTryScopeEnd(); -+ } -+ - // III. Figure out where we're going and build the cleanup - // epilogue. - -@@ -1248,11 +1278,18 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C, - // to the current RunCleanupsScope. - if (C == EHStack.stable_begin() && - CurrentCleanupScopeDepth.strictlyEncloses(C)) { -- // If it's a normal cleanup, we need to pretend that the -- // fallthrough is unreachable. -- CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); -- PopCleanupBlock(); -- Builder.restoreIP(SavedIP); -+ // Per comment below, checking EHAsynch is not really necessary -+ // it's there to assure zero-impact w/o EHAsynch option -+ if (!Scope.isNormalCleanup() && getLangOpts().EHAsynch) -+ PopCleanupBlock(); -+ else -+ { -+ // If it's a normal cleanup, we need to pretend that the -+ // fallthrough is unreachable. -+ CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); -+ PopCleanupBlock(); -+ Builder.restoreIP(SavedIP); -+ } - return; - } - -@@ -1276,3 +1313,60 @@ void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary, - pushDestroy(NormalAndEHCleanup, Ptr, TempType, destroyCXXObject, - /*useEHCleanup*/ true); - } -+ -+// Need to set "funclet" in OperandBundle properly for noThrow -+// intrinsic (see CGCall.cpp) -+static void EmitSehScope(CodeGenFunction &CGF, -+ llvm::FunctionCallee &SehCppScope) { -+ llvm::BasicBlock *InvokeDest = CGF.getInvokeDest(); -+ llvm::BasicBlock *BB = CGF.Builder.GetInsertBlock(); -+ assert(BB && InvokeDest); -+ llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont"); -+ SmallVector BundleList = -+ CGF.getBundlesForFunclet(SehCppScope.getCallee()); -+ if (CGF.CurrentFuncletPad) -+ BundleList.emplace_back("funclet", CGF.CurrentFuncletPad); -+ CGF.Builder.CreateInvoke(SehCppScope, Cont, InvokeDest, None, BundleList); -+ CGF.EmitBlock(Cont); -+} -+ -+// Invoke a llvm.seh.scope.begin at the beginning of a CPP scope for -EHa -+void CodeGenFunction::EmitSehCppScopeBegin() { -+ assert(getLangOpts().EHAsynch); -+ llvm::FunctionType *FTy = -+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); -+ llvm::FunctionCallee SehCppScope = -+ CGM.CreateRuntimeFunction(FTy, "llvm.seh.scope.begin"); -+ EmitSehScope(*this, SehCppScope); -+} -+ -+// Invoke a llvm.seh.scope.end at the end of a CPP scope for -EHa -+// llvm.seh.scope.end is emitted before popCleanup, so it's "invoked" -+void CodeGenFunction::EmitSehCppScopeEnd() { -+ assert(getLangOpts().EHAsynch); -+ llvm::FunctionType *FTy = -+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); -+ llvm::FunctionCallee SehCppScope = -+ CGM.CreateRuntimeFunction(FTy, "llvm.seh.scope.end"); -+ EmitSehScope(*this, SehCppScope); -+} -+ -+// Invoke a llvm.seh.try.begin at the beginning of a SEH scope for -EHa -+void CodeGenFunction::EmitSehTryScopeBegin() { -+ assert(getLangOpts().EHAsynch); -+ llvm::FunctionType* FTy = -+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); -+ llvm::FunctionCallee SehCppScope = -+ CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.begin"); -+ EmitSehScope(*this, SehCppScope); -+} -+ -+// Invoke a llvm.seh.try.end at the end of a SEH scope for -EHa -+void CodeGenFunction::EmitSehTryScopeEnd() { -+ assert(getLangOpts().EHAsynch); -+ llvm::FunctionType* FTy = -+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); -+ llvm::FunctionCallee SehCppScope = -+ CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.end"); -+ EmitSehScope(*this, SehCppScope); -+} -\ No newline at end of file -diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp -index bdf70252b5a..a4e4d7d8120 100644 ---- a/clang/lib/CodeGen/CGException.cpp -+++ b/clang/lib/CodeGen/CGException.cpp -@@ -39,6 +39,18 @@ static llvm::FunctionCallee getFreeExceptionFn(CodeGenModule &CGM) { - return CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception"); - } - -+static llvm::FunctionCallee getSehTryBeginFn(CodeGenModule &CGM) { -+ llvm::FunctionType *FTy = -+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); -+ return CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.begin"); -+} -+ -+static llvm::FunctionCallee getSehTryEndFn(CodeGenModule &CGM) { -+ llvm::FunctionType *FTy = -+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); -+ return CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.end"); -+} -+ - static llvm::FunctionCallee getUnexpectedFn(CodeGenModule &CGM) { - // void __cxa_call_unexpected(void *thrown_exception); - -@@ -451,7 +463,7 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { - if (!FD) { - // Check if CapturedDecl is nothrow and create terminate scope for it. - if (const CapturedDecl* CD = dyn_cast_or_null(D)) { -- if (CD->isNothrow()) -+ if (CD->isNothrow() && !getLangOpts().EHAsynch /* !IsEHa */) - EHStack.pushTerminate(); - } - return; -@@ -463,7 +475,8 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { - ExceptionSpecificationType EST = Proto->getExceptionSpecType(); - if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot) { - // noexcept functions are simple terminate scopes. -- EHStack.pushTerminate(); -+ if (!getLangOpts().EHAsynch) // -EHa: HW exception still can occur -+ EHStack.pushTerminate(); - } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { - // TODO: Revisit exception specifications for the MS ABI. There is a way to - // encode these in an object file but MSVC doesn't do anything with it. -@@ -540,7 +553,7 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) { - if (!FD) { - // Check if CapturedDecl is nothrow and pop terminate scope for it. - if (const CapturedDecl* CD = dyn_cast_or_null(D)) { -- if (CD->isNothrow()) -+ if (CD->isNothrow() && !EHStack.empty()) - EHStack.popTerminate(); - } - return; -@@ -550,7 +563,8 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) { - return; - - ExceptionSpecificationType EST = Proto->getExceptionSpecType(); -- if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot) { -+ if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot && -+ !EHStack.empty() /* possible empty when -EHa */) { - EHStack.popTerminate(); - } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { - // TODO: Revisit exception specifications for the MS ABI. There is a way to -@@ -606,6 +620,9 @@ void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { - } else { - // No exception decl indicates '...', a catch-all. - CatchScope->setHandler(I, CGM.getCXXABI().getCatchAllTypeInfo(), Handler); -+ // Mark scope with SehTryBegin -+ if (getLangOpts().EHAsynch) -+ EmitRuntimeCallOrInvoke(getSehTryBeginFn(CGM)); - } - } - } -@@ -720,7 +737,7 @@ llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() { - // If exceptions are disabled/ignored and SEH is not in use, then there is no - // invoke destination. SEH "works" even if exceptions are off. In practice, - // this means that C++ destructors and other EH cleanups don't run, which is -- // consistent with MSVC's behavior. -+ // consistent with MSVC's behavior, except in the presence of -EHa - const LangOptions &LO = CGM.getLangOpts(); - if (!LO.Exceptions || LO.IgnoreExceptions) { - if (!LO.Borland && !LO.MicrosoftExt) -@@ -1610,7 +1627,23 @@ void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) { - JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave"); - - SEHTryEpilogueStack.push_back(&TryExit); -+ -+ llvm::BasicBlock *TryBB = nullptr; -+ // IsEHa: emit an invoke to _seh_try_begin() runtime for -EHa -+ if (getLangOpts().EHAsynch) { -+ EmitRuntimeCallOrInvoke(getSehTryBeginFn(CGM)); -+ if (SEHTryEpilogueStack.size() == 1) // outermost only -+ TryBB = Builder.GetInsertBlock(); -+ } -+ - EmitStmt(S.getTryBlock()); -+ -+ // Volatilize all blocks in Try, till current insert point -+ if (TryBB) { -+ llvm::SmallPtrSet Visited; -+ VolatilizeTryBlocks(TryBB, Visited); -+ } -+ - SEHTryEpilogueStack.pop_back(); - - if (!TryExit.getBlock()->use_empty()) -@@ -1621,6 +1654,38 @@ void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) { - ExitSEHTryStmt(S); - } - -+// Recursively walk through blocks in a _try -+// and make all memory instructions volatile -+void CodeGenFunction::VolatilizeTryBlocks( -+ llvm::BasicBlock *BB, llvm::SmallPtrSet &V) { -+ if (BB == SEHTryEpilogueStack.back()->getBlock() /* end of Try */ || -+ !V.insert(BB).second /* already visited */ || -+ !BB->getParent() /* not emitted */ || BB->empty()) -+ return; -+ -+ if (!BB->isEHPad()) { -+ for (llvm::BasicBlock::iterator J = BB->begin(), JE = BB->end(); J != JE; -+ ++J) { -+ if (isa(J)) { -+ auto LI = cast(J); -+ LI->setVolatile(true); -+ } else if (isa(J)) { -+ auto SI = cast(J); -+ SI->setVolatile(true); -+ } else if (isa(J)) { -+ auto *MCI = cast(J); -+ MCI->setVolatile(llvm::ConstantInt::get(Builder.getInt1Ty(), 1)); -+ } -+ } -+ } -+ const llvm::Instruction *TI = BB->getTerminator(); -+ if (TI) { -+ unsigned N = TI->getNumSuccessors(); -+ for (unsigned I = 0; I < N; I++) -+ VolatilizeTryBlocks(TI->getSuccessor(I), V); -+ } -+} -+ - namespace { - struct PerformSEHFinally final : EHScopeStack::Cleanup { - llvm::Function *OutlinedFinally; -@@ -2101,6 +2166,12 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) { - return; - } - -+ // IsEHa: emit an invoke _seh_try_end() to mark end of FT flow -+ if (getLangOpts().EHAsynch && Builder.GetInsertBlock()) { -+ llvm::FunctionCallee SehTryEnd = getSehTryEndFn(CGM); -+ EmitRuntimeCallOrInvoke(SehTryEnd); -+ } -+ - // Otherwise, we must have an __except block. - const SEHExceptStmt *Except = S.getExceptHandler(); - assert(Except && "__try must have __finally xor __except"); -diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp -index 672909849bb..32dca08b8cf 100644 ---- a/clang/lib/CodeGen/CGStmt.cpp -+++ b/clang/lib/CodeGen/CGStmt.cpp -@@ -606,6 +606,11 @@ void CodeGenFunction::LexicalScope::rescopeLabels() { - - void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) { - EmitLabel(S.getDecl()); -+ -+ // IsEHa - emit eha.scope.begin if it's a side entry of a scope -+ if (getLangOpts().EHAsynch && S.isSideEntry()) -+ EmitSehCppScopeBegin(); -+ - EmitStmt(S.getSubStmt()); - } - -diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp -index 8ce488f35dd..4cc8304c455 100644 ---- a/clang/lib/CodeGen/CodeGenFunction.cpp -+++ b/clang/lib/CodeGen/CodeGenFunction.cpp -@@ -71,6 +71,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) - shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())) { - if (!suppressNewContext) - CGM.getCXXABI().getMangleContext().startNewFunction(); -+ EHStack.setCGF(this); - - SetFastMathFlags(CurFPFeatures); - SetFPModel(); -diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h -index d794f4f0fa8..1b5892c7459 100644 ---- a/clang/lib/CodeGen/CodeGenFunction.h -+++ b/clang/lib/CodeGen/CodeGenFunction.h -@@ -2784,6 +2784,11 @@ public: - void EmitCXXTemporary(const CXXTemporary *Temporary, QualType TempType, - Address Ptr); - -+ void EmitSehCppScopeBegin(); -+ void EmitSehCppScopeEnd(); -+ void EmitSehTryScopeBegin(); -+ void EmitSehTryScopeEnd(); -+ - llvm::Value *EmitLifetimeStart(uint64_t Size, llvm::Value *Addr); - void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr); - -@@ -3134,6 +3139,8 @@ public: - void EmitSEHLeaveStmt(const SEHLeaveStmt &S); - void EnterSEHTryStmt(const SEHTryStmt &S); - void ExitSEHTryStmt(const SEHTryStmt &S); -+ void VolatilizeTryBlocks(llvm::BasicBlock *BB, -+ llvm::SmallPtrSet &V); - - void pushSEHCleanup(CleanupKind kind, - llvm::Function *FinallyFunc); -diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp -index 4ae8ce7e5cc..5512c8fe88a 100644 ---- a/clang/lib/CodeGen/CodeGenModule.cpp -+++ b/clang/lib/CodeGen/CodeGenModule.cpp -@@ -593,6 +593,9 @@ void CodeGenModule::Release() { - llvm::DenormalMode::IEEE); - } - -+ if (LangOpts.EHAsynch) -+ getModule().addModuleFlag(llvm::Module::Warning, "eh-asynch", 1); -+ - // Emit OpenCL specific module metadata: OpenCL/SPIR version. - if (LangOpts.OpenCL) { - EmitOpenCLMetadata(); -diff --git a/clang/lib/CodeGen/EHScopeStack.h b/clang/lib/CodeGen/EHScopeStack.h -index 3a640d6117d..60fe9b3c9dd 100644 ---- a/clang/lib/CodeGen/EHScopeStack.h -+++ b/clang/lib/CodeGen/EHScopeStack.h -@@ -236,6 +236,9 @@ private: - /// The innermost EH scope on the stack. - stable_iterator InnermostEHScope; - -+ /// The CGF this Stack belong to -+ CodeGenFunction* CGF; -+ - /// The current set of branch fixups. A branch fixup is a jump to - /// an as-yet unemitted label, i.e. a label for which we don't yet - /// know the EH stack depth. Whenever we pop a cleanup, we have -@@ -263,7 +266,7 @@ private: - public: - EHScopeStack() : StartOfBuffer(nullptr), EndOfBuffer(nullptr), - StartOfData(nullptr), InnermostNormalCleanup(stable_end()), -- InnermostEHScope(stable_end()) {} -+ InnermostEHScope(stable_end()), CGF(nullptr) {} - ~EHScopeStack() { delete[] StartOfBuffer; } - - /// Push a lazily-created cleanup on the stack. -@@ -311,6 +314,8 @@ public: - std::memcpy(Buffer, Cleanup, Size); - } - -+ void setCGF(CodeGenFunction* inCGF) { CGF = inCGF; } -+ - /// Pops a cleanup scope off the stack. This is private to CGCleanup.cpp. - void popCleanup(); - -diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp -index 45c6cb6b2e0..a080c93356a 100644 ---- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp -+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp -@@ -131,7 +131,12 @@ public: - - /// MSVC needs an extra flag to indicate a catchall. - CatchTypeInfo getCatchAllTypeInfo() override { -- return CatchTypeInfo{nullptr, 0x40}; -+ // For -EHa catch(...) must handle HW exception -+ // Adjective = HT_IsStdDotDot (0x40), only catch C++ exceptions -+ if (getContext().getLangOpts().EHAsynch) -+ return CatchTypeInfo{nullptr, 0}; -+ else -+ return CatchTypeInfo{nullptr, 0x40}; - } - - bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override; -diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp -index af4bcf951e6..71112783ac0 100644 ---- a/clang/lib/Driver/ToolChains/Clang.cpp -+++ b/clang/lib/Driver/ToolChains/Clang.cpp -@@ -415,6 +415,7 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, - Args.ClaimAllArgs(options::OPT_fobjc_exceptions); - Args.ClaimAllArgs(options::OPT_fno_objc_exceptions); - Args.ClaimAllArgs(options::OPT_fcxx_exceptions); -+ Args.ClaimAllArgs(options::OPT_feh_asynch); - Args.ClaimAllArgs(options::OPT_fno_cxx_exceptions); - return; - } -@@ -423,6 +424,13 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, - bool EH = Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, - false); - -+ bool EHa = -+ Args.hasFlag(options::OPT_feh_asynch, options::OPT_fno_eh_asynch, false); -+ if (EHa) { -+ CmdArgs.push_back("-feh-asynch"); -+ EH = true; -+ } -+ - // Obj-C exceptions are enabled by default, regardless of -fexceptions. This - // is not necessarily sensible, but follows GCC. - if (types::isObjC(InputType) && -@@ -6581,7 +6589,10 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, - if (types::isCXX(InputType)) - CmdArgs.push_back("-fcxx-exceptions"); - CmdArgs.push_back("-fexceptions"); -+ if (EH.Asynch) -+ CmdArgs.push_back("-feh-asynch"); - } -+ - if (types::isCXX(InputType) && EH.Synch && EH.NoUnwindC) - CmdArgs.push_back("-fexternc-nounwind"); - -diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp -index 73114c6d76c..b58af0b68e7 100644 ---- a/clang/lib/Frontend/CompilerInvocation.cpp -+++ b/clang/lib/Frontend/CompilerInvocation.cpp -@@ -2819,6 +2819,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, - Opts.IgnoreExceptions = Args.hasArg(OPT_fignore_exceptions); - Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions); - Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions); -+ Opts.EHAsynch = Args.hasArg(OPT_feh_asynch); - - // -ffixed-point - Opts.FixedPoint = -diff --git a/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp -index b34243edea3..304f059a032 100644 ---- a/clang/lib/Sema/JumpDiagnostics.cpp -+++ b/clang/lib/Sema/JumpDiagnostics.cpp -@@ -930,6 +930,9 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, - if (!ToScopesWarning.empty()) { - S.Diag(DiagLoc, JumpDiagWarning); - NoteJumpIntoScopes(ToScopesWarning); -+ assert(isa(To)); -+ LabelStmt *Label = cast(To); -+ Label->setSideEntry(true); - } - - // Handle errors. -diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp -index a40c5499a6d..bfed22a1252 100644 ---- a/clang/lib/Serialization/ASTReaderStmt.cpp -+++ b/clang/lib/Serialization/ASTReaderStmt.cpp -@@ -185,11 +185,13 @@ void ASTStmtReader::VisitDefaultStmt(DefaultStmt *S) { - - void ASTStmtReader::VisitLabelStmt(LabelStmt *S) { - VisitStmt(S); -+ bool IsSideEntry = Record.readInt(); - auto *LD = readDeclAs(); - LD->setStmt(S); - S->setDecl(LD); - S->setSubStmt(Record.readSubStmt()); - S->setIdentLoc(readSourceLocation()); -+ S->setSideEntry(IsSideEntry); - } - - void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) { -diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp -index 0767b3a24bf..614fd45d193 100644 ---- a/clang/lib/Serialization/ASTWriterStmt.cpp -+++ b/clang/lib/Serialization/ASTWriterStmt.cpp -@@ -115,6 +115,7 @@ void ASTStmtWriter::VisitDefaultStmt(DefaultStmt *S) { - - void ASTStmtWriter::VisitLabelStmt(LabelStmt *S) { - VisitStmt(S); -+ Record.push_back(S->isSideEntry()); - Record.AddDeclRef(S->getDecl()); - Record.AddStmt(S->getSubStmt()); - Record.AddSourceLocation(S->getIdentLoc()); -diff --git a/clang/test/CodeGen/windows-seh-EHa-CppCatchDotDotDot.cpp b/clang/test/CodeGen/windows-seh-EHa-CppCatchDotDotDot.cpp -new file mode 100644 -index 00000000000..2928a610d3c ---- /dev/null -+++ b/clang/test/CodeGen/windows-seh-EHa-CppCatchDotDotDot.cpp -@@ -0,0 +1,58 @@ -+// RUN: %clang_cc1 -triple x86_64-windows -feh-asynch -fcxx-exceptions -fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration -S -emit-llvm %s -o - | FileCheck %s -+ -+// CHECK: define dso_local void @"?crash@@YAXH@Z -+// CHECK: invoke void @llvm.seh.try.begin() -+// CHECK: invoke void @llvm.seh.scope.begin() -+// CHECK: invoke void @llvm.seh.scope.end() -+ -+// CHECK: %[[dst:[0-9-]+]] = catchswitch within none [label %catch] unwind to caller -+// CHECK: %[[dst1:[0-9-]+]] = catchpad within %[[dst]] [i8* null, i32 0, i8* null] -+// CHECK: "funclet"(token %[[dst1]]) -+ -+// CHECK: invoke void @llvm.seh.try.begin() -+// CHECK: %[[src:[0-9-]+]] = load volatile i32, i32* %i -+// CHECK-NEXT: invoke void @"?crash@@YAXH@Z"(i32 %[[src]]) -+// CHECK: invoke void @llvm.seh.try.end() -+ -+// ***************************************************************************** -+// Abstract: Test CPP catch(...) under SEH -EHa option -+ -+void printf(...); -+int volatile *NullPtr = 0; -+void foo() { -+ *NullPtr = 0; -+} -+int *pt1, *pt2, *pt3; -+int g; -+void crash(int i) { -+ g = i; -+ try { -+ struct A { -+ A() { -+ printf(" in A ctor \n"); -+ if (g == 0) -+ *NullPtr = 0; -+ } -+ ~A() { -+ printf(" in A dtor \n"); -+ } -+ } ObjA; -+ if (i == 1) -+ *NullPtr = 0; -+ } catch (...) { -+ printf(" in catch(...) funclet \n"); -+ if (i == 1) -+ throw(i); -+ } -+} -+ -+int main() { -+ for (int i = 0; i < 2; i++) { -+ __try { -+ crash(i); -+ } __except (1) { -+ printf(" Test CPP unwind: in except handler i = %d \n", i); -+ } -+ } -+ return 0; -+} -diff --git a/clang/test/CodeGen/windows-seh-EHa-CppCondiTemps.cpp b/clang/test/CodeGen/windows-seh-EHa-CppCondiTemps.cpp -new file mode 100644 -index 00000000000..d588d6e2292 ---- /dev/null -+++ b/clang/test/CodeGen/windows-seh-EHa-CppCondiTemps.cpp -@@ -0,0 +1,129 @@ -+// RUN: %clang_cc1 -triple x86_64-windows -feh-asynch -fcxx-exceptions -fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration -S -emit-llvm %s -o - | FileCheck %s -+ -+// CHECK: define dso_local i32 @"?bar@@YAHHVB1@@VB2@@@Z" -+// CHECK: %coerce.dive1 = getelementptr inbounds %class.B2 -+// CHECK: %coerce.dive2 = getelementptr inbounds %class.B1 -+// ----- scope begin of two passed-by-value temps -+// CHECK: invoke void @llvm.seh.scope.begin() -+// CHECK: invoke void @llvm.seh.scope.begin() -+// CHECK: invoke void @llvm.seh.scope.end() -+// CHECK: call void @"??1B1@@QEAA@XZ" -+// CHECK: invoke void @llvm.seh.scope.end() -+// CHECK: call void @"??1B2@@QEAA@XZ" -+ -+// CHECK: define linkonce_odr dso_local void @"??1B2@@QEAA@XZ" -+// CHECK: %this.addr = alloca %class.B2* -+// ----- B1 scope begin without base ctor -+// CHECK: invoke void @llvm.seh.scope.begin() -+// CHECK: invoke void @llvm.seh.scope.end() -+// CHECK: call void @"??1B1@@QEAA@XZ" -+ -+// CHECK: define dso_local void @"?goo@@YA?AVB1@@H@Z" -+// CHECK: call %class.B2* @"??0B2@@QEAA@XZ"(%class.B2* %b2ingoo) -+// CHECK: invoke void @llvm.seh.scope.begin() -+// check: call void @llvm.memcpy -+// CHECK: invoke void @llvm.seh.scope.end() -+// CHECK: call void @"??1B2@@QEAA@XZ"(%class.B2* %b2ingoo) -+ -+// CHECK: define linkonce_odr dso_local %class.B2* @"??0B2@@QEAA@XZ" -+// CHECK: call %class.B1* @"??0B1@@QEAA@XZ"(%class.B1* -+// ----- scope begin of base ctor -+// CHECK: invoke void @llvm.seh.scope.begin() -+// CHECK: invoke void @llvm.seh.scope.end() -+// ----- B1 scope end without base dtor -+ -+// **************************************************************************** -+// Abstract: Test CPP Conditional-Expr & ABI Temps under SEH -EHa option -+ -+void printf(...); -+ -+int xxxx = 0; -+int* ptr; -+ -+int foo(int a) -+{ -+ return xxxx + a; -+} -+ -+class B1 { -+public: -+ int data = 90; -+ B1() { foo(data + 111); } -+ ~B1() { printf("in B1 Dtor \n"); } -+}; -+class B2 : public B1 { -+public: -+ B2() { foo(data + 222); } -+ ~B2() { printf("in B2 Dtor \n");; } -+}; -+class B3 : public B2 { -+public: -+ B3() { foo(data + 333); } -+ ~B3() { printf("in B3 Dtor \n");; } -+}; -+ -+int bar(int j, class B1 b1Bar, class B2 b2Bar) -+{ -+ int ww; -+ if ( j > 0) -+ ww = b1Bar.data; -+ else -+ ww = b2Bar.data; -+ return ww + *ptr; -+} -+ -+class B1 goo(int w) -+{ -+ class B2 b2ingoo; -+ b2ingoo.data += w; -+ return b2ingoo; -+} -+ -+// CHECK: define dso_local i32 @main() -+// CHECK: invoke void @llvm.seh.scope.begin() -+// --- beginning of conditional temp test -+// CHECK: invoke %class.B2* @"??0B2@@QEAA@XZ" -+// CHECK: invoke void @llvm.seh.scope.begin() -+// CHECK: invoke %class.B3* @"??0B3@@QEAA@XZ" -+// CHECK: invoke void @llvm.seh.scope.begin() -+// CHECK: invoke void @llvm.seh.scope.end() -+// CHECK: call void @"??1B3@@QEAA@XZ" -+// CHECK: invoke void @llvm.seh.scope.end() -+// CHECK: call void @"??1B2@@QEAA@XZ" -+// ----- end of conditional temp test -+ -+// ----- testing caller's passed-by-value temps -+// setting scope in case exception occurs before the call -+// check: invoke %class.B2* @"??0B2@@QEAA@XZ" -+// CHECK: invoke void @llvm.seh.scope.begin() -+// CHECK: invoke %class.B1* @"??0B1@@QEAA@XZ" -+// CHECK: invoke void @llvm.seh.scope.begin() -+// ----- end of temps' scope right before callee -+// CHECK: invoke void @llvm.seh.scope.end() -+// CHECK: invoke void @llvm.seh.scope.end() -+// CHECK: invoke i32 @"?bar@@YAHHVB1@@VB2@@@Z" -+ -+// ----- testing caller's return-by-value temp -+// scope begins right after callee which is the ctor of return temp -+// CHECK: void @"?goo@@YA?AVB1@@H@Z" -+// CHECK: invoke void @llvm.seh.scope.begin() -+// CHECK: invoke void @llvm.seh.scope.end() -+ -+int main() { -+ class B3 b3inmain; -+ -+ // Test conditional ctor and dtor -+ int m = (xxxx > 1) ? B2().data + foo(99) : -+ B3().data + foo(88); -+ -+ // Test: passed-in by value -+ // Per Windows ABI, ctored by caller, dtored by callee -+ int i = bar(foo(0), B1(), B2()); -+ -+ // Test: returned by value -+ // Per Windows ABI, caller allocate a temp in stack, then ctored by callee, -+ // finally dtored in caller after consumed -+ class B1 b1fromgoo = goo(i); -+ -+ return m + b1fromgoo.data + b3inmain.data; -+} -\ No newline at end of file -diff --git a/clang/test/CodeGen/windows-seh-EHa-CppDtors01.cpp b/clang/test/CodeGen/windows-seh-EHa-CppDtors01.cpp -new file mode 100644 -index 00000000000..8fdb1e889c4 ---- /dev/null -+++ b/clang/test/CodeGen/windows-seh-EHa-CppDtors01.cpp -@@ -0,0 +1,60 @@ -+// RUN: %clang_cc1 -triple x86_64-windows -feh-asynch -fcxx-exceptions -fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration -S -emit-llvm %s -o - | FileCheck %s -+ -+// CHECK: invoke void @llvm.seh.scope.begin() -+// CHECK: invoke void @llvm.seh.scope.begin() -+// CHECK: invoke void @llvm.seh.scope.begin() -+// CHECK: invoke void @llvm.seh.scope.end() -+// CHECK: invoke void @llvm.seh.scope.end() -+// CHECK: invoke void @llvm.seh.scope.end() -+ -+// CHECK: invoke void @llvm.seh.try.begin() -+// CHECK: %[[src:[0-9-]+]] = load volatile i32, i32* %i -+// CHECK-NEXT: invoke void @"?crash@@YAXH@Z"(i32 %[[src]]) -+// CHECK: invoke void @llvm.seh.try.end() -+ -+// **************************************************************************** -+// Abstract: Test CPP unwind Dtoring under SEH -EHa option -+ -+void printf(...); -+int volatile *NullPtr = 0; -+void crash(int i) { -+ struct A { -+ ~A() { -+ printf(" in A dtor \n"); -+ } -+ } ObjA; -+ if (i == 0) -+ *NullPtr = 0; -+ -+ struct B { -+ ~B() { -+ printf(" in B dtor \n"); -+ } -+ } ObjB; -+ if (i == 1) -+ *NullPtr = 0; -+ -+ struct C { -+ ~C() { -+ printf(" in C dtor \n"); -+ } -+ } ObjC; -+ if (i == 2) -+ *NullPtr = 0; -+} -+ -+#define TRY __try -+#define CATCH_ALL __except (1) -+ -+int g; -+int main() { -+ for (int i = 0; i < 3; i++) { -+ TRY { -+ crash(i); -+ } -+ CATCH_ALL { -+ printf(" Test CPP unwind: in catch handler i = %d \n", i); -+ } -+ } -+ return 0; -+} -diff --git a/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp b/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp -new file mode 100644 -index 00000000000..3efd7d6505f ---- /dev/null -+++ b/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp -@@ -0,0 +1,42 @@ -+// RUN: %clang_cc1 -triple x86_64-windows -feh-asynch -fcxx-exceptions -fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration -S -emit-llvm %s -o - | FileCheck %s -+ -+// CHECK: invoke void @llvm.seh.try.begin() -+// CHECK: invoke void @llvm.seh.try.begin() -+// CHECK: %[[src:[0-9-]+]] = load volatile i32, i32* %i -+// CHECK-NEXT: i32 %[[src]] -+// CHECK: invoke void @llvm.seh.try.end() -+// CHECK: invoke void @llvm.seh.try.end() -+ -+// CHECK: define internal void @"?fin$0@0@main@@"(i8 %abnormal_termination -+// CHECK: invoke void @llvm.seh.try.begin() -+// CHECK: invoke void @llvm.seh.try.end() -+ -+// ***************************************************************************** -+// Abstract: Test __Try in __finally under SEH -EHa option -+void printf(...); -+int volatile *NullPtr = 0; -+int main() { -+ for (int i = 0; i < 3; i++) { -+ printf(" --- Test _Try in _finally --- i = %d \n", i); -+ __try { -+ __try { -+ printf(" In outer _try i = %d \n", i); -+ if (i == 0) -+ *NullPtr = 0; -+ } __finally { -+ __try { -+ printf(" In outer _finally i = %d \n", i); -+ if (i == 1) -+ *NullPtr = 0; -+ } __finally { -+ printf(" In Inner _finally i = %d \n", i); -+ if (i == 2) -+ *NullPtr = 0; -+ } -+ } -+ } __except (1) { -+ printf(" --- In outer except handler i = %d \n", i); -+ } -+ } -+ return 0; -+} -diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst -index 9b58b9dfb17..7ba418ab7d0 100644 ---- a/llvm/docs/LangRef.rst -+++ b/llvm/docs/LangRef.rst -@@ -11642,6 +11642,66 @@ The '``llvm.localescape``' intrinsic blocks inlining, as inlining changes where - the escaped allocas are allocated, which would break attempts to use - '``llvm.localrecover``'. - -+'``llvm.seh.try.begin``' and '``llvm.seh.try.end``' Intrinsics -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+ -+Syntax: -+""""""" -+ -+:: -+ -+ declare void @llvm.seh.try.begin() -+ declare void @llvm.seh.try.end() -+ -+Overview: -+""""""""" -+ -+The '``llvm.seh.try.begin``' and '``llvm.seh.try.end``' intrinsics mark -+the boundary of a _try region for Windows SEH Asynchrous Exception Handling. -+ -+Semantics: -+"""""""""" -+ -+When a C-function is compiled with Windows SEH Asynchrous Exception option, -+-feh_asynch (aka MSVC -EHa), these two intrinsics are injected to mark _try -+boundary and to prevent from potential exceptions being moved across boundary. -+ -+'``llvm.seh.scope.begin``' and '``llvm.seh.scope.end``' Intrinsics -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+ -+Syntax: -+""""""" -+ -+:: -+ -+ declare void @llvm.seh.scope.begin() -+ declare void @llvm.seh.scope.end() -+ -+Overview: -+""""""""" -+ -+The '``llvm.seh.scope.begin``' and '``llvm.seh.scope.end``' intrinsics mark -+the boundary of a CPP object lifetime for Windows SEH Asynchrous Exception -+Handling (MSVC option -EHa). -+ -+Semantics: -+"""""""""" -+ -+LLVM's ordinary exception-handling representation associates EH cleanups and -+handlers only with ``invoke``s, which normally correspond only to call sites. To -+support arbitrary faulting instructions, it must be possible to recover the current -+EH scope for any instruction. Turning every operation in LLVM that could fault -+into an ``invoke`` of a new, potentially-throwing intrinsic would require adding a -+large number of intrinsics, impede optimization of those operations, and make -+compilation slower by introducing many extra basic blocks. These intrinsics can -+be used instead to mark the region protected by a cleanup, such as for a local -+C++ object with a non-trivial destructor. ``llvm.seh.scope.begin`` is used to mark -+the start of the region; it is aways called with ``invoke``, with the unwind block -+being the desired unwind destination for any potentially-throwing instructions -+within the region. `llvm.seh.scope.end` is used to mark when the scope ends -+and the EH cleanup is no longer required (e.g. because the destructor is being -+called). -+ - .. _int_read_register: - .. _int_read_volatile_register: - .. _int_write_register: -diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td -index 4918ea876df..0d33b64998d 100644 ---- a/llvm/include/llvm/IR/Intrinsics.td -+++ b/llvm/include/llvm/IR/Intrinsics.td -@@ -481,6 +481,16 @@ def int_eh_recoverfp : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty, llvm_ptr_ty], - [IntrNoMem]>; - -+// To mark the beginning/end of a try-scope for Windows SEH -EHa -+// calls/invokes to these intrinsics are placed to model control flows -+// caused by HW exceptions under option -EHa. -+// calls/invokes to these intrinsics will be discarded during a codegen pass -+// after EH tables are generated -+def int_seh_try_begin : Intrinsic<[], [], [IntrReadMem, IntrWriteMem, IntrWillReturn]>; -+def int_seh_try_end : Intrinsic<[], [], [IntrReadMem, IntrWriteMem, IntrWillReturn]>; -+def int_seh_scope_begin : Intrinsic<[], [], [IntrNoMem]>; -+def int_seh_scope_end : Intrinsic<[], [], [IntrNoMem]>; -+ - // Note: we treat stacksave/stackrestore as writemem because we don't otherwise - // model their dependencies on allocas. - def int_stacksave : Intrinsic<[llvm_ptr_ty]>, -diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp -index d2930391f87..0e5a78f314b 100644 ---- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp -+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp -@@ -2801,6 +2801,10 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) { - llvm_unreachable("Cannot invoke this intrinsic"); - case Intrinsic::donothing: - // Ignore invokes to @llvm.donothing: jump directly to the next BB. -+ case Intrinsic::seh_try_begin: -+ case Intrinsic::seh_scope_begin: -+ case Intrinsic::seh_try_end: -+ case Intrinsic::seh_scope_end: - break; - case Intrinsic::experimental_patchpoint_void: - case Intrinsic::experimental_patchpoint_i64: -@@ -6635,6 +6639,10 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, - lowerCallToExternalSymbol(I, FunctionName); - return; - case Intrinsic::donothing: -+ case Intrinsic::seh_try_begin: -+ case Intrinsic::seh_scope_begin: -+ case Intrinsic::seh_try_end: -+ case Intrinsic::seh_scope_end: - // ignore - return; - case Intrinsic::experimental_stackmap: -diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp -index c518ae87ea9..6fb5e60c34a 100644 ---- a/llvm/lib/IR/Verifier.cpp -+++ b/llvm/lib/IR/Verifier.cpp -@@ -4269,6 +4269,10 @@ void Verifier::visitInstruction(Instruction &I) { - Assert( - !F->isIntrinsic() || isa(I) || - F->getIntrinsicID() == Intrinsic::donothing || -+ F->getIntrinsicID() == Intrinsic::seh_try_begin || -+ F->getIntrinsicID() == Intrinsic::seh_try_end || -+ F->getIntrinsicID() == Intrinsic::seh_scope_begin || -+ F->getIntrinsicID() == Intrinsic::seh_scope_end || - F->getIntrinsicID() == Intrinsic::coro_resume || - F->getIntrinsicID() == Intrinsic::coro_destroy || - F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void ||