diff options
Diffstat (limited to 'test/CodeGenObjCXX')
-rw-r--r-- | test/CodeGenObjCXX/arc-blocks.mm | 120 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-forwarded-lambda-call.mm | 4 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc.mm | 6 | ||||
-rw-r--r-- | test/CodeGenObjCXX/inheriting-constructor-cleanup.mm | 2 | ||||
-rw-r--r-- | test/CodeGenObjCXX/literals.mm | 8 | ||||
-rw-r--r-- | test/CodeGenObjCXX/msabi-stret.mm | 3 | ||||
-rw-r--r-- | test/CodeGenObjCXX/os_log.mm | 19 | ||||
-rw-r--r-- | test/CodeGenObjCXX/property-lvalue-lambda.mm | 47 |
8 files changed, 197 insertions, 12 deletions
diff --git a/test/CodeGenObjCXX/arc-blocks.mm b/test/CodeGenObjCXX/arc-blocks.mm index ec0c12456a..24697cf1bd 100644 --- a/test/CodeGenObjCXX/arc-blocks.mm +++ b/test/CodeGenObjCXX/arc-blocks.mm @@ -201,3 +201,123 @@ void foo1() { ^{ (void)t0; (void)t1; (void)t2; (void)t3; (void)t4; (void)t5; }; } } + +// Test that calls to @llvm.objc.retainBlock aren't emitted in some cases. + +namespace test_block_retain { + typedef void (^BlockTy)(); + + void foo1(id); + +// CHECK-LABEL: define void @_ZN17test_block_retain14initializationEP11objc_object( +// CHECK-NOT: @llvm.objc.retainBlock( + void initialization(id a) { + BlockTy b0 = ^{ foo1(a); }; + BlockTy b1 = (^{ foo1(a); }); + b0(); + b1(); + } + +// CHECK-LABEL: define void @_ZN17test_block_retain20initializationStaticEP11objc_object( +// CHECK: @llvm.objc.retainBlock( + void initializationStatic(id a) { + static BlockTy b0 = ^{ foo1(a); }; + b0(); + } + +// CHECK-LABEL: define void @_ZN17test_block_retain15initialization2EP11objc_object +// CHECK: %[[B0:.*]] = alloca void ()*, align 8 +// CHECK: %[[B1:.*]] = alloca void ()*, align 8 +// CHECK: load void ()*, void ()** %[[B0]], align 8 +// CHECK-NOT: @llvm.objc.retainBlock +// CHECK: %[[V9:.*]] = load void ()*, void ()** %[[B0]], align 8 +// CHECK: %[[V10:.*]] = bitcast void ()* %[[V9]] to i8* +// CHECK: %[[V11:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V10]]) +// CHECK: %[[V12:.*]] = bitcast i8* %[[V11]] to void ()* +// CHECK: store void ()* %[[V12]], void ()** %[[B1]], align 8 + void initialization2(id a) { + BlockTy b0 = ^{ foo1(a); }; + b0(); + BlockTy b1 = b0; // can't optimize this yet. + b1(); + } + +// CHECK-LABEL: define void @_ZN17test_block_retain10assignmentEP11objc_object( +// CHECK-NOT: @llvm.objc.retainBlock( + void assignment(id a) { + BlockTy b0; + (b0) = ^{ foo1(a); }; + b0(); + b0 = (^{ foo1(a); }); + b0(); + } + +// CHECK-LABEL: define void @_ZN17test_block_retain16assignmentStaticEP11objc_object( +// CHECK: @llvm.objc.retainBlock( + void assignmentStatic(id a) { + static BlockTy b0; + b0 = ^{ foo1(a); }; + b0(); + } + +// CHECK-LABEL: define void @_ZN17test_block_retain21assignmentConditionalEP11objc_objectb( +// CHECK: @llvm.objc.retainBlock( + void assignmentConditional(id a, bool c) { + BlockTy b0; + if (c) + // can't optimize this since 'b0' is declared in the outer scope. + b0 = ^{ foo1(a); }; + b0(); + } + +// CHECK-LABEL: define void @_ZN17test_block_retain11assignment2EP11objc_object( +// CHECK: %[[B0:.*]] = alloca void ()*, align 8 +// CHECK: %[[B1:.*]] = alloca void ()*, align 8 +// CHECK-NOT: @llvm.objc.retainBlock +// CHECK: store void ()* null, void ()** %[[B1]], align 8 +// CHECK: %[[V9:.*]] = load void ()*, void ()** %[[B0]], align 8 +// CHECK: %[[V10:.*]] = bitcast void ()* %[[V9]] to i8* +// CHECK: %[[V11:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V10]] +// CHECK: %[[V12:.*]] = bitcast i8* %[[V11]] to void ()* +// CHECK: store void ()* %[[V12]], void ()** %[[B1]], align 8 + void assignment2(id a) { + BlockTy b0 = ^{ foo1(a); }; + b0(); + BlockTy b1; + b1 = b0; // can't optimize this yet. + b1(); + } + +// We cannot remove the call to @llvm.objc.retainBlock if the variable is of type id. + +// CHECK: define void @_ZN17test_block_retain21initializationObjCPtrEP11objc_object( +// CHECK: alloca i8*, align 8 +// CHECK: %[[B0:.*]] = alloca i8*, align 8 +// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8 +// CHECK: %[[V3:.*]] = bitcast <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]] to void ()* +// CHECK: %[[V4:.*]] = bitcast void ()* %[[V3]] to i8* +// CHECK: %[[V5:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V4]]) +// CHECK: %[[V6:.*]] = bitcast i8* %[[V5]] to void ()* +// CHECK: %[[V7:.*]] = bitcast void ()* %[[V6]] to i8* +// CHECK: store i8* %[[V7]], i8** %[[B0]], align 8 + void initializationObjCPtr(id a) { + id b0 = ^{ foo1(a); }; + ((BlockTy)b0)(); + } + +// CHECK: define void @_ZN17test_block_retain17assignmentObjCPtrEP11objc_object( +// CHECK: %[[B0:.*]] = alloca void ()*, align 8 +// CHECK: %[[B1:.*]] = alloca i8*, align 8 +// CHECK: %[[V4:.*]] = load void ()*, void ()** %[[B0]], align 8 +// CHECK: %[[V5:.*]] = bitcast void ()* %[[V4]] to i8* +// CHECK: %[[V6:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V5]]) +// CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to void ()* +// CHECK: %[[V8:.*]] = bitcast void ()* %[[V7]] to i8* +// CHECK: store i8* %[[V8]], i8** %[[B1]], align 8 + void assignmentObjCPtr(id a) { + BlockTy b0 = ^{ foo1(a); }; + id b1; + b1 = b0; + ((BlockTy)b1)(); + } +} diff --git a/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm b/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm index 5a5cb42067..37a68136dd 100644 --- a/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm +++ b/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm @@ -5,7 +5,7 @@ void test0(id x) { test0_helper([=]() { return x; }); // CHECK-LABEL: define internal i8* @___Z5test0P11objc_object_block_invoke // CHECK: [[T0:%.*]] = call i8* @"_ZZ5test0P11objc_objectENK3$_0clEv" - // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) // CHECK-NEXT: [[T2:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[T1]]) // CHECK-NEXT: ret i8* [[T2]] } @@ -28,7 +28,7 @@ void test1() { test1_helper([](){ return test1_rv; }); // CHECK-LABEL: define internal i8* @"_ZZ5test1vEN3$_18__invokeEv" // CHECK: [[T0:%.*]] = call i8* @"_ZZ5test1vENK3$_1clEv" - // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) // CHECK-NEXT: [[T2:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[T1]]) // CHECK-NEXT: ret i8* [[T2]] } diff --git a/test/CodeGenObjCXX/arc.mm b/test/CodeGenObjCXX/arc.mm index e32c1f8921..f351ff6089 100644 --- a/test/CodeGenObjCXX/arc.mm +++ b/test/CodeGenObjCXX/arc.mm @@ -20,7 +20,7 @@ void test0(__weak id *wp, __weak volatile id *wvp) { // TODO: in the non-volatile case, we do not need to be reloading. // CHECK: [[T0:%.*]] = call i8* @_Z12test0_helperv() - // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) // CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** {{%.*}}, align 8 // CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.storeWeak(i8** [[T2]], i8* [[T1]]) // CHECK-NEXT: [[T4:%.*]] = call i8* @llvm.objc.retain(i8* [[T3]]) @@ -29,7 +29,7 @@ void test0(__weak id *wp, __weak volatile id *wvp) { id x = *wp = test0_helper(); // CHECK: [[T0:%.*]] = call i8* @_Z12test0_helperv() - // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) // CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** {{%.*}}, align 8 // CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.storeWeak(i8** [[T2]], i8* [[T1]]) // CHECK-NEXT: [[T4:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[T2]]) @@ -224,7 +224,7 @@ template void test37<Test37>(Test37 *a); // CHECK-LABEL: define weak_odr void @_Z6test37I6Test37EvPT_( // CHECK: [[T0:%.*]] = call [[NSARRAY]]* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to [[NSARRAY]]* (i8*, i8*)*)( // CHECK-NEXT: [[T1:%.*]] = bitcast [[NSARRAY]]* [[T0]] to i8* -// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]]) +// CHECK-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]]) // CHECK-NEXT: [[COLL:%.*]] = bitcast i8* [[T2]] to [[NSARRAY]]* // Make sure it's not immediately released before starting the iteration. diff --git a/test/CodeGenObjCXX/inheriting-constructor-cleanup.mm b/test/CodeGenObjCXX/inheriting-constructor-cleanup.mm index 229e84a0f5..a7770e07e4 100644 --- a/test/CodeGenObjCXX/inheriting-constructor-cleanup.mm +++ b/test/CodeGenObjCXX/inheriting-constructor-cleanup.mm @@ -23,7 +23,7 @@ void f() { } // CHECK-LABEL: define void @_Z1fv // CHECK: %[[TMP:.*]] = call i8* @_Z1gv() -// CHECK: {{.*}} = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[TMP]]) +// CHECK: {{.*}} = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[TMP]]) // CHECK: call void (%struct.Base*, i8*, ...) @_ZN4BaseC2E6Strongz(%struct.Base* {{.*}}, i8* {{.*}}) // CHECK-NEXT: call void @_ZN9InheritorD1Ev(%struct.Inheritor* {{.*}}) diff --git a/test/CodeGenObjCXX/literals.mm b/test/CodeGenObjCXX/literals.mm index 0a14d330bd..612d12dd13 100644 --- a/test/CodeGenObjCXX/literals.mm +++ b/test/CodeGenObjCXX/literals.mm @@ -29,7 +29,7 @@ void test_array() { // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[TMP_CAST]]) // CHECK-NEXT: call void @_ZN1XC1Ev({{.*}} [[TMPX]]) // CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv - // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[OBJECT0]]) + // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[OBJECT0]]) // CHECK: store i8* [[RET0]], i8** [[ELEMENT0]] // Initializing the second element @@ -38,7 +38,7 @@ void test_array() { // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[TMP_CAST]]) // CHECK-NEXT: invoke void @_ZN1YC1Ev({{.*}} [[TMPY]]) // CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv - // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[OBJECT1]]) + // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[OBJECT1]]) // CHECK: store i8* [[RET1]], i8** [[ELEMENT1]] // Build the array @@ -83,14 +83,14 @@ void test_array_instantiation() { // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 0 // CHECK: call void @_ZN1XC1Ev // CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv - // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[OBJECT0]]) + // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[OBJECT0]]) // CHECK: store i8* [[RET0]], i8** [[ELEMENT0]] // Initializing the second element // CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 1 // CHECK: invoke void @_ZN1YC1Ev // CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv - // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[OBJECT1]]) + // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[OBJECT1]]) // CHECK: store i8* [[RET1]], i8** [[ELEMENT1]] // Build the array diff --git a/test/CodeGenObjCXX/msabi-stret.mm b/test/CodeGenObjCXX/msabi-stret.mm index 765c23887b..66e407af27 100644 --- a/test/CodeGenObjCXX/msabi-stret.mm +++ b/test/CodeGenObjCXX/msabi-stret.mm @@ -13,6 +13,5 @@ S f() { return [I m:S()]; } -// CHECK: declare dllimport void @objc_msgSend_stret(i8*, i8*, ...) +// CHECK: declare dso_local void @objc_msgSend_stret(i8*, i8*, ...) // CHECK-NOT: declare dllimport void @objc_msgSend(i8*, i8*, ...) - diff --git a/test/CodeGenObjCXX/os_log.mm b/test/CodeGenObjCXX/os_log.mm new file mode 100644 index 0000000000..78bc902f73 --- /dev/null +++ b/test/CodeGenObjCXX/os_log.mm @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-darwin-apple -fobjc-arc \ +// RUN: -fexceptions -fcxx-exceptions -O1 | FileCheck %s + +// Check that no EH cleanup is emitted around the call to __os_log_helper. +namespace no_eh_cleanup { + void release(int *lock); + + // CHECK-LABEL: define {{.*}} @_ZN13no_eh_cleanup3logERiPcS1_( + void log(int &i, char *data, char *buf) { + int lock __attribute__((cleanup(release))); + // CHECK: call void @__os_log_helper_1_2_2_4_0_8_34( + // CHECK-NEXT: call void @_ZN13no_eh_cleanup7releaseEPi + __builtin_os_log_format(buf, "%d %{public}s", i, data); + } + + // CHECK: define {{.*}} @__os_log_helper_1_2_2_4_0_8_34({{.*}} [[NUW:#[0-9]+]] +} + +// CHECK: attributes [[NUW]] = { {{.*}}nounwind diff --git a/test/CodeGenObjCXX/property-lvalue-lambda.mm b/test/CodeGenObjCXX/property-lvalue-lambda.mm new file mode 100644 index 0000000000..4bc6ca6f07 --- /dev/null +++ b/test/CodeGenObjCXX/property-lvalue-lambda.mm @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fblocks -disable-llvm-passes -triple x86_64-apple-darwin10 -std=c++17 -emit-llvm -o - %s | FileCheck %s + +typedef void (^blk_t)(); +typedef void (*fnptr_t)(); + +@interface X +@property blk_t blk; +@property fnptr_t fnptr; +@end + +template <class T> +blk_t operator+(blk_t lhs, T) { return lhs; } + +template <class T> +fnptr_t operator+(fnptr_t lhs, T) { return lhs; } + +// CHECK-LABEL: define void @_Z2t1P1X +void t1(X *x) { + // Check that we call lambda.operator blk_t(), and that we send that result to + // the setter. + + // CHECK: [[CALL:%.*]] = call void ()* @"_ZZ2t1P1XENK3$_0cvU13block_pointerFvvEEv" + // CHECK: call void{{.*}}@objc_msgSend{{.*}}({{.*}} void ()* [[CALL]]) + x.blk = [] {}; + + // CHECK: [[CALL2:%.*]] = call void ()* @"_ZZ2t1P1XENK3$_1cvPFvvEEv" + // CHECK: call void{{.*}}@objc_msgSend{{.*}}({{.*}} void ()* [[CALL2]]) + x.fnptr = [] {}; +} + +// CHECK-LABEL: define void @_Z2t2P1X +void t2(X *x) { + // Test the case when the lambda isn't unique. (see OpaqueValueExpr::isUnique) + // FIXME: This asserts if the lambda isn't trivially copy/movable. + + // [x setBlk: operator+([x blk], [] {})] + + // CHECK: call void{{.*}}@objc_msgSend{{.*}} + // CHECK: [[PLUS:%.*]] = call void ()* @"_ZplIZ2t2P1XE3$_2EU13block_pointerFvvES4_T_" + // CHECK: call void{{.*}}@objc_msgSend{{.*}}({{.*}} [[PLUS]]) + x.blk += [] {}; + + // CHECK: call void{{.*}}@objc_msgSend{{.*}} + // CHECK: [[PLUS:%.*]] = call void ()* @"_ZplIZ2t2P1XE3$_3EPFvvES4_T_" + // CHECK: call void{{.*}}@objc_msgSend{{.*}}({{.*}} [[PLUS]]) + x.fnptr += [] {}; +} |