[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