[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