diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2013-02-21 00:40:10 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2013-02-21 00:40:10 +0000 |
commit | 41a6a3e064192e98a48f5fabccf262412fe37d10 (patch) | |
tree | 9293d25e1c441a94ac6c2455b21d6e0e1153ed1b | |
parent | e2e1fa27e2533410f744137b0db1bc9491543392 (diff) |
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
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 25 | ||||
-rw-r--r-- | test/CodeGenObjC/arc-blocks.m | 4 | ||||
-rw-r--r-- | test/CodeGenObjC/arc-foreach.m | 8 | ||||
-rw-r--r-- | test/CodeGenObjC/arc-property.m | 4 | ||||
-rw-r--r-- | test/CodeGenObjC/arc-related-result-type.m | 4 | ||||
-rw-r--r-- | test/CodeGenObjC/arc.m | 4 | ||||
-rw-r--r-- | test/CodeGenObjC/debug-info-block-line.m | 4 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-new-delete.mm | 5 |
8 files changed, 35 insertions, 23 deletions
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index a43a38360b..a4d673b8c3 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -1526,13 +1526,14 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg, // 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 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg, } 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 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg, } // 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 48c4f08c71..49628ef62b 100644 --- a/test/CodeGenObjC/arc-blocks.m +++ b/test/CodeGenObjC/arc-blocks.m @@ -614,8 +614,8 @@ void test18(id x) { // 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 bb2485580c..7494451105 100644 --- a/test/CodeGenObjC/arc-foreach.m +++ b/test/CodeGenObjC/arc-foreach.m @@ -30,10 +30,10 @@ void test0(NSArray *array) { // 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 db00e369cf..0e0dabe6de 100644 --- a/test/CodeGenObjC/arc-property.m +++ b/test/CodeGenObjC/arc-property.m @@ -8,8 +8,8 @@ void test0(Test0 *t0, id value) { 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 ee0a41dd00..e8b97012cd 100644 --- a/test/CodeGenObjC/arc-related-result-type.m +++ b/test/CodeGenObjC/arc-related-result-type.m @@ -9,10 +9,10 @@ void test0(Test0 *val) { // 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 599753ee9c..726ba32f64 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 1e02e5876f..cca11a0397 100644 --- a/test/CodeGenObjC/debug-info-block-line.m +++ b/test/CodeGenObjC/debug-info-block-line.m @@ -62,12 +62,14 @@ typedef enum : NSUInteger { 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 ce7eb3deb1..c061e5dbdf 100644 --- a/test/CodeGenObjCXX/arc-new-delete.mm +++ b/test/CodeGenObjCXX/arc-new-delete.mm @@ -5,8 +5,9 @@ typedef __weak id weak_id; // 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\*\*}} |