[cfe-commits] r134988 - in /cfe/trunk: lib/CodeGen/CGBlocks.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CGDecl.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CGObjC.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenObjC/arc.m test/CodeGenObjCXX/arc-special-member-functions.mm

John McCall rjmccall at apple.com
Tue Jul 12 09:41:09 PDT 2011


Author: rjmccall
Date: Tue Jul 12 11:41:08 2011
New Revision: 134988

URL: http://llvm.org/viewvc/llvm-project?rev=134988&view=rev
Log:
Switch field destruction over to use the new destroyer-based API
and kill a lot of redundant code.


Modified:
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGClass.cpp
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/test/CodeGenObjC/arc.m
    cfe/trunk/test/CodeGenObjCXX/arc-special-member-functions.mm

Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=134988&r1=134987&r2=134988&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Tue Jul 12 11:41:08 2011
@@ -627,18 +627,21 @@
     // Push a destructor if necessary.  The semantics for when this
     // actually gets run are really obscure.
     if (!ci->isByRef()) {
-      switch (type.isDestructedType()) {
+      switch (QualType::DestructionKind dtorKind = type.isDestructedType()) {
       case QualType::DK_none:
         break;
-      case QualType::DK_cxx_destructor:
-        PushDestructorCleanup(type, blockField);
-        break;
+
+      // Block captures count as local values and have imprecise semantics.
+      // They also can't be arrays, so need to worry about that.
       case QualType::DK_objc_strong_lifetime:
-        PushARCReleaseCleanup(getARCCleanupKind(), type, blockField, false);
+        pushDestroy(getCleanupKind(dtorKind), blockField, type,
+                    destroyARCStrongImprecise,
+                    /*useEHCleanupForArray*/ false);
         break;
+
       case QualType::DK_objc_weak_lifetime:
-        // __weak objects on the stack always get EH cleanups.
-        PushARCWeakReleaseCleanup(NormalAndEHCleanup, type, blockField);
+      case QualType::DK_cxx_destructor:
+        pushDestroy(dtorKind, blockField, type);
         break;
       }
     }

Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=134988&r1=134987&r2=134988&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Tue Jul 12 11:41:08 2011
@@ -929,47 +929,25 @@
     }
   };
 
-  struct CallArrayFieldDtor : EHScopeStack::Cleanup {
-    const FieldDecl *Field;
-    CallArrayFieldDtor(const FieldDecl *Field) : Field(Field) {}
-
-    void Emit(CodeGenFunction &CGF, bool IsForEH) {
-      QualType FieldType = Field->getType();      
-      QualType BaseType = CGF.getContext().getBaseElementType(FieldType);
-      const CXXRecordDecl *FieldClassDecl = BaseType->getAsCXXRecordDecl();
-
-      llvm::Value *ThisPtr = CGF.LoadCXXThis();
-      LValue LHS = CGF.EmitLValueForField(ThisPtr, Field, 
-                                          // FIXME: Qualifiers?
-                                          /*CVRQualifiers=*/0);
-
-      const llvm::Type *BasePtr 
-        = CGF.ConvertType(BaseType)->getPointerTo();
-      llvm::Value *BaseAddrPtr
-        = CGF.Builder.CreateBitCast(LHS.getAddress(), BasePtr);
-      const ConstantArrayType *Array
-        = CGF.getContext().getAsConstantArrayType(FieldType);
-      CGF.EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(),
-                                    Array, BaseAddrPtr);
-    }
-  };
-
-  struct CallFieldDtor : EHScopeStack::Cleanup {
-    const FieldDecl *Field;
-    CallFieldDtor(const FieldDecl *Field) : Field(Field) {}
-
-    void Emit(CodeGenFunction &CGF, bool IsForEH) {
-      const CXXRecordDecl *FieldClassDecl =
-        Field->getType()->getAsCXXRecordDecl();
-
-      llvm::Value *ThisPtr = CGF.LoadCXXThis();
-      LValue LHS = CGF.EmitLValueForField(ThisPtr, Field, 
-                                          // FIXME: Qualifiers?
-                                          /*CVRQualifiers=*/0);
-
-      CGF.EmitCXXDestructorCall(FieldClassDecl->getDestructor(),
-                                Dtor_Complete, /*ForVirtualBase=*/false,
-                                LHS.getAddress());
+  class DestroyField  : public EHScopeStack::Cleanup {
+    const FieldDecl *field;
+    CodeGenFunction::Destroyer &destroyer;
+    bool useEHCleanupForArray;
+
+  public:
+    DestroyField(const FieldDecl *field, CodeGenFunction::Destroyer *destroyer,
+                 bool useEHCleanupForArray)
+      : field(field), destroyer(*destroyer),
+        useEHCleanupForArray(useEHCleanupForArray) {}
+
+    void Emit(CodeGenFunction &CGF, bool isForEH) {
+      // Find the address of the field.
+      llvm::Value *thisValue = CGF.LoadCXXThis();
+      LValue LV = CGF.EmitLValueForField(thisValue, field, /*CVRQualifiers=*/0);
+      assert(LV.isSimple());
+      
+      CGF.emitDestroy(LV.getAddress(), field->getType(), destroyer,
+                      !isForEH && useEHCleanupForArray);
     }
   };
 }
@@ -1043,33 +1021,15 @@
   llvm::SmallVector<const FieldDecl *, 16> FieldDecls;
   for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
        E = ClassDecl->field_end(); I != E; ++I) {
-    const FieldDecl *Field = *I;
-    
-    QualType FieldType = getContext().getCanonicalType(Field->getType());
-    const ConstantArrayType *Array = 
-      getContext().getAsConstantArrayType(FieldType);
-    if (Array)
-      FieldType = getContext().getBaseElementType(Array->getElementType());
-
-    switch (FieldType.isDestructedType()) {
-    case QualType::DK_none:
-      continue;
-        
-    case QualType::DK_cxx_destructor:
-      if (Array)
-        EHStack.pushCleanup<CallArrayFieldDtor>(NormalAndEHCleanup, Field);
-      else
-        EHStack.pushCleanup<CallFieldDtor>(NormalAndEHCleanup, Field);
-      break;
-        
-    case QualType::DK_objc_strong_lifetime:
-      PushARCFieldReleaseCleanup(getARCCleanupKind(), Field);
-      break;
-
-    case QualType::DK_objc_weak_lifetime:
-      PushARCFieldWeakReleaseCleanup(getARCCleanupKind(), Field);
-      break;
-    }
+    const FieldDecl *field = *I;
+    QualType type = field->getType();
+    QualType::DestructionKind dtorKind = type.isDestructedType();
+    if (!dtorKind) continue;
+
+    CleanupKind cleanupKind = getCleanupKind(dtorKind);
+    EHStack.pushCleanup<DestroyField>(cleanupKind, field,
+                                      getDestroyer(dtorKind),
+                                      cleanupKind & EHCleanup);
   }
 }
 

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=134988&r1=134987&r2=134988&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Tue Jul 12 11:41:08 2011
@@ -427,9 +427,14 @@
     break;
 
   case Qualifiers::OCL_Strong: {
-    CGF.PushARCReleaseCleanup(CGF.getARCCleanupKind(),
-                              var.getType(), addr,
-                              var.hasAttr<ObjCPreciseLifetimeAttr>());
+    CodeGenFunction::Destroyer &destroyer =
+      (var.hasAttr<ObjCPreciseLifetimeAttr>()
+       ? CodeGenFunction::destroyARCStrongPrecise
+       : CodeGenFunction::destroyARCStrongImprecise);
+
+    CleanupKind cleanupKind = CGF.getARCCleanupKind();
+    CGF.pushDestroy(cleanupKind, addr, var.getType(), destroyer,
+                    cleanupKind & EHCleanup);
     break;
   }
   case Qualifiers::OCL_Autoreleasing:
@@ -439,7 +444,9 @@
   case Qualifiers::OCL_Weak:
     // __weak objects always get EH cleanups; otherwise, exceptions
     // could cause really nasty crashes instead of mere leaks.
-    CGF.PushARCWeakReleaseCleanup(NormalAndEHCleanup, var.getType(), addr);
+    CGF.pushDestroy(NormalAndEHCleanup, addr, var.getType(),
+                    CodeGenFunction::destroyARCWeak,
+                    /*useEHCleanup*/ true);
     break;
   }
 }
@@ -1129,11 +1136,21 @@
   return *destroyer;
 }
 
+/// pushDestroy - Push the standard destructor for the given type.
+void CodeGenFunction::pushDestroy(QualType::DestructionKind dtorKind,
+                                  llvm::Value *addr, QualType type) {
+  assert(dtorKind && "cannot push destructor for trivial type");
+
+  CleanupKind cleanupKind = getCleanupKind(dtorKind);
+  pushDestroy(cleanupKind, addr, type, getDestroyer(dtorKind),
+              cleanupKind & EHCleanup);
+}
+
 void CodeGenFunction::pushDestroy(CleanupKind cleanupKind, llvm::Value *addr,
                                   QualType type, Destroyer &destroyer,
                                   bool useEHCleanupForArray) {
-  EHStack.pushCleanup<DestroyObject>(cleanupKind, addr, type, destroyer,
-                                     useEHCleanupForArray);
+  pushFullExprCleanup<DestroyObject>(cleanupKind, addr, type,
+                                     destroyer, useEHCleanupForArray);
 }
 
 /// emitDestroy - Immediately perform the destruction of the given
@@ -1324,13 +1341,12 @@
 /// \param destructionKind - the kind of destruction required
 /// \param initializedElementCount - a value of type size_t* holding
 ///   the number of successfully-constructed elements
-void CodeGenFunction::pushIrregularPartialArrayCleanup(llvm::Value *array,
+void CodeGenFunction::pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin,
                                                  llvm::Value *arrayEndPointer,
                                                        QualType elementType,
                                                        Destroyer &destroyer) {
-  // FIXME: can this be in a conditional expression?
-  EHStack.pushCleanup<IrregularPartialArrayDestroy>(EHCleanup, array,
-                                                    arrayEndPointer,
+  pushFullExprCleanup<IrregularPartialArrayDestroy>(EHCleanup,
+                                                    arrayBegin, arrayEndPointer,
                                                     elementType, &destroyer);
 }
 
@@ -1348,8 +1364,7 @@
                                                      llvm::Value *arrayEnd,
                                                      QualType elementType,
                                                      Destroyer &destroyer) {
-  // FIXME: can this be in a conditional expression?
-  EHStack.pushCleanup<RegularPartialArrayDestroy>(EHCleanup,
+  pushFullExprCleanup<RegularPartialArrayDestroy>(EHCleanup,
                                                   arrayBegin, arrayEnd,
                                                   elementType, &destroyer);
 }

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=134988&r1=134987&r2=134988&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Tue Jul 12 11:41:08 2011
@@ -283,19 +283,24 @@
         case Qualifiers::OCL_Autoreleasing:
           break;
             
-        case Qualifiers::OCL_Strong:
-          CGF.PushARCReleaseCleanup(CGF.getARCCleanupKind(), 
-                                    ObjCARCReferenceLifetimeType, 
-                                    ReferenceTemporary,
-                                    /*Precise lifetime=*/false, 
-                                    /*For full expression=*/true);
+        case Qualifiers::OCL_Strong: {
+          assert(!ObjCARCReferenceLifetimeType->isArrayType());
+          CleanupKind cleanupKind = CGF.getARCCleanupKind();
+          CGF.pushDestroy(cleanupKind, 
+                          ReferenceTemporary,
+                          ObjCARCReferenceLifetimeType,
+                          CodeGenFunction::destroyARCStrongImprecise,
+                          cleanupKind & EHCleanup);
           break;
+        }
           
         case Qualifiers::OCL_Weak:
-          CGF.PushARCWeakReleaseCleanup(NormalAndEHCleanup, 
-                                        ObjCARCReferenceLifetimeType, 
-                                        ReferenceTemporary,
-                                        /*For full expression=*/true);
+          assert(!ObjCARCReferenceLifetimeType->isArrayType());
+          CGF.pushDestroy(NormalAndEHCleanup, 
+                          ReferenceTemporary,
+                          ObjCARCReferenceLifetimeType,
+                          CodeGenFunction::destroyARCWeak,
+                          /*useEHCleanupForArray*/ true);
           break;
         }
         
@@ -467,18 +472,21 @@
       // Nothing to do.
       break;        
         
-    case Qualifiers::OCL_Strong:
-      PushARCReleaseCleanup(getARCCleanupKind(), ObjCARCReferenceLifetimeType, 
-                            ReferenceTemporary,
-                            VD && VD->hasAttr<ObjCPreciseLifetimeAttr>());
+    case Qualifiers::OCL_Strong: {
+      bool precise = VD && VD->hasAttr<ObjCPreciseLifetimeAttr>();
+      CleanupKind cleanupKind = getARCCleanupKind();
+      pushDestroy(cleanupKind, ReferenceTemporary,
+                  ObjCARCReferenceLifetimeType,
+                  precise ? destroyARCStrongPrecise : destroyARCStrongImprecise,
+                  cleanupKind & EHCleanup);
       break;
+    }
         
     case Qualifiers::OCL_Weak:
       // __weak objects always get EH cleanups; otherwise, exceptions
       // could cause really nasty crashes instead of mere leaks.
-      PushARCWeakReleaseCleanup(NormalAndEHCleanup, 
-                                ObjCARCReferenceLifetimeType, 
-                                ReferenceTemporary);
+      pushDestroy(NormalAndEHCleanup, ReferenceTemporary,
+                  ObjCARCReferenceLifetimeType, destroyARCWeak, true);
       break;        
     }
   }

Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=134988&r1=134987&r2=134988&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Tue Jul 12 11:41:08 2011
@@ -677,56 +677,36 @@
   FinishFunction();
 }
 
-// FIXME: these are stolen from CGClass.cpp, which is lame.
 namespace {
-  struct CallArrayIvarDtor : EHScopeStack::Cleanup {
+  struct DestroyIvar : EHScopeStack::Cleanup {
+  private:
+    llvm::Value *addr;
     const ObjCIvarDecl *ivar;
-    llvm::Value *self;
-    CallArrayIvarDtor(const ObjCIvarDecl *ivar, llvm::Value *self)
-      : ivar(ivar), self(self) {}
-
-    void Emit(CodeGenFunction &CGF, bool IsForEH) {
-      LValue lvalue =
-        CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), self, ivar, 0);
-
-      QualType type = ivar->getType();
-      const ConstantArrayType *arrayType
-        = CGF.getContext().getAsConstantArrayType(type);
-      QualType baseType = CGF.getContext().getBaseElementType(arrayType);
-      const CXXRecordDecl *classDecl = baseType->getAsCXXRecordDecl();
-
-      llvm::Value *base
-        = CGF.Builder.CreateBitCast(lvalue.getAddress(),
-                                    CGF.ConvertType(baseType)->getPointerTo());
-      CGF.EmitCXXAggrDestructorCall(classDecl->getDestructor(),
-                                    arrayType, base);
-    }
-  };
+    CodeGenFunction::Destroyer &destroyer;
+    bool useEHCleanupForArray;
+  public:
+    DestroyIvar(llvm::Value *addr, const ObjCIvarDecl *ivar,
+                CodeGenFunction::Destroyer *destroyer,
+                bool useEHCleanupForArray)
+      : addr(addr), ivar(ivar), destroyer(*destroyer),
+        useEHCleanupForArray(useEHCleanupForArray) {}
 
-  struct CallIvarDtor : EHScopeStack::Cleanup {
-    const ObjCIvarDecl *ivar;
-    llvm::Value *self;
-    CallIvarDtor(const ObjCIvarDecl *ivar, llvm::Value *self)
-      : ivar(ivar), self(self) {}
-
-    void Emit(CodeGenFunction &CGF, bool IsForEH) {
-      LValue lvalue =
-        CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), self, ivar, 0);
-
-      QualType type = ivar->getType();
-      const CXXRecordDecl *classDecl = type->getAsCXXRecordDecl();
-
-      CGF.EmitCXXDestructorCall(classDecl->getDestructor(),
-                                Dtor_Complete, /*ForVirtualBase=*/false,
-                                lvalue.getAddress());
+    void Emit(CodeGenFunction &CGF, bool isForEH) {
+      LValue lvalue
+        = CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), addr, ivar, /*CVR*/ 0);
+      CGF.emitDestroy(lvalue.getAddress(), ivar->getType(), destroyer,
+                      !isForEH && useEHCleanupForArray);
     }
   };
 }
 
-static void pushReleaseForIvar(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
-                               llvm::Value *self);
-static void pushWeakReleaseForIvar(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
-                                   llvm::Value *self);
+/// Like CodeGenFunction::destroyARCStrong, but do it with a call.
+static void destroyARCStrongWithStore(CodeGenFunction &CGF,
+                                      llvm::Value *addr,
+                                      QualType type) {
+  llvm::Value *null = getNullForVariable(addr);
+  CGF.EmitARCStoreStrongCall(addr, null, /*ignored*/ true);
+}
 
 static void emitCXXDestructMethod(CodeGenFunction &CGF,
                                   ObjCImplementationDecl *impl) {
@@ -740,37 +720,26 @@
        ivar; ivar = ivar->getNextIvar()) {
     QualType type = ivar->getType();
 
-    // Drill down to the base element type.
-    QualType baseType = type;
-    const ConstantArrayType *arrayType = 
-      CGF.getContext().getAsConstantArrayType(baseType);
-    if (arrayType) baseType = CGF.getContext().getBaseElementType(arrayType);
-
     // Check whether the ivar is a destructible type.
-    QualType::DestructionKind destructKind = baseType.isDestructedType();
-    assert(destructKind == type.isDestructedType());
+    QualType::DestructionKind dtorKind = type.isDestructedType();
+    if (!dtorKind) continue;
+
+    CodeGenFunction::Destroyer *destroyer = 0;
+
+    // Use a call to objc_storeStrong to destroy strong ivars, for the
+    // general benefit of the tools.
+    if (dtorKind == QualType::DK_objc_strong_lifetime) {
+      destroyer = &destroyARCStrongWithStore;
 
-    switch (destructKind) {
-    case QualType::DK_none:
-      continue;
-
-    case QualType::DK_cxx_destructor:
-      if (arrayType)
-        CGF.EHStack.pushCleanup<CallArrayIvarDtor>(NormalAndEHCleanup,
-                                                   ivar, self);
-      else
-        CGF.EHStack.pushCleanup<CallIvarDtor>(NormalAndEHCleanup,
-                                              ivar, self);
-      break;
-
-    case QualType::DK_objc_strong_lifetime:
-      pushReleaseForIvar(CGF, ivar, self);
-      break;
-
-    case QualType::DK_objc_weak_lifetime:
-      pushWeakReleaseForIvar(CGF, ivar, self);
-      break;
+    // Otherwise use the default for the destruction kind.
+    } else {
+      destroyer = &CGF.getDestroyer(dtorKind);
     }
+
+    CleanupKind cleanupKind = CGF.getCleanupKind(dtorKind);
+
+    CGF.EHStack.pushCleanup<DestroyIvar>(cleanupKind, self, ivar, destroyer,
+                                         cleanupKind & EHCleanup);
   }
 
   assert(scope.requiresCleanups() && "nothing to do in .cxx_destruct?");
@@ -1828,157 +1797,6 @@
 }
 
 namespace {
-  struct ObjCReleasingCleanup : EHScopeStack::Cleanup {
-  private:
-    QualType type;
-    llvm::Value *addr;
-    CodeGenFunction::Destroyer &destroyer;
-
-  protected:
-    ObjCReleasingCleanup(QualType type, llvm::Value *addr,
-                         CodeGenFunction::Destroyer *destroyer)
-      : type(type), addr(addr), destroyer(*destroyer) {}
-
-    virtual llvm::Value *getAddress(CodeGenFunction &CGF,
-                                    llvm::Value *addr) {
-      return addr;
-    }
-
-  public:
-    void Emit(CodeGenFunction &CGF, bool isForEH) {
-      const ArrayType *arrayType = CGF.getContext().getAsArrayType(type);
-
-      llvm::Value *addr = getAddress(CGF, this->addr);
-
-      // If we don't have an array type, this is easy.
-      if (!arrayType)
-        return destroyer(CGF, addr, type);
-
-      llvm::Value *begin = addr;
-      QualType baseType;
-
-      // Otherwise, this is more painful.
-      llvm::Value *count = CGF.emitArrayLength(arrayType, baseType, begin);
-
-      assert(baseType == CGF.getContext().getBaseElementType(arrayType));
-
-      llvm::BasicBlock *incomingBB = CGF.Builder.GetInsertBlock();
-
-      //   id *cur = begin;
-      //   id *end = begin + count;
-      llvm::Value *end =
-        CGF.Builder.CreateInBoundsGEP(begin, count, "array.end");
-
-      // loopBB:
-      llvm::BasicBlock *loopBB = CGF.createBasicBlock("release-loop");
-      CGF.EmitBlock(loopBB);
-
-      llvm::PHINode *cur = CGF.Builder.CreatePHI(begin->getType(), 2, "cur");
-      cur->addIncoming(begin, incomingBB);
-
-      //   if (cur == end) goto endBB;
-      llvm::Value *eq = CGF.Builder.CreateICmpEQ(cur, end, "release-loop.done");
-      llvm::BasicBlock *bodyBB = CGF.createBasicBlock("release-loop.body");
-      llvm::BasicBlock *endBB = CGF.createBasicBlock("release-loop.cont");
-      CGF.Builder.CreateCondBr(eq, endBB, bodyBB);
-      CGF.EmitBlock(bodyBB);
-
-      // Release the value at 'cur'.
-      destroyer(CGF, cur, baseType);
-
-      //   ++cur;
-      //   goto loopBB;
-      llvm::Value *next = CGF.Builder.CreateConstInBoundsGEP1_32(cur, 1);
-      cur->addIncoming(next, CGF.Builder.GetInsertBlock());
-      CGF.Builder.CreateBr(loopBB);
-
-      // endBB:
-      CGF.EmitBlock(endBB);
-    }
-  };
-
-  /// A cleanup that calls @objc_release on all the objects to release.
-  struct CallReleaseForObject : ObjCReleasingCleanup {
-    CallReleaseForObject(QualType type, llvm::Value *addr,
-                         CodeGenFunction::Destroyer *destroyer)
-      : ObjCReleasingCleanup(type, addr, destroyer) {}
-  };
-
-  /// A cleanup that calls @objc_storeStrong(nil) on all the objects to
-  /// release in an ivar.
-  struct CallReleaseForIvar : ObjCReleasingCleanup {
-    const ObjCIvarDecl *ivar;
-    CallReleaseForIvar(const ObjCIvarDecl *ivar, llvm::Value *self)
-      : ObjCReleasingCleanup(ivar->getType(), self,
-                             destroyARCStrongIvar), ivar(ivar) {}
-
-    llvm::Value *getAddress(CodeGenFunction &CGF, llvm::Value *addr) {
-      LValue lvalue
-        = CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), addr, ivar, /*CVR*/ 0);
-      return lvalue.getAddress();
-    }
-
-    static void destroyARCStrongIvar(CodeGenFunction &CGF,
-                                     llvm::Value *addr,
-                                     QualType type) {
-      llvm::Value *null = getNullForVariable(addr);
-      CGF.EmitARCStoreStrongCall(addr, null, /*ignored*/ true);
-    }
-  };
-
-  /// A cleanup that calls @objc_release on all of the objects to release in
-  /// a field.
-  struct CallReleaseForField : CallReleaseForObject {
-    const FieldDecl *Field;
-    
-    explicit CallReleaseForField(const FieldDecl *Field)
-      : CallReleaseForObject(Field->getType(), 0,
-                             CodeGenFunction::destroyARCStrongPrecise),
-        Field(Field) { }
-    
-    llvm::Value *getAddress(CodeGenFunction &CGF, llvm::Value *) {
-      llvm::Value *This = CGF.LoadCXXThis();      
-      LValue LV = CGF.EmitLValueForField(This, Field, 0);
-      return LV.getAddress();
-    }
-  };
-  
-  /// A cleanup that calls @objc_weak_release on all the objects to
-  /// release in an object.
-  struct CallWeakReleaseForObject : ObjCReleasingCleanup {
-    CallWeakReleaseForObject(QualType type, llvm::Value *addr)
-      : ObjCReleasingCleanup(type, addr, CodeGenFunction::destroyARCWeak) {}
-  };
-
-  
-  /// A cleanup that calls @objc_weak_release on all the objects to
-  /// release in an ivar.
-  struct CallWeakReleaseForIvar : CallWeakReleaseForObject {
-    const ObjCIvarDecl *ivar;
-    CallWeakReleaseForIvar(const ObjCIvarDecl *ivar, llvm::Value *self)
-    : CallWeakReleaseForObject(ivar->getType(), self), ivar(ivar) {}
-    
-    llvm::Value *getAddress(CodeGenFunction &CGF, llvm::Value *addr) {
-      LValue lvalue
-      = CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), addr, ivar, /*CVR*/ 0);
-      return lvalue.getAddress();
-    }
-  };
-
-  /// A cleanup that calls @objc_weak_release on all the objects to
-  /// release in a field;
-  struct CallWeakReleaseForField : CallWeakReleaseForObject {
-    const FieldDecl *Field;
-    CallWeakReleaseForField(const FieldDecl *Field)
-      : CallWeakReleaseForObject(Field->getType(), 0), Field(Field) {}
-    
-    llvm::Value *getAddress(CodeGenFunction &CGF, llvm::Value *) {
-      llvm::Value *This = CGF.LoadCXXThis();      
-      LValue LV = CGF.EmitLValueForField(This, Field, 0);
-      return LV.getAddress();
-    }
-  };
-  
   struct CallObjCAutoreleasePoolObject : EHScopeStack::Cleanup {
     llvm::Value *Token;
 
@@ -2006,59 +1824,6 @@
     EHStack.pushCleanup<CallObjCMRRAutoreleasePoolObject>(NormalCleanup, Ptr);
 }
 
-/// PushARCReleaseCleanup - Enter a cleanup to perform a release on a
-/// given object or array of objects.
-void CodeGenFunction::PushARCReleaseCleanup(CleanupKind cleanupKind,
-                                            QualType type,
-                                            llvm::Value *addr,
-                                            bool precise,
-                                            bool forFullExpr) {
-  Destroyer *dtor =
-    (precise ? destroyARCStrongPrecise : destroyARCStrongImprecise);
-  if (forFullExpr)
-    pushFullExprCleanup<CallReleaseForObject>(cleanupKind, type, addr, dtor);
-  else
-    EHStack.pushCleanup<CallReleaseForObject>(cleanupKind, type, addr, dtor);
-}
-
-/// PushARCWeakReleaseCleanup - Enter a cleanup to perform a weak
-/// release on the given object or array of objects.
-void CodeGenFunction::PushARCWeakReleaseCleanup(CleanupKind cleanupKind,
-                                                QualType type,
-                                                llvm::Value *addr,
-                                                bool forFullExpr) {
-  if (forFullExpr)
-    pushFullExprCleanup<CallWeakReleaseForObject>(cleanupKind, type, addr);
-  else
-    EHStack.pushCleanup<CallWeakReleaseForObject>(cleanupKind, type, addr);
-}
-
-/// PushARCReleaseCleanup - Enter a cleanup to perform a release on a
-/// given object or array of objects.
-void CodeGenFunction::PushARCFieldReleaseCleanup(CleanupKind cleanupKind,
-                                                 const FieldDecl *field) {
-  EHStack.pushCleanup<CallReleaseForField>(cleanupKind, field);
-}
-
-/// PushARCWeakReleaseCleanup - Enter a cleanup to perform a weak
-/// release on the given object or array of objects.
-void CodeGenFunction::PushARCFieldWeakReleaseCleanup(CleanupKind cleanupKind,
-                                                     const FieldDecl *field) {
-  EHStack.pushCleanup<CallWeakReleaseForField>(cleanupKind, field);
-}
-
-static void pushReleaseForIvar(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
-                               llvm::Value *self) {
-  CGF.EHStack.pushCleanup<CallReleaseForIvar>(CGF.getARCCleanupKind(),
-                                              ivar, self);
-}
-
-static void pushWeakReleaseForIvar(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
-                                   llvm::Value *self) {
-  CGF.EHStack.pushCleanup<CallWeakReleaseForIvar>(CGF.getARCCleanupKind(),
-                                                  ivar, self);
-}
-
 static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF,
                                                   LValue lvalue,
                                                   QualType type) {

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=134988&r1=134987&r2=134988&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Jul 12 11:41:08 2011
@@ -255,6 +255,30 @@
       : a0_saved(a0), a1_saved(a1), a2_saved(a2) {}
   };
 
+  template <class T, class A0, class A1, class A2, class A3>
+  class ConditionalCleanup4 : public Cleanup {
+    typedef typename DominatingValue<A0>::saved_type A0_saved;
+    typedef typename DominatingValue<A1>::saved_type A1_saved;
+    typedef typename DominatingValue<A2>::saved_type A2_saved;
+    typedef typename DominatingValue<A3>::saved_type A3_saved;
+    A0_saved a0_saved;
+    A1_saved a1_saved;
+    A2_saved a2_saved;
+    A3_saved a3_saved;
+    
+    void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
+      A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
+      A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
+      A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved);
+      A3 a3 = DominatingValue<A3>::restore(CGF, a3_saved);
+      T(a0, a1, a2, a3).Emit(CGF, IsForEHCleanup);
+    }
+    
+  public:
+    ConditionalCleanup4(A0_saved a0, A1_saved a1, A2_saved a2, A3_saved a3)
+      : a0_saved(a0), a1_saved(a1), a2_saved(a2), a3_saved(a3) {}
+  };
+
 private:
   // The implementation for this class is in CGException.h and
   // CGException.cpp; the definition is here because it's used as a
@@ -710,6 +734,28 @@
     initFullExprCleanup();
   }
 
+  /// pushFullExprCleanup - Push a cleanup to be run at the end of the
+  /// current full-expression.  Safe against the possibility that
+  /// we're currently inside a conditionally-evaluated expression.
+  template <class T, class A0, class A1, class A2, class A3>
+  void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1, A2 a2, A3 a3) {
+    // If we're not in a conditional branch, or if none of the
+    // arguments requires saving, then use the unconditional cleanup.
+    if (!isInConditionalBranch()) {
+      return EHStack.pushCleanup<T>(kind, a0, a1, a2, a3);
+    }
+    
+    typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
+    typename DominatingValue<A1>::saved_type a1_saved = saveValueInCond(a1);
+    typename DominatingValue<A2>::saved_type a2_saved = saveValueInCond(a2);
+    typename DominatingValue<A3>::saved_type a3_saved = saveValueInCond(a3);
+    
+    typedef EHScopeStack::ConditionalCleanup4<T, A0, A1, A2, A3> CleanupType;
+    EHStack.pushCleanup<CleanupType>(kind, a0_saved, a1_saved,
+                                     a2_saved, a3_saved);
+    initFullExprCleanup();
+  }
+
   /// PushDestructorCleanup - Push a cleanup to call the
   /// complete-object destructor of an object of the given type at the
   /// given address.  Does nothing if T is not a C++ class type with a
@@ -1126,7 +1172,8 @@
                                       QualType elementType,
                                       Destroyer &destroyer);
 
-  Destroyer &getDestroyer(QualType::DestructionKind destructionKind);
+  void pushDestroy(QualType::DestructionKind dtorKind,
+                   llvm::Value *addr, QualType type);
   void pushDestroy(CleanupKind kind, llvm::Value *addr, QualType type,
                    Destroyer &destroyer, bool useEHCleanupForArray);
   void emitDestroy(llvm::Value *addr, QualType type, Destroyer &destroyer,
@@ -1135,6 +1182,8 @@
                         QualType type, Destroyer &destroyer,
                         bool useEHCleanup);
 
+  Destroyer &getDestroyer(QualType::DestructionKind destructionKind);
+
   /// Determines whether an EH cleanup is required to destroy a type
   /// with the given destruction kind.
   bool needsEHCleanup(QualType::DestructionKind kind) {
@@ -1151,6 +1200,10 @@
     llvm_unreachable("bad destruction kind");
   }
 
+  CleanupKind getCleanupKind(QualType::DestructionKind kind) {
+    return (needsEHCleanup(kind) ? NormalAndEHCleanup : NormalCleanup);
+  }
+
   //===--------------------------------------------------------------------===//
   //                                  Objective-C
   //===--------------------------------------------------------------------===//
@@ -2109,28 +2162,10 @@
   llvm::Value *EmitARCRetainScalarExpr(const Expr *expr);
   llvm::Value *EmitARCRetainAutoreleaseScalarExpr(const Expr *expr);
 
-  void PushARCReleaseCleanup(CleanupKind kind, QualType type,
-                             llvm::Value *addr, bool precise,
-                             bool forFullExpr = false);
-  void PushARCArrayReleaseCleanup(CleanupKind kind, QualType elementType,
-                                  llvm::Value *addr,
-                                  llvm::Value *countOrCountPtr,
-                                  bool precise, bool forFullExpr = false);
-  void PushARCWeakReleaseCleanup(CleanupKind kind, QualType type,
-                                 llvm::Value *addr, bool forFullExpr = false);
-  void PushARCArrayWeakReleaseCleanup(CleanupKind kind, QualType elementType,
-                                      llvm::Value *addr,
-                                      llvm::Value *countOrCountPtr,
-                                      bool forFullExpr = false);
   static Destroyer destroyARCStrongImprecise;
   static Destroyer destroyARCStrongPrecise;
   static Destroyer destroyARCWeak;
 
-  void PushARCFieldReleaseCleanup(CleanupKind cleanupKind,
-                                  const FieldDecl *Field);
-  void PushARCFieldWeakReleaseCleanup(CleanupKind cleanupKind,
-                                      const FieldDecl *Field);
-
   void EmitObjCAutoreleasePoolPop(llvm::Value *Ptr); 
   llvm::Value *EmitObjCAutoreleasePoolPush();
   llvm::Value *EmitObjCMRRAutoreleasePoolPush();

Modified: cfe/trunk/test/CodeGenObjC/arc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc.m?rev=134988&r1=134987&r2=134988&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/arc.m (original)
+++ cfe/trunk/test/CodeGenObjC/arc.m Tue Jul 12 11:41:08 2011
@@ -641,12 +641,11 @@
 // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [4 x i8*]* [[X]], i32 0, i32 0
 // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 4
 // CHECK-NEXT: br label
-// CHECK:      [[CUR:%.*]] = phi i8**
-// CHECK-NEXT: [[ISDONE:%.*]] = icmp eq i8** [[CUR]], [[END]]
+// CHECK:      [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
+// CHECK-NEXT: [[CUR]] = getelementptr inbounds i8** [[PAST]], i64 -1
+// CHECK-NEXT: call void @objc_storeStrong(i8** [[CUR]], i8* null)
+// CHECK-NEXT: [[ISDONE:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]]
 // CHECK-NEXT: br i1 [[ISDONE]],
-// CHECK:      call void @objc_storeStrong(i8** [[CUR]], i8* null)
-// CHECK-NEXT: [[NEXT:%.*]] = getelementptr inbounds i8** [[CUR]], i32 1
-// CHECK-NEXT: br label
 // CHECK:      ret void
 
 // Check that 'init' retains self.

Modified: cfe/trunk/test/CodeGenObjCXX/arc-special-member-functions.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc-special-member-functions.mm?rev=134988&r1=134987&r2=134988&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/arc-special-member-functions.mm (original)
+++ cfe/trunk/test/CodeGenObjCXX/arc-special-member-functions.mm Tue Jul 12 11:41:08 2011
@@ -124,10 +124,17 @@
 // CHECK: ret
 
 // Implicitly-generated destructor for ObjCArrayMember
-// CHECK: define linkonce_odr void @_ZN15ObjCArrayMemberD2Ev
-// CHECK: call void @objc_release
-// CHECK: br label
-// CHECK: ret
+// CHECK:    define linkonce_odr void @_ZN15ObjCArrayMemberD2Ev
+// CHECK:      [[BEGIN:%.*]] = getelementptr inbounds [2 x [3 x i8*]]*
+// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 6
+// CHECK-NEXT: br label
+// 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: [[T1:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]]
+// CHECK-NEXT: br i1 [[T1]], 
+// CHECK:      ret void
 
 // Implicitly-generated default constructor for ObjCArrayMember
 // CHECK: define linkonce_odr void @_ZN15ObjCArrayMemberC2Ev





More information about the cfe-commits mailing list