diff options
Diffstat (limited to 'lib/CodeGen/CGCleanup.cpp')
-rw-r--r-- | lib/CodeGen/CGCleanup.cpp | 48 |
1 files changed, 33 insertions, 15 deletions
diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp index 22055b2cb902..cfd230997ed0 100644 --- a/lib/CodeGen/CGCleanup.cpp +++ b/lib/CodeGen/CGCleanup.cpp @@ -281,10 +281,10 @@ void EHScopeStack::popNullFixups() { BranchFixups.pop_back(); } -void CodeGenFunction::initFullExprCleanup() { +Address CodeGenFunction::createCleanupActiveFlag() { // Create a variable to decide whether the cleanup needs to be run. - Address active = CreateTempAlloca(Builder.getInt1Ty(), CharUnits::One(), - "cleanup.cond"); + Address active = CreateTempAllocaWithoutCast( + Builder.getInt1Ty(), CharUnits::One(), "cleanup.cond"); // Initialize it to false at a site that's guaranteed to be run // before each evaluation. @@ -293,10 +293,14 @@ void CodeGenFunction::initFullExprCleanup() { // Initialize it to true at the current location. Builder.CreateStore(Builder.getTrue(), active); + return active; +} + +void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) { // Set that as the active flag in the cleanup. EHCleanupScope &cleanup = cast<EHCleanupScope>(*EHStack.begin()); assert(!cleanup.hasActiveFlag() && "cleanup already has active flag?"); - cleanup.setActiveFlag(active); + cleanup.setActiveFlag(ActiveFlag); if (cleanup.isNormalCleanup()) cleanup.setTestFlagInNormalCleanup(); if (cleanup.isEHCleanup()) cleanup.setTestFlagInEHCleanup(); @@ -494,6 +498,13 @@ void CodeGenFunction::PopCleanupBlocks( &LifetimeExtendedCleanupStack[I], Header.getSize()); I += Header.getSize(); + + if (Header.isConditional()) { + Address ActiveFlag = + reinterpret_cast<Address &>(LifetimeExtendedCleanupStack[I]); + initFullExprCleanupWithFlag(ActiveFlag); + I += sizeof(ActiveFlag); + } } LifetimeExtendedCleanupStack.resize(OldLifetimeExtendedSize); } @@ -624,7 +635,7 @@ static void destroyOptimisticNormalEntry(CodeGenFunction &CGF, si->eraseFromParent(); // Destroy the load. - assert(condition->getOperand(0) == CGF.NormalCleanupDest); + assert(condition->getOperand(0) == CGF.NormalCleanupDest.getPointer()); assert(condition->use_empty()); condition->eraseFromParent(); } @@ -833,7 +844,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { if (NormalCleanupDestSlot->hasOneUse()) { NormalCleanupDestSlot->user_back()->eraseFromParent(); NormalCleanupDestSlot->eraseFromParent(); - NormalCleanupDest = nullptr; + NormalCleanupDest = Address::invalid(); } llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0); @@ -971,16 +982,21 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad( CurrentFuncletPad); llvm::CleanupPadInst *CPI = nullptr; - if (!EHPersonality::get(*this).usesFuncletPads()) { - EHStack.pushTerminate(); - PushedTerminate = true; - } else { + + const EHPersonality &Personality = EHPersonality::get(*this); + if (Personality.usesFuncletPads()) { llvm::Value *ParentPad = CurrentFuncletPad; if (!ParentPad) ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext()); CurrentFuncletPad = CPI = Builder.CreateCleanupPad(ParentPad); } + // Non-MSVC personalities need to terminate when an EH cleanup throws. + if (!Personality.isMSVCPersonality()) { + EHStack.pushTerminate(); + PushedTerminate = true; + } + // We only actually emit the cleanup code if the cleanup is either // active or was used before it was deactivated. if (EHActiveFlag.isValid() || IsActive) { @@ -1233,8 +1249,10 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C, EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C)); assert(Scope.isActive() && "double deactivation"); - // If it's the top of the stack, just pop it. - if (C == EHStack.stable_begin()) { + // If it's the top of the stack, just pop it, but do so only if it belongs + // 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(); @@ -1250,10 +1268,10 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C, } Address CodeGenFunction::getNormalCleanupDestSlot() { - if (!NormalCleanupDest) + if (!NormalCleanupDest.isValid()) NormalCleanupDest = - CreateTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot"); - return Address(NormalCleanupDest, CharUnits::fromQuantity(4)); + CreateDefaultAlignTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot"); + return NormalCleanupDest; } /// Emits all the code to cause the given temporary to be cleaned up. |