diff options
Diffstat (limited to 'lib/CodeGen/CGTemporaries.cpp')
-rw-r--r-- | lib/CodeGen/CGTemporaries.cpp | 144 |
1 files changed, 41 insertions, 103 deletions
diff --git a/lib/CodeGen/CGTemporaries.cpp b/lib/CodeGen/CGTemporaries.cpp index a8f0467590..fd7c616b11 100644 --- a/lib/CodeGen/CGTemporaries.cpp +++ b/lib/CodeGen/CGTemporaries.cpp @@ -15,14 +15,38 @@ using namespace clang; using namespace CodeGen; -void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary, - llvm::Value *Ptr) { - assert((LiveTemporaries.empty() || - LiveTemporaries.back().ThisPtr != Ptr || - ConditionalBranchLevel) && - "Pushed the same temporary twice; AST is likely wrong"); - llvm::BasicBlock *DtorBlock = createBasicBlock("temp.dtor"); +static void EmitTemporaryCleanup(CodeGenFunction &CGF, + const CXXTemporary *Temporary, + llvm::Value *Addr, + llvm::Value *CondPtr) { + 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 (CondPtr) { + llvm::BasicBlock *CondBlock = CGF.createBasicBlock("temp.cond-dtor.call"); + CondEnd = CGF.createBasicBlock("temp.cond-dtor.cont"); + + llvm::Value *Cond = CGF.Builder.CreateLoad(CondPtr); + CGF.Builder.CreateCondBr(Cond, CondBlock, CondEnd); + CGF.EmitBlock(CondBlock); + } + + CGF.EmitCXXDestructorCall(Temporary->getDestructor(), + Dtor_Complete, /*ForVirtualBase=*/false, + Addr); + + if (CondPtr) { + // Reset the condition to false. + CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(CGF.getLLVMContext()), + CondPtr); + CGF.EmitBlock(CondEnd); + } +} +/// Emits all the code to cause the given temporary to be cleaned up. +void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary, + llvm::Value *Ptr) { llvm::AllocaInst *CondPtr = 0; // Check if temporaries need to be conditional. If so, we'll create a @@ -38,82 +62,13 @@ void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary, Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext), CondPtr); } - LiveTemporaries.push_back(CXXLiveTemporaryInfo(Temporary, Ptr, DtorBlock, - CondPtr)); - - PushCleanupBlock(DtorBlock); + CleanupBlock Cleanup(*this, NormalCleanup); + EmitTemporaryCleanup(*this, Temporary, Ptr, CondPtr); if (Exceptions) { - const CXXLiveTemporaryInfo& Info = LiveTemporaries.back(); - llvm::BasicBlock *CondEnd = 0; - - EHCleanupBlock Cleanup(*this); - - // 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, /*ForVirtualBase=*/false, - Info.ThisPtr); - - if (CondEnd) { - // Reset the condition. to false. - Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), Info.CondPtr); - EmitBlock(CondEnd); - } - } -} - -void CodeGenFunction::PopCXXTemporary() { - const CXXLiveTemporaryInfo& Info = LiveTemporaries.back(); - - CleanupBlockInfo CleanupInfo = PopCleanupBlock(); - assert(CleanupInfo.CleanupBlock == Info.DtorBlock && - "Cleanup block mismatch!"); - assert(!CleanupInfo.SwitchBlock && - "Should not have a switch block for temporary cleanup!"); - assert(!CleanupInfo.EndBlock && - "Should not have an end block for temporary cleanup!"); - - llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); - if (CurBB && !CurBB->getTerminator() && - Info.DtorBlock->getNumUses() == 0) { - CurBB->getInstList().splice(CurBB->end(), Info.DtorBlock->getInstList()); - delete Info.DtorBlock; - } else - 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, /*ForVirtualBase=*/false, Info.ThisPtr); - - if (CondEnd) { - // Reset the condition. to false. - Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), Info.CondPtr); - EmitBlock(CondEnd); + Cleanup.beginEHCleanup(); + EmitTemporaryCleanup(*this, Temporary, Ptr, CondPtr); } - - LiveTemporaries.pop_back(); } RValue @@ -121,40 +76,23 @@ CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E, llvm::Value *AggLoc, bool IsAggLocVolatile, bool IsInitializer) { - // Keep track of the current cleanup stack depth. - size_t CleanupStackDepth = CleanupEntries.size(); - (void) CleanupStackDepth; - RValue RV; - { - CXXTemporariesCleanupScope Scope(*this); + RunCleanupsScope Scope(*this); RV = EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile, /*IgnoreResult=*/false, IsInitializer); } - assert(CleanupEntries.size() == CleanupStackDepth && - "Cleanup size mismatch!"); - return RV; } LValue CodeGenFunction::EmitCXXExprWithTemporariesLValue( const CXXExprWithTemporaries *E) { - // Keep track of the current cleanup stack depth. - size_t CleanupStackDepth = CleanupEntries.size(); - (void) CleanupStackDepth; - - unsigned OldNumLiveTemporaries = LiveTemporaries.size(); - - LValue LV = EmitLValue(E->getSubExpr()); - - // Pop temporaries. - while (LiveTemporaries.size() > OldNumLiveTemporaries) - PopCXXTemporary(); - - assert(CleanupEntries.size() == CleanupStackDepth && - "Cleanup size mismatch!"); + LValue LV; + { + RunCleanupsScope Scope(*this); + LV = EmitLValue(E->getSubExpr()); + } return LV; } |