diff options
Diffstat (limited to 'test/CodeGenObjC')
69 files changed, 1527 insertions, 525 deletions
diff --git a/test/CodeGenObjC/arc-arm.m b/test/CodeGenObjC/arc-arm.m index 2ab8cb6..3989f56 100644 --- a/test/CodeGenObjC/arc-arm.m +++ b/test/CodeGenObjC/arc-arm.m @@ -11,9 +11,9 @@ void test1(void) { extern id test1_helper(void); // CHECK: [[T0:%.*]] = call arm_aapcscc i8* @test1_helper() // CHECK-NEXT: call void asm sideeffect "mov\09r7, r7 - // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T1:%.*]] = call arm_aapcscc i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) // CHECK-NEXT: store i8* [[T1]], - // CHECK-NEXT: call void @objc_storeStrong( + // CHECK-NEXT: call arm_aapcscc void @objc_storeStrong( // CHECK-NEXT: ret void id x = test1_helper(); } diff --git a/test/CodeGenObjC/arc-block-copy-escape.m b/test/CodeGenObjC/arc-block-copy-escape.m index 15c0d1d..3ba7426 100644 --- a/test/CodeGenObjC/arc-block-copy-escape.m +++ b/test/CodeGenObjC/arc-block-copy-escape.m @@ -9,14 +9,16 @@ void use_int(int); void test0(int i) { block_t block = ^{ use_int(i); }; // CHECK: define void @test0( - // CHECK: call i8* @objc_retainBlock(i8* {{%.*}}) nounwind, !clang.arc.copy_on_escape + // CHECK: call i8* @objc_retainBlock(i8* {{%.*}}) [[NUW:#[0-9]+]], !clang.arc.copy_on_escape // CHECK: ret void } void test1(int i) { id block = ^{ use_int(i); }; // CHECK: define void @test1( - // CHECK: call i8* @objc_retainBlock(i8* {{%.*}}) nounwind + // CHECK: call i8* @objc_retainBlock(i8* {{%.*}}) [[NUW]] // CHECK-NOT: !clang.arc.copy_on_escape // CHECK: ret void } + +// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenObjC/arc-blocks.m b/test/CodeGenObjC/arc-blocks.m index e776517..3281b2a 100644 --- a/test/CodeGenObjC/arc-blocks.m +++ b/test/CodeGenObjC/arc-blocks.m @@ -13,10 +13,10 @@ int (^test1(int x))(void) { // CHECK-NEXT: store i32 {{%.*}}, i32* [[X]] // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to i32 ()* // CHECK-NEXT: [[T1:%.*]] = bitcast i32 ()* [[T0]] to i8* - // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) nounwind + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) [[NUW:#[0-9]+]] // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i32 ()* // CHECK-NEXT: [[T4:%.*]] = bitcast i32 ()* [[T3]] to i8* - // CHECK-NEXT: [[T5:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[T4]]) nounwind + // CHECK-NEXT: [[T5:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T4]]) [[NUW]] // CHECK-NEXT: [[T6:%.*]] = bitcast i8* [[T5]] to i32 ()* // CHECK-NEXT: ret i32 ()* [[T6]] return ^{ return x; }; @@ -36,9 +36,9 @@ void test2(id x) { // CHECK-NEXT: bitcast // CHECK-NEXT: call void @test2_helper( // CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOTREL]] -// CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release +// CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]] -// CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release +// CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release // CHECK-NEXT: ret void extern void test2_helper(id (^)(void)); test2_helper(^{ return x; }); @@ -50,7 +50,7 @@ void test2(id x) { // CHECK-NEXT: [[DST:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]* // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[SRC]], i32 0, i32 5 // CHECK-NEXT: [[T1:%.*]] = load i8** [[T0]] -// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) nounwind +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) [[NUW]] // CHECK-NEXT: ret void // CHECK: define internal void @__destroy_helper_block_ @@ -80,13 +80,14 @@ void test3(void (^sink)(id*)) { // CHECK-NEXT: bitcast // CHECK-NEXT: getelementptr // CHECK-NEXT: [[BLOCK:%.*]] = bitcast - // CHECK-NEXT: [[T0:%.*]] = load i8** [[STRONG]] - // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP]] + // CHECK-NEXT: [[V:%.*]] = load i8** [[STRONG]] + // CHECK-NEXT: store i8* [[V]], i8** [[TEMP]] // CHECK-NEXT: [[F0:%.*]] = load i8** // CHECK-NEXT: [[F1:%.*]] = bitcast i8* [[F0]] to void (i8*, i8**)* // CHECK-NEXT: call void [[F1]](i8* [[BLOCK]], i8** [[TEMP]]) // CHECK-NEXT: [[T0:%.*]] = load i8** [[TEMP]] // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) + // CHECK-NEXT: call void (...)* @clang.arc.use(i8* [[V]]) [[NUW]] // CHECK-NEXT: [[T2:%.*]] = load i8** [[STRONG]] // CHECK-NEXT: store i8* [[T1]], i8** [[STRONG]] // CHECK-NEXT: call void @objc_release(i8* [[T2]]) @@ -111,8 +112,8 @@ void test4(void) { // CHECK: [[VAR:%.*]] = alloca [[BYREF_T:%.*]], // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 2 - // 0x02000000 - has copy/dispose helpers - // CHECK-NEXT: store i32 33554432, i32* [[T0]] + // 0x02000000 - has copy/dispose helpers strong + // CHECK-NEXT: store i32 838860800, i32* [[T0]] // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6 // CHECK-NEXT: [[T0:%.*]] = call i8* @test4_source() // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) @@ -127,7 +128,7 @@ void test4(void) { // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8) // CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]] // CHECK-NEXT: call void @objc_release(i8* [[T0]]) - // CHECK-NEXT: ret void + // CHECK: ret void // CHECK: define internal void @__Block_byref_object_copy_ // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6 @@ -190,8 +191,8 @@ void test6(void) { // CHECK: [[VAR:%.*]] = alloca [[BYREF_T:%.*]], // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 2 - // 0x02000000 - has copy/dispose helpers - // CHECK-NEXT: store i32 33554432, i32* [[T0]] + // 0x02000000 - has copy/dispose helpers weak + // CHECK-NEXT: store i32 1107296256, i32* [[T0]] // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6 // CHECK-NEXT: [[T0:%.*]] = call i8* @test6_source() // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) @@ -206,7 +207,7 @@ void test6(void) { // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8* // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8) // CHECK-NEXT: call void @objc_destroyWeak(i8** [[SLOT]]) - // CHECK-NEXT: ret void + // CHECK: ret void // CHECK: define internal void @__Block_byref_object_copy_ // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6 @@ -250,18 +251,19 @@ void test7(void) { // 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT // CHECK: store i32 -1040187392, // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 - // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeak(i8** [[VAR]]) + // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[VAR]]) // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T0]]) // CHECK: call void @test7_helper( // CHECK-NEXT: call void @objc_destroyWeak(i8** {{%.*}}) // CHECK-NEXT: call void @objc_destroyWeak(i8** [[VAR]]) - // CHECK-NEXT: ret void + // CHECK: ret void // CHECK: define internal void @__test7_block_invoke // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* {{%.*}}, i32 0, i32 5 - // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeak(i8** [[SLOT]]) + // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[SLOT]]) // CHECK-NEXT: call void @test7_consume(i8* [[T0]]) - // CHECK-NEXT: ret void + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + // CHECK: ret void // CHECK: define internal void @__copy_helper_block_ // CHECK: getelementptr @@ -294,7 +296,7 @@ void test7(void) { // CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[D0]] // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8* // CHECK-NEXT: call void @objc_release(i8* [[T2]]) -// CHECK-NEXT: ret void +// CHECK: ret void extern void test8_helper(void (^)(void)); test8_helper(^{ (void) self; }); @@ -313,7 +315,7 @@ id test9(void) { // CHECK: load i8** getelementptr // CHECK-NEXT: bitcast i8* // CHECK-NEXT: call i8* -// CHECK-NEXT: call i8* @objc_autoreleaseReturnValue +// CHECK-NEXT: tail call i8* @objc_autoreleaseReturnValue // CHECK-NEXT: ret i8* // CHECK: call i8* @test9_produce() @@ -352,7 +354,7 @@ void test10a(void) { // CHECK-NEXT: [[T1:%.*]] = load void ()** [[SLOT]] // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8* // CHECK-NEXT: call void @objc_release(i8* [[T2]]) - // CHECK-NEXT: ret void + // CHECK: ret void } // <rdar://problem/10402698>: do this copy and dispose with @@ -372,7 +374,7 @@ void test10a(void) { // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()* // CHECK-NEXT: store void ()* [[T3]], void ()** [[D2]], align 8 -// CHECK-NEXT: ret void +// CHECK: ret void // CHECK: define internal void @__Block_byref_object_dispose // CHECK: [[T0:%.*]] = load i8** {{%.*}} @@ -416,7 +418,7 @@ void test10b(void) { // CHECK-NEXT: [[T1:%.*]] = load void ()** [[SLOT]] // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8* // CHECK-NEXT: call void @objc_release(i8* [[T2]]) - // CHECK-NEXT: ret void + // CHECK: ret void } // rdar://problem/10088932 @@ -436,7 +438,7 @@ void test11a(void) { // CHECK-NEXT: call void @test11_helper(i8* [[T4]]) // CHECK-NEXT: [[T5:%.*]] = bitcast void ()* [[T3]] to i8* // CHECK-NEXT: call void @objc_release(i8* [[T5]]) - // CHECK-NEXT: ret void + // CHECK: ret void } void test11b(void) { int x; @@ -454,7 +456,7 @@ void test11b(void) { // CHECK-NEXT: store i8* [[T4]], i8** [[B]], align 8 // CHECK-NEXT: [[T5:%.*]] = load i8** [[B]] // CHECK-NEXT: call void @objc_release(i8* [[T5]]) - // CHECK-NEXT: ret void + // CHECK: ret void } // rdar://problem/9979150 @@ -613,8 +615,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]], @@ -622,8 +624,8 @@ void test18(id x) { // CHECK-UNOPT-NEXT: store i8* [[T1]], i8** [[SLOT]], // CHECK-UNOPT-NEXT: bitcast // CHECK-UNOPT-NEXT: call void @test18_helper( -// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[SLOTREL]], i8* null) nounwind -// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null) nounwind +// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[SLOTREL]], i8* null) [[NUW:#[0-9]+]] +// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null) [[NUW]] // CHECK-UNOPT-NEXT: ret void extern void test18_helper(id (^)(void)); test18_helper(^{ return x; }); @@ -637,7 +639,7 @@ void test18(id x) { // CHECK-UNOPT-NEXT: [[T1:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[DST]], i32 0, i32 5 // CHECK-UNOPT-NEXT: [[T2:%.*]] = load i8** [[T0]] // CHECK-UNOPT-NEXT: store i8* null, i8** [[T1]] -// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T1]], i8* [[T2]]) nounwind +// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T1]], i8* [[T2]]) [[NUW]] // CHECK-UNOPT-NEXT: ret void // CHECK-UNOPT: define internal void @__destroy_helper_block_ @@ -647,3 +649,6 @@ void test18(id x) { // CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null) // CHECK-UNOPT-NEXT: ret void } + +// CHECK: attributes [[NUW]] = { nounwind } +// CHECK-UNOPT: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenObjC/arc-captured-32bit-block-var-layout-2.m b/test/CodeGenObjC/arc-captured-32bit-block-var-layout-2.m new file mode 100644 index 0000000..3072316 --- /dev/null +++ b/test/CodeGenObjC/arc-captured-32bit-block-var-layout-2.m @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple i386-apple-darwin -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-32.layout +// RUN: FileCheck --input-file=%t-32.layout %s +// rdar://12184410 +// rdar://12752901 + +@class NSString; +extern void NSLog(NSString *format, ...); +extern int printf(const char *, ...); + +int main() { + NSString *strong; + unsigned long long eightByte = 0x8001800181818181ull; + // Test1 +// CHECK: block variable layout: BL_NON_OBJECT_WORD:3, BL_STRONG:1, BL_OPERATOR:0 + void (^block1)() = ^{ printf("%#llx", eightByte); NSLog(@"%@", strong); }; + + // Test2 + int i = 1; +// CHECK: block variable layout: BL_NON_OBJECT_WORD:3, BL_STRONG:1, BL_OPERATOR:0 + void (^block2)() = ^{ printf("%#llx, %d", eightByte, i); NSLog(@"%@", strong); }; + + // Test3 + char ch = 'a'; +// CHECK: block variable layout: BL_NON_OBJECT_WORD:3, BL_STRONG:1, BL_OPERATOR:0 + void (^block3)() = ^{ printf("%c %#llx", ch, eightByte); NSLog(@"%@", strong); }; + + // Test4 + unsigned long fourByte = 0x8001ul; +// block variable layout: BL_NON_OBJECT_WORD:1, BL_STRONG:1, BL_OPERATOR:0 +// CHECK: Inline instruction for block variable layout: 0x0100 + void (^block4)() = ^{ printf("%c %#lx", ch, fourByte); NSLog(@"%@", strong); }; + + // Test5 +// CHECK: block variable layout: BL_NON_OBJECT_WORD:3, BL_STRONG:1, BL_OPERATOR:0 + void (^block5)() = ^{ NSLog(@"%@", strong); printf("%c %#llx", ch, eightByte); }; + + // Test6 +// CHECK: block variable layout: BL_OPERATOR:0 + void (^block6)() = ^{ printf("%#llx", eightByte); }; +} + +/** +struct __block_literal_generic { // 32bytes (64bit) and 20 bytes (32bit). +0 void *__isa; +4 int __flags; +8 int __reserved; +12 void (*__invoke)(void *); +16 struct __block_descriptor *__descriptor; +}; +*/ diff --git a/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m b/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m index 6c72138..7ecdb4b 100644 --- a/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m +++ b/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m @@ -1,6 +1,7 @@ -// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple i386-apple-darwin -O0 -emit-llvm %s -o %t-64.s -// RUN: FileCheck --input-file=%t-64.s %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple i386-apple-darwin -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-32.layout +// RUN: FileCheck --input-file=%t-32.layout %s // rdar://12184410 +// rdar://12752901 void x(id y) {} void y(int a) {} @@ -32,8 +33,7 @@ void f() { // and a descriptor pointer). // Test 1 -// block variable layout: BL_BYREF:1, BL_STRONG:3, BL_BYREF:1, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"@2@\00" +// CHECK: Inline instruction for block variable layout: 0x0320 void (^b)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -44,8 +44,7 @@ void f() { b(); // Test 2 -// block variable layout: BL_BYREF:1, BL_STRONG:3, BL_WEAK:1, BL_BYREF:2, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"@2PA\00" +// CHECK: Inline instruction for block variable layout: 0x0331 void (^c)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -66,8 +65,7 @@ void g() { unsigned int i; NSString *y; NSString *z; -// block variable layout: BL_STRONG:2, BL_WEAK:1, BL_STRONG:2, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"!1P1\00" +// CHECK: Inline instruction for block variable layout: 0x0401 void (^c)() = ^{ int j = i + bletch; x(foo); @@ -112,7 +110,7 @@ void h() { block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, BL_NON_OBJECT_WORD:3, BL_BYREF:1, BL_OPERATOR:0 */ -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [7 x i8] c" ` `\22@\00" +// CHECK: block variable layout: BL_BYREF:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_OPERATOR:0 void (^c)() = ^{ x(s2.ui.o1); x(u2.o1); @@ -127,8 +125,7 @@ void arr1() { __unsafe_unretained id unsafe_unretained_var[4]; } imported_s; -// block variable layout: BL_UNRETAINE:4, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"c\00" +// CHECK: block variable layout: BL_UNRETAINED:4, BL_OPERATOR:0 void (^c)() = ^{ x(imported_s.unsafe_unretained_var[2]); }; @@ -143,8 +140,7 @@ void arr2() { __unsafe_unretained id unsafe_unretained_var[4]; } imported_s; -// block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINE:4, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c" c\00" +// CHECK: block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINED:4, BL_OPERATOR:0 void (^c)() = ^{ x(imported_s.unsafe_unretained_var[2]); }; @@ -159,8 +155,7 @@ void arr3() { __unsafe_unretained id unsafe_unretained_var[0]; } imported_s; -// block variable layout: BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 void (^c)() = ^{ int i = imported_s.a; }; @@ -186,15 +181,7 @@ void arr4() { } f4[2][2]; } captured_s; -/** -block variable layout: BL_UNRETAINE:3, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_OPERATOR:0 -*/ -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [10 x i8] +// CHECK: block variable layout: BL_UNRETAINED:3, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_OPERATOR:0 void (^c)() = ^{ id i = captured_s.f0.s_f1; }; @@ -212,8 +199,7 @@ void bf1() { int flag4: 24; } s; -// block variable layout: BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 int (^c)() = ^{ return s.flag; }; @@ -226,8 +212,7 @@ void bf2() { int flag : 1; } s; -// block variable layout: BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 int (^c)() = ^{ return s.flag; }; @@ -258,8 +243,7 @@ void bf3() { unsigned int _filler : 32; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags._draggedNodesAreDeletable; }; @@ -294,8 +278,7 @@ void bf4() { unsigned int _filler : 32; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags._draggedNodesAreDeletable; }; @@ -313,8 +296,7 @@ void bf5() { unsigned char flag1 : 1; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags.flag; }; @@ -331,8 +313,7 @@ void bf6() { unsigned char flag1 : 1; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags.flag; }; @@ -348,8 +329,7 @@ void Test7() { __weak id wid9, wid10, wid11, wid12; __weak id wid13, wid14, wid15, wid16; const id bar = (id) opaque_id(); -//block variable layout: BL_STRONG:1, BL_WEAK:16, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"0_\00" +// CHECK: block variable layout: BL_STRONG:1, BL_WEAK:16, BL_OPERATOR:0 void (^b)() = ^{ x(bar); x(wid1); @@ -384,8 +364,7 @@ __weak id wid; __weak id w9, w10, w11, w12; __weak id w13, w14, w15, w16; const id bar = (id) opaque_id(); -// block variable layout: BL_STRONG:1, BL_WEAK:16, BL_WEAK:16, BL_WEAK:1, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] +// CHECK: block variable layout: BL_STRONG:1, BL_WEAK:16, BL_WEAK:16, BL_WEAK:1, BL_OPERATOR:0 void (^b)() = ^{ x(bar); x(wid1); diff --git a/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m b/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m index b930737..28c5bb4 100644 --- a/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m +++ b/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple i386-apple-darwin -O0 -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-i386 %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout +// RUN: FileCheck --input-file=%t-64.layout %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple i386-apple-darwin -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-32.layout +// RUN: FileCheck -check-prefix=CHECK-i386 --input-file=%t-32.layout %s // rdar://12184410 void x(id y) {} @@ -15,25 +17,22 @@ void f() { __block id byref_bab = (id)0; __block id bl_var1; -// Inline instruction for block variable layout: 0x0100 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 256 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 256 } +// CHECK: Inline instruction for block variable layout: 0x0100 +// CHECK-i386: Inline instruction for block variable layout: 0x0100 void (^b)() = ^{ x(bar); }; -// Inline instruction for block variable layout: 0x0210 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 528 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 528 } +// CHECK: Inline instruction for block variable layout: 0x0210 +// CHECK-i386: Inline instruction for block variable layout: 0x0210 void (^c)() = ^{ x(bar); x(baz); byref_int = 1; }; -// Inline instruction for block variable layout: 0x0230 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 560 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 560 } +// CHECK: Inline instruction for block variable layout: 0x0230 +// CHECK-i386: Inline instruction for block variable layout: 0x0230 void (^d)() = ^{ x(bar); x(baz); @@ -42,9 +41,8 @@ void f() { byref_bab = 0; }; -// Inline instruction for block variable layout: 0x0231 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 561 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 561 } +// CHECK: Inline instruction for block variable layout: 0x0231 +// CHECK-i386: Inline instruction for block variable layout: 0x0231 __weak id wid; id (^e)() = ^{ x(bar); @@ -55,9 +53,8 @@ void f() { return wid; }; -// Inline instruction for block variable layout: 0x0235 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 565 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 565 } +// CHECK: Inline instruction for block variable layout: 0x0235 +// CHECK-i386: Inline instruction for block variable layout: 0x0235 __weak id wid1, wid2, wid3, wid4; id (^f)() = ^{ x(bar); @@ -72,9 +69,8 @@ void f() { return wid; }; -// Inline instruction for block variable layout: 0x035 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 53 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 53 } +// CHECK: Inline instruction for block variable layout: 0x035 +// CHECK-i386: Inline instruction for block variable layout: 0x035 id (^g)() = ^{ byref_int = 1; bl_var1 = 0; @@ -86,27 +82,41 @@ void f() { return wid; }; -// Inline instruction for block variable layout: 0x01 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 1 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 1 } +// CHECK: Inline instruction for block variable layout: 0x01 +// CHECK-i386: Inline instruction for block variable layout: 0x01 id (^h)() = ^{ return wid; }; -// Inline instruction for block variable layout: 0x020 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 32 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 32 } +// CHECK: Inline instruction for block variable layout: 0x020 +// CHECK-i386: Inline instruction for block variable layout: 0x020 void (^ii)() = ^{ byref_int = 1; byref_bab = 0; }; -// Inline instruction for block variable layout: 0x0102 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 258 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 258 } +// CHECK: Inline instruction for block variable layout: 0x0102 +// CHECK-i386: Inline instruction for block variable layout: 0x0102 void (^jj)() = ^{ x(bar); x(wid1); x(wid2); }; } + +// rdar://12752901 +@class NSString; +extern void NSLog(NSString *format, ...); +typedef void (^dispatch_block_t)(void); +int main() { + __strong NSString *s1 = 0; + __strong NSString *s2 = 0; + __weak NSString *w1 = 0; + + +// CHECK: Inline instruction for block variable layout: 0x0201 +// CHECK-i386: Inline instruction for block variable layout: 0x0201 + dispatch_block_t block2 = ^{ + NSLog(@"%@, %@, %@", s1, w1, s2); + }; +} diff --git a/test/CodeGenObjC/arc-captured-block-var-layout.m b/test/CodeGenObjC/arc-captured-block-var-layout.m index 77f042e..bc20307 100644 --- a/test/CodeGenObjC/arc-captured-block-var-layout.m +++ b/test/CodeGenObjC/arc-captured-block-var-layout.m @@ -1,6 +1,7 @@ -// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -emit-llvm %s -o %t-64.s -// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.layout %s // rdar://12184410 +// rdar://12752901 void x(id y) {} void y(int a) {} @@ -32,8 +33,8 @@ void f() { // and a descriptor pointer). // Test 1 -// block variable layout: BL_BYREF:1, BL_STRONG:3, BL_BYREF:1, BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"@2@\00" +// Inline instruction for block variable layout: 0x0320 (3 strong 2 byref) +// CHECK-LP64: Inline instruction for block variable layout: 0x0320 void (^b)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -44,8 +45,8 @@ void f() { b(); // Test 2 -// block variable layout: BL_BYREF:1, BL_STRONG:3, BL_WEAK:1, BL_BYREF:2, BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"@2PA\00" +// Inline instruction for block variable layout: 0x0331 (3 strong 3 byref 1 weak) +// CHECK-LP64: Inline instruction for block variable layout: 0x0331 void (^c)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -66,8 +67,8 @@ void g() { unsigned int i; NSString *y; NSString *z; -// block variable layout: BL_STRONG:2, BL_WEAK:1, BL_STRONG:2, BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"1P1\00" +// Inline instruction for block variable layout: 0x0401 (4 strong 0 byref 1 weak) +// CHECK-LP64: Inline instruction for block variable layout: 0x0401 void (^c)() = ^{ int j = i + bletch; x(foo); @@ -108,11 +109,7 @@ void h() { union U u2; __block id block_id; -/** -block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, BL_NON_OBJECT_WORD:1, - BL_UNRETAINE:1, BL_NON_OBJECT_WORD:3, BL_BYREF:1, BL_OPERATOR:0 -*/ -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [7 x i8] c" ` `\22@\00" +// CHECK-LP64: block variable layout: BL_BYREF:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_OPERATOR:0 void (^c)() = ^{ x(s2.ui.o1); x(u2.o1); @@ -127,8 +124,7 @@ void arr1() { __unsafe_unretained id unsafe_unretained_var[4]; } imported_s; -// block variable layout: BL_UNRETAINE:4, BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"c\00" +// CHECK-LP64: block variable layout: BL_UNRETAINED:4, BL_OPERATOR:0 void (^c)() = ^{ x(imported_s.unsafe_unretained_var[2]); }; @@ -143,8 +139,7 @@ void arr2() { __unsafe_unretained id unsafe_unretained_var[4]; } imported_s; -// block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINE:4, BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c" c\00" +// CHECK-LP64: block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINED:4, BL_OPERATOR:0 void (^c)() = ^{ x(imported_s.unsafe_unretained_var[2]); }; @@ -159,8 +154,7 @@ void arr3() { __unsafe_unretained id unsafe_unretained_var[0]; } imported_s; -// block variable layout: BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK-LP64: block variable layout: BL_OPERATOR:0 void (^c)() = ^{ int i = imported_s.a; }; @@ -186,15 +180,7 @@ void arr4() { } f4[2][2]; } captured_s; -/** -block variable layout: BL_UNRETAINE:3, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_OPERATOR:0 -*/ -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [10 x i8] +// CHECK-LP64: block variable layout: BL_UNRETAINED:3, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_OPERATOR:0 void (^c)() = ^{ id i = captured_s.f0.s_f1; }; @@ -212,8 +198,7 @@ void bf1() { int flag4: 24; } s; -// block variable layout: BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK-LP64: block variable layout: BL_OPERATOR:0 int (^c)() = ^{ return s.flag; }; @@ -226,8 +211,7 @@ void bf2() { int flag : 1; } s; -// block variable layout: BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK-LP64: block variable layout: BL_OPERATOR:0 int (^c)() = ^{ return s.flag; }; @@ -258,8 +242,7 @@ void bf3() { unsigned int _filler : 32; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK-LP64: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags._draggedNodesAreDeletable; }; @@ -294,8 +277,7 @@ void bf4() { unsigned int _filler : 32; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK-LP64: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags._draggedNodesAreDeletable; }; @@ -313,8 +295,7 @@ void bf5() { unsigned char flag1 : 1; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK-LP64: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags.flag; }; @@ -331,8 +312,7 @@ void bf6() { unsigned char flag1 : 1; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK-LP64: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags.flag; }; @@ -348,8 +328,7 @@ void Test7() { __weak id wid9, wid10, wid11, wid12; __weak id wid13, wid14, wid15, wid16; const id bar = (id) opaque_id(); -//block variable layout: BL_STRONG:1, BL_WEAK:16, BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"0_\00" +// CHECK-LP64: block variable layout: BL_STRONG:1, BL_WEAK:16, BL_OPERATOR:0 void (^b)() = ^{ x(bar); x(wid1); @@ -384,8 +363,7 @@ __weak id wid; __weak id w9, w10, w11, w12; __weak id w13, w14, w15, w16; const id bar = (id) opaque_id(); -// block variable layout: BL_STRONG:1, BL_WEAK:16, BL_WEAK:16, BL_WEAK:1, BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] +// CHECK-LP64: block variable layout: BL_STRONG:1, BL_WEAK:16, BL_WEAK:16, BL_WEAK:1, BL_OPERATOR:0 void (^b)() = ^{ x(bar); x(wid1); diff --git a/test/CodeGenObjC/arc-exceptions.m b/test/CodeGenObjC/arc-exceptions.m index 63945e3..aa3d2f3 100644 --- a/test/CodeGenObjC/arc-exceptions.m +++ b/test/CodeGenObjC/arc-exceptions.m @@ -17,12 +17,12 @@ void test0(void) { // CHECK: [[T0:%.*]] = call i8* @objc_begin_catch( // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]* // CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8* -// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) nounwind +// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) [[NUW:#[0-9]+]] // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]* // CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]] // CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8** -// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) nounwind -// CHECK-NEXT: call void @objc_end_catch() nounwind +// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) [[NUW]] +// CHECK-NEXT: call void @objc_end_catch() [[NUW]] void test1_helper(void); void test1(void) { @@ -38,7 +38,9 @@ void test1(void) { // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]* // CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8** // CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8* -// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) nounwind +// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) [[NUW]] // CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8** -// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) nounwind -// CHECK-NEXT: call void @objc_end_catch() nounwind +// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) [[NUW]] +// CHECK-NEXT: call void @objc_end_catch() [[NUW]] + +// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenObjC/arc-foreach.m b/test/CodeGenObjC/arc-foreach.m index b8d2d30..176b28d 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]]) [[NUW:#[0-9]+]] // Initialize the fast enumaration state. // CHECK-LP64-NEXT: [[T0:%.*]] = bitcast [[STATE_T]]* [[STATE]] to i8* @@ -84,7 +84,8 @@ void test0(NSArray *array) { // CHECK-LP64: define internal void @__test0_block_invoke // CHECK-LP64: [[BLOCK:%.*]] = bitcast i8* {{%.*}} to [[BLOCK_T]]* -// CHECK-LP64-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 +// CHECK-LP64-NOT: ret +// CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK-LP64-NEXT: [[T2:%.*]] = load i8** [[T0]], align 8 // CHECK-LP64-NEXT: call void @use(i8* [[T2]]) @@ -109,8 +110,9 @@ void test1(NSArray *array) { // CHECK-LP64: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 -// CHECK-LP64-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[X]]) +// CHECK-LP64-NEXT: [[T1:%.*]] = call i8* @objc_loadWeakRetained(i8** [[X]]) // CHECK-LP64-NEXT: call i8* @objc_initWeak(i8** [[T0]], i8* [[T1]]) +// CHECK-LP64-NEXT: call void @objc_release(i8* [[T1]]) // CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to // CHECK-LP64: call void @use_block // CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[D0]]) @@ -169,3 +171,5 @@ void test3(NSArray *array) { // CHECK-LP64-NEXT: call void @use(i8* [[T0]]) // CHECK-LP64-NEXT: br label [[L]] } + +// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenObjC/arc-literals.m b/test/CodeGenObjC/arc-literals.m index 203c2ad..78c5d9d 100644 --- a/test/CodeGenObjC/arc-literals.m +++ b/test/CodeGenObjC/arc-literals.m @@ -35,18 +35,28 @@ void test_numeric() { // CHECK: define void @test_array void test_array(id a, id b) { + // CHECK: [[A:%.*]] = alloca i8*, + // CHECK: [[B:%.*]] = alloca i8*, + // Retaining parameters // CHECK: call i8* @objc_retain(i8* // CHECK: call i8* @objc_retain(i8* // Constructing the array - // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS:%[A-Za-z0-9]+]], i32 0, i32 0 - // CHECK: store i8* - // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1 - // CHECK: store i8* - - // CHECK: {{call i8*.*objc_msgSend.*i64 2}} - // CHECK: call i8* @objc_retainAutoreleasedReturnValue + // CHECK: [[T0:%.*]] = getelementptr inbounds [2 x i8*]* [[OBJECTS:%[A-Za-z0-9]+]], i32 0, i32 0 + // CHECK-NEXT: [[V0:%.*]] = load i8** [[A]], + // CHECK-NEXT: store i8* [[V0]], i8** [[T0]] + // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1 + // CHECK-NEXT: [[V1:%.*]] = load i8** [[B]], + // CHECK-NEXT: store i8* [[V1]], i8** [[T0]] + + // CHECK-NEXT: [[T0:%.*]] = load [[CLASS_T:%.*]]** @"\01L_OBJC_CLASSLIST + // CHECK-NEXT: [[SEL:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES + // CHECK-NEXT: [[T1:%.*]] = bitcast [[CLASS_T]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = bitcast [2 x i8*]* [[OBJECTS]] to i8** + // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast ({{.*@objc_msgSend.*}})(i8* [[T1]], i8* [[SEL]], i8** [[T2]], i64 2) + // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T3]]) + // CHECK: call void (...)* @clang.arc.use(i8* [[V0]], i8* [[V1]]) id arr = @[a, b]; // CHECK: call void @objc_release @@ -57,6 +67,11 @@ void test_array(id a, id b) { // CHECK: define void @test_dictionary void test_dictionary(id k1, id o1, id k2, id o2) { + // CHECK: [[K1:%.*]] = alloca i8*, + // CHECK: [[O1:%.*]] = alloca i8*, + // CHECK: [[K2:%.*]] = alloca i8*, + // CHECK: [[O2:%.*]] = alloca i8*, + // Retaining parameters // CHECK: call i8* @objc_retain(i8* // CHECK: call i8* @objc_retain(i8* @@ -64,18 +79,29 @@ void test_dictionary(id k1, id o1, id k2, id o2) { // CHECK: call i8* @objc_retain(i8* // Constructing the arrays - // CHECK: getelementptr inbounds [2 x i8*]* [[KEYS:%[A-Za-z0-9]+]], i32 0, i32 0 - // CHECK: store i8* - // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS:%[A-Za-z0-9]+]], i32 0, i32 0 - // CHECK: store i8* - // CHECK: getelementptr inbounds [2 x i8*]* [[KEYS]], i32 0, i32 1 - // CHECK: store i8* - // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1 - // CHECK: store i8* + // CHECK: [[T0:%.*]] = getelementptr inbounds [2 x i8*]* [[KEYS:%[A-Za-z0-9]+]], i32 0, i32 0 + // CHECK-NEXT: [[V0:%.*]] = load i8** [[K1]], + // CHECK-NEXT: store i8* [[V0]], i8** [[T0]] + // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [2 x i8*]* [[OBJECTS:%[A-Za-z0-9]+]], i32 0, i32 0 + // CHECK-NEXT: [[V1:%.*]] = load i8** [[O1]], + // CHECK-NEXT: store i8* [[V1]], i8** [[T0]] + // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [2 x i8*]* [[KEYS]], i32 0, i32 1 + // CHECK-NEXT: [[V2:%.*]] = load i8** [[K2]], + // CHECK-NEXT: store i8* [[V2]], i8** [[T0]] + // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1 + // CHECK-NEXT: [[V3:%.*]] = load i8** [[O2]], + // CHECK-NEXT: store i8* [[V3]], i8** [[T0]] // Constructing the dictionary - // CHECK: {{call i8.*@objc_msgSend}} - // CHECK: call i8* @objc_retainAutoreleasedReturnValue + // CHECK-NEXT: [[T0:%.*]] = load [[CLASS_T:%.*]]** @"\01L_OBJC_CLASSLIST + // CHECK-NEXT: [[SEL:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES + // CHECK-NEXT: [[T1:%.*]] = bitcast [[CLASS_T]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = bitcast [2 x i8*]* [[OBJECTS]] to i8** + // CHECK-NEXT: [[T3:%.*]] = bitcast [2 x i8*]* [[KEYS]] to i8** + // CHECK-NEXT: [[T4:%.*]] = call i8* bitcast ({{.*@objc_msgSend.*}})(i8* [[T1]], i8* [[SEL]], i8** [[T2]], i8** [[T3]], i64 2) + // CHECK-NEXT: [[T5:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T4]]) + // CHECK-NEXT: call void (...)* @clang.arc.use(i8* [[V0]], i8* [[V1]], i8* [[V2]], i8* [[V3]]) + id dict = @{ k1 : o1, k2 : o2 }; // CHECK: call void @objc_release @@ -98,19 +124,36 @@ void test_property(B *b) { // Retain parameter // CHECK: call i8* @objc_retain + // CHECK: [[T0:%.*]] = getelementptr inbounds [1 x i8*]* [[OBJECTS:%.*]], i32 0, i32 0 + // Invoke 'prop' - // CHECK: load i8** @"\01L_OBJC_SELECTOR_REFERENCES - // CHECK: {{call.*@objc_msgSend}} - // CHECK: call i8* @objc_retainAutoreleasedReturnValue + // CHECK: [[SEL:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES + // CHECK-NEXT: [[T1:%.*]] = bitcast + // CHECK-NEXT: [[T2:%.*]] = call [[B:%.*]]* bitcast ({{.*}} @objc_msgSend to {{.*}})(i8* [[T1]], i8* [[SEL]]) + // CHECK-NEXT: [[T3:%.*]] = bitcast [[B]]* [[T2]] to i8* + // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T3]]) + // CHECK-NEXT: [[V0:%.*]] = bitcast i8* [[T4]] to [[B]]* + // CHECK-NEXT: [[V1:%.*]] = bitcast [[B]]* [[V0]] to i8* + + // Store to array. + // CHECK-NEXT: store i8* [[V1]], i8** [[T0]] // Invoke arrayWithObjects:count: - // CHECK: load i8** @"\01L_OBJC_SELECTOR_REFERENCES - // CHECK: {{call.*objc_msgSend}} - // CHECK: call i8* @objc_retainAutoreleasedReturnValue + // CHECK-NEXT: [[T0:%.*]] = load [[CLASS_T]]** @"\01L_OBJC_CLASSLIST + // CHECK-NEXT: [[SEL:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES + // CHECK-NEXT: [[T1:%.*]] = bitcast [[CLASS_T]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = bitcast [1 x i8*]* [[OBJECTS]] to i8** + // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast ({{.*}} @objc_msgSend to {{.*}}(i8* [[T1]], i8* [[SEL]], i8** [[T2]], i64 1) + // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue(i8* [[T3]]) + // CHECK-NEXT: call void (...)* @clang.arc.use(i8* [[V1]]) + // CHECK-NEXT: bitcast + // CHECK-NEXT: bitcast + // CHECK-NEXT: store id arr = @[ b.prop ]; // Release b.prop - // CHECK: call void @objc_release + // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* [[V0]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) // Destroy arr // CHECK: call void @objc_release diff --git a/test/CodeGenObjC/arc-loadweakretained-release.m b/test/CodeGenObjC/arc-loadweakretained-release.m new file mode 100644 index 0000000..00d25fa --- /dev/null +++ b/test/CodeGenObjC/arc-loadweakretained-release.m @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck %s +// rdar://10849570 + +@interface NSObject @end + +@interface SomeClass : NSObject +- (id) init; +@end + +@implementation SomeClass +- (void)foo { +} +- (id) init { + return 0; +} ++ alloc { return 0; } +@end + +int main (int argc, const char * argv[]) { + @autoreleasepool { + SomeClass *objPtr1 = [[SomeClass alloc] init]; + __weak SomeClass *weakRef = objPtr1; + + [weakRef foo]; + + objPtr1 = (void *)0; + return 0; + } +} + +// CHECK: [[SIXTEEN:%.*]] = call i8* @objc_loadWeakRetained(i8** {{%.*}}) +// CHECK-NEXT: [[SEVENTEEN:%.*]] = bitcast i8* [[SIXTEEN]] to {{%.*}} +// CHECK-NEXT: [[EIGHTEEN:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_6" +// CHECK-NEXT: [[NINETEEN:%.*]] = bitcast %0* [[SEVENTEEN]] to i8* +// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK-NEXT: [[TWENTY:%.*]] = bitcast %0* [[SEVENTEEN]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[TWENTY]]) + +void test1(int cond) { + extern void test34_sink(id *); + __weak id weak; + test34_sink(cond ? &weak : 0); +} + +// CHECK: define void @test1( +// CHECK: [[CONDADDR:%.*]] = alloca i32 +// CHECK-NEXT: [[WEAK:%.*]] = alloca i8* +// CHECK-NEXT: [[INCRTEMP:%.*]] = alloca i8* +// CHECK-NEXT: [[CONDCLEANUPSAVE:%.*]] = alloca i8* +// CHECK-NEXT: [[CONDCLEANUP:%.*]] = alloca i1 +// CHECK-NEXT: store i32 +// CHECK-NEXT: store i8* null, i8** [[WEAK]] +// CHECK: [[COND1:%.*]] = phi i8** +// CHECK-NEXT: [[ICRISNULL:%.*]] = icmp eq i8** [[COND1]], null +// CHECK-NEXT: [[ICRARGUMENT:%.*]] = select i1 [[ICRISNULL]], i8** null, i8** [[INCRTEMP]] +// CHECK-NEXT: store i1 false, i1* [[CONDCLEANUP]] +// CHECK-NEXT: br i1 [[ICRISNULL]], label [[ICRCONT:%.*]], label [[ICRCOPY:%.*]] +// CHECK: [[ONE:%.*]] = call i8* @objc_loadWeakRetained( +// CHECK-NEXT: store i8* [[ONE]], i8** [[CONDCLEANUPSAVE]] +// CHECK-NEXT: store i1 true, i1* [[CONDCLEANUP]] +// CHECK-NEXT: store i8* [[ONE]], i8** [[INCRTEMP]] +// CHECK-NEXT: br label + +// CHECK: call void @test34_sink( +// CHECK-NEXT: [[ICRISNULL1:%.*]] = icmp eq i8** [[COND1]], null +// CHECK-NEXT: br i1 [[ICRISNULL1]], label [[ICRDONE:%.*]], label [[ICRWRITEBACK:%.*]] +// CHECK: [[TWO:%.*]] = load i8** [[INCRTEMP]] +// CHECK-NEXT: [[THREE:%.*]] = call i8* @objc_storeWeak( +// CHECK-NEXT br label [[ICRDONE]] +// CHECK: [[CLEANUPISACTIVE:%.*]] = load i1* [[CONDCLEANUP]] +// CHECK-NEXT: br i1 [[CLEANUPISACTIVE]], label [[CLEASNUPACTION:%.*]], label [[CLEANUPDONE:%.*]] + +// CHECK: [[FOUR:%.*]] = load i8** [[CONDCLEANUPSAVE]] +// CHECK-NEXT: call void @objc_release(i8* [[FOUR]]) +// CHECK-NEXT: br label +// CHECK: call void @objc_destroyWeak(i8** [[WEAK]]) +// CHECK-NEXT: ret void diff --git a/test/CodeGenObjC/arc-no-arc-exceptions.m b/test/CodeGenObjC/arc-no-arc-exceptions.m index 7ae061f..008c848 100644 --- a/test/CodeGenObjC/arc-no-arc-exceptions.m +++ b/test/CodeGenObjC/arc-no-arc-exceptions.m @@ -10,7 +10,7 @@ void not(void) __attribute__((nothrow)); // CHECK: define void @test0( // CHECK: call void @thrower(), !clang.arc.no_objc_arc_exceptions ! -// CHECK: call void @not() nounwind, !clang.arc.no_objc_arc_exceptions ! +// CHECK: call void @not() [[NUW:#[0-9]+]], !clang.arc.no_objc_arc_exceptions ! // NO-METADATA: define void @test0( // NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions // NO-METADATA: } @@ -21,7 +21,7 @@ void test0(void) { // CHECK: define void @test1( // CHECK: call void @thrower(), !clang.arc.no_objc_arc_exceptions ! -// CHECK: call void @not() nounwind, !clang.arc.no_objc_arc_exceptions ! +// CHECK: call void @not() [[NUW]], !clang.arc.no_objc_arc_exceptions ! // NO-METADATA: define void @test1( // NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions // NO-METADATA: } @@ -76,3 +76,5 @@ void test4(void) { b(); } } + +// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenObjC/arc-precise-lifetime.m b/test/CodeGenObjC/arc-precise-lifetime.m new file mode 100644 index 0000000..595a4f9 --- /dev/null +++ b/test/CodeGenObjC/arc-precise-lifetime.m @@ -0,0 +1,120 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s + +#define PRECISE_LIFETIME __attribute__((objc_precise_lifetime)) + +id test0_helper(void) __attribute__((ns_returns_retained)); +void test0() { + PRECISE_LIFETIME id x = test0_helper(); + x = 0; + // CHECK: [[X:%.*]] = alloca i8* + // CHECK-NEXT: [[CALL:%.*]] = call i8* @test0_helper() + // CHECK-NEXT: store i8* [[CALL]], i8** [[X]] + + // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] + // CHECK-NEXT: store i8* null, i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW:#[0-9]+]] + // CHECK-NOT: clang.imprecise_release + + // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW:#[0-9]+]] + // CHECK-NOT: clang.imprecise_release + + // CHECK-NEXT: ret void +} + +// rdar://problem/9821110 +@interface Test1 +- (char*) interior __attribute__((objc_returns_inner_pointer)); +// Should we allow this on properties? +@end +extern Test1 *test1_helper(void); + +// CHECK: define void @test1a() +void test1a(void) { + // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* + // CHECK-NEXT: store [[TEST1]]* [[T3]] + // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]]) + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* + // CHECK-NEXT: [[T4:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8* + // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast + // CHECK-NEXT: store i8* [[T6]], i8** + // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release + // CHECK-NEXT: ret void + Test1 *ptr = test1_helper(); + char *c = [(ptr) interior]; +} + +// CHECK: define void @test1b() +void test1b(void) { + // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* + // CHECK-NEXT: store [[TEST1]]* [[T3]] + // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** + // CHECK-NEXT: [[T1:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* + // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast + // CHECK-NEXT: store i8* [[T3]], i8** + // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]] + // CHECK-NOT: clang.imprecise_release + // CHECK-NEXT: ret void + __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper(); + char *c = [ptr interior]; +} + +@interface Test2 { +@public + id ivar; +} +@end +// CHECK: define void @test2( +void test2(Test2 *x) { + x->ivar = 0; + // CHECK: [[X:%.*]] = alloca [[TEST2:%.*]]* + // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST2]]* {{%.*}} to i8* + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) [[NUW]] + // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST2]]* + // CHECK-NEXT: store [[TEST2]]* [[T2]], [[TEST2]]** [[X]], + + // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]** [[X]], + // CHECK-NEXT: [[OFFSET:%.*]] = load i64* @"OBJC_IVAR_$_Test2.ivar" + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8* [[T1]], i64 [[OFFSET]] + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8** + // CHECK-NEXT: [[T4:%.*]] = load i8** [[T3]], + // CHECK-NEXT: store i8* null, i8** [[T3]], + // CHECK-NEXT: call void @objc_release(i8* [[T4]]) [[NUW]] + // CHECK-NOT: imprecise + + // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]** [[X]] + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release + + // CHECK-NEXT: ret void +} + +// CHECK: define void @test3(i8* +void test3(PRECISE_LIFETIME id x) { + // CHECK: [[X:%.*]] = alloca i8*, + // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}}) [[NUW]] + // CHECK-NEXT: store i8* [[T0]], i8** [[X]], + + // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]] + // CHECK-NOT: imprecise_release + + // CHECK-NEXT: ret void +} + +// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenObjC/arc-property.m b/test/CodeGenObjC/arc-property.m index db00e36..dde02d7 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( @@ -62,7 +62,7 @@ static Class theGlobalClass; // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST2]]* [[T1]] to i8* // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8* [[T2]], i64 [[OFFSET]] // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** -// CHECK-NEXT: call void @objc_storeStrong(i8** [[T4]], i8* [[T0]]) nounwind +// CHECK-NEXT: call void @objc_storeStrong(i8** [[T4]], i8* [[T0]]) [[NUW:#[0-9]+]] // CHECK-NEXT: ret void // CHECK: define internal i8* @"\01-[Test2 theClass]"( @@ -83,5 +83,52 @@ static Class theGlobalClass; // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8* // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8* [[T1]], i64 [[OFFSET]] // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8** -// CHECK-NEXT: call void @objc_storeStrong(i8** [[T3]], i8* null) nounwind +// CHECK-NEXT: call void @objc_storeStrong(i8** [[T3]], i8* null) [[NUW]] // CHECK-NEXT: ret void + +// rdar://13115896 +@interface Test3 +@property id copyMachine; +@end + +void test3(Test3 *t) { + id x = t.copyMachine; + x = [t copyMachine]; +} +// CHECK: define void @test3([[TEST3:%.*]]* +// Prologue. +// CHECK: [[T:%.*]] = alloca [[TEST3]]*, +// CHECK-NEXT: [[X:%.*]] = alloca i8*, +// Property access. +// CHECK: [[T0:%.*]] = load [[TEST3]]** [[T]], +// CHECK-NEXT: [[SEL:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST3]]* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = call i8* bitcast ({{.*}} @objc_msgSend to {{.*}})(i8* [[T1]], i8* [[SEL]]) +// CHECK-NEXT: store i8* [[T2]], i8** [[X]], +// Message send. +// CHECK-NEXT: [[T0:%.*]] = load [[TEST3]]** [[T]], +// CHECK-NEXT: [[SEL:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST3]]* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = call i8* bitcast ({{.*}} @objc_msgSend to {{.*}})(i8* [[T1]], i8* [[SEL]]) +// CHECK-NEXT: [[T3:%.*]] = load i8** [[X]], +// CHECK-NEXT: store i8* [[T2]], i8** [[X]], +// CHECK-NEXT: call void @objc_release(i8* [[T3]]) +// Epilogue. +// CHECK-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null) +// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST3]]** [[T]] to i8** +// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) +// CHECK-NEXT: ret void + +@implementation Test3 +- (id) copyMachine { + extern id test3_helper(void); + return test3_helper(); +} +// CHECK: define internal i8* @"\01-[Test3 copyMachine]"( +// CHECK: [[T0:%.*]] = call i8* @test3_helper() +// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) +// CHECK-NEXT: ret i8* [[T1]] +- (void) setCopyMachine: (id) x {} +@end + +// CHECK: attributes [[NUW]] = { nounwind } 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 @@ 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-ternary-op.m b/test/CodeGenObjC/arc-ternary-op.m new file mode 100644 index 0000000..f70e886 --- /dev/null +++ b/test/CodeGenObjC/arc-ternary-op.m @@ -0,0 +1,138 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s + +void test0(_Bool cond) { + id test0_helper(void) __attribute__((ns_returns_retained)); + + // CHECK: define void @test0( + // CHECK: [[COND:%.*]] = alloca i8, + // CHECK-NEXT: [[X:%.*]] = alloca i8*, + // CHECK-NEXT: [[RELVAL:%.*]] = alloca i8* + // CHECK-NEXT: [[RELCOND:%.*]] = alloca i1 + // CHECK-NEXT: zext + // CHECK-NEXT: store + // CHECK-NEXT: [[T0:%.*]] = load i8* [[COND]] + // CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1 + // CHECK-NEXT: store i1 false, i1* [[RELCOND]] + // CHECK-NEXT: br i1 [[T1]], + // CHECK: br label + // CHECK: [[CALL:%.*]] = call i8* @test0_helper() + // CHECK-NEXT: store i8* [[CALL]], i8** [[RELVAL]] + // CHECK-NEXT: store i1 true, i1* [[RELCOND]] + // CHECK-NEXT: br label + // CHECK: [[T0:%.*]] = phi i8* [ null, {{%.*}} ], [ [[CALL]], {{%.*}} ] + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) [[NUW:#[0-9]+]] + // CHECK-NEXT: store i8* [[T1]], i8** [[X]], + // CHECK-NEXT: [[REL:%.*]] = load i1* [[RELCOND]] + // CHECK-NEXT: br i1 [[REL]], + // CHECK: [[T0:%.*]] = load i8** [[RELVAL]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]] + // CHECK-NEXT: br label + // CHECK: [[T0:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]] + // CHECK-NEXT: ret void + id x = (cond ? 0 : test0_helper()); +} + +void test1(int cond) { + __strong id strong; + __weak id weak; + extern void test1_sink(id *); + test1_sink(cond ? &strong : 0); + test1_sink(cond ? &weak : 0); + + // CHECK: define void @test1( + // CHECK: [[COND:%.*]] = alloca i32 + // CHECK-NEXT: [[STRONG:%.*]] = alloca i8* + // CHECK-NEXT: [[WEAK:%.*]] = alloca i8* + // CHECK-NEXT: [[TEMP1:%.*]] = alloca i8* + // CHECK-NEXT: [[TEMP2:%.*]] = alloca i8* + // CHECK-NEXT: [[CONDCLEANUPSAVE:%.*]] = alloca i8* + // CHECK-NEXT: [[CONDCLEANUP:%.*]] = alloca i1 + // CHECK-NEXT: store i32 + // CHECK-NEXT: store i8* null, i8** [[STRONG]] + // CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null) + + // CHECK-NEXT: [[T0:%.*]] = load i32* [[COND]] + // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0 + // CHECK: [[ARG:%.*]] = phi i8** + // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null + // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP1]] + // CHECK-NEXT: br i1 [[T0]], + // CHECK: [[T0:%.*]] = load i8** [[ARG]] + // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP1]] + // CHECK-NEXT: br label + // CHECK: [[W:%.*]] = phi i8* [ [[T0]], {{%.*}} ], [ undef, {{%.*}} ] + // CHECK-NEXT: call void @test1_sink(i8** [[T1]]) + // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null + // CHECK-NEXT: br i1 [[T0]], + // CHECK: [[T0:%.*]] = load i8** [[TEMP1]] + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) + // CHECK-NEXT: call void (...)* @clang.arc.use(i8* [[W]]) [[NUW]] + // CHECK-NEXT: [[T2:%.*]] = load i8** [[ARG]] + // CHECK-NEXT: store i8* [[T1]], i8** [[ARG]] + // CHECK-NEXT: call void @objc_release(i8* [[T2]]) + // CHECK-NEXT: br label + + // CHECK: [[T0:%.*]] = load i32* [[COND]] + // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0 + // CHECK: [[ARG:%.*]] = phi i8** + // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null + // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP2]] + // CHECK-NEXT: store i1 false, i1* [[CONDCLEANUP]] + // CHECK-NEXT: br i1 [[T0]], + // CHECK: [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[ARG]]) + // CHECK-NEXT: store i8* [[T0]], i8** [[CONDCLEANUPSAVE]] + // CHECK-NEXT: store i1 true, i1* [[CONDCLEANUP]] + // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP2]] + // CHECK-NEXT: br label + // CHECK: call void @test1_sink(i8** [[T1]]) + // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null + // CHECK-NEXT: br i1 [[T0]], + // CHECK: [[T0:%.*]] = load i8** [[TEMP2]] + // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[ARG]], i8* [[T0]]) + // CHECK-NEXT: br label + + // CHECK: call void @objc_destroyWeak(i8** [[WEAK]]) + // CHECK: ret void +} + +// rdar://13113981 +// Test that, when emitting an expression at +1 that we can't peephole, +// we emit the retain inside the full-expression. If we ever peephole +// +1s of conditional expressions (which we probably ought to), we'll +// need to find another example of something we need to do this for. +void test2(int cond) { + extern id test2_producer(void); + for (id obj in cond ? test2_producer() : (void*) 0) { + } + + // CHECK: define void @test2( + // CHECK: [[COND:%.*]] = alloca i32, + // CHECK: alloca i8* + // CHECK: [[CLEANUP_SAVE:%.*]] = alloca i8* + // CHECK: [[RUN_CLEANUP:%.*]] = alloca i1 + // Evaluate condition; cleanup disabled by default. + // CHECK: [[T0:%.*]] = load i32* [[COND]], + // CHECK-NEXT: icmp ne i32 [[T0]], 0 + // CHECK-NEXT: store i1 false, i1* [[RUN_CLEANUP]] + // CHECK-NEXT: br i1 + // Within true branch, cleanup enabled. + // CHECK: [[T0:%.*]] = call i8* @test2_producer() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: store i8* [[T1]], i8** [[CLEANUP_SAVE]] + // CHECK-NEXT: store i1 true, i1* [[RUN_CLEANUP]] + // CHECK-NEXT: br label + // Join point for conditional operator; retain immediately. + // CHECK: [[T0:%.*]] = phi i8* [ [[T1]], {{%.*}} ], [ null, {{%.*}} ] + // CHECK-NEXT: [[RESULT:%.*]] = call i8* @objc_retain(i8* [[T0]]) + // Leaving full-expression; run conditional cleanup. + // CHECK-NEXT: [[T0:%.*]] = load i1* [[RUN_CLEANUP]] + // CHECK-NEXT: br i1 [[T0]] + // CHECK: [[T0:%.*]] = load i8** [[CLEANUP_SAVE]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + // CHECK-NEXT: br label + // And way down at the end of the loop: + // CHECK: call void @objc_release(i8* [[RESULT]]) +} + +// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenObjC/arc-unopt.m b/test/CodeGenObjC/arc-unopt.m index c319bf2..84f5d34 100644 --- a/test/CodeGenObjC/arc-unopt.m +++ b/test/CodeGenObjC/arc-unopt.m @@ -9,7 +9,7 @@ Test0 *test0(void) { // CHECK: [[LD:%.*]] = load [[TEST0:%.*]]** @test0_helper // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST0]]* [[LD]] to i8* - // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleaseReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T1:%.*]] = tail call i8* @objc_retainAutoreleaseReturnValue(i8* [[T0]]) // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST0]]* // CHECK-NEXT: ret [[TEST0]]* [[T2]] } @@ -19,7 +19,7 @@ id test1(void) { return test1_helper; // CHECK: [[LD:%.*]] = load i8** @test1_helper - // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retainAutoreleaseReturnValue(i8* [[LD]]) + // CHECK-NEXT: [[T0:%.*]] = tail call i8* @objc_retainAutoreleaseReturnValue(i8* [[LD]]) // CHECK-NEXT: ret i8* [[T0]] } diff --git a/test/CodeGenObjC/arc-unoptimized-byref-var.m b/test/CodeGenObjC/arc-unoptimized-byref-var.m new file mode 100644 index 0000000..d3189e1 --- /dev/null +++ b/test/CodeGenObjC/arc-unoptimized-byref-var.m @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-UNOPT %s +// rdar://12530881 + +void test19() { + __block id x; +// CHECK-UNOPT: define internal void @__Block_byref_object_copy +// CHECK-UNOPT: [[X:%.*]] = getelementptr inbounds [[BYREF_T:%.*]]* [[VAR:%.*]], i32 0, i32 6 +// CHECK-UNOPT: [[X2:%.*]] = getelementptr inbounds [[BYREF_T:%.*]]* [[VAR1:%.*]], i32 0, i32 6 +// CHECK-UNOPT-NEXT: [[SIX:%.*]] = load i8** [[X2]], align 8 +// CHECK-UNOPT-NEXT: store i8* null, i8** [[X]], align 8 +// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X]], i8* [[SIX]]) [[NUW:#[0-9]+]] +// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X2]], i8* null) [[NUW]] +// CHECK-UNOPT-NEXT: ret void +} + +// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenObjC/arc-weak-property.m b/test/CodeGenObjC/arc-weak-property.m index 0a6b2a6..e8d57bc 100644 --- a/test/CodeGenObjC/arc-weak-property.m +++ b/test/CodeGenObjC/arc-weak-property.m @@ -22,7 +22,7 @@ // 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: [[T6:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T5]]) // CHECK-NEXT: ret i8* [[T6]] // CHECK: define internal void @"\01-[WeakPropertyTest setPROP:]" diff --git a/test/CodeGenObjC/arc-with-atthrow.m b/test/CodeGenObjC/arc-with-atthrow.m index 213b05b..2570376 100644 --- a/test/CodeGenObjC/arc-with-atthrow.m +++ b/test/CodeGenObjC/arc-with-atthrow.m @@ -13,5 +13,7 @@ void test() { // CHECK: [[T0:%.*]] = call i8* @make() // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_autorelease(i8* [[T1]]) -// CHECK-NEXT: call void @objc_exception_throw(i8* [[T2]]) noreturn +// CHECK-NEXT: call void @objc_exception_throw(i8* [[T2]]) [[NR:#[0-9]+]] // CHECK-NEXT: unreachable + +// CHECK: attributes [[NR]] = { noreturn } diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m index 8e38019..7262dc8 100644 --- a/test/CodeGenObjC/arc.m +++ b/test/CodeGenObjC/arc.m @@ -1,6 +1,37 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-GLOBALS %s +// rdar://13129783. Check both native/non-native arc platforms. Here we check +// that they treat nonlazybind differently. +// 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 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*, ...) [[NLB:#[0-9]+]] +// ARC-ALIEN: declare extern_weak void @objc_release(i8*) +// ARC-ALIEN: declare extern_weak i8* @objc_retainAutoreleasedReturnValue(i8*) +// ARC-ALIEN: declare extern_weak i8* @objc_initWeak(i8**, i8*) +// ARC-ALIEN: declare extern_weak i8* @objc_storeWeak(i8**, i8*) +// ARC-ALIEN: declare extern_weak i8* @objc_loadWeakRetained(i8**) +// ARC-ALIEN: declare extern_weak void @objc_destroyWeak(i8**) +// ARC-ALIEN: declare extern_weak i8* @objc_autorelease(i8*) +// ARC-ALIEN: declare extern_weak i8* @objc_retainAutorelease(i8*) + +// ARC-NATIVE: declare void @objc_storeStrong(i8**, i8*) +// ARC-NATIVE: declare i8* @objc_retain(i8*) [[NLB:#[0-9]+]] +// ARC-NATIVE: declare i8* @objc_autoreleaseReturnValue(i8*) +// ARC-NATIVE: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB]] +// ARC-NATIVE: declare void @objc_release(i8*) [[NLB]] +// ARC-NATIVE: declare i8* @objc_retainAutoreleasedReturnValue(i8*) +// ARC-NATIVE: declare i8* @objc_initWeak(i8**, i8*) +// ARC-NATIVE: declare i8* @objc_storeWeak(i8**, i8*) +// ARC-NATIVE: declare i8* @objc_loadWeakRetained(i8**) +// ARC-NATIVE: declare void @objc_destroyWeak(i8**) +// ARC-NATIVE: declare i8* @objc_autorelease(i8*) +// ARC-NATIVE: declare i8* @objc_retainAutorelease(i8*) + // CHECK: define void @test0 void test0(id x) { // CHECK: [[X:%.*]] = alloca i8* @@ -9,9 +40,6 @@ void test0(id x) { // CHECK-NEXT: [[TMP:%.*]] = load i8** [[X]] // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) // CHECK-NEXT: ret void -// rdar://12040837 - // CHECK: declare extern_weak i8* @objc_retain(i8*) nonlazybind - // CHECK: declare extern_weak void @objc_release(i8*) nonlazybind } // CHECK: define i8* @test1(i8* @@ -29,7 +57,7 @@ id test1(id x) { // CHECK-NEXT: call void @objc_release(i8* [[T0]]) // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] // CHECK-NEXT: call void @objc_release(i8* [[T1]]) - // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[RET]]) + // CHECK-NEXT: [[T1:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[RET]]) // CHECK-NEXT: ret i8* [[T1]] id y; return y; @@ -88,12 +116,12 @@ void test3_unelided() { // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST3]]* [[T0]] to i8* // CHECK-NEXT: [[COPY:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend {{.*}})(i8* [[T1]], - // CHECK-NEXT: call void @objc_release(i8* [[COPY]]) nounwind + // CHECK-NEXT: call void @objc_release(i8* [[COPY]]) [[NUW:#[0-9]+]] [x copy]; // CHECK-NEXT: [[T0:%.*]] = load [[TEST3]]** [[X]] // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST3]]* [[T0]] to i8* - // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]] // CHECK-NEXT: ret void } @@ -127,13 +155,13 @@ void test3() { // Assignment to x. // CHECK-NEXT: [[TMP:%.*]] = load i8** [[X]] // CHECK-NEXT: store i8* [[COPY]], i8** [[X]] - // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) nounwind + // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) [[NUW]] x = [x copy]; // Cleanup for x. // CHECK-NEXT: [[TMP:%.*]] = load i8** [[X]] - // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) nounwind + // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) [[NUW]] // CHECK-NEXT: ret void } @@ -156,7 +184,7 @@ id test4() { // Retain/release elided. // CHECK-NEXT: bitcast // CHECK-NEXT: [[INIT:%.*]] = bitcast - // CHECK-NEXT: [[RET:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[INIT]]) + // CHECK-NEXT: [[RET:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[INIT]]) // CHECK-NEXT: ret i8* [[RET]] @@ -188,7 +216,7 @@ void test5(Test5 *x, id y) { // CHECK-NEXT: [[VAR:%.*]] = bitcast // CHECK-NEXT: [[TMP:%.*]] = load i8** [[VAR]] // CHECK-NEXT: store i8* null, i8** [[VAR]] - // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) nounwind + // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) [[NUW]] x->var = 0; // CHECK-NEXT: [[YVAL:%.*]] = load i8** [[Y]] @@ -197,18 +225,18 @@ void test5(Test5 *x, id y) { // CHECK-NEXT: bitcast // CHECK-NEXT: getelementptr // CHECK-NEXT: [[VAR:%.*]] = bitcast - // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[YVAL]]) nounwind + // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[YVAL]]) [[NUW]] // CHECK-NEXT: [[TMP:%.*]] = load i8** [[VAR]] // CHECK-NEXT: store i8* [[T0]], i8** [[VAR]] - // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) nounwind + // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) [[NUW]] x->var = y; // Epilogue. // CHECK-NEXT: [[TMP:%.*]] = load i8** [[Y]] - // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) nounwind + // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) [[NUW]] // CHECK-NEXT: [[T0:%.*]] = load [[TEST5]]** [[X]] // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST5]]* [[T0]] to i8* - // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]] // CHECK-NEXT: ret void } @@ -219,7 +247,7 @@ void test6() { // CHECK-NEXT: [[CALL:%.*]] = call i8* @test6_helper() // CHECK-NEXT: store i8* [[CALL]], i8** [[X]] // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] - // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release // CHECK-NEXT: ret void id x = test6_helper(); } @@ -230,10 +258,10 @@ void test7() { // CHECK: [[X:%.*]] = alloca i8* // CHECK-NEXT: store i8* null, i8** [[X]] // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]] - // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) nounwind + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) [[NUW]] // CHECK-NEXT: call void @test7_helper(i8* [[T1]]) // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] - // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release // CHECK-NEXT: ret void id x; test7_helper(x); @@ -245,27 +273,7 @@ void test8() { // CHECK: [[X:%.*]] = alloca i8* // CHECK-NEXT: [[T0:%.*]] = call i8* @test8_helper() // CHECK-NEXT: store i8* [[T0]], i8** [[X]] - // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind - // CHECK-NOT: imprecise_release - // CHECK-NEXT: ret void -} - -id test9_helper(void) __attribute__((ns_returns_retained)); -void test9() { - id x __attribute__((objc_precise_lifetime)) = test9_helper(); - x = 0; - // CHECK: [[X:%.*]] = alloca i8* - // CHECK-NEXT: [[CALL:%.*]] = call i8* @test9_helper() - // CHECK-NEXT: store i8* [[CALL]], i8** [[X]] - - // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] - // CHECK-NEXT: store i8* null, i8** [[X]] - // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind, !clang.imprecise_release - - // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] - // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind - // CHECK-NOT: clang.imprecise_release - + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release // CHECK-NEXT: ret void } @@ -314,7 +322,7 @@ void test11(id (*f)(void) __attribute__((ns_returns_retained))) { // CHECK-NEXT: [[T1:%.*]] = call i8* [[T0]]() // CHECK-NEXT: store i8* [[T1]], i8** [[X]], align // CHECK-NEXT: [[T3:%.*]] = load i8** [[X]] - // CHECK-NEXT: call void @objc_release(i8* [[T3]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: call void @objc_release(i8* [[T3]]) [[NUW]], !clang.imprecise_release // CHECK-NEXT: ret void id x = f(); } @@ -343,9 +351,9 @@ void test12(void) { // CHECK-NEXT: store i8* [[T2]], i8** [[Y]], align // CHECK-NEXT: [[T4:%.*]] = load i8** [[Y]] - // CHECK-NEXT: call void @objc_release(i8* [[T4]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: call void @objc_release(i8* [[T4]]) [[NUW]], !clang.imprecise_release // CHECK-NEXT: call void @objc_destroyWeak(i8** [[X]]) - // CHECK-NEXT: ret void + // CHECK: ret void } // Indirect consuming calls. @@ -359,7 +367,7 @@ void test13(void) { extern fnty *test13_func; // CHECK-NEXT: [[FN:%.*]] = load void (i8*)** @test13_func, align // CHECK-NEXT: [[X_VAL:%.*]] = load i8** [[X]], align - // CHECK-NEXT: [[X_TMP:%.*]] = call i8* @objc_retain(i8* [[X_VAL]]) nounwind + // CHECK-NEXT: [[X_TMP:%.*]] = call i8* @objc_retain(i8* [[X_VAL]]) [[NUW]] // CHECK-NEXT: call void [[FN]](i8* [[X_TMP]]) test13_func(x); @@ -369,14 +377,14 @@ void test13(void) { // CHECK-NEXT: [[BLOCK_FN_PTR:%.*]] = getelementptr inbounds [[BLOCKTY]]* [[BLOCK]], i32 0, i32 3 // CHECK-NEXT: [[BLOCK_OPAQUE:%.*]] = bitcast [[BLOCKTY]]* [[BLOCK]] to i8* // CHECK-NEXT: [[X_VAL:%.*]] = load i8** [[X]], align - // CHECK-NEXT: [[X_TMP:%.*]] = call i8* @objc_retain(i8* [[X_VAL]]) nounwind + // CHECK-NEXT: [[X_TMP:%.*]] = call i8* @objc_retain(i8* [[X_VAL]]) [[NUW]] // CHECK-NEXT: [[BLOCK_FN_TMP:%.*]] = load i8** [[BLOCK_FN_PTR]] // CHECK-NEXT: [[BLOCK_FN:%.*]] = bitcast i8* [[BLOCK_FN_TMP]] to void (i8*, i8*)* // CHECK-NEXT: call void [[BLOCK_FN]](i8* [[BLOCK_OPAQUE]], i8* [[X_TMP]]) test13_block(x); // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]] - // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]] // CHECK-NEXT: ret void } @@ -426,14 +434,14 @@ void test13(void) { // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST16]]* [[BASE]] to i8* // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8* [[T0]], i64 [[Y_OFF]] // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to i8** - // CHECK-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null) nounwind + // CHECK-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null) [[NUW]] // Destroy z. // CHECK-NEXT: [[Z_OFF:%.*]] = load i64* @"OBJC_IVAR_$_Test16.z" // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST16]]* [[BASE]] to i8* // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8* [[T0]], i64 [[Z_OFF]] // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to i8** - // CHECK-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null) nounwind + // CHECK-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null) [[NUW]] // CHECK-NEXT: ret void @@ -452,19 +460,20 @@ void test13(void) { void test19() { // CHECK: define void @test19() // CHECK: [[X:%.*]] = alloca [5 x i8*], align 16 + // CHECK: call void @llvm.lifetime.start // CHECK-NEXT: [[T0:%.*]] = bitcast [5 x i8*]* [[X]] to i8* - // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 40, i32 16, i1 false) + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 40, i32 16, i1 false) id x[5]; extern id test19_helper(void); x[2] = test19_helper(); // CHECK-NEXT: [[CALL:%.*]] = call i8* @test19_helper() - // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[CALL]]) nounwind + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[CALL]]) [[NUW]] // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [5 x i8*]* [[X]], i32 0, i64 2 // CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]] // CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]] - // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]] // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x i8*]* [[X]], i32 0, i32 0 // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 5 @@ -473,7 +482,7 @@ void test19() { // CHECK: [[AFTER:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ] // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds i8** [[AFTER]], i64 -1 // CHECK-NEXT: [[T0:%.*]] = load i8** [[CUR]] - // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release // CHECK-NEXT: [[EQ:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]] // CHECK-NEXT: br i1 [[EQ]], @@ -512,7 +521,7 @@ void test20(unsigned n) { // CHECK: [[AFTER:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds i8** [[AFTER]], i64 -1 // CHECK-NEXT: [[T0:%.*]] = load i8** [[CUR]] - // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release // CHECK-NEXT: [[EQ:%.*]] = icmp eq i8** [[CUR]], [[VLA]] // CHECK-NEXT: br i1 [[EQ]], @@ -558,7 +567,7 @@ void test21(unsigned n) { // CHECK: [[AFTER:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds i8** [[AFTER]], i64 -1 // CHECK-NEXT: [[T0:%.*]] = load i8** [[CUR]] - // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release // CHECK-NEXT: [[EQ:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]] // CHECK-NEXT: br i1 [[EQ]], @@ -567,39 +576,6 @@ void test21(unsigned n) { // CHECK-NEXT: ret void } -void test22(_Bool cond) { - id test22_helper(void) __attribute__((ns_returns_retained)); - - // CHECK: define void @test22( - // CHECK: [[COND:%.*]] = alloca i8, - // CHECK-NEXT: [[X:%.*]] = alloca i8*, - // CHECK-NEXT: [[RELVAL:%.*]] = alloca i8* - // CHECK-NEXT: [[RELCOND:%.*]] = alloca i1 - // CHECK-NEXT: zext - // CHECK-NEXT: store - // CHECK-NEXT: [[T0:%.*]] = load i8* [[COND]] - // CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1 - // CHECK-NEXT: store i1 false, i1* [[RELCOND]] - // CHECK-NEXT: br i1 [[T1]], - // CHECK: br label - // CHECK: [[CALL:%.*]] = call i8* @test22_helper() - // CHECK-NEXT: store i8* [[CALL]], i8** [[RELVAL]] - // CHECK-NEXT: store i1 true, i1* [[RELCOND]] - // CHECK-NEXT: br label - // CHECK: [[T0:%.*]] = phi i8* [ null, {{%.*}} ], [ [[CALL]], {{%.*}} ] - // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) nounwind - // CHECK-NEXT: store i8* [[T1]], i8** [[X]], - // CHECK-NEXT: [[REL:%.*]] = load i1* [[RELCOND]] - // CHECK-NEXT: br i1 [[REL]], - // CHECK: [[T0:%.*]] = load i8** [[RELVAL]] - // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind - // CHECK-NEXT: br label - // CHECK: [[T0:%.*]] = load i8** [[X]] - // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind - // CHECK-NEXT: ret void - id x = (cond ? 0 : test22_helper()); -} - // rdar://problem/8922540 // Note that we no longer emit .release_ivars flags. // rdar://problem/12492434 @@ -646,7 +622,9 @@ void test22(_Bool cond) { // CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]] // CHECK-NEXT: [[T0:%.*]] = load [[TEST27]]** [[SELF]] // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST27]]* [[T0]] to i8* -// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST27]]* +// CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST27]]* [[T3]] to i8* // CHECK-NEXT: store i32 {{[0-9]+}}, i32* [[DEST]] // CHECK-NEXT: [[T0:%.*]] = load [[TEST27]]** [[SELF]] // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST27]]* [[T0]] to i8* @@ -681,7 +659,7 @@ void test22(_Bool cond) { @implementation Test29 static id _test29_allocator = 0; - (id) init { -// CHECK: define internal i8* @"\01-[Test29 init]"([[TEST29:%.*]]* {{%.*}}, +// CHECK: define internal i8* @"\01-[Test29 init]"([[TEST29:%[^*]*]]* {{%.*}}, // CHECK: [[SELF:%.*]] = alloca [[TEST29]]*, align 8 // CHECK-NEXT: [[CMD:%.*]] = alloca i8*, align 8 // CHECK-NEXT: [[CLEANUP:%.*]] = alloca i32 @@ -710,13 +688,15 @@ static id _test29_allocator = 0; // Return statement. // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[CALL]] // CHECK-NEXT: [[CALL:%.*]] = bitcast -// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[CALL]]) nounwind +// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[CALL]]) [[NUW]] +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST29]]* +// CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST29]]* [[T1]] to i8* // CHECK-NEXT: store i32 1, i32* [[CLEANUP]] // Cleanup. // CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]** [[SELF]] // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8* -// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind, !clang.imprecise_release +// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release // Return. // CHECK-NEXT: ret i8* [[RET]] @@ -754,7 +734,7 @@ static id _test29_allocator = 0; // Assignment. // CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[CALL]] to [[TEST29]]* // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8* -// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) nounwind +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) [[NUW]] // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST29]]* // CHECK-NEXT: [[T4:%.*]] = load [[TEST29]]** [[SELF]], align // CHECK-NEXT: store [[TEST29]]* [[T3]], [[TEST29]]** [[SELF]], align @@ -764,16 +744,18 @@ static id _test29_allocator = 0; // Return statement. // CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]** [[SELF]] // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8* -// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T1]]) nounwind +// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[T1]]) [[NUW]] +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST29]]* +// CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST29]]* [[T1]] to i8* // CHECK-NEXT: store i32 1, i32* [[CLEANUP]] // Cleanup. // CHECK-NEXT: [[T0:%.*]] = load i8** [[ALLOCATOR]] -// CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release +// CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release // CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]** [[SELF]] // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8* -// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind, !clang.imprecise_release +// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release // Return. // CHECK-NEXT: ret i8* [[RET]] @@ -791,7 +773,7 @@ typedef struct Test30_helper Test30_helper; char *helper; } - (id) init { -// CHECK: define internal i8* @"\01-[Test30 init]"([[TEST30:%.*]]* {{%.*}}, +// CHECK: define internal i8* @"\01-[Test30 init]"([[TEST30:%[^*]*]]* {{%.*}}, // CHECK: [[RET:%.*]] = alloca [[TEST30]]* // CHECK-NEXT: alloca i8* // CHECK-NEXT: alloca i32 @@ -819,7 +801,9 @@ char *helper; // Return. // CHECK-NEXT: [[T0:%.*]] = load [[TEST30]]** [[SELF]] // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST30]]* [[T0]] to i8* -// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST30]]* +// CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST30]]* [[T1]] to i8* // CHECK-NEXT: store i32 1 // Cleanup. @@ -882,8 +866,8 @@ void test33(Test33 *ptr) { // CHECK-NEXT: store [[A_T]]* null, [[A_T]]** [[A]] // CHECK-NEXT: load [[TEST33]]** [[PTR]] - // CHECK-NEXT: [[T0:%.*]] = load [[A_T]]** [[A]] - // CHECK-NEXT: store [[A_T]]* [[T0]], [[A_T]]** [[TEMP0]] + // CHECK-NEXT: [[W0:%.*]] = load [[A_T]]** [[A]] + // CHECK-NEXT: store [[A_T]]* [[W0]], [[A_T]]** [[TEMP0]] // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ // CHECK-NEXT: bitcast // CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[TEMP0]]) @@ -891,14 +875,15 @@ void test33(Test33 *ptr) { // CHECK-NEXT: [[T1:%.*]] = bitcast [[A_T]]* [[T0]] to i8* // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A_T]]* + // CHECK-NEXT: call void (...)* @clang.arc.use([[A_T]]* [[W0]]) [[NUW]] // CHECK-NEXT: [[T4:%.*]] = load [[A_T]]** [[A]] // CHECK-NEXT: store [[A_T]]* [[T3]], [[A_T]]** [[A]] // CHECK-NEXT: [[T5:%.*]] = bitcast [[A_T]]* [[T4]] to i8* // CHECK-NEXT: call void @objc_release(i8* [[T5]]) // CHECK-NEXT: load [[TEST33]]** [[PTR]] - // CHECK-NEXT: [[T0:%.*]] = load [[A_T]]** [[A]] - // CHECK-NEXT: store [[A_T]]* [[T0]], [[A_T]]** [[TEMP1]] + // CHECK-NEXT: [[W0:%.*]] = load [[A_T]]** [[A]] + // CHECK-NEXT: store [[A_T]]* [[W0]], [[A_T]]** [[TEMP1]] // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ // CHECK-NEXT: bitcast // CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[TEMP1]]) @@ -906,6 +891,7 @@ void test33(Test33 *ptr) { // CHECK-NEXT: [[T1:%.*]] = bitcast [[A_T]]* [[T0]] to i8* // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A_T]]* + // CHECK-NEXT: call void (...)* @clang.arc.use([[A_T]]* [[W0]]) [[NUW]] // CHECK-NEXT: [[T4:%.*]] = load [[A_T]]** [[A]] // CHECK-NEXT: store [[A_T]]* [[T3]], [[A_T]]** [[A]] // CHECK-NEXT: [[T5:%.*]] = bitcast [[A_T]]* [[T4]] to i8* @@ -945,61 +931,6 @@ void test33(Test33 *ptr) { // CHECK-NEXT: ret void } -void test34(int cond) { - __strong id strong; - __weak id weak; - extern void test34_sink(id *); - test34_sink(cond ? &strong : 0); - test34_sink(cond ? &weak : 0); - - // CHECK: define void @test34( - // CHECK: [[COND:%.*]] = alloca i32 - // CHECK-NEXT: [[STRONG:%.*]] = alloca i8* - // CHECK-NEXT: [[WEAK:%.*]] = alloca i8* - // CHECK-NEXT: [[TEMP1:%.*]] = alloca i8* - // CHECK-NEXT: [[TEMP2:%.*]] = alloca i8* - // CHECK-NEXT: store i32 - // CHECK-NEXT: store i8* null, i8** [[STRONG]] - // CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null) - - // CHECK-NEXT: [[T0:%.*]] = load i32* [[COND]] - // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0 - // CHECK: [[ARG:%.*]] = phi i8** - // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null - // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP1]] - // CHECK-NEXT: br i1 [[T0]], - // CHECK: [[T0:%.*]] = load i8** [[ARG]] - // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP1]] - // CHECK-NEXT: br label - // CHECK: call void @test34_sink(i8** [[T1]]) - // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null - // CHECK-NEXT: br i1 [[T0]], - // CHECK: [[T0:%.*]] = load i8** [[TEMP1]] - // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) - // CHECK-NEXT: [[T2:%.*]] = load i8** [[ARG]] - // CHECK-NEXT: store i8* [[T1]], i8** [[ARG]] - // CHECK-NEXT: call void @objc_release(i8* [[T2]]) - // CHECK-NEXT: br label - - // CHECK: [[T0:%.*]] = load i32* [[COND]] - // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0 - // CHECK: [[ARG:%.*]] = phi i8** - // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null - // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP2]] - // CHECK-NEXT: br i1 [[T0]], - // CHECK: [[T0:%.*]] = call i8* @objc_loadWeak(i8** [[ARG]]) - // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP2]] - // CHECK-NEXT: br label - // CHECK: call void @test34_sink(i8** [[T1]]) - // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null - // CHECK-NEXT: br i1 [[T0]], - // CHECK: [[T0:%.*]] = load i8** [[TEMP2]] - // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[ARG]], i8* [[T0]]) - // CHECK-NEXT: br label - - // CHECK: call void @objc_destroyWeak(i8** [[WEAK]]) - // CHECK: ret void -} // CHECK: define void @test36 void test36(id x) { @@ -1034,15 +965,16 @@ void test37(void) { // CHECK-NEXT: [[TEMP:%.*]] = alloca i8* // CHECK-NEXT: store [[TEST37]]* null, [[TEST37]]** [[VAR]] - // CHECK-NEXT: [[T0:%.*]] = load [[TEST37]]** [[VAR]] - // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST37]]* [[T0]] to i8* - // CHECK-NEXT: store i8* [[T1]], i8** [[TEMP]] + // CHECK-NEXT: [[W0:%.*]] = load [[TEST37]]** [[VAR]] + // CHECK-NEXT: [[W1:%.*]] = bitcast [[TEST37]]* [[W0]] to i8* + // CHECK-NEXT: store i8* [[W1]], i8** [[TEMP]] // CHECK-NEXT: call void @test37_helper(i8** [[TEMP]]) // CHECK-NEXT: [[T0:%.*]] = load i8** [[TEMP]] // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST37]]* // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST37]]* [[T1]] to i8* // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST37]]* + // CHECK-NEXT: call void (...)* @clang.arc.use(i8* [[W1]]) [[NUW]] // CHECK-NEXT: [[T5:%.*]] = load [[TEST37]]** [[VAR]] // CHECK-NEXT: store [[TEST37]]* [[T4]], [[TEST37]]** [[VAR]] // CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST37]]* [[T5]] to i8* @@ -1186,7 +1118,7 @@ id test52(void) { // CHECK-NEXT: store i32 5, i32* [[X]], // CHECK-NEXT: [[T0:%.*]] = load i32* [[X]], // CHECK-NEXT: [[T1:%.*]] = call i8* @test52_helper(i32 [[T0]]) -// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[T1]]) +// CHECK-NEXT: [[T2:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T1]]) // CHECK-NEXT: ret i8* [[T2]] } @@ -1287,7 +1219,7 @@ void test56_test(void) { // 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: [[T6:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T5]]) // CHECK-NEXT: ret i8* [[T6]] // CHECK: define internal i8* @"\01-[Test57 unsafe]"( @@ -1299,57 +1231,6 @@ void test56_test(void) { // CHECK-NEXT: [[T5:%.*]] = load i8** [[T4]] // CHECK-NEXT: ret i8* [[T5]] -// rdar://problem/9821110 -@interface Test58 -- (char*) interior __attribute__((objc_returns_inner_pointer)); -// Should we allow this on properties? -@end -extern Test58 *test58_helper(void); - -// CHECK: define void @test58a() -void test58a(void) { - // CHECK: [[T0:%.*]] = call [[TEST58:%.*]]* @test58_helper() - // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST58]]* [[T0]] to i8* - // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) - // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST58]]* - // CHECK-NEXT: store [[TEST58]]* [[T3]] - // CHECK-NEXT: [[T0:%.*]] = load [[TEST58]]** - // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST58]]* [[T0]] to i8* - // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]]) - // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST58]]* - // CHECK-NEXT: [[T4:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ - // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST58]]* [[T3]] to i8* - // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast - // CHECK-NEXT: store i8* [[T6]], i8** - // CHECK-NEXT: [[T0:%.*]] = load [[TEST58]]** - // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST58]]* [[T0]] to i8* - // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind, !clang.imprecise_release - // CHECK-NEXT: ret void - Test58 *ptr = test58_helper(); - char *c = [(ptr) interior]; -} - -// CHECK: define void @test58b() -void test58b(void) { - // CHECK: [[T0:%.*]] = call [[TEST58:%.*]]* @test58_helper() - // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST58]]* [[T0]] to i8* - // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) - // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST58]]* - // CHECK-NEXT: store [[TEST58]]* [[T3]] - // CHECK-NEXT: [[T0:%.*]] = load [[TEST58]]** - // CHECK-NEXT: [[T1:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ - // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST58]]* [[T0]] to i8* - // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast - // CHECK-NEXT: store i8* [[T3]], i8** - // CHECK-NEXT: [[T0:%.*]] = load [[TEST58]]** - // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST58]]* [[T0]] to i8* - // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind - // CHECK-NOT: clang.imprecise_release - // CHECK-NEXT: ret void - __attribute__((objc_precise_lifetime)) Test58 *ptr = test58_helper(); - char *c = [ptr interior]; -} - // rdar://problem/9842343 void test59(void) { extern id test59_getlock(void); @@ -1491,7 +1372,7 @@ void test66(void) { // CHECK-NEXT: br i1 [[SIX]], label [[NULINIT:%.*]], label [[CALL:%.*]] // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*)*)(i8* [[T7]], i8* [[T6]], i8* [[T5]]) // CHECK-NEXT: br label [[CONT:%.*]] -// CHECK: call void @objc_release(i8* [[T5]]) nounwind +// CHECK: call void @objc_release(i8* [[T5]]) [[NUW]] // CHECK-NEXT: br label [[CONT:%.*]] // CHECK: [[T8:%.*]] = bitcast [[TEST66]]* [[T3]] to i8* // CHECK-NEXT: call void @objc_release(i8* [[T8]]) @@ -1543,3 +1424,7 @@ void test70(id i) { [2] = i }; } + +// ARC-ALIEN: attributes [[NLB]] = { nonlazybind } +// ARC-NATIVE: attributes [[NLB]] = { nonlazybind } +// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenObjC/attr-exception.m b/test/CodeGenObjC/attr-exception.m new file mode 100644 index 0000000..4d8c425 --- /dev/null +++ b/test/CodeGenObjC/attr-exception.m @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -fobjc-exceptions -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -fobjc-exceptions -fvisibility hidden -o - %s | FileCheck -check-prefix=CHECK-HIDDEN %s + +__attribute__((objc_root_class)) +@interface Root { + Class isa; +} +@end + +__attribute__((objc_exception)) +@interface A : Root +@end + +@implementation A +@end +// CHECK: @"OBJC_EHTYPE_$_A" = global {{%.*}} { i8** getelementptr (i8** @objc_ehtype_vtable, i32 2) +// CHECK-HIDDEN: @"OBJC_EHTYPE_$_A" = hidden global {{%.*}} { i8** getelementptr (i8** @objc_ehtype_vtable, i32 2) + +__attribute__((objc_exception)) +__attribute__((visibility("default"))) +@interface B : Root +@end + +@implementation B +@end +// CHECK: @"OBJC_EHTYPE_$_B" = global {{%.*}} { i8** getelementptr (i8** @objc_ehtype_vtable, i32 2) +// CHECK-HIDDEN: @"OBJC_EHTYPE_$_B" = global {{%.*}} { i8** getelementptr (i8** @objc_ehtype_vtable, i32 2) diff --git a/test/CodeGenObjC/bitfield-access.m b/test/CodeGenObjC/bitfield-access.m index 6d4c82a..597fe35 100644 --- a/test/CodeGenObjC/bitfield-access.m +++ b/test/CodeGenObjC/bitfield-access.m @@ -15,8 +15,8 @@ // end of the structure. // // CHECK-I386: define i32 @f0( -// CHECK-I386: [[t0_0:%.*]] = load i16* {{.*}}, align 1 -// CHECK-I386: lshr i16 [[t0_0]], 7 +// CHECK-I386: [[t0_0:%.*]] = load i8* {{.*}}, align 1 +// CHECK-I386: lshr i8 [[t0_0]], 7 // CHECK-I386: } int f0(I0 *a) { return a->y; @@ -26,13 +26,11 @@ int f0(I0 *a) { // // CHECK-ARM: define i32 @f1( // CHECK-ARM: [[t1_ptr:%.*]] = getelementptr -// CHECK-ARM: [[t1_base:%.*]] = bitcast i8* [[t1_ptr]] to i32* -// CHECK-ARM: [[t1_0:%.*]] = load i32* [[t1_base]], align 1 -// CHECK-ARM: lshr i32 [[t1_0]], 1 -// CHECK-ARM: [[t1_base_2_cast:%.*]] = bitcast i32* %{{.*}} to i8* -// CHECK-ARM: [[t1_base_2:%.*]] = getelementptr i8* [[t1_base_2_cast]] -// CHECK-ARM: [[t1_1:%.*]] = load i8* [[t1_base_2]], align 1 -// CHECK-ARM: and i8 [[t1_1:%.*]], 1 +// CHECK-ARM: [[t1_base:%.*]] = bitcast i8* [[t1_ptr]] to i40* +// CHECK-ARM: [[t1_0:%.*]] = load i40* [[t1_base]], align 1 +// CHECK-ARM: [[t1_1:%.*]] = lshr i40 [[t1_0]], 1 +// CHECK-ARM: [[t1_2:%.*]] = and i40 [[t1_1]], +// CHECK-ARM: trunc i40 [[t1_2]] to i32 // CHECK-ARM: } @interface I1 { @public diff --git a/test/CodeGenObjC/bitfield-ivar-offsets.m b/test/CodeGenObjC/bitfield-ivar-offsets.m index b0c848f..7a07f27 100644 --- a/test/CodeGenObjC/bitfield-ivar-offsets.m +++ b/test/CodeGenObjC/bitfield-ivar-offsets.m @@ -1,4 +1,3 @@ -// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s && // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o %t %s // RUN: grep -F '@"OBJC_IVAR_$_I0._b0" = global i64 0, section "__DATA, __objc_ivar", align 8' %t // RUN: grep -F '@"OBJC_IVAR_$_I0._b1" = global i64 0, section "__DATA, __objc_ivar", align 8' %t diff --git a/test/CodeGenObjC/block-byref-variable-layout.m b/test/CodeGenObjC/block-byref-variable-layout.m new file mode 100644 index 0000000..9c8f674 --- /dev/null +++ b/test/CodeGenObjC/block-byref-variable-layout.m @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -emit-llvm %s -o - | FileCheck %s + +// rdar://12759433 +@class NSString; + +void Test12759433() { + __block __unsafe_unretained NSString *uuByref = (__bridge NSString *)(void*)0x102030405060708; + void (^block)() = ^{ uuByref = 0; }; + block(); +} +// CHECK: %struct.__block_byref_uuByref = type { i8*, %struct.__block_byref_uuByref*, i32, i32, [[ZERO:%.*]]* } +int main() { + __block __weak id wid; + __block long XXX; + __block id ID; + __block struct S { + int iS; + double iD; + void *pv; + __unsafe_unretained id unsunr; + } import; + void (^c)() = ^{ +// Inline flag for BYREF variable layout (1107296256): BLOCK_BYREF_HAS_COPY_DISPOSE BLOCK_BYREF_LAYOUT_WEAK +// CHECK: store i32 1107296256, i32* [[T0:%.*]] + wid = 0; + +// Inline flag for BYREF variable layout (536870912): BLOCK_BYREF_LAYOUT_NON_OBJECT +// CHECK: store i32 536870912, i32* [[T1:%.*]] + XXX = 12345; + +// Inline flag for BYREF variable layout (838860800): BLOCK_BYREF_HAS_COPY_DISPOSE BLOCK_BYREF_LAYOUT_STRONG +// CHECK: store i32 838860800, i32* [[T2:%.*]] + ID = 0; + +// Inline flag for BYREF variable layout (268435456): BLOCK_BYREF_LAYOUT_EXTENDED +// BYREF variable layout: BL_NON_OBJECT_WORD:3, BL_UNRETAINED:1, BL_OPERATOR:0 +// CHECK: store i32 268435456, i32* [[T3:%.*]] + import.iD = 3.14; + + }; + c(); +} + +// rdar://12787751 +typedef char mds_path_t[1024]; +void directVolumePerfWaitForStoreState() +{ + __block mds_path_t path; +} diff --git a/test/CodeGenObjC/block-var-layout.m b/test/CodeGenObjC/block-var-layout.m index 71b14da..ab95231 100644 --- a/test/CodeGenObjC/block-var-layout.m +++ b/test/CodeGenObjC/block-var-layout.m @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 -O0 -emit-llvm %s -o %t-64.s -// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s +// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.layout %s +// rdar://12752901 struct S { int i1; @@ -46,8 +47,7 @@ void f() { // Test 1 // byref int, short, char, char, char, id, id, strong void*, byref id -// 01 35 10 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\015\10\00" +// CHECK-LP64: block variable layout for block: 0x01, 0x35, 0x10, 0x00 void (^b)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -60,7 +60,7 @@ void f() { // Test 2 // byref int, short, char, char, char, id, id, strong void*, byref void*, byref id // 01 36 10 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\016\10\00" +// CHECK-LP64: block variable layout for block: 0x01, 0x36, 0x10, 0x00 void (^c)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -76,7 +76,7 @@ void f() { // byref int, short, char, char, char, id, id, byref void*, int, double, byref id // 01 34 11 30 00 // FIXME: we'd get a better format here if we sorted by scannability, not just alignment -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\014\11 \00" +// CHECK-LP64: block variable layout for block: 0x01, 0x35, 0x30, 0x00 void (^d)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -91,7 +91,7 @@ void f() { // Test 4 // struct S (int, id, int, id, int, id) // 01 41 11 11 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\11\00" +// CHECK-LP64: block variable layout for block: 0x01, 0x41, 0x11, 0x11, 0x00 struct S s2; void (^e)() = ^{ x(s2.o1); @@ -129,7 +129,7 @@ void Test5() { // struct s2 (int, id, int, id, int, id?), union u2 (id?) // 01 41 11 12 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\12\00" +// CHECK-LP64: block variable layout for block: 0x01, 0x41, 0x11, 0x12, 0x00 void (^c)() = ^{ x(s2.ui.o1); x(u2.o1); @@ -146,7 +146,7 @@ void notifyBlock(id dependentBlock) { // id, id, void(^)() // 01 33 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"\013\00" +// CHECK-LP64: block variable layout for block: 0x01, 0x33, 0x00 void (^wrapperBlock)() = ^() { CFRelease(singleObservationToken); CFRelease(singleObservationToken); @@ -159,7 +159,7 @@ void notifyBlock(id dependentBlock) { void test_empty_block() { // 01 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"\01\00" +// CHECK-LP64: block variable layout for block: 0x01, 0x00 void (^wrapperBlock)() = ^() { }; wrapperBlock(); diff --git a/test/CodeGenObjC/blocks.m b/test/CodeGenObjC/blocks.m index 6c85da9..3718ad5 100644 --- a/test/CodeGenObjC/blocks.m +++ b/test/CodeGenObjC/blocks.m @@ -57,9 +57,9 @@ void test2(Test2 *x) { // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 1 // CHECK-NEXT: store [[WEAK_T]]* [[WEAKX]], [[WEAK_T]]** [[T1]] - // Flags. This is just BLOCK_HAS_COPY_DISPOSE. + // Flags. This is just BLOCK_HAS_COPY_DISPOSE BLOCK_BYREF_LAYOUT_UNRETAINED // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 2 - // CHECK-NEXT: store i32 33554432, i32* [[T2]] + // CHECK-NEXT: store i32 1375731712, i32* [[T2]] // Size. // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 3 @@ -93,10 +93,43 @@ void test2(Test2 *x) { // doesn't require a read barrier. // CHECK: define internal void @__test2_block_invoke // CHECK: [[BLOCK:%.*]] = bitcast i8* {{%.*}} to [[BLOCK_T]]* -// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 +// CHECK-NOT: bitcast +// CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK-NEXT: [[T1:%.*]] = load i8** [[T0]] // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[WEAK_T]]{{.*}}* // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[WEAK_T]]{{.*}}* [[T2]], i32 0, i32 1 // CHECK-NEXT: [[T4:%.*]] = load [[WEAK_T]]{{.*}}** [[T3]] // CHECK-NEXT: [[WEAKX:%.*]] = getelementptr inbounds [[WEAK_T]]{{.*}}* [[T4]], i32 0, i32 6 // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]** [[WEAKX]], align 4 + +// rdar://problem/12722954 +// Make sure that ... is appropriately positioned in a block call. +void test3(void (^block)(int, ...)) { + block(0, 1, 2, 3); +} +// CHECK: define void @test3( +// CHECK: [[BLOCK:%.*]] = alloca void (i32, ...)*, align 4 +// CHECK-NEXT: store void (i32, ...)* +// CHECK-NEXT: [[T0:%.*]] = load void (i32, ...)** [[BLOCK]], align 4 +// CHECK-NEXT: [[T1:%.*]] = bitcast void (i32, ...)* [[T0]] to [[BLOCK_T:%.*]]* +// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[T1]], i32 0, i32 3 +// CHECK-NEXT: [[T3:%.*]] = bitcast [[BLOCK_T]]* [[T1]] to i8* +// CHECK-NEXT: [[T4:%.*]] = load i8** [[T2]] +// CHECK-NEXT: [[T5:%.*]] = bitcast i8* [[T4]] to void (i8*, i32, ...)* +// CHECK-NEXT: call void (i8*, i32, ...)* [[T5]](i8* [[T3]], i32 0, i32 1, i32 2, i32 3) +// CHECK-NEXT: ret void + +void test4(void (^block)()) { + block(0, 1, 2, 3); +} +// CHECK: define void @test4( +// CHECK: [[BLOCK:%.*]] = alloca void (...)*, align 4 +// CHECK-NEXT: store void (...)* +// CHECK-NEXT: [[T0:%.*]] = load void (...)** [[BLOCK]], align 4 +// CHECK-NEXT: [[T1:%.*]] = bitcast void (...)* [[T0]] to [[BLOCK_T:%.*]]* +// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[T1]], i32 0, i32 3 +// CHECK-NEXT: [[T3:%.*]] = bitcast [[BLOCK_T]]* [[T1]] to i8* +// CHECK-NEXT: [[T4:%.*]] = load i8** [[T2]] +// CHECK-NEXT: [[T5:%.*]] = bitcast i8* [[T4]] to void (i8*, i32, i32, i32, i32)* +// CHECK-NEXT: call void [[T5]](i8* [[T3]], i32 0, i32 1, i32 2, i32 3) +// CHECK-NEXT: ret void diff --git a/test/CodeGenObjC/boxing.m b/test/CodeGenObjC/boxing.m index 9664298..87ff0e7 100644 --- a/test/CodeGenObjC/boxing.m +++ b/test/CodeGenObjC/boxing.m @@ -54,17 +54,17 @@ typedef signed char BOOL; @end // CHECK: [[WithIntMeth:@".*"]] = internal global [15 x i8] c"numberWithInt:\00" -// CHECK: [[WithIntSEL:@".*"]] = internal global i8* getelementptr inbounds ([15 x i8]* [[WithIntMeth]] +// CHECK: [[WithIntSEL:@".*"]] = internal externally_initialized global i8* getelementptr inbounds ([15 x i8]* [[WithIntMeth]] // CHECK: [[WithCharMeth:@".*"]] = internal global [16 x i8] c"numberWithChar:\00" -// CHECK: [[WithCharSEL:@".*"]] = internal global i8* getelementptr inbounds ([16 x i8]* [[WithCharMeth]] +// CHECK: [[WithCharSEL:@".*"]] = internal externally_initialized global i8* getelementptr inbounds ([16 x i8]* [[WithCharMeth]] // CHECK: [[WithBoolMeth:@".*"]] = internal global [16 x i8] c"numberWithBool:\00" -// CHECK: [[WithBoolSEL:@".*"]] = internal global i8* getelementptr inbounds ([16 x i8]* [[WithBoolMeth]] +// CHECK: [[WithBoolSEL:@".*"]] = internal externally_initialized global i8* getelementptr inbounds ([16 x i8]* [[WithBoolMeth]] // CHECK: [[WithIntegerMeth:@".*"]] = internal global [19 x i8] c"numberWithInteger:\00" -// CHECK: [[WithIntegerSEL:@".*"]] = internal global i8* getelementptr inbounds ([19 x i8]* [[WithIntegerMeth]] +// CHECK: [[WithIntegerSEL:@".*"]] = internal externally_initialized global i8* getelementptr inbounds ([19 x i8]* [[WithIntegerMeth]] // CHECK: [[WithUnsignedIntegerMeth:@".*"]] = internal global [27 x i8] c"numberWithUnsignedInteger:\00" -// CHECK: [[WithUnsignedIntegerSEL:@".*"]] = internal global i8* getelementptr inbounds ([27 x i8]* [[WithUnsignedIntegerMeth]] +// CHECK: [[WithUnsignedIntegerSEL:@".*"]] = internal externally_initialized global i8* getelementptr inbounds ([27 x i8]* [[WithUnsignedIntegerMeth]] // CHECK: [[stringWithUTF8StringMeth:@".*"]] = internal global [22 x i8] c"stringWithUTF8String:\00" -// CHECK: [[stringWithUTF8StringSEL:@".*"]] = internal global i8* getelementptr inbounds ([22 x i8]* [[stringWithUTF8StringMeth]] +// CHECK: [[stringWithUTF8StringSEL:@".*"]] = internal externally_initialized global i8* getelementptr inbounds ([22 x i8]* [[stringWithUTF8StringMeth]] int main() { // CHECK: load i8** [[WithIntSEL]] diff --git a/test/CodeGenObjC/catch-lexical-block.m b/test/CodeGenObjC/catch-lexical-block.m index f4a6a22..618d3a2 100644 --- a/test/CodeGenObjC/catch-lexical-block.m +++ b/test/CodeGenObjC/catch-lexical-block.m @@ -7,10 +7,9 @@ void f0() { } } -// We should have 4 lexical blocks here at the moment, including one +// We should have 3 lexical blocks here at the moment, including one // for the catch block. // CHECK: lexical_block // CHECK: lexical_block -// CHECK: lexical_block // CHECK: auto_variable // CHECK: lexical_block diff --git a/test/CodeGenObjC/complex-double-abi.m b/test/CodeGenObjC/complex-double-abi.m index 08246d5..6353520 100644 --- a/test/CodeGenObjC/complex-double-abi.m +++ b/test/CodeGenObjC/complex-double-abi.m @@ -9,8 +9,7 @@ double _Complex foo(CNumber *x) { return [x sum]; } -// CHECK: [[T4:%.*]] = phi double [ 0.000000e+00, [[NULLINIT:%.*]] ], [ [[R1:%.*]], [[MSGCALL:%.*]] ] -// CHECK: [[T5:%.*]] = phi double [ 0.000000e+00, [[NULLINIT:%.*]] ], [ [[I1:%.*]], [[MSGCALL:%.*]] ] - -// CHECK: store double [[T4]] -// CHECK: store double [[T5]] +// CHECK: [[R:%.*]] = phi double [ [[R1:%.*]], [[MSGCALL:%.*]] ], [ 0.000000e+00, [[NULLINIT:%.*]] ] +// CHECK-NEXT: [[I:%.*]] = phi double [ [[I1:%.*]], [[MSGCALL]] ], [ 0.000000e+00, [[NULLINIT]] ] +// CHECK: store double [[R]] +// CHECK: store double [[I]] diff --git a/test/CodeGenObjC/debug-info-block-captured-self.m b/test/CodeGenObjC/debug-info-block-captured-self.m new file mode 100644 index 0000000..0316013 --- /dev/null +++ b/test/CodeGenObjC/debug-info-block-captured-self.m @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -fblocks -g -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s +// +// Test that debug location is generated for a captured "self" inside +// a block. +// +// This test is split into two parts, this one for the frontend, and +// then llvm/test/DebugInfo/debug-info-block-captured-self.ll to +// ensure that DW_AT_location is generated for the captured self. +@class T; +@interface S +@end +@interface Mode +-(int) count; +@end +@interface Context +@end +@interface ViewController +@property (nonatomic, readwrite, strong) Context *context; +@end +typedef enum { + Unknown = 0, +} State; +@interface Main : ViewController +{ + T * t1; + T * t2; +} +@property(readwrite, nonatomic) State state; +@end +@implementation Main +- (id) initWithContext:(Context *) context +{ + t1 = [self.context withBlock:^(id obj){ + id *mode1; + t2 = [mode1 withBlock:^(id object){ + Mode *mode2 = object; + if ([mode2 count] != 0) { + self.state = 0; + } + }]; + }]; +} +@end +// The important part of this test is that there is a dbg.value +// intrinsic associated with the implicit .block_descriptor argument +// of the block. We also test that this value gets alloca'd, so the +// register llocator won't accidentally kill it. + +// outer block: +// CHECK: define internal void {{.*}}_block_invoke{{.*}} + +// inner block: +// CHECK: define internal void {{.*}}_block_invoke{{.*}} +// CHECK: %[[MEM1:.*]] = alloca i8*, align 8 +// CHECK-NEXT: %[[MEM2:.*]] = alloca i8*, align 8 +// CHECK: store i8* [[BLOCK_DESC:%.*]], i8** %[[MEM1]], align 8 +// CHECK: %[[TMP0:.*]] = load i8** %[[MEM1]] +// CHECK: call void @llvm.dbg.value(metadata !{i8* %[[TMP0]]}, i64 0, metadata ![[BDMD:[0-9]+]]) +// CHECK: call void @llvm.dbg.declare(metadata !{i8* [[BLOCK_DESC]]}, metadata ![[BDMD:[0-9]+]]) +// CHECK: %[[TMP1:.*]] = bitcast +// CHECK-NEXT: store +// CHECK-NEXT: %[[TMP2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %[[TMP1]] +// CHECK: call void @llvm.dbg.declare(metadata !{<{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** {{.*}}}, metadata ![[SELF:.*]]) +// make sure we are still in the same function +// CHECK: define {{.*}}__copy_helper_block_ +// Metadata +// CHECK: ![[MAIN:.*]] = {{.*}}!"Main"{{.*}}DW_TAG_structure_type{{.*}}line 23 +// CHECK: ![[PMAIN:.*]] = {{.*}}![[MAIN]]} ; [ DW_TAG_pointer_type ]{{.*}}from Main +// CHECK: ![[BDMD]] = metadata {{.*}}.block_descriptor +// CHECK: ![[SELF]] = {{.*}}![[PMAIN]]{{.*}}[ DW_TAG_auto_variable ] [self] [line 40] diff --git a/test/CodeGenObjC/debug-info-block-helper.m b/test/CodeGenObjC/debug-info-block-helper.m index cf8c2a2..49c8c5d 100644 --- a/test/CodeGenObjC/debug-info-block-helper.m +++ b/test/CodeGenObjC/debug-info-block-helper.m @@ -2,7 +2,7 @@ // RUN: %clang_cc1 -emit-llvm -fblocks -g -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 %s -o - | FileCheck %s extern void foo(void(^)(void)); -// CHECK: metadata !{i32 786478, i32 0, metadata !27, metadata !"__destroy_helper_block_", metadata !"__destroy_helper_block_", metadata !"", metadata !27, i32 24, metadata !37, i1 true, i1 true, i32 0, i32 0, null, i32 0, i1 false, void (i8*)* @__destroy_helper_block_, null, null, metadata !5, i32 24} ; [ DW_TAG_subprogram ] +// CHECK: [ DW_TAG_subprogram ] {{.*}} [__destroy_helper_block_] @interface NSObject { struct objc_object *isa; diff --git a/test/CodeGenObjC/debug-info-block-line.m b/test/CodeGenObjC/debug-info-block-line.m new file mode 100644 index 0000000..c913a97 --- /dev/null +++ b/test/CodeGenObjC/debug-info-block-line.m @@ -0,0 +1,89 @@ +// REQUIRES: x86-64-registered-target +// RUN: %clang_cc1 -emit-llvm -fblocks -fobjc-default-synthesize-properties -fobjc-arc -O0 -g -triple x86_64-apple-darwin10 %s -o - | FileCheck %s + +// rdar://11562117 +typedef unsigned int NSUInteger; +typedef long NSInteger; +typedef signed char BOOL; + +#define nil ((void*) 0) +#define YES ((BOOL)1) +#define NO ((BOOL)0) + +@interface NSObject +- (id)init; +@end + +@interface NSError : NSObject +@end + +@interface NSString : NSObject +@end + +@interface NSString (NSStringExtensionMethods) +- (void)enumerateLinesUsingBlock:(void (^)(NSString *line, BOOL *stop))block; +@end + +@interface NSData : NSObject +@end + +@interface NSData (ASBase64) +- (NSString *)encodedString:(NSInteger)position; +- (NSData *)compressedData; +@end + +typedef void (^TDataCompletionBlock)(NSData *data, NSError *error); +@interface TMap : NSObject +- (NSString *)identifier; +- (NSString *)name; ++ (TMap *)mapForID:(NSString *)identifier; +- (void)dataWithCompletionBlock:(TDataCompletionBlock)block; +@end + +typedef enum : NSUInteger { + TOK = 100, + TError = 125, +} TResponseCode; + +@interface TConnection : NSObject +- (void)sendString:(NSString *)string; +- (void)sendFormat:(NSString *)format, ...; +- (void)sendResponseCode:(TResponseCode)responseCode dataFollows:(BOOL)flag + format:(NSString *)format, ...; +@end + +@interface TServer : NSObject +@end + +@implementation TServer +- (void)serverConnection:(TConnection *)connection getCommand:(NSString *)str +{ + NSString *mapID = nil; + 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:%.*]]) [[NUW:#[0-9]+]] +// CHECK: call void @objc_storeStrong(i8** [[TWO:%.*]], i8* [[THREE:%.*]]) [[NUW]] +// CHECK: bitcast %5** [[TMP:%.*]] to i8** +// CHECK: call void @objc_storeStrong(i8** [[VAL1:%.*]], i8* null) [[NUW]], !dbg ![[MD1:.*]] +// CHECK: bitcast %4** [[TMP:%.*]] to i8** +// CHECK: call void @objc_storeStrong(i8** [[VAL2:%.*]], i8* null) [[NUW]], !dbg ![[MD1]] +// CHECK-NEXT: ret +// CHECK: attributes [[NUW]] = { nounwind } +// CHECK: ![[MD1]] = metadata !{i32 87 + [map dataWithCompletionBlock:^(NSData *data, NSError *error) { + if (data) { + NSString *encoded = [[data compressedData] encodedString:18]; + [connection sendResponseCode:TOK dataFollows:YES + format:@"Sending \"%@\" (%@)", [map name], [map identifier]]; + [encoded enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) { + [connection sendFormat:@"%@\r\n", line]; + }]; + [connection sendString:@".\r\n"]; + } else { + [connection sendResponseCode:TError dataFollows:NO + format:@"Failed \"%@\" (%@)", [map name], [map identifier]]; + } + }]; +} +@end diff --git a/test/CodeGenObjC/debug-info-blocks.m b/test/CodeGenObjC/debug-info-blocks.m index 71ae8a6..f50ddf0 100644 --- a/test/CodeGenObjC/debug-info-blocks.m +++ b/test/CodeGenObjC/debug-info-blocks.m @@ -1,9 +1,17 @@ -// REQUIRES: x86-64-registered-target -// RUN: %clang_cc1 -masm-verbose -S -fblocks -g -triple x86_64-apple-darwin10 -fobjc-dispatch-method=mixed %s -o - | FileCheck %s - -//Radar 9279956 -//CHECK: ## DW_OP_deref -//CHECK-NEXT: ## DW_OP_plus_uconst +// RUN: %clang_cc1 -emit-llvm -fblocks -g -triple x86_64-apple-darwin10 -fobjc-dispatch-method=mixed %s -o - | FileCheck %s + +// rdar://problem/9279956 +// Test that we generate the proper debug location for a captured self. +// The second half of this patch is in llvm/tests/DebugInfo/debug-info-blocks.ll + +// CHECK: define {{.*}}_block_invoke +// CHECK: %[[BLOCK:.*]] = bitcast i8* %.block_descriptor to <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>*, !dbg +// CHECK-NEXT: store <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %[[BLOCK]], <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** %[[ALLOCA:.*]], align +// CHECK-NEXT: getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %[[BLOCK]], i32 0, i32 5 +// CHECK-NEXT: call void @llvm.dbg.declare(metadata !{<{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** %[[ALLOCA]]}, metadata ![[SELF:[0-9]+]]) +// CHECK-NEXT: call void @llvm.dbg.declare(metadata !{%1** %d}, metadata ![[D:[0-9]+]]) +// CHECK: ![[SELF]] = {{.*}} [ DW_TAG_auto_variable ] [self] [line 52] +// CHECK: ![[D]] = {{.*}} [d] [line 50] typedef unsigned int NSUInteger; diff --git a/test/CodeGenObjC/debug-info-fwddecl.m b/test/CodeGenObjC/debug-info-fwddecl.m index 8f2860c..b41c485 100644 --- a/test/CodeGenObjC/debug-info-fwddecl.m +++ b/test/CodeGenObjC/debug-info-fwddecl.m @@ -2,4 +2,4 @@ @class ForwardObjcClass; ForwardObjcClass *ptr = 0; -// CHECK: metadata !{i32 {{.*}}, null, metadata !"ForwardObjcClass", metadata !{{.*}}, i32 2, i64 0, i64 0, i32 0, i32 4, null, null, i32 16} ; [ DW_TAG_structure_type ] +// CHECK: {{.*}} [ DW_TAG_structure_type ] [ForwardObjcClass] [line 2, size 0, align 0, offset 0] [fwd] diff --git a/test/CodeGenObjC/debug-info-id-with-protocol.m b/test/CodeGenObjC/debug-info-id-with-protocol.m new file mode 100644 index 0000000..db1a3ef --- /dev/null +++ b/test/CodeGenObjC/debug-info-id-with-protocol.m @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-default-synthesize-properties -emit-llvm -g %s -o - | FileCheck %s +__attribute((objc_root_class)) @interface NSObject { + id isa; +} ++ (id)alloc; +- (id)init; +- (id)retain; +@end + +void NSLog(id, ...); + +@protocol MyProtocol + +-(const char *)hello; + +@end + +@interface MyClass : NSObject { +} + +@property (nonatomic, assign) id <MyProtocol> bad_carrier; +@property (nonatomic, assign) id good_carrier; + +@end + +@implementation MyClass +@end + +int main() +{ + @autoreleasepool + { + MyClass *my_class = [MyClass alloc]; + NSLog(@"%p\n", my_class.bad_carrier); + NSLog(@"%p\n", my_class.good_carrier); + } +} +// Verify that the debug type for both variables is 'id'. +// CHECK: metadata !{i32 {{[0-9]+}}, metadata !{{[0-9]+}}, metadata !"bad_carrier", metadata !{{[0-9]+}}, i32 {{[0-9]+}}, metadata ![[IDTYPE:[0-9]+]], i32 0, i32 0} ; [ DW_TAG_arg_variable ] [bad_carrier] [line 21] +// CHECK: metadata !{i32 {{[0-9]+}}, metadata !{{[0-9]+}}, metadata !"good_carrier", metadata !{{[0-9]+}}, i32 {{[0-9]+}}, metadata !{{.*}}[[IDTYPE]], i32 0, i32 0} ; [ DW_TAG_arg_variable ] [good_carrier] [line 22] +// CHECK !{{.*}}[[IDTYPE]] = metadata !{i32 {{[0-9]+}}, null, metadata !"id", metadata !{{[0-9]+}}, i32 !{{[0-9]+}}, i64 0, i64 0, i64 0, i32 0, metadata !{{[0-9]+}}} ; [ DW_TAG_typedef ] [id] diff --git a/test/CodeGenObjC/debug-info-impl.m b/test/CodeGenObjC/debug-info-impl.m index a8450dd..8991a88 100644 --- a/test/CodeGenObjC/debug-info-impl.m +++ b/test/CodeGenObjC/debug-info-impl.m @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -S -emit-llvm %s -o - | FileCheck %s -// CHECK: metadata !{i32 {{.*}}, metadata {{.*}}, metadata !"Circle", metadata {{.*}}, i32 11, i64 64, i64 64, i32 0, i32 512, null, metadata {{.*}}, i32 16, i32 0, i32 0} ; [ DW_TAG_structure_type ] +// CHECK: {{.*}} [ DW_TAG_structure_type ] [Circle] [line 11, @interface NSObject { struct objc_object *isa; } diff --git a/test/CodeGenObjC/debug-info-ivars-extension.m b/test/CodeGenObjC/debug-info-ivars-extension.m new file mode 100644 index 0000000..e43b598 --- /dev/null +++ b/test/CodeGenObjC/debug-info-ivars-extension.m @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -g %s -o - | FileCheck %s + +// Make sure we generate debug symbols for ivars added by a class extension. + +@interface I +{ + @public int a; +} +@end + +void foo(I* pi) { + // poking into pi for primary class ivars. + int _a = pi->a; +} + +@interface I() +{ + @public int b; +} +@end + +void gorf (I* pg) { + // poking into pg for ivars for class extension + int _b = pg->b; +} + +// CHECK: {{.*}} [ DW_TAG_structure_type ] [I] +// Check for "a". +// CHECK: {{.*}} [ DW_TAG_member ] [a] [line 7, size 32, align 32, offset 0] [from int] +// Make sure we don't output the same type twice. +// CHECK-NOT: {{.*}} [ DW_TAG_structure_type ] [I] +// Check for "b". +// CHECK: {{.*}} [ DW_TAG_member ] [b] [line 18, size 32, align 32, offset 0] [from int] diff --git a/test/CodeGenObjC/debug-info-ivars-indirect.m b/test/CodeGenObjC/debug-info-ivars-indirect.m new file mode 100644 index 0000000..1548ddd --- /dev/null +++ b/test/CodeGenObjC/debug-info-ivars-indirect.m @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -g %s -o - | FileCheck %s + +// Make sure we generate debug symbols for an indirectly referenced +// extension to an interface. + +@interface I +{ + @public int a; +} +@end + +void foo(I* pi) { + int _a = pi->a; +} + +// another layer of indirection +struct S +{ + I* i; +}; + +@interface I() +{ + @public int b; +} +@end + +void gorf (struct S* s) { + int _b = s->i->b; +} + +// CHECK: {{.*}} [ DW_TAG_member ] [b] [line 24, size 32, align 32, offset 0] [from int] diff --git a/test/CodeGenObjC/debug-info-ivars-private.m b/test/CodeGenObjC/debug-info-ivars-private.m new file mode 100644 index 0000000..8505da1 --- /dev/null +++ b/test/CodeGenObjC/debug-info-ivars-private.m @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -g %s -o - | FileCheck %s + +// Debug symbols for private ivars. This test ensures that we are +// generating debug info for ivars added by the implementation. +__attribute((objc_root_class)) @interface NSObject { + id isa; +} +@end + +@protocol Protocol +@end + +@interface Delegate : NSObject<Protocol> { + @protected int foo; +} +@end + +@interface Delegate(NSObject) +- (void)f; +@end + +@implementation Delegate(NSObject) +- (void)f { return; } +@end + +@implementation Delegate { + int bar; +} + +- (void)g:(NSObject*) anObject { + bar = foo; +} +@end + +// CHECK: {{.*}} [ DW_TAG_member ] [foo] [line 14, size 32, align 32, offset 0] [protected] [from int] +// CHECK: {{.*}} [ DW_TAG_member ] [bar] [line 27, size 32, align 32, offset 0] [private] [from int] diff --git a/test/CodeGenObjC/debug-info-ivars.m b/test/CodeGenObjC/debug-info-ivars.m index 24705e1a..a0f2963 100644 --- a/test/CodeGenObjC/debug-info-ivars.m +++ b/test/CodeGenObjC/debug-info-ivars.m @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -g %s -o - | FileCheck %s __attribute((objc_root_class)) @interface NSObject { - id isa; + id isa; } @end @@ -10,15 +10,15 @@ __attribute((objc_root_class)) @interface NSObject { int i; unsigned flag_1 : 9; unsigned flag_2 : 9; - unsigned : 1; - unsigned flag_3 : 9; + unsigned : 1; + unsigned flag_3 : 9; } @end @implementation BaseClass @end -// CHECK: metadata !{i32 786445, metadata !{{[0-9]*}}, metadata !"i", metadata !{{[0-9]*}}, i32 10, i64 32, i64 32, i64 0, i32 2, metadata !{{[0-9]*}}, null} ; [ DW_TAG_member ] [i] [line 10, size 32, align 32, offset 0] [protected] [from int] -// CHECK: metadata !{i32 786445, metadata !{{[0-9]*}}, metadata !"flag_1", metadata !{{[0-9]*}}, i32 11, i64 9, i64 32, i64 0, i32 2, metadata !{{[0-9]*}}, null} ; [ DW_TAG_member ] [flag_1] [line 11, size 9, align 32, offset 0] [protected] [from unsigned int] -// CHECK: metadata !{i32 786445, metadata !{{[0-9]*}}, metadata !"flag_2", metadata !{{[0-9]*}}, i32 12, i64 9, i64 32, i64 1, i32 2, metadata !{{[0-9]*}}, null} ; [ DW_TAG_member ] [flag_2] [line 12, size 9, align 32, offset 1] [protected] [from unsigned int] -// CHECK: metadata !{i32 786445, metadata !{{[0-9]*}}, metadata !"flag_3", metadata !{{[0-9]*}}, i32 14, i64 9, i64 32, i64 3, i32 2, metadata !{{[0-9]*}}, null} ; [ DW_TAG_member ] [flag_3] [line 14, size 9, align 32, offset 3] [protected] [from unsigned int]
\ No newline at end of file +// CHECK: {{.*}} [ DW_TAG_member ] [i] [line 10, size 32, align 32, offset 0] [protected] [from int] +// CHECK: {{.*}} [ DW_TAG_member ] [flag_1] [line 11, size 9, align 32, offset 0] [protected] [from unsigned int] +// CHECK: {{.*}} [ DW_TAG_member ] [flag_2] [line 12, size 9, align 32, offset 1] [protected] [from unsigned int] +// CHECK: {{.*}} [ DW_TAG_member ] [flag_3] [line 14, size 9, align 32, offset 3] [protected] [from unsigned int] diff --git a/test/CodeGenObjC/debug-info-property3.m b/test/CodeGenObjC/debug-info-property3.m index f96ec44..f63e744 100644 --- a/test/CodeGenObjC/debug-info-property3.m +++ b/test/CodeGenObjC/debug-info-property3.m @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -S -emit-llvm -g %s -o - | FileCheck %s -// CHECK: metadata !"p1", metadata !6, i32 5, metadata !"", metadata !"", i32 2316, metadata !9} ; [ DW_TAG_APPLE_property ] +// CHECK: metadata !"p1", metadata !{{.*}}, i32 5, metadata !"", metadata !"", i32 2316, metadata !{{.*}}} ; [ DW_TAG_APPLE_property ] @interface I1 @property int p1; @end diff --git a/test/CodeGenObjC/debug-info-pubtypes.m b/test/CodeGenObjC/debug-info-pubtypes.m index 91d9cd1..8b7dfad 100644 --- a/test/CodeGenObjC/debug-info-pubtypes.m +++ b/test/CodeGenObjC/debug-info-pubtypes.m @@ -1,7 +1,7 @@ // REQUIRES: x86-64-registered-target // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -emit-llvm %s -o - | FileCheck %s -// CHECK: !5 = metadata !{i32 {{.*}}, metadata !6, metadata !"H", metadata !6, i32 6, i64 0, i64 8, i32 0, i32 512, null, metadata !2, i32 16, i32 0, i32 0} ; [ DW_TAG_structure_type ] +// CHECK: {{.*}} [ DW_TAG_structure_type ] [H] [line 6, @interface H -(void) foo; diff --git a/test/CodeGenObjC/debug-info-self.m b/test/CodeGenObjC/debug-info-self.m index 9f23435..7803467 100644 --- a/test/CodeGenObjC/debug-info-self.m +++ b/test/CodeGenObjC/debug-info-self.m @@ -2,11 +2,6 @@ // self and _cmd are marked as DW_AT_artificial. // myarg is not marked as DW_AT_artificial. -// CHECK: metadata !{i32 {{.*}}, metadata !9, metadata !"self", metadata !15, i32 16777232, metadata !30, i32 1088, i32 0} ; [ DW_TAG_arg_variable ] [self] [line 16] -// CHECK: metadata !{i32 {{.*}}, metadata !9, metadata !"_cmd", metadata !15, i32 33554448, metadata !33, i32 64, i32 0} ; [ DW_TAG_arg_variable ] [_cmd] [line 16] -// CHECK: metadata !{i32 {{.*}}, metadata !9, metadata !"myarg", metadata !6, i32 50331664, metadata !24, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [myarg] [line 16] - - @interface MyClass { } - (id)init:(int) myarg; @@ -18,3 +13,11 @@ return self; } @end + +// It's weird that the first two parameters are recorded as being in a +// different, ("<unknown>") file compared to the third parameter which is 'in' +// the actual source file. (see the metadata node after the arg name in each +// line) +// CHECK: metadata !{i32 {{.*}}, metadata ![[CTOR:.*]], metadata !"self", metadata ![[UNKFILE:.*]], i32 16777227, metadata !{{.*}}, i32 1088, i32 0} ; [ DW_TAG_arg_variable ] [self] [line 11] +// CHECK: metadata !{i32 {{.*}}, metadata ![[CTOR]], metadata !"_cmd", metadata ![[UNKFILE]], i32 33554443, metadata !{{.*}}, i32 64, i32 0} ; [ DW_TAG_arg_variable ] [_cmd] [line 11] +// CHECK: metadata !{i32 {{.*}}, metadata ![[CTOR]], metadata !"myarg", metadata !{{.*}}, i32 50331659, metadata !{{.*}}, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [myarg] [line 11] diff --git a/test/CodeGenObjC/debug-info-static-var.m b/test/CodeGenObjC/debug-info-static-var.m index 8602ffb..2c10d59 100644 --- a/test/CodeGenObjC/debug-info-static-var.m +++ b/test/CodeGenObjC/debug-info-static-var.m @@ -1,14 +1,8 @@ -// REQUIRES: x86-64-registered-target -// RUN: %clang_cc1 -g -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -S -masm-verbose -o - %s | FileCheck %s +// RUN: %clang_cc1 -g -emit-llvm -o - %s | FileCheck %s // Radar 8801045 // Do not emit AT_MIPS_linkage_name for static variable i -// CHECK: Lset6 = Lstring3-Lsection_str ## DW_AT_name -// CHECK-NEXT: .long Lset6 -// CHECK-NEXT: DW_AT_type -// CHECK-NEXT: DW_AT_decl_file -// CHECK-NEXT: DW_AT_decl_line -// CHECK-NEXT: DW_AT_location +// CHECK: metadata !"i", metadata !"i", metadata !"" @interface A { } diff --git a/test/CodeGenObjC/debug-info-synthesis.m b/test/CodeGenObjC/debug-info-synthesis.m index bf8e6d1..1bf7576 100644 --- a/test/CodeGenObjC/debug-info-synthesis.m +++ b/test/CodeGenObjC/debug-info-synthesis.m @@ -30,5 +30,5 @@ int main(int argc, char *argv[]) { } } -// CHECK: !7 = metadata !{i32 {{.*}}, metadata !"./foo.h" -// CHECK: !29 = metadata !{i32 {{.*}}, i32 0, metadata !7, metadata !"-[Foo dict]", metadata !"-[Foo dict]", metadata !"", metadata !7, i32 8, metadata !30, i1 true, i1 true, i32 0, i32 0, null, i32 320, i1 false, %1* (%0*, i8*)* @"\01-[Foo dict]", null, null, metadata !1, i32 8} ; [ DW_TAG_subprogram ] +// CHECK: ![[FILE:.*]] = {{.*}}[ DW_TAG_file_type ] [{{.*}}/foo.h] +// CHECK: metadata ![[FILE]], {{.*}} ; [ DW_TAG_subprogram ] [line 8] [local] [def] [-[Foo dict]] diff --git a/test/CodeGenObjC/encode-test-6.m b/test/CodeGenObjC/encode-test-6.m index 10681db..b7feb14 100644 --- a/test/CodeGenObjC/encode-test-6.m +++ b/test/CodeGenObjC/encode-test-6.m @@ -17,3 +17,21 @@ typedef struct {} Z; // CHECK: internal global [14 x i8] c"v16@0:8{?=}16 // CHECK: internal global [26 x i8] c"v32@0:8{?=}16*16{?=}24d24 + +// rdar://13190095 +@interface NSObject @end + +@class BABugExample; +typedef BABugExample BABugExampleRedefinition; + +@interface BABugExample : NSObject { + BABugExampleRedefinition *_property; // .asciz "^{BABugExample=^{BABugExample}}" +} +@property (copy) BABugExampleRedefinition *property; +@end + +@implementation BABugExample +@synthesize property = _property; +@end + +// CHECK: internal global [24 x i8] c"^{BABugExample=@}16 diff --git a/test/CodeGenObjC/encode-test.m b/test/CodeGenObjC/encode-test.m index 3780068..e8d6541 100644 --- a/test/CodeGenObjC/encode-test.m +++ b/test/CodeGenObjC/encode-test.m @@ -165,3 +165,7 @@ const char g10[] = @encode(struct f); // rdar://9622422 // CHECK: @g11 = constant [2 x i8] c"v\00" const char g11[] = @encode(void); + +// PR14628 +// CHECK: @g12 = constant [3 x i8] c"Ai\00" +const char g12[] = @encode(_Atomic(int)); diff --git a/test/CodeGenObjC/exceptions.m b/test/CodeGenObjC/exceptions.m index 551e67c..408b94d 100644 --- a/test/CodeGenObjC/exceptions.m +++ b/test/CodeGenObjC/exceptions.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -fexceptions -fobjc-exceptions -O2 -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -fobjc-exceptions -O2 -o - %s | FileCheck %s // // <rdar://problem/7471679> [irgen] [eh] Exception code built with clang (x86_64) crashes @@ -28,7 +28,7 @@ void f1() { // CHECK: call void asm sideeffect "", "*m" // CHECK-NEXT: call void @foo() foo(); - // CHECK-NEXT: call void @objc_exception_try_exit + // CHECK: call void @objc_exception_try_exit // CHECK: call void asm sideeffect "", "=*m" } @finally { diff --git a/test/CodeGenObjC/extended-block-signature-encode.m b/test/CodeGenObjC/extended-block-signature-encode.m new file mode 100644 index 0000000..a380856 --- /dev/null +++ b/test/CodeGenObjC/extended-block-signature-encode.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin -fencode-extended-block-signature -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin -emit-llvm %s -o - | FileCheck %s -check-prefix=BRIEF +// rdar://12109031 + +@class NSString, NSArray; + +typedef NSString*(^BBB)(NSArray*); + +int main () +{ + BBB b1; + ^(BBB arg1, double arg2){ return b1; }(0, 3.14); +} +// CHECK: @{{.*}} = private unnamed_addr constant [64 x i8] c"@?<@\22NSString\22@?@\22NSArray\22>24@?0@?<@\22NSString\22@?@\22NSArray\22>8d16\00" +// CHECK-BRIEF: @{{.*}} = private unnamed_addr constant [14 x i8] c"@?24@?0@?8d16\00" diff --git a/test/CodeGenObjC/externally-initialized-selectors.m b/test/CodeGenObjC/externally-initialized-selectors.m new file mode 100644 index 0000000..87a7c04 --- /dev/null +++ b/test/CodeGenObjC/externally-initialized-selectors.m @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -cc1 -fobjc-runtime=macosx-fragile-10.5 -o - -emit-llvm %s | FileCheck %s +// RUN: %clang_cc1 -cc1 -o - -emit-llvm %s | FileCheck %s + +// CHECK: @"\01L_OBJC_SELECTOR_REFERENCES_" = internal externally_initialized global + +void test(id x) { + [x doSomething]; +} diff --git a/test/CodeGenObjC/gc.m b/test/CodeGenObjC/gc.m index b672181..ce2611e 100644 --- a/test/CodeGenObjC/gc.m +++ b/test/CodeGenObjC/gc.m @@ -9,6 +9,8 @@ void test0(void) { // CHECK-NEXT: store i8* [[T0]], i8** [[X:%.*]], align 8 // CHECK-NEXT: call i8* @test0_helper() // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]], align 8 - // CHECK-NEXT: call void asm sideeffect "", "r"(i8* [[T0]]) nounwind + // CHECK-NEXT: call void asm sideeffect "", "r"(i8* [[T0]]) [[NUW:#[0-9]+]] // CHECK-NEXT: ret void } + +// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenObjC/gnu-exceptions.m b/test/CodeGenObjC/gnu-exceptions.m index b7d0adb..7aa9709 100644 --- a/test/CodeGenObjC/gnu-exceptions.m +++ b/test/CodeGenObjC/gnu-exceptions.m @@ -1,11 +1,12 @@ // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fexceptions -fobjc-exceptions -fobjc-runtime=gcc -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -emit-llvm -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep-1.7 -o - %s | FileCheck -check-prefix=NEW-ABI %s void opaque(void); void log(int i); @class C; -// CHECK: define void @test0() { +// CHECK: define void @test0() [[TF:#[0-9]+]] { void test0() { @try { // CHECK: invoke void @opaque() @@ -21,9 +22,13 @@ void test0() { // CHECK: call void @log(i32 0) // CHECK: resume + // NEW-ABI: objc_begin_catch + // NEW-ABI: objc_end_catch log(0); } log(1); } + +// CHECK: attributes [[TF]] = { "{{.*}} } diff --git a/test/CodeGenObjC/interface-layout-64.m b/test/CodeGenObjC/interface-layout-64.m index 16361a2..4b41cf8 100644 --- a/test/CodeGenObjC/interface-layout-64.m +++ b/test/CodeGenObjC/interface-layout-64.m @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s -// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s && // CHECK: @"OBJC_IVAR_$_I3._iv2" = global i64 8, section "__DATA, __objc_ivar", align 8 // CHECK: @"OBJC_IVAR_$_I3._iv3" = global i64 12, section "__DATA, __objc_ivar", align 8 diff --git a/test/CodeGenObjC/ivar-invariant.m b/test/CodeGenObjC/ivar-invariant.m new file mode 100644 index 0000000..7cafee7 --- /dev/null +++ b/test/CodeGenObjC/ivar-invariant.m @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fblocks -emit-llvm -o - %s | FileCheck %s + +@interface NSObject ++ (id) new; +- (id) init; +@end + +@interface Base : NSObject @end + +// @implementation Base +// { +// int dummy; +// } +// @end + +@interface Derived : Base +{ + @public int member; +} +@end + +@implementation Derived +- (id) init +{ + self = [super init]; + member = 42; + return self; +} +@end + +// CHECK: define internal i8* @"\01-[Derived init]" +// CHECK: [[IVAR:%.*]] = load i64* @"OBJC_IVAR_$_Derived.member", !invariant.load + +void * variant_load_1(int i) { + void *ptr; + while (i--) { + Derived *d = [Derived new]; + ptr = &d->member; + } + return ptr; +} + +// CHECK: define i8* @variant_load_1(i32 %i) +// CHECK: [[IVAR:%.*]] = load i64* @"OBJC_IVAR_$_Derived.member"{{$}} + +@interface Container : Derived @end +@implementation Container +- (void *) invariant_load_1 +{ + return &self->member; +} +@end + +// CHECK: define internal i8* @"\01-[Container invariant_load_1]" +// CHECK: [[IVAR:%.*]] = load i64* @"OBJC_IVAR_$_Derived.member", !invariant.load + +@interface ForBlock +{ +@public + id foo; +} +@end + +// CHECK: define internal i8* @block_block_invoke +// CHECK: load i64* @"OBJC_IVAR_$_ForBlock.foo" +id (^block)(ForBlock*) = ^(ForBlock* a) { + return a->foo; +}; diff --git a/test/CodeGenObjC/metadata-symbols-32.m b/test/CodeGenObjC/metadata-symbols-32.m index 1df1560..e8d2512 100644 --- a/test/CodeGenObjC/metadata-symbols-32.m +++ b/test/CodeGenObjC/metadata-symbols-32.m @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -o %t %s -// RUNX: llvm-gcc -m32 -emit-llvm -S -o %t %s && // RUN: grep '@"\\01L_OBJC_CATEGORY_A_Cat" = internal global .*section "__OBJC,__category,regular,no_dead_strip", align 4' %t // RUN: grep '@"\\01L_OBJC_CATEGORY_CLASS_METHODS_A_Cat" = internal global .*section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t @@ -24,7 +23,7 @@ // RUN: grep '@"\\01L_OBJC_PROTOCOL_CLASS_METHODS_P" = internal global .*section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t // RUN: grep '@"\\01L_OBJC_PROTOCOL_INSTANCE_METHODS_P" = internal global .*section "__OBJC,__cat_inst_meth,regular,no_dead_strip", align 4' %t // RUN: grep '@"\\01L_OBJC_PROTOCOL_P" = internal global .*section "__OBJC,__protocol,regular,no_dead_strip", align 4' %t -// RUN: grep '@"\\01L_OBJC_SELECTOR_REFERENCES_[0-9]*" = internal global .*section "__OBJC,__message_refs,literal_pointers,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_SELECTOR_REFERENCES_[0-9]*" = internal externally_initialized global .*section "__OBJC,__message_refs,literal_pointers,no_dead_strip", align 4' %t // RUN: grep '@"\\01L_OBJC_SYMBOLS" = internal global .*section "__OBJC,__symbols,regular,no_dead_strip", align 4' %t // RUN: grep '@"\\01l_OBJC_$_PROP_LIST_A" = internal global .*section "__OBJC,__property,regular,no_dead_strip", align 4' %t // RUN: grep "\.lazy_reference \.objc_class_name_J0" %t diff --git a/test/CodeGenObjC/metadata-symbols-64.m b/test/CodeGenObjC/metadata-symbols-64.m index 57f5d50..27017b7 100644 --- a/test/CodeGenObjC/metadata-symbols-64.m +++ b/test/CodeGenObjC/metadata-symbols-64.m @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-dispatch-method=mixed -emit-llvm -o %t %s -// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s && // RUN: grep '@"OBJC_CLASS_$_A" = global' %t // RUN: grep '@"OBJC_CLASS_$_B" = external global' %t @@ -13,7 +12,7 @@ // RUN: grep '@"\\01L_OBJC_METH_VAR_NAME_[0-9]*" = internal global .* section "__TEXT,__objc_methname,cstring_literals", align 1' %t // RUN: grep '@"\\01L_OBJC_METH_VAR_TYPE_[0-9]*" = internal global .* section "__TEXT,__objc_methtype,cstring_literals", align 1' %t // RUN: grep '@"\\01L_OBJC_PROP_NAME_ATTR_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t -// RUN: grep '@"\\01L_OBJC_SELECTOR_REFERENCES_*" = internal global .* section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"' %t +// RUN: grep '@"\\01L_OBJC_SELECTOR_REFERENCES_*" = internal externally_initialized global .* section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"' %t // RUN: grep '@"\\01l_OBJC_$_CATEGORY_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t // RUN: grep '@"\\01l_OBJC_$_CATEGORY_CLASS_METHODS_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t // RUN: grep '@"\\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t diff --git a/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m b/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m index f1e02dd..bb3a20b 100644 --- a/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m +++ b/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m @@ -1,5 +1,8 @@ -// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin -O0 -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -fblocks -triple i386-apple-darwin -O0 -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-i386 %s +// RUN: %clang_cc1 -fblocks -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout +// RUN: FileCheck --input-file=%t-64.layout %s +// RUN: %clang_cc1 -fblocks -fobjc-runtime-has-weak -triple i386-apple-darwin -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-32.layout +// RUN: FileCheck -check-prefix=CHECK-i386 --input-file=%t-32.layout %s +// rdar://12184410 // rdar://12184410 void x(id y) {} @@ -16,25 +19,25 @@ void f() { __block id byref_bab = (id)0; __block id bl_var1; -// block variable layout: BL_UNRETAINED:1, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"`\00" -// CHECK-i386: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"`\00" +// block variable layout: BL_STRONG:1, BL_OPERATOR:0 +// CHECK: Inline instruction for block variable layout: 0x0100 +// CHECK-i386: Inline instruction for block variable layout: 0x0100 void (^b)() = ^{ x(bar); }; -// block variable layout: BL_UNRETAINED:2, BL_BYREF:1, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"a@\00" -// CHECK-i386: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"a@\00" +// block variable layout: BL_STRONG:2, BL_BYREF:1, BL_OPERATOR:0 +// CHECK: Inline instruction for block variable layout: 0x0210 +// CHECK-i386: Inline instruction for block variable layout: 0x0210 void (^c)() = ^{ x(bar); x(baz); byref_int = 1; }; -// block variable layout: BL_UNRETAINED:2, BL_BYREF:3, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"aB\00 -// CHECK-i386: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"aB\00 +// block variable layout: BL_STRONG:2, BL_BYREF:3, BL_OPERATOR:0 +// CHECK: Inline instruction for block variable layout: 0x0230 +// CHECK-i386: Inline instruction for block variable layout: 0x0230 void (^d)() = ^{ x(bar); x(baz); @@ -43,9 +46,9 @@ void f() { byref_bab = 0; }; -// block variable layout: BL_UNRETAINED:2, BL_BYREF:3, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"aB\00" -// CHECK-i386: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"aB\00" +// block variable layout: BL_STRONG:2, BL_BYREF:3, BL_OPERATOR:0 +// CHECK: Inline instruction for block variable layout: 0x0230 +// CHECK-i386: Inline instruction for block variable layout: 0x0230 id (^e)() = ^{ x(bar); x(baz); @@ -55,9 +58,8 @@ void f() { return wid; }; -// Inline instruction for block variable layout: 0x020 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 32 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 32 } +// CHECK: Inline instruction for block variable layout: 0x020 +// CHECK-i386: Inline instruction for block variable layout: 0x020 void (^ii)() = ^{ byref_int = 1; byref_bab = 0; diff --git a/test/CodeGenObjC/non-lazy-classes.m b/test/CodeGenObjC/non-lazy-classes.m index 5d82901..d95cb78d 100644 --- a/test/CodeGenObjC/non-lazy-classes.m +++ b/test/CodeGenObjC/non-lazy-classes.m @@ -1,4 +1,3 @@ -// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s && // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o %t %s // RUN: grep '@".01L_OBJC_LABEL_NONLAZY_CLASS_$" = internal global \[1 x .*\] .*@"OBJC_CLASS_$_A".*, section "__DATA, __objc_nlclslist, regular, no_dead_strip", align 8' %t // RUN: grep '@".01L_OBJC_LABEL_NONLAZY_CATEGORY_$" = internal global \[1 x .*\] .*@".01l_OBJC_$_CATEGORY_A_$_Cat".*, section "__DATA, __objc_nlcatlist, regular, no_dead_strip", align 8' %t diff --git a/test/CodeGenObjC/nonlazy-msgSend.m b/test/CodeGenObjC/nonlazy-msgSend.m index 7c349b2..0ae9f11 100644 --- a/test/CodeGenObjC/nonlazy-msgSend.m +++ b/test/CodeGenObjC/nonlazy-msgSend.m @@ -1,6 +1,8 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -o %t %s -// RUN: grep -F 'declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind' %t +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm %s -o - | FileCheck %s +// CHECK: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB:#[0-9]+]] void f0(id x) { [x foo]; } + +// CHECK: attributes [[NLB]] = { nonlazybind } diff --git a/test/CodeGenObjC/ns_consume_null_check.m b/test/CodeGenObjC/ns_consume_null_check.m index a8e5acd..6a31a80 100644 --- a/test/CodeGenObjC/ns_consume_null_check.m +++ b/test/CodeGenObjC/ns_consume_null_check.m @@ -1,5 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fobjc-dispatch-method=mixed -o - %s | FileCheck %s -// rdar://10444476 +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fobjc-dispatch-method=mixed -fobjc-runtime-has-weak -fexceptions -o - %s | FileCheck %s @interface NSObject - (id) new; @@ -7,26 +6,80 @@ @interface MyObject : NSObject - (char)isEqual:(id) __attribute__((ns_consumed)) object; +- (_Complex float) asComplexWithArg: (id) __attribute__((ns_consumed)) object; @end MyObject *x; -void foo() -{ - id obj = [NSObject new]; - [x isEqual : obj]; +// rdar://10444476 +void test0(void) { + id obj = [NSObject new]; + [x isEqual : obj]; } - -// CHECK: [[TMP:%.*]] = alloca i8{{$}} -// CHECK: [[FIVE:%.*]] = call i8* @objc_retain +// CHECK: define void @test0() +// CHECK: [[FIVE:%.*]] = call i8* @objc_retain // CHECK-NEXT: [[SIX:%.*]] = bitcast // CHECK-NEXT: [[SEVEN:%.*]] = icmp eq i8* [[SIX]], null // CHECK-NEXT: br i1 [[SEVEN]], label [[NULLINIT:%.*]], label [[CALL_LABEL:%.*]] -// CHECK: [[FN:%.*]] = load i8** getelementptr inbounds +// CHECK: [[FN:%.*]] = load i8** getelementptr inbounds // CHECK-NEXT: [[EIGHT:%.*]] = bitcast i8* [[FN]] // CHECK-NEXT: [[CALL:%.*]] = call signext i8 [[EIGHT]] -// CHECK-NEXT: store i8 [[CALL]], i8* [[TMP]] // CHECK-NEXT: br label [[CONT:%.*]] -// CHECK: call void @objc_release(i8* [[FIVE]]) nounwind -// CHECK-NEXT: call void @llvm.memset +// CHECK: call void @objc_release(i8* [[FIVE]]) [[NUW:#[0-9]+]] // CHECK-NEXT: br label [[CONT]] +// CHECK: phi i8 [ [[CALL]], {{%.*}} ], [ 0, {{%.*}} ] + +// Ensure that we build PHIs correctly in the presence of cleanups. +// rdar://12046763 +void test1(void) { + id obj = [NSObject new]; + __weak id weakObj = obj; + _Complex float result = [x asComplexWithArg: obj]; +} +// CHECK: define void @test1() +// CHECK: [[OBJ:%.*]] = alloca i8*, align 8 +// CHECK-NEXT: [[WEAKOBJ:%.*]] = alloca i8*, align 8 +// CHECK-NEXT: [[RESULT:%.*]] = alloca { float, float }, align 4 +// Various initializations. +// CHECK: [[T0:%.*]] = call i8* bitcast ( +// CHECK-NEXT: store i8* [[T0]], i8** [[OBJ]] +// CHECK-NEXT: [[T0:%.*]] = load i8** [[OBJ]] +// CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAKOBJ]], i8* [[T0]]) [[NUW]] +// Okay, start the message-send. +// CHECK-NEXT: [[T0:%.*]] = load [[MYOBJECT:%.*]]** @x +// CHECK-NEXT: [[ARG:%.*]] = load i8** [[OBJ]] +// CHECK-NEXT: [[ARG_RETAINED:%.*]] = call i8* @objc_retain(i8* [[ARG]]) +// CHECK-NEXT: load i8** @ +// CHECK-NEXT: [[SELF:%.*]] = bitcast [[MYOBJECT]]* [[T0]] to i8* +// Null check. +// CHECK-NEXT: [[T0:%.*]] = icmp eq i8* [[SELF]], null +// CHECK-NEXT: br i1 [[T0]], label [[FORNULL:%.*]], label [[FORCALL:%.*]] +// Invoke and produce the return values. +// CHECK: [[CALL:%.*]] = invoke <2 x float> bitcast +// CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label {{%.*}} +// CHECK: [[T0:%.*]] = bitcast { float, float }* [[COERCE:%.*]] to <2 x float>* +// CHECK-NEXT: store <2 x float> [[CALL]], <2 x float>* [[T0]], +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds { float, float }* [[COERCE]], i32 0, i32 0 +// CHECK-NEXT: [[REALCALL:%.*]] = load float* [[T0]] +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds { float, float }* [[COERCE]], i32 0, i32 1 +// CHECK-NEXT: [[IMAGCALL:%.*]] = load float* [[T0]] +// CHECK-NEXT: br label [[CONT:%.*]]{{$}} +// Null path. +// CHECK: call void @objc_release(i8* [[ARG_RETAINED]]) [[NUW]] +// CHECK-NEXT: br label [[CONT]] +// Join point. +// CHECK: [[REAL:%.*]] = phi float [ [[REALCALL]], [[INVOKE_CONT]] ], [ 0.000000e+00, [[FORNULL]] ] +// CHECK-NEXT: [[IMAG:%.*]] = phi float [ [[IMAGCALL]], [[INVOKE_CONT]] ], [ 0.000000e+00, [[FORNULL]] ] +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds { float, float }* [[RESULT]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds { float, float }* [[RESULT]], i32 0, i32 1 +// CHECK-NEXT: store float [[REAL]], float* [[T0]] +// CHECK-NEXT: store float [[IMAG]], float* [[T1]] +// Epilogue. +// CHECK-NEXT: call void @objc_destroyWeak(i8** [[WEAKOBJ]]) [[NUW]] +// CHECK-NEXT: call void @objc_storeStrong(i8** [[OBJ]], i8* null) [[NUW]] +// CHECK-NEXT: ret void +// Cleanup. +// CHECK: landingpad +// CHECK: call void @objc_destroyWeak(i8** [[WEAKOBJ]]) [[NUW]] + +// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenObjC/objc-align.m b/test/CodeGenObjC/objc-align.m index 324740c..1a9e882 100644 --- a/test/CodeGenObjC/objc-align.m +++ b/test/CodeGenObjC/objc-align.m @@ -1,6 +1,5 @@ // 32-bit -// RUNX: llvm-gcc -m32 -emit-llvm -S -o %t %s && // RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -o %t %s // RUN: grep '@"\\01L_OBJC_CATEGORY_A_Cat" = internal global .*, section "__OBJC,__category,regular,no_dead_strip", align 4' %t // RUN: grep '@"\\01L_OBJC_CLASS_A" = internal global .*, section "__OBJC,__class,regular,no_dead_strip", align 4' %t diff --git a/test/CodeGenObjC/objc-arc-container-subscripting.m b/test/CodeGenObjC/objc-arc-container-subscripting.m index 71339c7..1824562 100644 --- a/test/CodeGenObjC/objc-arc-container-subscripting.m +++ b/test/CodeGenObjC/objc-arc-container-subscripting.m @@ -12,9 +12,10 @@ id func() { } // CHECK: [[call:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend -// CHECK: [[SIX:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[call]]) nounwind +// CHECK: [[SIX:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[call]]) [[NUW:#[0-9]+]] // CHECK: [[ARRAY_CASTED:%.*]] = bitcast %0** {{%.*}} to i8** // CHECK: call void @objc_storeStrong(i8** [[ARRAY_CASTED]], i8* null) -// CHECK: [[EIGHT:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[SIX]]) nounwind +// CHECK: [[EIGHT:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[SIX]]) [[NUW]] // CHECK: ret i8* [[EIGHT]] +// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenObjC/objc-literal-debugger-test.m b/test/CodeGenObjC/objc-literal-debugger-test.m index 5f69fd5..d4043aa 100644 --- a/test/CodeGenObjC/objc-literal-debugger-test.m +++ b/test/CodeGenObjC/objc-literal-debugger-test.m @@ -50,4 +50,6 @@ int main() { #endif } -// CHECK: declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind +// CHECK: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB:#[0-9]+]] + +// CHECK: attributes [[NLB]] = { nonlazybind } diff --git a/test/CodeGenObjC/objc-literal-tests.m b/test/CodeGenObjC/objc-literal-tests.m index c513d49..c53ee64 100644 --- a/test/CodeGenObjC/objc-literal-tests.m +++ b/test/CodeGenObjC/objc-literal-tests.m @@ -53,7 +53,7 @@ typedef signed char BOOL; id NSUserName(); -// CHECK: define i32 @main() nounwind +// CHECK: define i32 @main() [[NUW:#[0-9]+]] int main() { // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 97 NSNumber *aNumber = @'a'; @@ -93,3 +93,5 @@ extern void bar(foo a); void baz(void) { bar(^(void) { return YES; }); } + +// CHECK: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CodeGenObjC/optimized-setter.m b/test/CodeGenObjC/optimized-setter.m index 6f5cfb1..7e0a1d7 100644 --- a/test/CodeGenObjC/optimized-setter.m +++ b/test/CodeGenObjC/optimized-setter.m @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -emit-llvm -fobjc-runtime=macosx-10.8 -triple x86_64-apple-macosx10.8.0 -o - | FileCheck %s // RUN: %clang_cc1 %s -emit-llvm -fobjc-runtime=ios-6.0.0 -triple x86_64-apple-ios6.0.0 -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -fobjc-runtime=gnustep-1.7 -triple x86_64-unknown-freebsd -o - | FileCheck %s // rdar://10179974 @interface I diff --git a/test/CodeGenObjC/property.m b/test/CodeGenObjC/property.m index aab7c73..6a43826 100644 --- a/test/CodeGenObjC/property.m +++ b/test/CodeGenObjC/property.m @@ -1,8 +1,5 @@ // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck %s -// PR13820 -// REQUIRES: LP64 - // TODO: actually test most of this instead of just emitting it int printf(const char *, ...); diff --git a/test/CodeGenObjC/protocols-lazy.m b/test/CodeGenObjC/protocols-lazy.m index 877d492..642f886 100644 --- a/test/CodeGenObjC/protocols-lazy.m +++ b/test/CodeGenObjC/protocols-lazy.m @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -emit-llvm -triple i686-apple-darwin8 -fobjc-runtime=macosx-fragile-10.5 -o %t %s -// RUNX: llvm-gcc -S -emit-llvm -o %t %s && // No object generated // RUN: grep OBJC_PROTOCOL_P0 %t | count 0 diff --git a/test/CodeGenObjC/reorder-synthesized-ivars.m b/test/CodeGenObjC/reorder-synthesized-ivars.m new file mode 100644 index 0000000..747265d --- /dev/null +++ b/test/CodeGenObjC/reorder-synthesized-ivars.m @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-default-synthesize-properties -emit-llvm -x objective-c %s -o - | FileCheck %s +// rdar://13192366 +typedef signed char BOOL; +@interface NSObject +{ + id isa; +} +@end + +@interface MyClass : NSObject + +@property (readwrite) BOOL boolean1; +@property (readwrite, copy) id object1; +@property (readwrite) BOOL boolean2; +@property (readwrite, copy) id object2; +@property (readwrite) BOOL boolean3; +@property (readwrite, copy) id object3; +@property (readwrite) BOOL boolean4; +@property (readwrite, copy) id object4; +@property (readwrite) BOOL boolean5; +@property (readwrite, copy) id object5; +@property (readwrite) BOOL boolean6; +@property (readwrite, copy) id object6; +@property (readwrite) BOOL boolean7; +@property (readwrite) BOOL MyBool; +@property (readwrite, copy) id object7; +@property (readwrite) BOOL boolean8; +@property (readwrite, copy) id object8; +@property (readwrite) BOOL boolean9; +@property (readwrite, copy) id object9; +@end + +@implementation MyClass +{ + id MyIvar; + BOOL _MyBool; + char * pc; +} +@end + +// CHECK: @"{{.*}}" = internal global [10 x i8] c"_boolean1 +// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean2 +// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean3 +// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean4 +// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean5 +// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean6 +// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean7 +// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean8 +// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean9 +// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object1 +// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object2 +// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object3 +// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object4 +// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object5 +// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object6 +// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object7 +// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object8 +// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object9 |