diff options
Diffstat (limited to 'test/CodeGenObjC')
41 files changed, 1501 insertions, 139 deletions
diff --git a/test/CodeGenObjC/2008-10-3-EhValue.m b/test/CodeGenObjC/2008-10-3-EhValue.m index 0ed0d89..bc4dfdb 100644 --- a/test/CodeGenObjC/2008-10-3-EhValue.m +++ b/test/CodeGenObjC/2008-10-3-EhValue.m @@ -1,4 +1,4 @@ -// RUN: %clang -fexceptions -S -emit-llvm %s -o /dev/null +// RUN: %clang -fexceptions -fobjc-exceptions -S -emit-llvm %s -o /dev/null @interface Object { @public diff --git a/test/CodeGenObjC/arc-arm.m b/test/CodeGenObjC/arc-arm.m index 23da3be..2ab8cb6 100644 --- a/test/CodeGenObjC/arc-arm.m +++ b/test/CodeGenObjC/arc-arm.m @@ -13,8 +13,24 @@ void test1(void) { // CHECK-NEXT: call void asm sideeffect "mov\09r7, r7 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) // CHECK-NEXT: store i8* [[T1]], - // CHECK-NEXT: load - // CHECK-NEXT: call void @objc_release + // CHECK-NEXT: call void @objc_storeStrong( // CHECK-NEXT: ret void id x = test1_helper(); } + +// rdar://problem/12133032 +@class A; +A *test2(void) { + extern A *test2_helper(void); + // CHECK: [[T0:%.*]] = call arm_aapcscc [[A:%.*]]* @test2_helper() + // CHECK-NEXT: ret [[A]]* [[T0]] + return test2_helper(); +} + +id test3(void) { + extern A *test3_helper(void); + // CHECK: [[T0:%.*]] = call arm_aapcscc [[A:%.*]]* @test3_helper() + // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* + // CHECK-NEXT: ret i8* [[T1]] + return test3_helper(); +} diff --git a/test/CodeGenObjC/arc-block-ivar-layout.m b/test/CodeGenObjC/arc-block-ivar-layout.m deleted file mode 100644 index 6c82f29..0000000 --- a/test/CodeGenObjC/arc-block-ivar-layout.m +++ /dev/null @@ -1,60 +0,0 @@ -// 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 -// rdar://8991729 - -__weak id wid; -void x(id y) {} -void y(int a) {} - -extern id opaque_id(); - -void f() { - __block int byref_int = 0; - char ch = 'a'; - char ch1 = 'b'; - char ch2 = 'c'; - short sh = 2; - const id bar = (id) opaque_id(); - id baz = 0; - __strong id strong_void_sta; - __block id byref_bab = (id)0; - __block id bl_var1; - int i; double dob; - -// The patterns here are a sequence of bytes, each saying first how -// many sizeof(void*) chunks to skip (high nibble) and then how many -// to scan (low nibble). A zero byte says that we've reached the end -// of the pattern. -// -// All of these patterns start with 01 3x because the block header on -// LP64 consists of an isa pointer (which we're supposed to scan for -// some reason) followed by three words (2 ints, a function pointer, -// and a descriptor pointer). - -// Test 1 -// byref int, short, char, char, char, id, id, strong id, byref id -// 01 35 10 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\015\10\00" - void (^b)() = ^{ - byref_int = sh + ch+ch1+ch2 ; - x(bar); - x(baz); - x((id)strong_void_sta); - x(byref_bab); - }; - b(); - -// Test 2 -// byref int, short, char, char, char, id, id, strong id, byref void*, byref id -// 01 36 10 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\016\10\00" - void (^c)() = ^{ - byref_int = sh + ch+ch1+ch2 ; - x(bar); - x(baz); - x((id)strong_void_sta); - x(wid); - bl_var1 = 0; - x(byref_bab); - }; -} diff --git a/test/CodeGenObjC/arc-blocks.m b/test/CodeGenObjC/arc-blocks.m index 2326bce..e776517 100644 --- a/test/CodeGenObjC/arc-blocks.m +++ b/test/CodeGenObjC/arc-blocks.m @@ -1,4 +1,5 @@ // 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-UNOPT %s // This shouldn't crash. void test0(id (^maker)(void)) { @@ -41,6 +42,24 @@ void test2(id x) { // CHECK-NEXT: ret void extern void test2_helper(id (^)(void)); test2_helper(^{ return x; }); + +// CHECK: define internal void @__copy_helper_block_ +// CHECK: [[T0:%.*]] = load i8** +// CHECK-NEXT: [[SRC:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]* +// CHECK-NEXT: [[T0:%.*]] = load i8** +// 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: ret void + +// CHECK: define internal void @__destroy_helper_block_ +// CHECK: [[T0:%.*]] = load i8** +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]* +// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[T1]], i32 0, i32 5 +// CHECK-NEXT: [[T3:%.*]] = load i8** [[T2]] +// CHECK-NEXT: call void @objc_release(i8* [[T3]]) +// CHECK-NEXT: ret void } void test3(void (^sink)(id*)) { @@ -99,8 +118,8 @@ void test4(void) { // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) // CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]] // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6 - // 0x42000000 - has signature, copy/dispose helpers - // CHECK: store i32 1107296256, + // 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT + // CHECK: store i32 -1040187392, // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8* // CHECK-NEXT: store i8* [[T0]], i8** // CHECK: call void @test4_helper( @@ -151,8 +170,8 @@ void test5(void) { // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) // CHECK-NEXT: store i8* [[T1]], i8** [[VAR]], // CHECK-NEXT: call void @objc_release(i8* [[T1]]) - // 0x40000000 - has signature but no copy/dispose - // CHECK: store i32 1073741824, i32* + // 0x40800000 - has signature but no copy/dispose, as well as BLOCK_HAS_EXTENDED_LAYOUT + // CHECK: store i32 -1073741824, i32* // CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK-NEXT: [[T0:%.*]] = load i8** [[VAR]] // CHECK-NEXT: store i8* [[T0]], i8** [[CAPTURE]] @@ -179,8 +198,8 @@ void test6(void) { // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T1]]) // CHECK-NEXT: call void @objc_release(i8* [[T1]]) // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6 - // 0x42000000 - has signature, copy/dispose helpers - // CHECK: store i32 1107296256, + // 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT + // CHECK: store i32 -1040187392, // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8* // CHECK-NEXT: store i8* [[T0]], i8** // CHECK: call void @test6_helper( @@ -228,8 +247,8 @@ void test7(void) { // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) // CHECK-NEXT: call i8* @objc_initWeak(i8** [[VAR]], i8* [[T1]]) // CHECK-NEXT: call void @objc_release(i8* [[T1]]) - // 0x42000000 - has signature, copy/dispose helpers - // CHECK: store i32 1107296256, + // 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: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T0]]) @@ -359,7 +378,7 @@ void test10a(void) { // CHECK: [[T0:%.*]] = load i8** {{%.*}} // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BYREF_T]]* // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BYREF_T]]* [[T1]], i32 0, i32 6 -// CHECK-NEXT: [[T3:%.*]] = load void ()** [[T2]], align 8 +// CHECK-NEXT: [[T3:%.*]] = load void ()** [[T2]] // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8* // CHECK-NEXT: call void @objc_release(i8* [[T4]]) // CHECK-NEXT: ret void @@ -532,3 +551,99 @@ void test16() { // CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK-NEXT: store void ()* null, void ()** [[BLKVAR]], align 8 } + +// rdar://12151005 +// +// This is an intentional exception to our conservative jump-scope +// checking for full-expressions containing block literals with +// non-trivial cleanups: if the block literal appears in the operand +// of a return statement, there's no need to extend its lifetime. +id (^test17(id self, int which))(void) { + switch (which) { + case 1: return ^{ return self; }; + case 0: return ^{ return self; }; + } + return (void*) 0; +} +// CHECK: define i8* ()* @test17( +// CHECK: [[RET:%.*]] = alloca i8* ()*, align +// CHECK-NEXT: [[SELF:%.*]] = alloca i8*, +// CHECK: [[B0:%.*]] = alloca [[BLOCK:<.*>]], align +// CHECK: [[B1:%.*]] = alloca [[BLOCK]], align +// CHECK: [[T0:%.*]] = call i8* @objc_retain(i8* +// CHECK-NEXT: store i8* [[T0]], i8** [[SELF]], align +// CHECK-NOT: objc_retain +// CHECK-NOT: objc_release +// CHECK: [[DESTROY:%.*]] = getelementptr inbounds [[BLOCK]]* [[B0]], i32 0, i32 5 +// CHECK-NOT: objc_retain +// CHECK-NOT: objc_release +// CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK]]* [[B0]], i32 0, i32 5 +// CHECK-NEXT: [[T1:%.*]] = load i8** [[SELF]], align +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK-NEXT: store i8* [[T2]], i8** [[T0]], +// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK]]* [[B0]] to i8* ()* +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* ()* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) +// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8* ()* +// CHECK-NEXT: store i8* ()* [[T3]], i8* ()** [[RET]] +// CHECK-NEXT: [[T0:%.*]] = load i8** [[DESTROY]] +// CHECK-NEXT: call void @objc_release(i8* [[T0]]) +// CHECK-NEXT: store i32 +// CHECK-NEXT: br label +// CHECK-NOT: objc_retain +// CHECK-NOT: objc_release +// CHECK: [[DESTROY:%.*]] = getelementptr inbounds [[BLOCK]]* [[B1]], i32 0, i32 5 +// CHECK-NOT: objc_retain +// CHECK-NOT: objc_release +// CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK]]* [[B1]], i32 0, i32 5 +// CHECK-NEXT: [[T1:%.*]] = load i8** [[SELF]], align +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK-NEXT: store i8* [[T2]], i8** [[T0]], +// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK]]* [[B1]] to i8* ()* +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* ()* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) +// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8* ()* +// CHECK-NEXT: store i8* ()* [[T3]], i8* ()** [[RET]] +// CHECK-NEXT: [[T0:%.*]] = load i8** [[DESTROY]] +// CHECK-NEXT: call void @objc_release(i8* [[T0]]) +// CHECK-NEXT: store i32 +// CHECK-NEXT: br label + +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: [[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]], +// CHECK-UNOPT-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) +// 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: ret void + extern void test18_helper(id (^)(void)); + test18_helper(^{ return x; }); + +// CHECK-UNOPT: define internal void @__copy_helper_block_ +// CHECK-UNOPT: [[T0:%.*]] = load i8** +// CHECK-UNOPT-NEXT: [[SRC:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]* +// CHECK-UNOPT-NEXT: [[T0:%.*]] = load i8** +// CHECK-UNOPT-NEXT: [[DST:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]* +// CHECK-UNOPT-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[SRC]], i32 0, i32 5 +// 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: ret void + +// CHECK-UNOPT: define internal void @__destroy_helper_block_ +// CHECK-UNOPT: [[T0:%.*]] = load i8** +// CHECK-UNOPT-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]* +// CHECK-UNOPT-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[T1]], i32 0, i32 5 +// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null) +// CHECK-UNOPT-NEXT: ret void +} diff --git a/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m b/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m new file mode 100644 index 0000000..6c72138 --- /dev/null +++ b/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m @@ -0,0 +1,425 @@ +// 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 +// rdar://12184410 + +void x(id y) {} +void y(int a) {} + +extern id opaque_id(); + +void f() { + __weak id wid; + __block int byref_int = 0; + char ch = 'a'; + char ch1 = 'b'; + char ch2 = 'c'; + short sh = 2; + const id bar = (id) opaque_id(); + id baz = 0; + __strong id strong_void_sta; + __block id byref_bab = (id)0; + __block id bl_var1; + int i; double dob; + +// The patterns here are a sequence of bytes, each saying first how +// many sizeof(void*) chunks to skip (high nibble) and then how many +// to scan (low nibble). A zero byte says that we've reached the end +// of the pattern. +// +// All of these patterns start with 01 3x because the block header on +// LP64 consists of an isa pointer (which we're supposed to scan for +// some reason) followed by three words (2 ints, a function pointer, +// 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" + void (^b)() = ^{ + byref_int = sh + ch+ch1+ch2 ; + x(bar); + x(baz); + x((id)strong_void_sta); + x(byref_bab); + }; + 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" + void (^c)() = ^{ + byref_int = sh + ch+ch1+ch2 ; + x(bar); + x(baz); + x((id)strong_void_sta); + x(wid); + bl_var1 = 0; + x(byref_bab); + }; +} + +@class NSString, NSNumber; +void g() { + NSString *foo; + NSNumber *bar; + unsigned int bletch; + __weak id weak_delegate; + 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" + void (^c)() = ^{ + int j = i + bletch; + x(foo); + x(bar); + x(weak_delegate); + x(y); + x(z); + }; + c(); +} + +// Test 5 (unions/structs and their nesting): +void h() { + struct S5 { + int i1; + __unsafe_unretained id o1; + struct V { + int i2; + __unsafe_unretained id o2; + } v1; + int i3; + union UI { + void * i1; + __unsafe_unretained id o1; + int i3; + __unsafe_unretained id o3; + }ui; + }; + + union U { + void * i1; + __unsafe_unretained id o1; + int i3; + __unsafe_unretained id o3; + }ui; + + struct S5 s2; + 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: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [7 x i8] c" ` `\22@\00" + void (^c)() = ^{ + x(s2.ui.o1); + x(u2.o1); + block_id = 0; + }; + c(); +} + +// Test for array of stuff. +void arr1() { + struct S { + __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" + void (^c)() = ^{ + x(imported_s.unsafe_unretained_var[2]); + }; + + c(); +} + +// Test2 for array of stuff. +void arr2() { + struct S { + int a; + __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" + void (^c)() = ^{ + x(imported_s.unsafe_unretained_var[2]); + }; + + c(); +} + +// Test3 for array of stuff. +void arr3() { + struct S { + int a; + __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 + void (^c)() = ^{ + int i = imported_s.a; + }; + + c(); +} + + +// Test4 for array of stuff. +@class B; +void arr4() { + struct S { + struct s0 { + __unsafe_unretained id s_f0; + __unsafe_unretained id s_f1; + } f0; + + __unsafe_unretained id f1; + + struct s1 { + int *f0; + __unsafe_unretained B *f1; + } 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] + void (^c)() = ^{ + id i = captured_s.f0.s_f1; + }; + + c(); +} + +// Test1 bitfield in cpatured aggregate. +void bf1() { + struct S { + int flag : 25; + int flag1: 7; + int flag2 :1; + int flag3: 7; + int flag4: 24; + } s; + +// block variable layout: BL_OPERATOR:0 +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + int (^c)() = ^{ + return s.flag; + }; + c(); +} + +// Test2 bitfield in cpatured aggregate. +void bf2() { + struct S { + int flag : 1; + } s; + +// block variable layout: BL_OPERATOR:0 +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + int (^c)() = ^{ + return s.flag; + }; + c(); +} + +// Test3 bitfield in cpatured aggregate. +void bf3() { + + struct { + unsigned short _reserved : 16; + + unsigned char _draggedNodesAreDeletable: 1; + unsigned char _draggedOutsideOutlineView : 1; + unsigned char _adapterRespondsTo_addRootPaths : 1; + unsigned char _adapterRespondsTo_moveDataNodes : 1; + unsigned char _adapterRespondsTo_removeRootDataNode : 1; + unsigned char _adapterRespondsTo_doubleClickDataNode : 1; + unsigned char _adapterRespondsTo_selectDataNode : 1; + unsigned char _adapterRespondsTo_textDidEndEditing : 1; + unsigned char _adapterRespondsTo_updateAndSaveRoots : 1; + unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1; + unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1; + unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1; + unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1; + unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1; + + unsigned int _filler : 32; + } _flags; + +// block variable layout: BL_OPERATOR:0 +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + unsigned char (^c)() = ^{ + return _flags._draggedNodesAreDeletable; + }; + + c(); +} + +// Test4 unnamed bitfield +void bf4() { + + struct { + unsigned short _reserved : 16; + + unsigned char _draggedNodesAreDeletable: 1; + unsigned char _draggedOutsideOutlineView : 1; + unsigned char _adapterRespondsTo_addRootPaths : 1; + unsigned char _adapterRespondsTo_moveDataNodes : 1; + unsigned char _adapterRespondsTo_removeRootDataNode : 1; + unsigned char _adapterRespondsTo_doubleClickDataNode : 1; + unsigned char _adapterRespondsTo_selectDataNode : 1; + unsigned char _adapterRespondsTo_textDidEndEditing : 1; + + unsigned long long : 64; + + unsigned char _adapterRespondsTo_updateAndSaveRoots : 1; + unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1; + unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1; + unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1; + unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1; + unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1; + + unsigned int _filler : 32; + } _flags; + +// block variable layout: BL_OPERATOR:0 +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + unsigned char (^c)() = ^{ + return _flags._draggedNodesAreDeletable; + }; + + c(); +} + + + +// Test5 unnamed bitfield. +void bf5() { + struct { + unsigned char flag : 1; + unsigned int : 32; + unsigned char flag1 : 1; + } _flags; + +// block variable layout: BL_OPERATOR:0 +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + unsigned char (^c)() = ^{ + return _flags.flag; + }; + + c(); +} + + +// Test6 0 length bitfield. +void bf6() { + struct { + unsigned char flag : 1; + unsigned int : 0; + unsigned char flag1 : 1; + } _flags; + +// block variable layout: BL_OPERATOR:0 +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + unsigned char (^c)() = ^{ + return _flags.flag; + }; + + c(); +} + +// Test7 large number of captured variables. +void Test7() { + __weak id wid; + __weak id wid1, wid2, wid3, wid4; + __weak id wid5, wid6, wid7, wid8; + __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" + void (^b)() = ^{ + x(bar); + x(wid1); + x(wid2); + x(wid3); + x(wid4); + x(wid5); + x(wid6); + x(wid7); + x(wid8); + x(wid9); + x(wid10); + x(wid11); + x(wid12); + x(wid13); + x(wid14); + x(wid15); + x(wid16); + }; +} + + +// Test 8 very large number of captured variables. +void Test8() { +__weak id wid; + __weak id wid1, wid2, wid3, wid4; + __weak id wid5, wid6, wid7, wid8; + __weak id wid9, wid10, wid11, wid12; + __weak id wid13, wid14, wid15, wid16; + __weak id w1, w2, w3, w4; + __weak id w5, w6, w7, w8; + __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] + void (^b)() = ^{ + x(bar); + x(wid1); + x(wid2); + x(wid3); + x(wid4); + x(wid5); + x(wid6); + x(wid7); + x(wid8); + x(wid9); + x(wid10); + x(wid11); + x(wid12); + x(wid13); + x(wid14); + x(wid15); + x(wid16); + x(w1); + x(w2); + x(w3); + x(w4); + x(w5); + x(w6); + x(w7); + x(w8); + x(w9); + x(w10); + x(w11); + x(w12); + x(w13); + x(w14); + x(w15); + x(w16); + x(wid); + }; +} diff --git a/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m b/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m new file mode 100644 index 0000000..b930737 --- /dev/null +++ b/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m @@ -0,0 +1,112 @@ +// 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 +// rdar://12184410 + +void x(id y) {} +void y(int a) {} + +extern id opaque_id(); + +void f() { + __block int byref_int = 0; + const id bar = (id) opaque_id(); + id baz = 0; + __strong id strong_void_sta; + __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 } + 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 } + 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 } + void (^d)() = ^{ + x(bar); + x(baz); + byref_int = 1; + bl_var1 = 0; + 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 } + __weak id wid; + id (^e)() = ^{ + x(bar); + x(baz); + byref_int = 1; + bl_var1 = 0; + byref_bab = 0; + 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 } + __weak id wid1, wid2, wid3, wid4; + id (^f)() = ^{ + x(bar); + x(baz); + byref_int = 1; + bl_var1 = 0; + byref_bab = 0; + x(wid1); + x(wid2); + x(wid3); + x(wid4); + 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 } + id (^g)() = ^{ + byref_int = 1; + bl_var1 = 0; + byref_bab = 0; + x(wid1); + x(wid2); + x(wid3); + x(wid4); + 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 } + 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 } + 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 } + void (^jj)() = ^{ + x(bar); + x(wid1); + x(wid2); + }; +} diff --git a/test/CodeGenObjC/arc-captured-block-var-layout.m b/test/CodeGenObjC/arc-captured-block-var-layout.m new file mode 100644 index 0000000..77f042e --- /dev/null +++ b/test/CodeGenObjC/arc-captured-block-var-layout.m @@ -0,0 +1,425 @@ +// 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 +// rdar://12184410 + +void x(id y) {} +void y(int a) {} + +extern id opaque_id(); + +void f() { + __weak id wid; + __block int byref_int = 0; + char ch = 'a'; + char ch1 = 'b'; + char ch2 = 'c'; + short sh = 2; + const id bar = (id) opaque_id(); + id baz = 0; + __strong id strong_void_sta; + __block id byref_bab = (id)0; + __block id bl_var1; + int i; double dob; + +// The patterns here are a sequence of bytes, each saying first how +// many sizeof(void*) chunks to skip (high nibble) and then how many +// to scan (low nibble). A zero byte says that we've reached the end +// of the pattern. +// +// All of these patterns start with 01 3x because the block header on +// LP64 consists of an isa pointer (which we're supposed to scan for +// some reason) followed by three words (2 ints, a function pointer, +// 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" + void (^b)() = ^{ + byref_int = sh + ch+ch1+ch2 ; + x(bar); + x(baz); + x((id)strong_void_sta); + x(byref_bab); + }; + 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" + void (^c)() = ^{ + byref_int = sh + ch+ch1+ch2 ; + x(bar); + x(baz); + x((id)strong_void_sta); + x(wid); + bl_var1 = 0; + x(byref_bab); + }; +} + +@class NSString, NSNumber; +void g() { + NSString *foo; + NSNumber *bar; + unsigned int bletch; + __weak id weak_delegate; + 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" + void (^c)() = ^{ + int j = i + bletch; + x(foo); + x(bar); + x(weak_delegate); + x(y); + x(z); + }; + c(); +} + +// Test 5 (unions/structs and their nesting): +void h() { + struct S5 { + int i1; + __unsafe_unretained id o1; + struct V { + int i2; + __unsafe_unretained id o2; + } v1; + int i3; + union UI { + void * i1; + __unsafe_unretained id o1; + int i3; + __unsafe_unretained id o3; + }ui; + }; + + union U { + void * i1; + __unsafe_unretained id o1; + int i3; + __unsafe_unretained id o3; + }ui; + + struct S5 s2; + 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" + void (^c)() = ^{ + x(s2.ui.o1); + x(u2.o1); + block_id = 0; + }; + c(); +} + +// Test for array of stuff. +void arr1() { + struct S { + __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" + void (^c)() = ^{ + x(imported_s.unsafe_unretained_var[2]); + }; + + c(); +} + +// Test2 for array of stuff. +void arr2() { + struct S { + int a; + __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" + void (^c)() = ^{ + x(imported_s.unsafe_unretained_var[2]); + }; + + c(); +} + +// Test3 for array of stuff. +void arr3() { + struct S { + int a; + __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 + void (^c)() = ^{ + int i = imported_s.a; + }; + + c(); +} + + +// Test4 for array of stuff. +@class B; +void arr4() { + struct S { + struct s0 { + __unsafe_unretained id s_f0; + __unsafe_unretained id s_f1; + } f0; + + __unsafe_unretained id f1; + + struct s1 { + int *f0; + __unsafe_unretained B *f1; + } 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] + void (^c)() = ^{ + id i = captured_s.f0.s_f1; + }; + + c(); +} + +// Test1 bitfield in cpatured aggregate. +void bf1() { + struct S { + int flag : 25; + int flag1: 7; + int flag2 :1; + int flag3: 7; + int flag4: 24; + } s; + +// block variable layout: BL_OPERATOR:0 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + int (^c)() = ^{ + return s.flag; + }; + c(); +} + +// Test2 bitfield in cpatured aggregate. +void bf2() { + struct S { + int flag : 1; + } s; + +// block variable layout: BL_OPERATOR:0 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + int (^c)() = ^{ + return s.flag; + }; + c(); +} + +// Test3 bitfield in cpatured aggregate. +void bf3() { + + struct { + unsigned short _reserved : 16; + + unsigned char _draggedNodesAreDeletable: 1; + unsigned char _draggedOutsideOutlineView : 1; + unsigned char _adapterRespondsTo_addRootPaths : 1; + unsigned char _adapterRespondsTo_moveDataNodes : 1; + unsigned char _adapterRespondsTo_removeRootDataNode : 1; + unsigned char _adapterRespondsTo_doubleClickDataNode : 1; + unsigned char _adapterRespondsTo_selectDataNode : 1; + unsigned char _adapterRespondsTo_textDidEndEditing : 1; + unsigned char _adapterRespondsTo_updateAndSaveRoots : 1; + unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1; + unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1; + unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1; + unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1; + unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1; + + unsigned int _filler : 32; + } _flags; + +// block variable layout: BL_OPERATOR:0 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + unsigned char (^c)() = ^{ + return _flags._draggedNodesAreDeletable; + }; + + c(); +} + +// Test4 unnamed bitfield +void bf4() { + + struct { + unsigned short _reserved : 16; + + unsigned char _draggedNodesAreDeletable: 1; + unsigned char _draggedOutsideOutlineView : 1; + unsigned char _adapterRespondsTo_addRootPaths : 1; + unsigned char _adapterRespondsTo_moveDataNodes : 1; + unsigned char _adapterRespondsTo_removeRootDataNode : 1; + unsigned char _adapterRespondsTo_doubleClickDataNode : 1; + unsigned char _adapterRespondsTo_selectDataNode : 1; + unsigned char _adapterRespondsTo_textDidEndEditing : 1; + + unsigned long long : 64; + + unsigned char _adapterRespondsTo_updateAndSaveRoots : 1; + unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1; + unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1; + unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1; + unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1; + unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1; + + unsigned int _filler : 32; + } _flags; + +// block variable layout: BL_OPERATOR:0 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + unsigned char (^c)() = ^{ + return _flags._draggedNodesAreDeletable; + }; + + c(); +} + + + +// Test5 unnamed bitfield. +void bf5() { + struct { + unsigned char flag : 1; + unsigned int : 32; + unsigned char flag1 : 1; + } _flags; + +// block variable layout: BL_OPERATOR:0 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + unsigned char (^c)() = ^{ + return _flags.flag; + }; + + c(); +} + + +// Test6 0 length bitfield. +void bf6() { + struct { + unsigned char flag : 1; + unsigned int : 0; + unsigned char flag1 : 1; + } _flags; + +// block variable layout: BL_OPERATOR:0 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + unsigned char (^c)() = ^{ + return _flags.flag; + }; + + c(); +} + +// Test7 large number of captured variables. +void Test7() { + __weak id wid; + __weak id wid1, wid2, wid3, wid4; + __weak id wid5, wid6, wid7, wid8; + __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" + void (^b)() = ^{ + x(bar); + x(wid1); + x(wid2); + x(wid3); + x(wid4); + x(wid5); + x(wid6); + x(wid7); + x(wid8); + x(wid9); + x(wid10); + x(wid11); + x(wid12); + x(wid13); + x(wid14); + x(wid15); + x(wid16); + }; +} + + +// Test 8 very large number of captured variables. +void Test8() { +__weak id wid; + __weak id wid1, wid2, wid3, wid4; + __weak id wid5, wid6, wid7, wid8; + __weak id wid9, wid10, wid11, wid12; + __weak id wid13, wid14, wid15, wid16; + __weak id w1, w2, w3, w4; + __weak id w5, w6, w7, w8; + __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] + void (^b)() = ^{ + x(bar); + x(wid1); + x(wid2); + x(wid3); + x(wid4); + x(wid5); + x(wid6); + x(wid7); + x(wid8); + x(wid9); + x(wid10); + x(wid11); + x(wid12); + x(wid13); + x(wid14); + x(wid15); + x(wid16); + x(w1); + x(w2); + x(w3); + x(w4); + x(w5); + x(w6); + x(w7); + x(w8); + x(w9); + x(w10); + x(w11); + x(w12); + x(w13); + x(w14); + x(w15); + x(w16); + x(wid); + }; +} diff --git a/test/CodeGenObjC/arc-exceptions.m b/test/CodeGenObjC/arc-exceptions.m index 5ef5aba..63945e3 100644 --- a/test/CodeGenObjC/arc-exceptions.m +++ b/test/CodeGenObjC/arc-exceptions.m @@ -20,9 +20,8 @@ void test0(void) { // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) nounwind // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]* // CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]] -// CHECK-NEXT: [[T0:%.*]] = load [[ETY]]** [[E]] -// CHECK-NEXT: [[T1:%.*]] = bitcast [[ETY]]* [[T0]] to i8* -// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind +// 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 void test1_helper(void); diff --git a/test/CodeGenObjC/arc-foreach.m b/test/CodeGenObjC/arc-foreach.m index 67fad4d..b8d2d30 100644 --- a/test/CodeGenObjC/arc-foreach.m +++ b/test/CodeGenObjC/arc-foreach.m @@ -67,8 +67,7 @@ void test0(NSArray *array) { // CHECK-LP64-NEXT: store i8* [[T2]], i8** [[T0]] // CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] // CHECK-LP64: call void @use_block( -// CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[D0]] -// CHECK-LP64-NEXT: call void @objc_release(i8* [[T1]]) +// CHECK-LP64-NEXT: call void @objc_storeStrong(i8** [[D0]], i8* null) // CHECK-LP64: [[T0:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ // CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[SAVED_ARRAY]] to i8* @@ -79,9 +78,8 @@ void test0(NSArray *array) { // CHECK-LP64-NEXT: call void @objc_release(i8* [[T0]]) // Destroy 'array'. -// CHECK-LP64: [[T0:%.*]] = load [[ARRAY_T]]** [[ARRAY]] -// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[T0]] to i8* -// CHECK-LP64-NEXT: call void @objc_release(i8* [[T1]]) +// CHECK-LP64: [[T0:%.*]] = bitcast [[ARRAY_T]]** [[ARRAY]] to i8** +// CHECK-LP64-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) // CHECK-LP64-NEXT: ret void // CHECK-LP64: define internal void @__test0_block_invoke diff --git a/test/CodeGenObjC/arc-ivar-layout.m b/test/CodeGenObjC/arc-ivar-layout.m index 7f58a0c..9068314 100644 --- a/test/CodeGenObjC/arc-ivar-layout.m +++ b/test/CodeGenObjC/arc-ivar-layout.m @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -S %s -o %t-64.s // RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s +// REQUIRES: x86-64-registered-target // rdar://8991729 @interface NSObject { diff --git a/test/CodeGenObjC/arc-no-runtime.m b/test/CodeGenObjC/arc-no-runtime.m index 3c85e87..f5f5b90 100644 --- a/test/CodeGenObjC/arc-no-runtime.m +++ b/test/CodeGenObjC/arc-no-runtime.m @@ -1,9 +1,13 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc -emit-llvm %s -o - | FileCheck %s // rdar://problem/9224855 +id make(void) __attribute__((ns_returns_retained)); void test0() { + make(); id x = 0; // CHECK: call void @objc_release( + // CHECK: call void @objc_storeStrong( } // CHECK: declare extern_weak void @objc_release( +// CHECK: declare extern_weak void @objc_storeStrong( diff --git a/test/CodeGenObjC/arc-property.m b/test/CodeGenObjC/arc-property.m index 6c5180b..db00e36 100644 --- a/test/CodeGenObjC/arc-property.m +++ b/test/CodeGenObjC/arc-property.m @@ -11,5 +11,77 @@ void test0(Test0 *t0, id value) { // CHECK: call i8* @objc_retain( // CHECK: call i8* @objc_retain( // CHECK: @objc_msgSend -// CHECK: call void @objc_release( -// CHECK: call void @objc_release( +// CHECK: call void @objc_storeStrong( +// CHECK: call void @objc_storeStrong( + +struct S1 { Class isa; }; +@interface Test1 +@property (nonatomic, strong) __attribute__((NSObject)) struct S1 *pointer; +@end +@implementation Test1 +@synthesize pointer; +@end +// The getter should be a simple load. +// CHECK: define internal [[S1:%.*]]* @"\01-[Test1 pointer]"( +// CHECK: [[OFFSET:%.*]] = load i64* @"OBJC_IVAR_$_Test1.pointer" +// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST1:%.*]]* {{%.*}} to i8* +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8* [[T0]], i64 [[OFFSET]] +// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[S1]]** +// CHECK-NEXT: [[T3:%.*]] = load [[S1]]** [[T2]], align 8 +// CHECK-NEXT: ret [[S1]]* [[T3]] + +// The setter should be using objc_setProperty. +// CHECK: define internal void @"\01-[Test1 setPointer:]"( +// CHECK: [[T0:%.*]] = bitcast [[TEST1]]* {{%.*}} to i8* +// CHECK-NEXT: [[OFFSET:%.*]] = load i64* @"OBJC_IVAR_$_Test1.pointer" +// CHECK-NEXT: [[T1:%.*]] = load [[S1]]** {{%.*}} +// CHECK-NEXT: [[T2:%.*]] = bitcast [[S1]]* [[T1]] to i8* +// CHECK-NEXT: call void @objc_setProperty(i8* [[T0]], i8* {{%.*}}, i64 [[OFFSET]], i8* [[T2]], i1 zeroext false, i1 zeroext false) +// CHECK-NEXT: ret void + + +// rdar://problem/12039404 +@interface Test2 { +@private + Class _theClass; +} +@property (copy) Class theClass; +@end + +static Class theGlobalClass; +@implementation Test2 +@synthesize theClass = _theClass; +- (void) test { + _theClass = theGlobalClass; +} +@end +// CHECK: define internal void @"\01-[Test2 test]"( +// CHECK: [[T0:%.*]] = load i8** @theGlobalClass, align 8 +// CHECK-NEXT: [[T1:%.*]] = load [[TEST2:%.*]]** +// CHECK-NEXT: [[OFFSET:%.*]] = load i64* @"OBJC_IVAR_$_Test2._theClass" +// 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: ret void + +// CHECK: define internal i8* @"\01-[Test2 theClass]"( +// CHECK: [[OFFSET:%.*]] = load i64* @"OBJC_IVAR_$_Test2._theClass" +// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_getProperty(i8* {{.*}}, i8* {{.*}}, i64 [[OFFSET]], i1 zeroext true) +// CHECK-NEXT: ret i8* [[T0]] + +// CHECK: define internal void @"\01-[Test2 setTheClass:]"( +// CHECK: [[T0:%.*]] = bitcast [[TEST2]]* {{%.*}} to i8* +// CHECK-NEXT: [[OFFSET:%.*]] = load i64* @"OBJC_IVAR_$_Test2._theClass" +// CHECK-NEXT: [[T1:%.*]] = load i8** {{%.*}} +// CHECK-NEXT: call void @objc_setProperty(i8* [[T0]], i8* {{%.*}}, i64 [[OFFSET]], i8* [[T1]], i1 zeroext true, i1 zeroext true) +// CHECK-NEXT: ret void + +// CHECK: define internal void @"\01-[Test2 .cxx_destruct]"( +// CHECK: [[T0:%.*]] = load [[TEST2]]** +// CHECK-NEXT: [[OFFSET:%.*]] = load i64* @"OBJC_IVAR_$_Test2._theClass" +// 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: ret void diff --git a/test/CodeGenObjC/arc-related-result-type.m b/test/CodeGenObjC/arc-related-result-type.m index f73aa50..ee0a41d 100644 --- a/test/CodeGenObjC/arc-related-result-type.m +++ b/test/CodeGenObjC/arc-related-result-type.m @@ -20,11 +20,9 @@ void test0(Test0 *val) { // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST0]]* // CHECK-NEXT: store [[TEST0]]* [[T2]], [[TEST0]]** [[X]] -// CHECK-NEXT: [[T0:%.*]] = load [[TEST0]]** [[X]] -// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST0]]* [[T0]] to i8* -// CHECK-NEXT: call void @objc_release(i8* [[T1]]) -// CHECK-NEXT: [[T0:%.*]] = load [[TEST0]]** [[VAL]] -// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST0]]* [[T0]] to i8* -// CHECK-NEXT: call void @objc_release(i8* [[T1]]) +// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST0]]** [[X]] to i8** +// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) +// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST0]]** [[VAL]] to i8** +// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) // CHECK-NEXT: ret void } diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m index 66a6a2f..8e38019 100644 --- a/test/CodeGenObjC/arc.m +++ b/test/CodeGenObjC/arc.m @@ -602,7 +602,10 @@ void test22(_Bool cond) { // rdar://problem/8922540 // Note that we no longer emit .release_ivars flags. -// CHECK-GLOBALS: @"\01l_OBJC_CLASS_RO_$_Test23" = internal global [[RO_T:%.*]] { i32 134, +// rdar://problem/12492434 +// Note that we set the flag saying that we need destruction *and* +// the flag saying that we don't also need construction. +// CHECK-GLOBALS: @"\01l_OBJC_CLASS_RO_$_Test23" = internal global [[RO_T:%.*]] { i32 390, @interface Test23 { id x; } @end @implementation Test23 @end @@ -1358,9 +1361,9 @@ void test59(void) { // CHECK: define void @test59() // CHECK: [[T0:%.*]] = call i8* @test59_getlock() // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) - // CHECK-NEXT: call void @objc_sync_enter(i8* [[T1]]) + // CHECK-NEXT: call i32 @objc_sync_enter(i8* [[T1]]) // CHECK-NEXT: call void @test59_body() - // CHECK-NEXT: call void @objc_sync_exit(i8* [[T1]]) + // CHECK-NEXT: call i32 @objc_sync_exit(i8* [[T1]]) // CHECK-NEXT: call void @objc_release(i8* [[T1]]) // CHECK-NEXT: ret void } diff --git a/test/CodeGenObjC/atomic-aggregate-property.m b/test/CodeGenObjC/atomic-aggregate-property.m index 978299b..878255b 100644 --- a/test/CodeGenObjC/atomic-aggregate-property.m +++ b/test/CodeGenObjC/atomic-aggregate-property.m @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o - %s | FileCheck -check-prefix LP64 %s // RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o - %s | FileCheck -check-prefix LP64 %s // rdar: // 7849824 +// <rdar://problem/12547611> struct s { double a, b, c, d; @@ -12,16 +13,20 @@ struct s1 { id k; }; +struct s2 {}; + @interface A @property (readwrite) double x; @property (readwrite) struct s y; @property (nonatomic, readwrite) struct s1 z; +@property (readwrite) struct s2 a; @end @implementation A @synthesize x; @synthesize y; @synthesize z; +@synthesize a; @end // CHECK-LP64: define internal double @"\01-[A x]"( // CHECK-LP64: load atomic i64* {{%.*}} unordered, align 8 @@ -40,3 +45,9 @@ struct s1 { // CHECK-LP64: define internal void @"\01-[A setZ:]"( // CHECK-LP64: call i8* @objc_memmove_collectable( + +// CHECK-LP64: define internal void @"\01-[A a]"( +// (do nothing) + +// CHECK-LP64: define internal void @"\01-[A setA:]"( +// (do nothing) diff --git a/test/CodeGenObjC/attr-minsize.m b/test/CodeGenObjC/attr-minsize.m new file mode 100644 index 0000000..f46107e --- /dev/null +++ b/test/CodeGenObjC/attr-minsize.m @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +@interface Test +- (void)test; +@end + +@implementation Test +- (void)test __attribute__((minsize)) { + // CHECK: define{{.*}}Test test + // CHECK: minsize +} +@end diff --git a/test/CodeGenObjC/block-var-layout.m b/test/CodeGenObjC/block-var-layout.m index c8065be..71b14da 100644 --- a/test/CodeGenObjC/block-var-layout.m +++ b/test/CodeGenObjC/block-var-layout.m @@ -90,7 +90,7 @@ void f() { // Test 4 // struct S (int, id, int, id, int, id) -// 01 41 11 11 +// 01 41 11 11 00 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\11\00" struct S s2; void (^e)() = ^{ @@ -128,8 +128,8 @@ void Test5() { union U u2; // struct s2 (int, id, int, id, int, id?), union u2 (id?) -// 01 41 11 12 70 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [6 x i8] c"\01A\11\12p\00" +// 01 41 11 12 00 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\12\00" void (^c)() = ^{ x(s2.ui.o1); x(u2.o1); diff --git a/test/CodeGenObjC/builtin-memfns.m b/test/CodeGenObjC/builtin-memfns.m new file mode 100644 index 0000000..bb425c0 --- /dev/null +++ b/test/CodeGenObjC/builtin-memfns.m @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.8.0 -emit-llvm -o - %s | FileCheck %s + +void *memcpy(void *restrict s1, const void *restrict s2, unsigned long n); + +// PR13697 +void test1(int *a, id b) { + // CHECK: @test1 + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i32 1, i1 false) + memcpy(a, b, 8); +} diff --git a/test/CodeGenObjC/category-super-class-meth.m b/test/CodeGenObjC/category-super-class-meth.m index 6f02aff..5ba7adf 100644 --- a/test/CodeGenObjC/category-super-class-meth.m +++ b/test/CodeGenObjC/category-super-class-meth.m @@ -1,19 +1,29 @@ -// RUN: %clang_cc1 -emit-llvm -o %t %s - -@interface BASE -+ (int) BaseMeth; +// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-apple-darwin -o - | FileCheck %s +// rdar://12459358 +@interface NSObject +-(id)copy; ++(id)copy; @end -@interface Child: BASE -@end +@interface Sub1 : NSObject @end -@interface Child (Categ) -+ (int) flushCache2; +@implementation Sub1 +-(id)copy { return [super copy]; } // ok: instance method in class ++(id)copy { return [super copy]; } // ok: class method in class @end -@implementation Child @end +@interface Sub2 : NSObject @end + +@interface Sub2 (Category) @end -@implementation Child (Categ) -+ (int) flushCache2 { [super BaseMeth]; } +@implementation Sub2 (Category) +-(id)copy { return [super copy]; } // ok: instance method in category ++(id)copy { return [super copy]; } // BAD: class method in category @end +// CHECK: define internal i8* @"\01+[Sub2(Category) copy] +// CHECK: [[ONE:%.*]] = load %struct._class_t** @"\01L_OBJC_CLASSLIST_SUP_REFS_$_3" +// CHECK: [[TWO:%.*]] = bitcast %struct._class_t* [[ONE]] to i8* +// CHECK: [[THREE:%.*]] = getelementptr inbounds %struct._objc_super* [[OBJC_SUPER:%.*]], i32 0, i32 1 +// CHECK: store i8* [[TWO]], i8** [[THREE]] +// CHECK: [[FOUR:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_" diff --git a/test/CodeGenObjC/debug-info-crash-2.m b/test/CodeGenObjC/debug-info-crash-2.m index a2acd9d..7d05f53 100644 --- a/test/CodeGenObjC/debug-info-crash-2.m +++ b/test/CodeGenObjC/debug-info-crash-2.m @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin11 -g -S %s -o - +// REQUIRES: x86-64-registered-target + @class Bar; @interface Foo @property (strong, nonatomic) Bar *window; diff --git a/test/CodeGenObjC/debug-info-fwddecl.m b/test/CodeGenObjC/debug-info-fwddecl.m index ebdc5f2..8f2860c 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, i32 0, i32 0, i32 0, i32 4, null, null, i32 16} ; [ DW_TAG_structure_type ] +// 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 ] diff --git a/test/CodeGenObjC/debug-info-impl.m b/test/CodeGenObjC/debug-info-impl.m index 8ad5903..a8450dd 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} ; [ DW_TAG_structure_type ] +// 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 ] @interface NSObject { struct objc_object *isa; } diff --git a/test/CodeGenObjC/debug-info-ivars.m b/test/CodeGenObjC/debug-info-ivars.m new file mode 100644 index 0000000..24705e1a --- /dev/null +++ b/test/CodeGenObjC/debug-info-ivars.m @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -g %s -o - | FileCheck %s + +__attribute((objc_root_class)) @interface NSObject { + id isa; +} +@end + +@interface BaseClass : NSObject +{ + int i; + unsigned flag_1 : 9; + unsigned flag_2 : 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 diff --git a/test/CodeGenObjC/debug-info-pubtypes.m b/test/CodeGenObjC/debug-info-pubtypes.m index 658430d..91d9cd1 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 +// 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} ; [ DW_TAG_structure_type ] +// 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 ] @interface H -(void) foo; diff --git a/test/CodeGenObjC/debug-info-self.m b/test/CodeGenObjC/debug-info-self.m index 9146ab3..9f23435 100644 --- a/test/CodeGenObjC/debug-info-self.m +++ b/test/CodeGenObjC/debug-info-self.m @@ -1,8 +1,12 @@ -// RUN: %clang -fverbose-asm -g -S %s -o - | grep DW_AT_artificial | count 3 +// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s // self and _cmd are marked as DW_AT_artificial. -// abbrev code emits another DT_artificial comment. // 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; diff --git a/test/CodeGenObjC/exceptions.m b/test/CodeGenObjC/exceptions.m index 25780fd..551e67c 100644 --- a/test/CodeGenObjC/exceptions.m +++ b/test/CodeGenObjC/exceptions.m @@ -149,8 +149,8 @@ void f4() { // finally.call-exit: Predecessors are the @try and @catch fallthroughs // as well as the no-match case in the catch mechanism. The i1 is whether // to rethrow and should be true only in the last case. - // CHECK: phi i1 - // CHECK-NEXT: phi i8* + // CHECK: phi i8* + // CHECK-NEXT: phi i1 // CHECK-NEXT: call void @objc_exception_try_exit([[EXNDATA_T]]* [[EXNDATA]]) // CHECK-NEXT: call void @f4_help(i32 2) // CHECK-NEXT: br i1 diff --git a/test/CodeGenObjC/gnu-exceptions.m b/test/CodeGenObjC/gnu-exceptions.m index 141747e..b7d0adb 100644 --- a/test/CodeGenObjC/gnu-exceptions.m +++ b/test/CodeGenObjC/gnu-exceptions.m @@ -20,7 +20,7 @@ void test0() { // CHECK: call void @log(i32 0) - // CHECK: call void @objc_exception_throw + // CHECK: resume log(0); } diff --git a/test/CodeGenObjC/ivar-layout-64.m b/test/CodeGenObjC/ivar-layout-64.m index ea4cdce..91a8375 100644 --- a/test/CodeGenObjC/ivar-layout-64.m +++ b/test/CodeGenObjC/ivar-layout-64.m @@ -1,15 +1,5 @@ -// RUNX: llvm-gcc -m64 -fobjc-gc -emit-llvm -S -o %t %s && -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s -// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"A\\00"' %t -// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"\\11q\\10\\00"' %t -// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"!q\\00"' %t -// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"\\01\\14\\00"' %t -// RUNX: llvm-gcc -ObjC++ -m64 -fobjc-gc -emit-llvm -S -o %t %s && -// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s -// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"A\\00"' %t -// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"\\11q\\10\\00"' %t -// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"!q\\00"' %t -// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"\\01\\14\\00"' %t +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o - %s | FileCheck %s /* @@ -43,6 +33,11 @@ __weak B *f2; @property int p3; @end +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global {{.*}} c"C\00" +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global {{.*}} c"\11p\00" +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global {{.*}} c"!`\00" + + @implementation C @synthesize p3 = _p3; @end @@ -53,8 +48,10 @@ __weak B *f2; @property (assign) __weak id p2; @end -// FIXME: Check layout for this class, once it is clear what the right -// answer is. +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global {{.*}} c"A\00" +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global {{.*}} c"\11q\10\00" +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global {{.*}} c"!q\00" + @implementation A @synthesize p0 = _p0; @synthesize p1 = _p1; @@ -65,8 +62,10 @@ __weak B *f2; @property int p3; @end -// FIXME: Check layout for this class, once it is clear what the right -// answer is. +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global {{.*}} c"D\00" +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global {{.*}} c"\11p\00" +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global {{.*}} c"!`\00" + @implementation D @synthesize p3 = _p3; @end @@ -90,5 +89,26 @@ typedef unsigned int FSCatalogInfoBitmap; } @end +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global {{.*}} c"NSFileLocationComponent\00" +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global {{.*}} c"\01\14\00" + @implementation NSFileLocationComponent @end +@interface NSObject { + id isa; +} +@end + +@interface Foo : NSObject { + id ivar; + + unsigned long bitfield :31; + unsigned long bitfield2 :1; + unsigned long bitfield3 :32; +} +@end + +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global {{.*}} c"Foo\00" +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global {{.*}} c"\02\10\00" + +@implementation Foo @end diff --git a/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m b/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m new file mode 100644 index 0000000..f1e02dd --- /dev/null +++ b/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m @@ -0,0 +1,65 @@ +// 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 +// rdar://12184410 + +void x(id y) {} +void y(int a) {} + +extern id opaque_id(); +__weak id wid; + +void f() { + __block int byref_int = 0; + const id bar = (id) opaque_id(); + id baz = 0; + __strong id strong_void_sta; + __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" + 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" + 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 + void (^d)() = ^{ + x(bar); + x(baz); + byref_int = 1; + bl_var1 = 0; + 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" + id (^e)() = ^{ + x(bar); + x(baz); + byref_int = 1; + bl_var1 = 0; + byref_bab = 0; + 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 } + void (^ii)() = ^{ + byref_int = 1; + byref_bab = 0; + }; +} diff --git a/test/CodeGenObjC/newproperty-nested-synthesis-1.m b/test/CodeGenObjC/newproperty-nested-synthesis-1.m index 4831c22..aa0c8c9 100644 --- a/test/CodeGenObjC/newproperty-nested-synthesis-1.m +++ b/test/CodeGenObjC/newproperty-nested-synthesis-1.m @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -emit-llvm -o %t %s +// REQUIRES: LP64 @interface Object - (id) new; diff --git a/test/CodeGenObjC/objc-arc-container-subscripting.m b/test/CodeGenObjC/objc-arc-container-subscripting.m index 8924916..71339c7 100644 --- a/test/CodeGenObjC/objc-arc-container-subscripting.m +++ b/test/CodeGenObjC/objc-arc-container-subscripting.m @@ -13,9 +13,8 @@ id func() { // CHECK: [[call:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend // CHECK: [[SIX:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[call]]) nounwind -// CHECK: [[ARRAY:%.*]] = load %0** -// CHECK: [[ARRAY_CASTED:%.*]] = bitcast{{.*}}[[ARRAY]] to i8* -// CHECK: call void @objc_release(i8* [[ARRAY_CASTED]]) +// 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: ret i8* [[EIGHT]] diff --git a/test/CodeGenObjC/objc2-ivar-assign.m b/test/CodeGenObjC/objc2-ivar-assign.m index af76800..05a7b35 100644 --- a/test/CodeGenObjC/objc2-ivar-assign.m +++ b/test/CodeGenObjC/objc2-ivar-assign.m @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -fobjc-gc -emit-llvm -o %t %s // RUN: grep objc_assign_ivar %t | count 6 +// PR13820 +// REQUIRES: LP64 + @interface I @end typedef I TI; diff --git a/test/CodeGenObjC/optimized-setter-ios-device.m b/test/CodeGenObjC/optimized-setter-ios-device.m new file mode 100644 index 0000000..6fa322a --- /dev/null +++ b/test/CodeGenObjC/optimized-setter-ios-device.m @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 %s -emit-llvm -fobjc-runtime=ios-6.0.0 -triple thumbv7-apple-ios6.0.0 -o - | FileCheck %s +// rdar://11915017 + +@interface I +// void objc_setProperty_nonatomic(id self, SEL _cmd, id newValue, ptrdiff_t offset); +// objc_setProperty(..., NO, NO) +@property (nonatomic, retain) id nonatomicProperty; + +// void objc_setProperty_nonatomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset); +// objc_setProperty(..., NO, YES) +@property (nonatomic, copy) id nonatomicPropertyCopy; + +// void objc_setProperty_atomic(id self, SEL _cmd, id newValue, ptrdiff_t offset); +// objc_setProperty(..., YES, NO) +@property (retain) id atomicProperty; + +// void objc_setProperty_atomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset); +// objc_setProperty(..., YES, YES) +@property (copy) id atomicPropertyCopy; +@end + +@implementation I +@synthesize nonatomicProperty; +@synthesize nonatomicPropertyCopy; +@synthesize atomicProperty; +@synthesize atomicPropertyCopy; +@end + +// CHECK: call arm_aapcscc void @objc_setProperty_nonatomic +// CHECK: call arm_aapcscc void @objc_setProperty_nonatomic_copy +// CHECK: call arm_aapcscc void @objc_setProperty_atomic +// CHECK: call arm_aapcscc void @objc_setProperty_atomic_copy + diff --git a/test/CodeGenObjC/optimized-setter.m b/test/CodeGenObjC/optimized-setter.m index 0e1b388..6f5cfb1 100644 --- a/test/CodeGenObjC/optimized-setter.m +++ b/test/CodeGenObjC/optimized-setter.m @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-apple-macosx10.8.0 -o - | FileCheck %s +// 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 // rdar://10179974 @interface I diff --git a/test/CodeGenObjC/prop-metadata-gnu.m b/test/CodeGenObjC/prop-metadata-gnu.m new file mode 100644 index 0000000..c15d978 --- /dev/null +++ b/test/CodeGenObjC/prop-metadata-gnu.m @@ -0,0 +1,15 @@ +// RUN: %clang -S -emit-llvm %s -o - -x objective-c -fobjc-runtime=gcc | FileCheck --check-prefix=GCC %s +// RUN: %clang -S -emit-llvm %s -o - -x objective-c -fobjc-runtime=gnustep-1.5 | FileCheck --check-prefix=GCC %s +// RUN: %clang -S -emit-llvm %s -o - -x objective-c -fobjc-runtime=gnustep-1.6 | FileCheck --check-prefix=GNUSTEP %s +// +@interface helloclass { +@private int varName; +} +@property (readwrite,assign) int propName; +@end + +@implementation helloclass +@synthesize propName = varName; +@end +// GCC-NOT: Ti,VvarName +// GNUSTEP: Ti,VvarName diff --git a/test/CodeGenObjC/property.m b/test/CodeGenObjC/property.m index 16881d6..aab7c73 100644 --- a/test/CodeGenObjC/property.m +++ b/test/CodeGenObjC/property.m @@ -1,4 +1,7 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// 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 diff --git a/test/CodeGenObjC/synchronized.m b/test/CodeGenObjC/synchronized.m index 1f01282..e927882 100644 --- a/test/CodeGenObjC/synchronized.m +++ b/test/CodeGenObjC/synchronized.m @@ -11,7 +11,7 @@ // CHECK: define internal void @"\01-[MyClass method]" - (void)method { - // CHECK: call void @objc_sync_enter + // CHECK: call i32 @objc_sync_enter // CHECK: call void @objc_exception_try_enter // CHECK: call i32 @_setjmp @synchronized(self) { @@ -26,21 +26,21 @@ void foo(id a) { // CHECK: [[SYNC:%.*]] = alloca i8* // CHECK: store i8* [[AVAL:%.*]], i8** [[A]] - // CHECK-NEXT: call void @objc_sync_enter(i8* [[AVAL]]) + // CHECK-NEXT: call i32 @objc_sync_enter(i8* [[AVAL]]) // CHECK-NEXT: store i8* [[AVAL]], i8** [[SYNC]] // CHECK-NEXT: call void @objc_exception_try_enter // CHECK: call i32 @_setjmp @synchronized(a) { // This is unreachable, but the optimizers can't know that. // CHECK: call void asm sideeffect "", "=*m,=*m,=*m"(i8** [[A]], i8** [[SYNC]] - // CHECK: call void @objc_sync_exit + // CHECK: call i32 @objc_sync_exit // CHECK: call i8* @objc_exception_extract // CHECK: call void @objc_exception_throw // CHECK: unreachable // CHECK: call void @objc_exception_try_exit // CHECK: [[T:%.*]] = load i8** [[SYNC]] - // CHECK-NEXT: call void @objc_sync_exit + // CHECK-NEXT: call i32 @objc_sync_exit // CHECK: ret void return; } diff --git a/test/CodeGenObjC/synthesize_ivar-cont-class.m b/test/CodeGenObjC/synthesize_ivar-cont-class.m index 6bc7ac8..9822702 100644 --- a/test/CodeGenObjC/synthesize_ivar-cont-class.m +++ b/test/CodeGenObjC/synthesize_ivar-cont-class.m @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -emit-llvm -o %t %s // RUN: grep '@"OBJC_IVAR_$_XCOrganizerDeviceNodeInfo.viewController"' %t +// PR13820 +// REQUIRES: LP64 + @interface XCOrganizerNodeInfo @property (readonly, retain) id viewController; @end diff --git a/test/CodeGenObjC/synthesize_ivar.m b/test/CodeGenObjC/synthesize_ivar.m index e4fbe10..92f6096 100644 --- a/test/CodeGenObjC/synthesize_ivar.m +++ b/test/CodeGenObjC/synthesize_ivar.m @@ -1,5 +1,8 @@ // RUN: %clang_cc1 -emit-llvm -o %t %s +// PR13820 +// REQUIRES: LP64 + @interface I @property int IP; @end diff --git a/test/CodeGenObjC/undefined-protocol.m b/test/CodeGenObjC/undefined-protocol.m index e5a72ab..78cf8da 100644 --- a/test/CodeGenObjC/undefined-protocol.m +++ b/test/CodeGenObjC/undefined-protocol.m @@ -1,5 +1,8 @@ // RUN: %clang_cc1 -emit-llvm-only -fobjc-runtime=gcc %s +// PR13820 +// REQUIRES: LP64 + @protocol MadeUpProtocol; @interface Object <MadeUpProtocol> @end diff --git a/test/CodeGenObjC/unoptimized-setter.m b/test/CodeGenObjC/unoptimized-setter.m new file mode 100644 index 0000000..adcf087 --- /dev/null +++ b/test/CodeGenObjC/unoptimized-setter.m @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 %s -emit-llvm -fobjc-runtime=macosx-10.6.0 -triple x86_64-apple-macosx10.6.0 -o - | FileCheck %s +// rdar://11858187 + +@interface I +// void objc_setProperty_nonatomic(id self, SEL _cmd, id newValue, ptrdiff_t offset); +// objc_setProperty(..., NO, NO) +@property (nonatomic, retain) id nonatomicProperty; + +// void objc_setProperty_nonatomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset); +// objc_setProperty(..., NO, YES) +@property (nonatomic, copy) id nonatomicPropertyCopy; + +// void objc_setProperty_atomic(id self, SEL _cmd, id newValue, ptrdiff_t offset); +// objc_setProperty(..., YES, NO) +@property (retain) id atomicProperty; + +// void objc_setProperty_atomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset); +// objc_setProperty(..., YES, YES) +@property (copy) id atomicPropertyCopy; +@end + +@implementation I +@synthesize nonatomicProperty; +@synthesize nonatomicPropertyCopy; +@synthesize atomicProperty; +@synthesize atomicPropertyCopy; +@end + +// CHECK-NOT: call void @objc_setProperty_nonatomic +// CHECK-NOT: call void @objc_setProperty_nonatomic_copy +// CHECK-NOT: call void @objc_setProperty_atomic +// CHECK-NOT: call void @objc_setProperty_atomic_copy |