[cfe-commits] r135025 - in /cfe/trunk: lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/delete.cpp test/CodeGenObjCXX/arc-new-delete.mm
John McCall
rjmccall at apple.com
Tue Jul 12 18:41:37 PDT 2011
Author: rjmccall
Date: Tue Jul 12 20:41:37 2011
New Revision: 135025
URL: http://llvm.org/viewvc/llvm-project?rev=135025&view=rev
Log:
Switch delete[] IR-generation over to the destroy framework,
which implicitly makes it EH-safe as well.
Modified:
cfe/trunk/lib/CodeGen/CGExprCXX.cpp
cfe/trunk/test/CodeGenCXX/delete.cpp
cfe/trunk/test/CodeGenObjCXX/arc-new-delete.mm
Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=135025&r1=135024&r2=135025&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Tue Jul 12 20:41:37 2011
@@ -1351,90 +1351,50 @@
/// 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();
}
Modified: cfe/trunk/test/CodeGenCXX/delete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/delete.cpp?rev=135025&r1=135024&r2=135025&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/delete.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/delete.cpp Tue Jul 12 20:41:37 2011
@@ -67,31 +67,23 @@
// CHECK: define void @_ZN5test14testEPA10_A20_NS_1AE(
void test(A (*arr)[10][20]) {
delete [] arr;
- // CHECK: icmp eq [10 x [20 x [[S:%.*]]]]* [[PTR:%.*]], null
+ // CHECK: icmp eq [10 x [20 x [[A:%.*]]]]* [[PTR:%.*]], null
// CHECK-NEXT: br i1
- // CHECK: [[ARR:%.*]] = getelementptr inbounds [10 x [20 x [[S]]]]* [[PTR]], i32 0, i32 0, i32 0
- // CHECK-NEXT: bitcast {{.*}} to i8*
- // CHECK-NEXT: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8
- // CHECK-NEXT: bitcast i8* [[ALLOC]] to i64*
- // CHECK-NEXT: load
- // CHECK-NEXT: store i64 {{.*}}, i64* [[IDX:%.*]]
-
- // CHECK: load i64* [[IDX]]
- // CHECK-NEXT: icmp ne {{.*}}, 0
- // CHECK-NEXT: br i1
-
- // CHECK: load i64* [[IDX]]
- // CHECK-NEXT: [[I:%.*]] = sub i64 {{.*}}, 1
- // CHECK-NEXT: getelementptr inbounds [[S]]* [[ARR]], i64 [[I]]
- // CHECK-NEXT: call void @_ZN5test11AD1Ev(
+ // CHECK: [[BEGIN:%.*]] = getelementptr inbounds [10 x [20 x [[A]]]]* [[PTR]], i32 0, i32 0, i32 0
+ // CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[BEGIN]] to i8*
+ // CHECK-NEXT: [[ALLOC:%.*]] = getelementptr inbounds i8* [[T0]], i64 -8
+ // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[ALLOC]] to i64*
+ // CHECK-NEXT: [[COUNT:%.*]] = load i64* [[T1]]
+ // CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i64 [[COUNT]], 0
+ // CHECK-NEXT: br i1 [[ISZERO]],
+ // CHECK: [[END:%.*]] = getelementptr inbounds [[A]]* [[BEGIN]], i64 [[COUNT]]
// CHECK-NEXT: br label
-
- // CHECK: load i64* [[IDX]]
- // CHECK-NEXT: sub
- // CHECK-NEXT: store {{.*}}, i64* [[IDX]]
- // CHECK-NEXT: br label
-
+ // CHECK: [[PAST:%.*]] = phi [[A]]* [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
+ // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]]* [[PAST]], i64 -1
+ // CHECK-NEXT: call void @_ZN5test11AD1Ev([[A]]* [[CUR]])
+ // CHECK-NEXT: [[ISDONE:%.*]] = icmp eq [[A]]* [[CUR]], [[BEGIN]]
+ // CHECK-NEXT: br i1 [[ISDONE]]
// CHECK: call void @_ZdaPv(i8* [[ALLOC]])
}
}
Modified: cfe/trunk/test/CodeGenObjCXX/arc-new-delete.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc-new-delete.mm?rev=135025&r1=135024&r2=135025&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/arc-new-delete.mm (original)
+++ cfe/trunk/test/CodeGenObjCXX/arc-new-delete.mm Tue Jul 12 20:41:37 2011
@@ -70,17 +70,26 @@
// CHECK: define void @_Z17test_array_deletePU8__strongP11objc_objectPU6__weakS0_
void test_array_delete(__strong id *sptr, __weak id *wptr) {
- // CHECK: load i64*
- // CHECK: {{icmp ne i64.*, 0}}
- // CHECK: call void @objc_release
- // CHECK: br label
+ // CHECK: icmp eq i8** [[BEGIN:%.*]], null
+ // CHECK: [[LEN:%.*]] = load i64* {{%.*}}
+ // CHECK: icmp eq i64 [[LEN]], 0
+ // CHECK: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 [[LEN]]
+ // CHECK: [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]],
+ // CHECK-NEXT: [[CUR]] = getelementptr inbounds i8** [[PAST]], i64 -1
+ // CHECK-NEXT: [[T0:%.*]] = load i8** [[CUR]]
+ // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: icmp eq i8** [[CUR]], [[BEGIN]]
// CHECK: call void @_ZdaPv
delete [] sptr;
- // CHECK: load i64*
- // CHECK: {{icmp ne i64.*, 0}}
- // CHECK: call void @objc_destroyWeak
- // CHECK: br label
+ // CHECK: icmp eq i8** [[BEGIN:%.*]], null
+ // CHECK: [[LEN:%.*]] = load i64* {{%.*}}
+ // CHECK: icmp eq i64 [[LEN]], 0
+ // CHECK: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 [[LEN]]
+ // CHECK: [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]],
+ // CHECK-NEXT: [[CUR]] = getelementptr inbounds i8** [[PAST]], i64 -1
+ // CHECK-NEXT: call void @objc_destroyWeak(i8** [[CUR]])
+ // CHECK-NEXT: icmp eq i8** [[CUR]], [[BEGIN]]
// CHECK: call void @_ZdaPv
delete [] wptr;
}
More information about the cfe-commits
mailing list