aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGCXXTemp.cpp
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2009-06-04 02:47:33 +0000
committerAnders Carlsson <andersca@mac.com>2009-06-04 02:47:33 +0000
commit8c0b203879f5e2064731700980c41199c692ca2c (patch)
tree52911977777ba0e13c6f847996cb7fe7f74df888 /lib/CodeGen/CGCXXTemp.cpp
parent1d8475067d5b62ed5a57ba93862e23f3096a8bdd (diff)
Make PushCXXTemporary and PopCXXTemporary handle conditional temporaries.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72837 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGCXXTemp.cpp')
-rw-r--r--lib/CodeGen/CGCXXTemp.cpp70
1 files changed, 57 insertions, 13 deletions
diff --git a/lib/CodeGen/CGCXXTemp.cpp b/lib/CodeGen/CGCXXTemp.cpp
index b7bc6b7033..4b7349e41c 100644
--- a/lib/CodeGen/CGCXXTemp.cpp
+++ b/lib/CodeGen/CGCXXTemp.cpp
@@ -18,8 +18,27 @@ using namespace CodeGen;
void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary,
llvm::Value *Ptr) {
llvm::BasicBlock *DtorBlock = createBasicBlock("temp.dtor");
-
- LiveTemporaries.push_back(CXXLiveTemporaryInfo(Temporary, Ptr, DtorBlock, 0));
+
+ llvm::Value *CondPtr = 0;
+
+ // Check if temporaries need to be conditional. If so, we'll create a
+ // condition boolean, initialize it to 0 and
+ if (!ConditionalTempDestructionStack.empty()) {
+ CondPtr = CreateTempAlloca(llvm::Type::Int1Ty, "cond");
+
+ // Initialize it to false. This initialization takes place right after
+ // the alloca insert point.
+ llvm::StoreInst *SI =
+ new llvm::StoreInst(llvm::ConstantInt::getFalse(), CondPtr);
+ llvm::BasicBlock *Block = AllocaInsertPt->getParent();
+ Block->getInstList().insertAfter((llvm::Instruction *)AllocaInsertPt, SI);
+
+ // Now set it to true.
+ Builder.CreateStore(llvm::ConstantInt::getTrue(), CondPtr);
+ }
+
+ LiveTemporaries.push_back(CXXLiveTemporaryInfo(Temporary, Ptr, DtorBlock,
+ CondPtr));
PushCleanupBlock(DtorBlock);
}
@@ -37,9 +56,28 @@ void CodeGenFunction::PopCXXTemporary() {
EmitBlock(Info.DtorBlock);
+ llvm::BasicBlock *CondEnd = 0;
+
+ // If this is a conditional temporary, we need to check the condition
+ // boolean and only call the destructor if it's true.
+ if (Info.CondPtr) {
+ llvm::BasicBlock *CondBlock = createBasicBlock("cond.dtor.call");
+ CondEnd = createBasicBlock("cond.dtor.end");
+
+ llvm::Value *Cond = Builder.CreateLoad(Info.CondPtr);
+ Builder.CreateCondBr(Cond, CondBlock, CondEnd);
+ EmitBlock(CondBlock);
+ }
+
EmitCXXDestructorCall(Info.Temporary->getDestructor(),
Dtor_Complete, Info.ThisPtr);
+ if (CondEnd) {
+ // Reset the condition. to false.
+ Builder.CreateStore(llvm::ConstantInt::getFalse(), Info.CondPtr);
+ EmitBlock(CondEnd);
+ }
+
LiveTemporaries.pop_back();
}
@@ -54,17 +92,13 @@ CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
RValue RV = EmitAnyExpr(E->getSubExpr(), AggLoc, isAggLocVolatile);
- // Go through the temporaries backwards.
- for (unsigned i = E->getNumTemporaries(); i != 0; --i) {
- assert(LiveTemporaries.back().Temporary == E->getTemporary(i - 1));
- LiveTemporaries.pop_back();
- }
-
- assert(OldNumLiveTemporaries == LiveTemporaries.size() &&
- "Live temporary stack mismatch!");
+ // Pop temporaries.
+ while (LiveTemporaries.size() > OldNumLiveTemporaries)
+ PopCXXTemporary();
+
+ assert(CleanupEntries.size() == CleanupStackDepth &&
+ "Cleanup size mismatch!");
- EmitCleanupBlocks(CleanupStackDepth);
-
return RV;
}
@@ -75,6 +109,16 @@ CodeGenFunction::PushConditionalTempDestruction() {
}
void CodeGenFunction::PopConditionalTempDestruction() {
- ConditionalTempDestructionStack.pop_back();
+ size_t NumLiveTemporaries = ConditionalTempDestructionStack.back();
+ ConditionalTempDestructionStack.pop_back();
+
+ // Pop temporaries.
+ while (LiveTemporaries.size() > NumLiveTemporaries) {
+ const CXXLiveTemporaryInfo& TempInfo = LiveTemporaries.back();
+
+ assert(TempInfo.CondPtr && "Conditional temporary must have a cond ptr!");
+
+ PopCXXTemporary();
+ }
}