objective-C arc IR-gen. Retaining of strong
arguments in function prologue is done
with objc_StoreStrong to pair it with
similar objc_StoreStrong for release in function
epilogue. This is done with -O0 only.
// rdar://13145317


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175698 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index a43a383..a4d673b 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -1526,13 +1526,14 @@
     // Otherwise, create a temporary to hold the value.
     llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty),
                                                D.getName() + ".addr");
-    Alloc->setAlignment(getContext().getDeclAlign(&D).getQuantity());
+    CharUnits Align = getContext().getDeclAlign(&D);
+    Alloc->setAlignment(Align.getQuantity());
     DeclPtr = Alloc;
 
     bool doStore = true;
 
     Qualifiers qs = Ty.getQualifiers();
-
+    LValue lv = MakeAddrLValue(DeclPtr, Ty, Align);
     if (Qualifiers::ObjCLifetime lt = qs.getObjCLifetime()) {
       // We honor __attribute__((ns_consumed)) for types with lifetime.
       // For __strong, it's handled by just skipping the initial retain;
@@ -1553,11 +1554,22 @@
       }
 
       if (lt == Qualifiers::OCL_Strong) {
-        if (!isConsumed)
+        if (!isConsumed) {
+          if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
+            // use objc_storeStrong(&dest, value) for retaining the
+            // object. But first, store a null into 'dest' because
+            // objc_storeStrong attempts to release its old value.
+            llvm::Value * Null = CGM.EmitNullConstant(D.getType());
+            EmitStoreOfScalar(Null, lv, /* isInitialization */ true);
+            EmitARCStoreStrongCall(lv.getAddress(), Arg, true);
+            doStore = false;
+          }
+          else
           // Don't use objc_retainBlock for block pointers, because we
           // don't want to Block_copy something just because we got it
           // as a parameter.
-          Arg = EmitARCRetainNonBlock(Arg);
+            Arg = EmitARCRetainNonBlock(Arg);
+        }
       } else {
         // Push the cleanup for a consumed parameter.
         if (isConsumed)
@@ -1574,11 +1586,8 @@
     }
 
     // Store the initial value into the alloca.
-    if (doStore) {
-      LValue lv = MakeAddrLValue(DeclPtr, Ty,
-                                 getContext().getDeclAlign(&D));
+    if (doStore)
       EmitStoreOfScalar(Arg, lv, /* isInitialization */ true);
-    }
   }
 
   llvm::Value *&DMEntry = LocalDeclMap[&D];
diff --git a/test/CodeGenObjC/arc-blocks.m b/test/CodeGenObjC/arc-blocks.m
index 48c4f08..49628ef 100644
--- a/test/CodeGenObjC/arc-blocks.m
+++ b/test/CodeGenObjC/arc-blocks.m
@@ -614,8 +614,8 @@
 // CHECK-UNOPT:    define void @test18(
 // CHECK-UNOPT:      [[X:%.*]] = alloca i8*,
 // CHECK-UNOPT-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
-// CHECK-UNOPT-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})
-// CHECK-UNOPT-NEXT: store i8* [[PARM]], i8** [[X]]
+// CHECK-UNOPT-NEXT: store i8* null, i8** [[X]]
+// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X]], 
 // CHECK-UNOPT-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
 // CHECK-UNOPT:      [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
 // CHECK-UNOPT-NEXT: [[T0:%.*]] = load i8** [[X]],
diff --git a/test/CodeGenObjC/arc-foreach.m b/test/CodeGenObjC/arc-foreach.m
index bb24855..7494451 100644
--- a/test/CodeGenObjC/arc-foreach.m
+++ b/test/CodeGenObjC/arc-foreach.m
@@ -30,10 +30,10 @@
 // CHECK-LP64-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
 
 // Initialize 'array'.
-// CHECK-LP64-NEXT: [[T0:%.*]] = bitcast [[ARRAY_T:%.*]]* {{%.*}} to i8*
-// CHECK-LP64-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
-// CHECK-LP64-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[ARRAY_T]]*
-// CHECK-LP64-NEXT: store [[ARRAY_T]]* [[T2]], [[ARRAY_T]]** [[ARRAY]], align 8
+// CHECK-LP64-NEXT: store [[ARRAY_T]]* null, [[ARRAY_T]]** [[ARRAY]]
+// CHECK-LP64-NEXT: [[ZERO:%.*]] = bitcast [[ARRAY_T]]** [[ARRAY]] to i8**
+// CHECK-LP64-NEXT: [[ONE:%.*]] = bitcast [[ARRAY_T]]* {{%.*}} to i8*
+// CHECK-LP64-NEXT: call void @objc_storeStrong(i8** [[ZERO]], i8* [[ONE]]) nounwind
 
 // Initialize the fast enumaration state.
 // CHECK-LP64-NEXT: [[T0:%.*]] = bitcast [[STATE_T]]* [[STATE]] to i8*
diff --git a/test/CodeGenObjC/arc-property.m b/test/CodeGenObjC/arc-property.m
index db00e36..0e0dabe 100644
--- a/test/CodeGenObjC/arc-property.m
+++ b/test/CodeGenObjC/arc-property.m
@@ -8,8 +8,8 @@
   t0.value = value;
 }
 // CHECK: define void @test0(
-// CHECK: call i8* @objc_retain(
-// CHECK: call i8* @objc_retain(
+// CHECK: call void @objc_storeStrong
+// CHECK: call void @objc_storeStrong
 // CHECK: @objc_msgSend
 // CHECK: call void @objc_storeStrong(
 // CHECK: call void @objc_storeStrong(
diff --git a/test/CodeGenObjC/arc-related-result-type.m b/test/CodeGenObjC/arc-related-result-type.m
index ee0a41d..e8b9701 100644
--- a/test/CodeGenObjC/arc-related-result-type.m
+++ b/test/CodeGenObjC/arc-related-result-type.m
@@ -9,10 +9,10 @@
 // CHECK:    define void @test0(
 // CHECK:      [[VAL:%.*]] = alloca [[TEST0:%.*]]*
 // CHECK-NEXT: [[X:%.*]] = alloca [[TEST0]]*
+// CHECK-NEXT: store [[TEST0]]* null
 // CHECK-NEXT: bitcast
-// CHECK-NEXT: call i8* @objc_retain(
 // CHECK-NEXT: bitcast
-// CHECK-NEXT: store
+// CHECK-NEXT: call void @objc_storeStrong(
 // CHECK-NEXT: load [[TEST0]]** [[VAL]],
 // CHECK-NEXT: load
 // CHECK-NEXT: bitcast
diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m
index 599753e..726ba32 100644
--- a/test/CodeGenObjC/arc.m
+++ b/test/CodeGenObjC/arc.m
@@ -6,8 +6,8 @@
 // RUN: %clang_cc1 -fobjc-runtime=macosx-10.6.0 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-ALIEN %s
 // RUN: %clang_cc1 -fobjc-runtime=macosx-10.7.0 -triple x86_64-apple-darwin11 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-NATIVE %s
 
-// ARC-ALIEN: declare extern_weak i8* @objc_retain(i8*)
 // ARC-ALIEN: declare extern_weak void @objc_storeStrong(i8**, i8*)
+// ARC-ALIEN: declare extern_weak i8* @objc_retain(i8*)
 // ARC-ALIEN: declare extern_weak i8* @objc_autoreleaseReturnValue(i8*)
 // ARC-ALIEN: declare i8* @objc_msgSend(i8*, i8*, ...) #1
 // ARC-ALIEN: declare extern_weak void @objc_release(i8*)
@@ -19,8 +19,8 @@
 // ARC-ALIEN: declare extern_weak i8* @objc_autorelease(i8*)
 // ARC-ALIEN: declare extern_weak i8* @objc_retainAutorelease(i8*)
 
-// ARC-NATIVE: declare i8* @objc_retain(i8*) #1
 // ARC-NATIVE: declare void @objc_storeStrong(i8**, i8*)
+// ARC-NATIVE: declare i8* @objc_retain(i8*) #1
 // ARC-NATIVE: declare i8* @objc_autoreleaseReturnValue(i8*)
 // ARC-NATIVE: declare i8* @objc_msgSend(i8*, i8*, ...) #1
 // ARC-NATIVE: declare void @objc_release(i8*) #1
diff --git a/test/CodeGenObjC/debug-info-block-line.m b/test/CodeGenObjC/debug-info-block-line.m
index 1e02e58..cca11a0 100644
--- a/test/CodeGenObjC/debug-info-block-line.m
+++ b/test/CodeGenObjC/debug-info-block-line.m
@@ -62,12 +62,14 @@
     TMap       *map = [TMap mapForID:mapID];
 // Make sure we do not map code generated for the block to the above line.
 // CHECK: define internal void @"__39-[TServer serverConnection:getCommand:]_block_invoke"
+// CHECK: call void @objc_storeStrong(i8** [[ZERO:%.*]], i8* [[ONE:%.*]]) nounwind
+// CHECK: call void @objc_storeStrong(i8** [[TWO:%.*]], i8* [[THREE:%.*]]) nounwind
 // CHECK: bitcast %5** [[TMP:%.*]] to i8**
 // CHECK: call void @objc_storeStrong(i8** [[VAL1:%.*]], i8* null) nounwind, !dbg ![[MD1:.*]]
 // CHECK: bitcast %4** [[TMP:%.*]] to i8**
 // CHECK: call void @objc_storeStrong(i8** [[VAL2:%.*]], i8* null) nounwind, !dbg ![[MD1]]
 // CHECK-NEXT: ret
-// CHECK: ![[MD1]] = metadata !{i32 84
+// CHECK: ![[MD1]] = metadata !{i32 86
     [map dataWithCompletionBlock:^(NSData *data, NSError *error) {
         if (data) {
             NSString    *encoded = [[data compressedData] encodedString:18];
diff --git a/test/CodeGenObjCXX/arc-new-delete.mm b/test/CodeGenObjCXX/arc-new-delete.mm
index ce7eb3d..c061e5d 100644
--- a/test/CodeGenObjCXX/arc-new-delete.mm
+++ b/test/CodeGenObjCXX/arc-new-delete.mm
@@ -5,8 +5,9 @@
 
 // CHECK: define void @_Z8test_newP11objc_object
 void test_new(id invalue) {
-  // CHECK: alloca i8*
-  // CHECK-NEXT: call i8* @objc_retain
+  // CHECK: [[INVALUEADDR:%.*]] = alloca i8*
+  // CHECK-NEXT: store i8* null, i8** [[INVALUEADDR]]
+  // CHECK-NEXT: call void @objc_storeStrong(i8** [[INVALUEADDR]], i8* [[INVALUE:%.*]])
 
   // CHECK: call noalias i8* @_Znwm
   // CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}}