aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGCleanup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGCleanup.cpp')
-rw-r--r--lib/CodeGen/CGCleanup.cpp48
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.