diff options
author | John McCall <rjmccall@apple.com> | 2011-07-13 01:41:37 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-07-13 01:41:37 +0000 |
commit | 7cfd76cb5cec2aa7aaa4176339c806de6ec85a79 (patch) | |
tree | 6b1bed5477a9a7e745daa3ce3b6ff0e1b7e391ee /lib/CodeGen/CGExprCXX.cpp | |
parent | a8b20f70d562cdc2679f82d409832b79fc415277 (diff) |
Switch delete[] IR-generation over to the destroy framework,
which implicitly makes it EH-safe as well.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135025 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprCXX.cpp')
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 116 |
1 files changed, 38 insertions, 78 deletions
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 6b1b88924a..07997e4391 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -1351,90 +1351,50 @@ namespace { /// Emit the code for deleting an array of objects. static void EmitArrayDelete(CodeGenFunction &CGF, const CXXDeleteExpr *E, - llvm::Value *Ptr, - QualType ElementType) { - llvm::Value *NumElements = 0; - llvm::Value *AllocatedPtr = 0; - CharUnits CookieSize; - CGF.CGM.getCXXABI().ReadArrayCookie(CGF, Ptr, E, ElementType, - NumElements, AllocatedPtr, CookieSize); + llvm::Value *deletedPtr, + QualType elementType) { + llvm::Value *numElements = 0; + llvm::Value *allocatedPtr = 0; + CharUnits cookieSize; + CGF.CGM.getCXXABI().ReadArrayCookie(CGF, deletedPtr, E, elementType, + numElements, allocatedPtr, cookieSize); - assert(AllocatedPtr && "ReadArrayCookie didn't set AllocatedPtr"); + assert(allocatedPtr && "ReadArrayCookie didn't set allocated pointer"); // Make sure that we call delete even if one of the dtors throws. - const FunctionDecl *OperatorDelete = E->getOperatorDelete(); + const FunctionDecl *operatorDelete = E->getOperatorDelete(); CGF.EHStack.pushCleanup<CallArrayDelete>(NormalAndEHCleanup, - AllocatedPtr, OperatorDelete, - NumElements, ElementType, - CookieSize); - - if (const CXXRecordDecl *RD = ElementType->getAsCXXRecordDecl()) { - if (!RD->hasTrivialDestructor()) { - assert(NumElements && "ReadArrayCookie didn't find element count" - " for a class with destructor"); - CGF.EmitCXXAggrDestructorCall(RD->getDestructor(), NumElements, Ptr); - } - } else if (CGF.getLangOptions().ObjCAutoRefCount && - ElementType->isObjCLifetimeType() && - (ElementType.getObjCLifetime() == Qualifiers::OCL_Strong || - ElementType.getObjCLifetime() == Qualifiers::OCL_Weak)) { - bool IsStrong = ElementType.getObjCLifetime() == Qualifiers::OCL_Strong; - const llvm::Type *SizeLTy = CGF.ConvertType(CGF.getContext().getSizeType()); - llvm::Value *One = llvm::ConstantInt::get(SizeLTy, 1); - - // Create a temporary for the loop index and initialize it with count of - // array elements. - llvm::Value *IndexPtr = CGF.CreateTempAlloca(SizeLTy, "loop.index"); - - // Store the number of elements in the index pointer. - CGF.Builder.CreateStore(NumElements, IndexPtr); - - // Start the loop with a block that tests the condition. - llvm::BasicBlock *CondBlock = CGF.createBasicBlock("for.cond"); - llvm::BasicBlock *AfterFor = CGF.createBasicBlock("for.end"); - - CGF.EmitBlock(CondBlock); - - llvm::BasicBlock *ForBody = CGF.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(SizeLTy); - llvm::Value *Counter = CGF.Builder.CreateLoad(IndexPtr); - llvm::Value *IsNE = CGF.Builder.CreateICmpNE(Counter, zeroConstant, - "isne"); - // If the condition is true, execute the body. - CGF.Builder.CreateCondBr(IsNE, ForBody, AfterFor); - - CGF.EmitBlock(ForBody); - - llvm::BasicBlock *ContinueBlock = CGF.createBasicBlock("for.inc"); - // Inside the loop body, emit the constructor call on the array element. - Counter = CGF.Builder.CreateLoad(IndexPtr); - Counter = CGF.Builder.CreateSub(Counter, One); - llvm::Value *Address = CGF.Builder.CreateInBoundsGEP(Ptr, Counter, - "arrayidx"); - if (IsStrong) - CGF.EmitARCRelease(CGF.Builder.CreateLoad(Address, - ElementType.isVolatileQualified()), - /*precise*/ true); - else - CGF.EmitARCDestroyWeak(Address); - - CGF.EmitBlock(ContinueBlock); - - // Emit the decrement of the loop counter. - Counter = CGF.Builder.CreateLoad(IndexPtr); - Counter = CGF.Builder.CreateSub(Counter, One, "dec"); - CGF.Builder.CreateStore(Counter, IndexPtr); - - // Finally, branch back up to the condition for the next iteration. - CGF.EmitBranch(CondBlock); - - // Emit the fall-through block. - CGF.EmitBlock(AfterFor, true); + allocatedPtr, operatorDelete, + numElements, elementType, + cookieSize); + + // Destroy the elements. + if (QualType::DestructionKind dtorKind = elementType.isDestructedType()) { + assert(numElements && "no element count for a type with a destructor!"); + + // It's legal to allocate a zero-length array, but emitArrayDestroy + // won't handle that correctly, so we need to check that here. + llvm::Value *iszero = + CGF.Builder.CreateIsNull(numElements, "delete.isempty"); + + // We'll patch the 'true' successor of this to lead to the end of + // the emitArrayDestroy loop. + llvm::BasicBlock *destroyBB = CGF.createBasicBlock("delete.destroy"); + llvm::BranchInst *br = + CGF.Builder.CreateCondBr(iszero, destroyBB, destroyBB); + CGF.EmitBlock(destroyBB); + + llvm::Value *arrayEnd = + CGF.Builder.CreateInBoundsGEP(deletedPtr, numElements, "delete.end"); + CGF.emitArrayDestroy(deletedPtr, arrayEnd, elementType, + CGF.getDestroyer(dtorKind), + CGF.needsEHCleanup(dtorKind)); + + assert(CGF.Builder.GetInsertBlock()->empty()); + br->setSuccessor(0, CGF.Builder.GetInsertBlock()); } + // Pop the cleanup block. CGF.PopCleanupBlock(); } |