diff options
author | John McCall <rjmccall@apple.com> | 2011-07-22 05:23:13 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-07-22 05:23:13 +0000 |
commit | ba3dd902d1cde09776a50c1adf2cd40bf0a15a7f (patch) | |
tree | 7c26e9774d7744a75d29cff9a105acaa251b5812 | |
parent | da6d976b0f2470bb3f854913bc3af3245845ad60 (diff) |
In ARC, non-atomic getters do not need to retain and autorelease
their loaded values, although it still worth doing this for __weak
properties to get the autoreleased-return-value optimization.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135747 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 37 | ||||
-rw-r--r-- | test/CodeGenObjC/arc.m | 38 |
2 files changed, 58 insertions, 17 deletions
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 4beb704d15..fd686cc6a0 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -465,27 +465,30 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, EmitAggregateCopy(ReturnValue, LV.getAddress(), IVART); } } - } - else { - LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), - Ivar, 0); - QualType propType = PD->getType(); + } else { + LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), + Ivar, 0); + QualType propType = PD->getType(); - llvm::Value *value; - if (propType->isReferenceType()) { - value = LV.getAddress(); + llvm::Value *value; + if (propType->isReferenceType()) { + value = LV.getAddress(); + } else { + // We want to load and autoreleaseReturnValue ARC __weak ivars. + if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) { + value = emitARCRetainLoadOfScalar(*this, LV, IVART); + + // Otherwise we want to do a simple load, suppressing the + // final autorelease. } else { - // In ARC, we want to emit this retained. - if (getLangOptions().ObjCAutoRefCount && - PD->getType()->isObjCRetainableType()) - value = emitARCRetainLoadOfScalar(*this, LV, IVART); - else - value = EmitLoadOfLValue(LV).getScalarVal(); - - value = Builder.CreateBitCast(value, ConvertType(propType)); + value = EmitLoadOfLValue(LV).getScalarVal(); + AutoreleaseResult = false; } - EmitReturnOfRValue(RValue::get(value), propType); + value = Builder.CreateBitCast(value, ConvertType(propType)); + } + + EmitReturnOfRValue(RValue::get(value), propType); } } diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m index f6bd434195..8d74ab2a6a 100644 --- a/test/CodeGenObjC/arc.m +++ b/test/CodeGenObjC/arc.m @@ -1578,3 +1578,41 @@ void test56_test(void) { // CHECK-NEXT: call void @objc_release(i8* [[T0]]) // CHECK-NEXT: ret void } + +// rdar://problem/9784964 +@interface Test57 +@property (nonatomic, strong) id strong; +@property (nonatomic, weak) id weak; +@property (nonatomic, unsafe_unretained) id unsafe; +@end +@implementation Test57 +@synthesize strong, weak, unsafe; +@end +// CHECK: define internal i8* @"\01-[Test57 strong]"( +// CHECK: [[T0:%.*]] = load [[TEST57:%.*]]** {{%.*}} +// CHECK-NEXT: [[T1:%.*]] = load i64* @"OBJC_IVAR_$_Test57.strong" +// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST57]]* [[T0]] to i8* +// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8* [[T2]], i64 [[T1]] +// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** +// CHECK-NEXT: [[T5:%.*]] = load i8** [[T4]] +// CHECK-NEXT: ret i8* [[T5]] + +// CHECK: define internal i8* @"\01-[Test57 weak]"( +// CHECK: [[T0:%.*]] = load [[TEST57]]** {{%.*}} +// CHECK-NEXT: [[T1:%.*]] = load i64* @"OBJC_IVAR_$_Test57.weak" +// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST57]]* [[T0]] to i8* +// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8* [[T2]], i64 [[T1]] +// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** +// CHECK-NEXT: [[T5:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T4]]) +// CHECK-NEXT: [[T6:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[T5]]) +// CHECK-NEXT: ret i8* [[T6]] + +// CHECK: define internal i8* @"\01-[Test57 unsafe]"( +// CHECK: [[T0:%.*]] = load [[TEST57]]** {{%.*}} +// CHECK-NEXT: [[T1:%.*]] = load i64* @"OBJC_IVAR_$_Test57.unsafe" +// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST57]]* [[T0]] to i8* +// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8* [[T2]], i64 [[T1]] +// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** +// CHECK-NEXT: [[T5:%.*]] = load i8** [[T4]] +// CHECK-NEXT: ret i8* [[T5]] + |