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 | |
| 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')
| -rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 55 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 8 |
3 files changed, 52 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; diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 9dbd7cc3fcb..664b5107842 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -419,6 +419,9 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { EmitIfUsed(*this, TerminateHandler); EmitIfUsed(*this, UnreachableBlock); + for (const auto &FuncletAndParent : TerminateFunclets) + EmitIfUsed(*this, FuncletAndParent.second); + if (CGM.getCodeGenOpts().EmitDeclMetadata) EmitDeclMetadata(); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index a7c322d3b95..3e89586be3a 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -34,6 +34,7 @@ #include "clang/Frontend/CodeGenOptions.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Debug.h" @@ -1420,6 +1421,9 @@ private: llvm::BasicBlock *TerminateHandler; llvm::BasicBlock *TrapBB; + /// Terminate funclets keyed by parent funclet pad. + llvm::MapVector<llvm::Value *, llvm::BasicBlock *> TerminateFunclets; + /// True if we need emit the life-time markers. const bool ShouldEmitLifetimeMarkers; @@ -1808,6 +1812,10 @@ public: /// getTerminateLandingPad - Return a landing pad that just calls terminate. llvm::BasicBlock *getTerminateLandingPad(); + /// getTerminateLandingPad - Return a cleanup funclet that just calls + /// terminate. + llvm::BasicBlock *getTerminateFunclet(); + /// getTerminateHandler - Return a handler (not a landing pad, just /// a catch handler) that just calls terminate. This is used when /// a terminate scope encloses a try. |

