diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-08-20 23:02:58 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-08-20 23:02:58 +0000 |
commit | 1c536bf6bbb0cdc039cff754825b36f9abfe0629 (patch) | |
tree | f4adc662ec282cfe7e928ce7d5a8f291b8819921 /lib/CodeGen/CGCXX.cpp | |
parent | 37b372b76a3fafe77186d7e6079e5642e2017478 (diff) |
Patch to ir-gen destruction of array member elements in revers order
of their construction.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79571 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGCXX.cpp')
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 72aa9fc090..8b1f2fc1fe 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -412,10 +412,70 @@ CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, EmitBlock(AfterFor, true); } +/// EmitCXXAggrDestructorCall - calls the default destructor on array +/// elements in reverse order of construction. void CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D, const ArrayType *Array, llvm::Value *This) { + const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); + assert(CA && "Do we support VLA for destruction ?"); + llvm::Value *One = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + 1); + uint64_t ElementCount = 1; + const ConstantArrayType *CAW = CA; + do { + ElementCount *= CAW->getSize().getZExtValue(); + CAW = dyn_cast<ConstantArrayType>(CAW->getElementType()); + } while (CAW); + // Create a temporary for the loop index and initialize it with count of + // array elements. + llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), + "loop.index"); + // Index = ElementCount; + llvm::Value* UpperCount = + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), ElementCount); + Builder.CreateStore(UpperCount, IndexPtr, false); + + // Start the loop with a block that tests the condition. + llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); + llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); + + EmitBlock(CondBlock); + + llvm::BasicBlock *ForBody = createBasicBlock("for.body"); + + // Generate: if (loop-index != 0 fall to the loop body, + // otherwise, go to the block after the for-loop. + llvm::Value* zeroConstant = + llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); + llvm::Value *Counter = Builder.CreateLoad(IndexPtr); + llvm::Value *IsNE = Builder.CreateICmpNE(Counter, zeroConstant, + "isne"); + // If the condition is true, execute the body. + Builder.CreateCondBr(IsNE, ForBody, AfterFor); + + EmitBlock(ForBody); + + llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); + // Inside the loop body, emit the constructor call on the array element. + Counter = Builder.CreateLoad(IndexPtr); + Counter = Builder.CreateSub(Counter, One); + llvm::Value *Address = Builder.CreateInBoundsGEP(This, Counter, "arrayidx"); + EmitCXXDestructorCall(D, Dtor_Complete, Address); + + EmitBlock(ContinueBlock); + + // Emit the decrement of the loop counter. + Counter = Builder.CreateLoad(IndexPtr); + Counter = Builder.CreateSub(Counter, One, "dec"); + Builder.CreateStore(Counter, IndexPtr, false); + + // Finally, branch back up to the condition for the next iteration. + EmitBranch(CondBlock); + + // Emit the fall-through block. + EmitBlock(AfterFor, true); } void |