diff options
author | Anders Carlsson <andersca@mac.com> | 2009-06-04 02:47:33 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-06-04 02:47:33 +0000 |
commit | 8c0b203879f5e2064731700980c41199c692ca2c (patch) | |
tree | 52911977777ba0e13c6f847996cb7fe7f74df888 /lib/CodeGen/CGCXXTemp.cpp | |
parent | 1d8475067d5b62ed5a57ba93862e23f3096a8bdd (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.cpp | 70 |
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(); + } } |