aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-07-22 05:23:13 +0000
committerJohn McCall <rjmccall@apple.com>2011-07-22 05:23:13 +0000
commitba3dd902d1cde09776a50c1adf2cd40bf0a15a7f (patch)
tree7c26e9774d7744a75d29cff9a105acaa251b5812
parentda6d976b0f2470bb3f854913bc3af3245845ad60 (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.cpp37
-rw-r--r--test/CodeGenObjC/arc.m38
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]]
+