diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 31 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCleanup.cpp | 37 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCleanup.h | 8 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 74 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 8 | ||||
-rw-r--r-- | clang/lib/CodeGen/EHScopeStack.h | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 4 |
7 files changed, 63 insertions, 103 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 80f88fb8d15..891f9071bdc 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -15,6 +15,7 @@ #include "CGCall.h" #include "ABIInfo.h" #include "CGCXXABI.h" +#include "CGCleanup.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "TargetInfo.h" @@ -3472,11 +3473,21 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(), AttributeList); - llvm::BasicBlock *InvokeDest = nullptr; - if (!Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex, - llvm::Attribute::NoUnwind) || - currentFunctionUsesSEHTry()) - InvokeDest = getInvokeDest(); + bool CannotThrow; + if (currentFunctionUsesSEHTry()) { + // SEH cares about asynchronous exceptions, everything can "throw." + CannotThrow = false; + } else if (isCleanupPadScope() && + EHPersonality::get(*this).isMSVCXXPersonality()) { + // The MSVC++ personality will implicitly terminate the program if an + // exception is thrown. An unwind edge cannot be reached. + CannotThrow = true; + } else { + // Otherwise, nowunind callsites will never throw. + CannotThrow = Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex, + llvm::Attribute::NoUnwind); + } + llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest(); llvm::CallSite CS; if (!InvokeDest) { @@ -3495,14 +3506,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex, llvm::Attribute::AlwaysInline); - // Disable inlining inside SEH __try blocks and cleanup funclets. None of the - // funclet EH personalities that clang supports have tables that are - // expressive enough to describe catching an exception inside a cleanup. - // __CxxFrameHandler3, for example, will terminate the program without - // catching it. - // FIXME: Move this decision to the LLVM inliner. Before we can do that, the - // inliner needs to know if a given call site is part of a cleanuppad. - if (isSEHTryScope() || isCleanupPadScope()) + // Disable inlining inside SEH __try blocks. + if (isSEHTryScope()) Attrs = Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex, llvm::Attribute::NoInline); diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index 5b6e497673c..245d6a7e4b0 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -246,13 +246,6 @@ void EHScopeStack::pushTerminate() { InnermostEHScope = stable_begin(); } -void EHScopeStack::pushPadEnd(llvm::BasicBlock *PadEndBB) { - char *Buffer = allocate(EHPadEndScope::getSize()); - auto *CES = new (Buffer) EHPadEndScope(InnermostEHScope); - CES->setCachedEHDispatchBlock(PadEndBB); - InnermostEHScope = stable_begin(); -} - /// Remove any 'null' fixups on the stack. However, we can't pop more /// fixups than the fixup depth on the innermost normal cleanup, or /// else fixups that we try to add to that cleanup will end up in the @@ -909,24 +902,17 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { // throwing cleanups. For funclet EH personalities, the cleanupendpad models // program termination when cleanups throw. bool PushedTerminate = false; - SaveAndRestore<bool> RestoreIsCleanupPadScope(IsCleanupPadScope); + SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad( + CurrentFuncletPad); llvm::CleanupPadInst *CPI = nullptr; - llvm::BasicBlock *CleanupEndBB = nullptr; if (!EHPersonality::get(*this).usesFuncletPads()) { EHStack.pushTerminate(); PushedTerminate = true; } else { - CPI = Builder.CreateCleanupPad({}); - - // Build a cleanupendpad to unwind through. Our insertion point should be - // in the cleanuppad block. - CleanupEndBB = createBasicBlock("ehcleanup.end"); - CGBuilderTy(*this, CleanupEndBB).CreateCleanupEndPad(CPI, NextAction); - EHStack.pushPadEnd(CleanupEndBB); - - // Mark that we're inside a cleanuppad to block inlining. - // FIXME: Remove this once the inliner knows when it's safe to do so. - IsCleanupPadScope = true; + llvm::Value *ParentPad = CurrentFuncletPad; + if (!ParentPad) + ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext()); + CurrentFuncletPad = CPI = Builder.CreateCleanupPad(ParentPad); } // We only actually emit the cleanup code if the cleanup is either @@ -941,17 +927,6 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { else Builder.CreateBr(NextAction); - // Insert the cleanupendpad block here, if it has any uses. - if (CleanupEndBB) { - EHStack.popPadEnd(); - if (CleanupEndBB->hasNUsesOrMore(1)) { - CurFn->getBasicBlockList().insertAfter( - Builder.GetInsertBlock()->getIterator(), CleanupEndBB); - } else { - delete CleanupEndBB; - } - } - // Leave the terminate scope. if (PushedTerminate) EHStack.popTerminate(); diff --git a/clang/lib/CodeGen/CGCleanup.h b/clang/lib/CodeGen/CGCleanup.h index 5a0145eb0b8..909f00b0592 100644 --- a/clang/lib/CodeGen/CGCleanup.h +++ b/clang/lib/CodeGen/CGCleanup.h @@ -587,14 +587,6 @@ inline void EHScopeStack::popTerminate() { deallocate(EHTerminateScope::getSize()); } -inline void EHScopeStack::popPadEnd() { - assert(!empty() && "popping exception stack when not empty"); - - EHPadEndScope &scope = cast<EHPadEndScope>(*begin()); - InnermostEHScope = scope.getEnclosingEHScope(); - deallocate(EHPadEndScope::getSize()); -} - inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const { assert(sp.isValid() && "finding invalid savepoint"); assert(sp.Size <= stable_begin().Size && "finding savepoint after pop"); diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index eaa76109be1..b5e1dcdc6c9 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -871,58 +871,50 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { return lpad; } -static llvm::BasicBlock *emitCatchPadBlock(CodeGenFunction &CGF, - EHCatchScope &CatchScope) { +static void emitCatchPadBlock(CodeGenFunction &CGF, EHCatchScope &CatchScope) { llvm::BasicBlock *DispatchBlock = CatchScope.getCachedEHDispatchBlock(); assert(DispatchBlock); CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveIP(); CGF.EmitBlockAfterUses(DispatchBlock); - // Figure out the next block. - llvm::BasicBlock *NextBlock = nullptr; + llvm::Value *ParentPad = CGF.CurrentFuncletPad; + if (!ParentPad) + ParentPad = llvm::ConstantTokenNone::get(CGF.getLLVMContext()); + llvm::BasicBlock *UnwindBB = + CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope()); + + unsigned NumHandlers = CatchScope.getNumHandlers(); + llvm::CatchSwitchInst *CatchSwitch = + CGF.Builder.CreateCatchSwitch(ParentPad, UnwindBB, NumHandlers); // Test against each of the exception types we claim to catch. - for (unsigned I = 0, E = CatchScope.getNumHandlers(); I < E; ++I) { + for (unsigned I = 0; I < NumHandlers; ++I) { const EHCatchScope::Handler &Handler = CatchScope.getHandler(I); CatchTypeInfo TypeInfo = Handler.Type; if (!TypeInfo.RTTI) TypeInfo.RTTI = llvm::Constant::getNullValue(CGF.VoidPtrTy); - // If this is the last handler, we're at the end, and the next - // block is the block for the enclosing EH scope. - if (I + 1 == E) { - NextBlock = CGF.createBasicBlock("catchendblock"); - CGBuilderTy(CGF, NextBlock).CreateCatchEndPad( - CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope())); - } else { - NextBlock = CGF.createBasicBlock("catch.dispatch"); - } + CGF.Builder.SetInsertPoint(Handler.Block); if (EHPersonality::get(CGF).isMSVCXXPersonality()) { - CGF.Builder.CreateCatchPad(Handler.Block, NextBlock, - {TypeInfo.RTTI, - CGF.Builder.getInt32(TypeInfo.Flags), - llvm::Constant::getNullValue(CGF.VoidPtrTy)}); + CGF.Builder.CreateCatchPad( + CatchSwitch, {TypeInfo.RTTI, CGF.Builder.getInt32(TypeInfo.Flags), + llvm::Constant::getNullValue(CGF.VoidPtrTy)}); } else { - CGF.Builder.CreateCatchPad(Handler.Block, NextBlock, {TypeInfo.RTTI}); + CGF.Builder.CreateCatchPad(CatchSwitch, {TypeInfo.RTTI}); } - // Otherwise we need to emit and continue at that block. - CGF.EmitBlock(NextBlock); + CatchSwitch->addHandler(Handler.Block); } CGF.Builder.restoreIP(SavedIP); - - return NextBlock; } /// Emit the structure of the dispatch block for the given catch scope. /// It is an invariant that the dispatch block already exists. -/// If the catchblock instructions are used for EH dispatch, then the basic -/// block holding the final catchendblock instruction is returned. -static llvm::BasicBlock *emitCatchDispatchBlock(CodeGenFunction &CGF, - EHCatchScope &catchScope) { +static void emitCatchDispatchBlock(CodeGenFunction &CGF, + EHCatchScope &catchScope) { if (EHPersonality::get(CGF).usesFuncletPads()) return emitCatchPadBlock(CGF, catchScope); @@ -934,7 +926,7 @@ static llvm::BasicBlock *emitCatchDispatchBlock(CodeGenFunction &CGF, if (catchScope.getNumHandlers() == 1 && catchScope.getHandler(0).isCatchAll()) { assert(dispatchBlock == catchScope.getHandler(0).Block); - return nullptr; + return; } CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveIP(); @@ -992,12 +984,11 @@ static llvm::BasicBlock *emitCatchDispatchBlock(CodeGenFunction &CGF, // If the next handler is a catch-all, we're completely done. if (nextIsEnd) { CGF.Builder.restoreIP(savedIP); - return nullptr; + return; } // Otherwise we need to emit and continue at that block. CGF.EmitBlock(nextBlock); } - return nullptr; } void CodeGenFunction::popCatchScope() { @@ -1020,7 +1011,7 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { } // Emit the structure of the EH dispatch for this catch. - llvm::BasicBlock *CatchEndBlockBB = emitCatchDispatchBlock(*this, CatchScope); + emitCatchDispatchBlock(*this, CatchScope); // Copy the handler blocks off before we pop the EH stack. Emitting // the handlers might scribble on this memory. @@ -1043,9 +1034,6 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { doImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) || isa<CXXConstructorDecl>(CurCodeDecl); - if (CatchEndBlockBB) - EHStack.pushPadEnd(CatchEndBlockBB); - // Perversely, we emit the handlers backwards precisely because we // want them to appear in source order. In all of these cases, the // catch block will have exactly one predecessor, which will be a @@ -1065,6 +1053,8 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { RunCleanupsScope CatchScope(*this); // Initialize the catch variable and set up the cleanups. + SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad( + CurrentFuncletPad); CGM.getCXXABI().emitBeginCatch(*this, C); // Emit the PGO counter increment. @@ -1098,8 +1088,6 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { EmitBlock(ContBB); incrementProfileCounter(&S); - if (CatchEndBlockBB) - EHStack.popPadEnd(); } namespace { @@ -1338,7 +1326,11 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() { TerminateHandler = createBasicBlock("terminate.handler"); Builder.SetInsertPoint(TerminateHandler); if (EHPersonality::get(*this).usesFuncletPads()) { - Builder.CreateTerminatePad(/*UnwindBB=*/nullptr, CGM.getTerminateFn()); + llvm::Value *ParentPad = CurrentFuncletPad; + if (!ParentPad) + ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext()); + Builder.CreateTerminatePad(ParentPad, /*UnwindBB=*/nullptr, + {CGM.getTerminateFn()}); } else { llvm::Value *Exn = nullptr; if (getLangOpts().CPlusPlus) @@ -1857,18 +1849,16 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) { emitCatchDispatchBlock(*this, CatchScope); // Grab the block before we pop the handler. - llvm::BasicBlock *ExceptBB = CatchScope.getHandler(0).Block; + llvm::BasicBlock *CatchPadBB = CatchScope.getHandler(0).Block; EHStack.popCatch(); - EmitBlockAfterUses(ExceptBB); + EmitBlockAfterUses(CatchPadBB); // __except blocks don't get outlined into funclets, so immediately do a // catchret. - llvm::BasicBlock *CatchPadBB = ExceptBB->getSinglePredecessor(); - assert(CatchPadBB && "only ExceptBB pred should be catchpad"); llvm::CatchPadInst *CPI = cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI()); - ExceptBB = createBasicBlock("__except"); + llvm::BasicBlock *ExceptBB = createBasicBlock("__except"); Builder.CreateCatchRet(CPI, ExceptBB); EmitBlock(ExceptBB); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 714a641ba39..0302b0e6edd 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -279,8 +279,6 @@ public: /// finally block or filter expression. bool IsOutlinedSEHHelper; - bool IsCleanupPadScope = false; - const CodeGen::CGBlockInfo *BlockInfo; llvm::Value *BlockPointer; @@ -295,6 +293,8 @@ public: llvm::SmallVector<char, 256> LifetimeExtendedCleanupStack; llvm::SmallVector<const JumpDest *, 2> SEHTryEpilogueStack; + llvm::Instruction *CurrentFuncletPad = nullptr; + /// Header for data within LifetimeExtendedCleanupStack. struct LifetimeExtendedCleanupHeader { /// The size of the following cleanup object. @@ -375,7 +375,9 @@ public: bool isSEHTryScope() const { return !SEHTryEpilogueStack.empty(); } /// Returns true while emitting a cleanuppad. - bool isCleanupPadScope() const { return IsCleanupPadScope; } + bool isCleanupPadScope() const { + return CurrentFuncletPad && isa<llvm::CleanupPadInst>(CurrentFuncletPad); + } /// pushFullExprCleanup - Push a cleanup to be run at the end of the /// current full-expression. Safe against the possibility that diff --git a/clang/lib/CodeGen/EHScopeStack.h b/clang/lib/CodeGen/EHScopeStack.h index 9840afe6bc5..85cd1543e5b 100644 --- a/clang/lib/CodeGen/EHScopeStack.h +++ b/clang/lib/CodeGen/EHScopeStack.h @@ -334,10 +334,6 @@ public: /// Pops a terminate handler off the stack. void popTerminate(); - void pushPadEnd(llvm::BasicBlock *PadEndBB); - - void popPadEnd(); - // Returns true iff the current scope is either empty or contains only // lifetime markers, i.e. no real cleanup code bool containsOnlyLifetimeMarkers(stable_iterator Old) const; diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 711b08e6a29..f22c5b8b60d 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -893,10 +893,10 @@ void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF, // In the MS ABI, the runtime handles the copy, and the catch handler is // responsible for destruction. VarDecl *CatchParam = S->getExceptionDecl(); - llvm::BasicBlock *CatchPadBB = - CGF.Builder.GetInsertBlock()->getSinglePredecessor(); + llvm::BasicBlock *CatchPadBB = CGF.Builder.GetInsertBlock(); llvm::CatchPadInst *CPI = cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI()); + CGF.CurrentFuncletPad = CPI; // If this is a catch-all or the catch parameter is unnamed, we don't need to // emit an alloca to the object. |