diff options
| author | Reid Kleckner <rnk@google.com> | 2018-01-02 21:34:16 +0000 |
|---|---|---|
| committer | Reid Kleckner <rnk@google.com> | 2018-01-02 21:34:16 +0000 |
| commit | 06f19a0de07d16325993285327a02ac727baab50 (patch) | |
| tree | d416c4a6c76ceca3868216afd72588432da11824 /clang/lib/CodeGen/CGException.cpp | |
| parent | e5e4afd6dbe25bea9988aa044805aff0261d8187 (diff) | |
| download | bcm5719-llvm-06f19a0de07d16325993285327a02ac727baab50.tar.gz bcm5719-llvm-06f19a0de07d16325993285327a02ac727baab50.zip | |
[WinEH] Allow for multiple terminatepads
Fixes verifier errors with Windows EH and OpenMP, which injects a
terminate scope around parallel blocks.
Fixes PR35778
llvm-svn: 321676
Diffstat (limited to 'clang/lib/CodeGen/CGException.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 1ec084ff3f5..1978d2757ac 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -646,7 +646,7 @@ CodeGenFunction::getMSVCDispatchBlock(EHScopeStack::stable_iterator SI) { return DispatchBlock; if (EHS.getKind() == EHScope::Terminate) - DispatchBlock = getTerminateHandler(); + DispatchBlock = getTerminateFunclet(); else DispatchBlock = createBasicBlock(); CGBuilderTy Builder(*this, DispatchBlock); @@ -1334,24 +1334,15 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() { if (TerminateHandler) return TerminateHandler; - CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); - // Set up the terminate handler. This block is inserted at the very // end of the function by FinishFunction. TerminateHandler = createBasicBlock("terminate.handler"); + CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); Builder.SetInsertPoint(TerminateHandler); + llvm::Value *Exn = nullptr; - SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad( - CurrentFuncletPad); - if (EHPersonality::get(*this).usesFuncletPads()) { - llvm::Value *ParentPad = CurrentFuncletPad; - if (!ParentPad) - ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext()); - CurrentFuncletPad = Builder.CreateCleanupPad(ParentPad); - } else { - if (getLangOpts().CPlusPlus) - Exn = getExceptionFromSlot(); - } + if (getLangOpts().CPlusPlus) + Exn = getExceptionFromSlot(); llvm::CallInst *terminateCall = CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn); terminateCall->setDoesNotReturn(); @@ -1363,6 +1354,42 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() { return TerminateHandler; } +llvm::BasicBlock *CodeGenFunction::getTerminateFunclet() { + assert(EHPersonality::get(*this).usesFuncletPads() && + "use getTerminateLandingPad for non-funclet EH"); + + llvm::BasicBlock *&TerminateFunclet = TerminateFunclets[CurrentFuncletPad]; + if (TerminateFunclet) + return TerminateFunclet; + + CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); + + // Set up the terminate handler. This block is inserted at the very + // end of the function by FinishFunction. + TerminateFunclet = createBasicBlock("terminate.handler"); + Builder.SetInsertPoint(TerminateFunclet); + + // Create the cleanuppad using the current parent pad as its token. Use 'none' + // if this is a top-level terminate scope, which is the common case. + SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad( + CurrentFuncletPad); + llvm::Value *ParentPad = CurrentFuncletPad; + if (!ParentPad) + ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext()); + CurrentFuncletPad = Builder.CreateCleanupPad(ParentPad); + + // Emit the __std_terminate call. + llvm::CallInst *terminateCall = + CGM.getCXXABI().emitTerminateForUnexpectedException(*this, nullptr); + terminateCall->setDoesNotReturn(); + Builder.CreateUnreachable(); + + // Restore the saved insertion state. + Builder.restoreIP(SavedIP); + + return TerminateFunclet; +} + llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) { if (EHResumeBlock) return EHResumeBlock; |

