blob: 71b14dab24bdb57890bba7a0a542456e494bf1cf [file] [log] [blame]
John McCall260611a2012-06-20 06:18:46 +00001// 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
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00002// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003
Fariborz Jahaniane1a48982010-08-05 21:00:25 +00004struct S {
5 int i1;
6 id o1;
7 struct V {
8 int i2;
9 id o2;
10 } v1;
11 int i3;
12 id o3;
13};
14
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +000015__weak id wid;
16void x(id y) {}
17void y(int a) {}
18
John McCall6b5a61b2011-02-07 10:33:21 +000019extern id opaque_id();
20
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +000021void f() {
22 __block int byref_int = 0;
23 char ch = 'a';
24 char ch1 = 'b';
25 char ch2 = 'c';
26 short sh = 2;
John McCall6b5a61b2011-02-07 10:33:21 +000027 const id bar = (id) opaque_id();
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +000028 id baz = 0;
29 __strong void *strong_void_sta;
30 __block id byref_bab = (id)0;
31 __block void *bl_var1;
32 int i; double dob;
33
John McCall6b5a61b2011-02-07 10:33:21 +000034// The patterns here are a sequence of bytes, each saying first how
35// many sizeof(void*) chunks to skip (high nibble) and then how many
36// to scan (low nibble). A zero byte says that we've reached the end
37// of the pattern.
38//
39// All of these patterns start with 01 3x because the block header on
40// LP64 consists of an isa pointer (which we're supposed to scan for
41// some reason) followed by three words (2 ints, a function pointer,
42// and a descriptor pointer).
43
44// FIXME: do these really have to be named L_OBJC_CLASS_NAME_xxx?
45// FIXME: sequences should never end in x0 00 instead of just 00
46
47// Test 1
48// byref int, short, char, char, char, id, id, strong void*, byref id
49// 01 35 10 00
50// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\015\10\00"
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +000051 void (^b)() = ^{
52 byref_int = sh + ch+ch1+ch2 ;
53 x(bar);
54 x(baz);
55 x((id)strong_void_sta);
56 x(byref_bab);
57 };
58 b();
59
60// Test 2
John McCall6b5a61b2011-02-07 10:33:21 +000061// byref int, short, char, char, char, id, id, strong void*, byref void*, byref id
62// 01 36 10 00
63// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\016\10\00"
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +000064 void (^c)() = ^{
65 byref_int = sh + ch+ch1+ch2 ;
66 x(bar);
67 x(baz);
68 x((id)strong_void_sta);
69 x(wid);
70 bl_var1 = 0;
71 x(byref_bab);
72 };
73 c();
74
75// Test 3
John McCall6b5a61b2011-02-07 10:33:21 +000076// byref int, short, char, char, char, id, id, byref void*, int, double, byref id
77// 01 34 11 30 00
78// FIXME: we'd get a better format here if we sorted by scannability, not just alignment
79// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\014\11 \00"
80 void (^d)() = ^{
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +000081 byref_int = sh + ch+ch1+ch2 ;
82 x(bar);
83 x(baz);
84 x(wid);
85 bl_var1 = 0;
86 y(i + dob);
87 x(byref_bab);
88 };
89 d();
Fariborz Jahaniane1a48982010-08-05 21:00:25 +000090
John McCall6b5a61b2011-02-07 10:33:21 +000091// Test 4
92// struct S (int, id, int, id, int, id)
Eli Friedmana2f9d212012-11-06 03:38:02 +000093// 01 41 11 11 00
John McCall6b5a61b2011-02-07 10:33:21 +000094// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\11\00"
Fariborz Jahaniane1a48982010-08-05 21:00:25 +000095 struct S s2;
96 void (^e)() = ^{
97 x(s2.o1);
98 };
99 e();
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +0000100}
101
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +0000102// Test 5 (unions/structs and their nesting):
103void Test5() {
John McCall6b5a61b2011-02-07 10:33:21 +0000104 struct S5 {
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +0000105 int i1;
106 id o1;
107 struct V {
108 int i2;
109 id o2;
110 } v1;
111 int i3;
112 union UI {
113 void * i1;
114 id o1;
115 int i3;
116 id o3;
117 }ui;
John McCall6b5a61b2011-02-07 10:33:21 +0000118 };
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +0000119
John McCall6b5a61b2011-02-07 10:33:21 +0000120 union U {
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +0000121 void * i1;
122 id o1;
123 int i3;
124 id o3;
John McCall6b5a61b2011-02-07 10:33:21 +0000125 }ui;
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +0000126
John McCall6b5a61b2011-02-07 10:33:21 +0000127 struct S5 s2;
128 union U u2;
129
130// struct s2 (int, id, int, id, int, id?), union u2 (id?)
Eli Friedmana2f9d212012-11-06 03:38:02 +0000131// 01 41 11 12 00
132// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\12\00"
John McCall6b5a61b2011-02-07 10:33:21 +0000133 void (^c)() = ^{
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +0000134 x(s2.ui.o1);
135 x(u2.o1);
John McCall6b5a61b2011-02-07 10:33:21 +0000136 };
137 c();
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +0000138}
139
Fariborz Jahanianc5904b42010-09-11 01:27:29 +0000140// rdar: //8417746
141void CFRelease(id);
142void notifyBlock(id dependentBlock) {
143 id singleObservationToken;
144 id token;
145 void (^b)();
John McCall6b5a61b2011-02-07 10:33:21 +0000146
147// id, id, void(^)()
148// 01 33 00
149// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"\013\00"
Fariborz Jahanianc5904b42010-09-11 01:27:29 +0000150 void (^wrapperBlock)() = ^() {
151 CFRelease(singleObservationToken);
152 CFRelease(singleObservationToken);
153 CFRelease(token);
154 CFRelease(singleObservationToken);
155 b();
156 };
157 wrapperBlock();
158}
159
Fariborz Jahanianfb550312010-09-13 16:09:44 +0000160void test_empty_block() {
John McCall6b5a61b2011-02-07 10:33:21 +0000161// 01 00
162// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"\01\00"
163 void (^wrapperBlock)() = ^() {
164 };
Fariborz Jahanianfb550312010-09-13 16:09:44 +0000165 wrapperBlock();
166}