1// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout
2// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.layout %s
3// rdar://12184410
4// rdar://12752901
5
6void x(id y) {}
7void y(int a) {}
8
9extern id opaque_id();
10
11void f() {
12    __weak id wid;
13    __block int byref_int = 0;
14    char ch = 'a';
15    char ch1 = 'b';
16    char ch2 = 'c';
17    short sh = 2;
18    const id bar = (id) opaque_id();
19    id baz = 0;
20    __strong id strong_void_sta;
21    __block id byref_bab = (id)0;
22    __block id bl_var1;
23    int i; double dob;
24
25// The patterns here are a sequence of bytes, each saying first how
26// many sizeof(void*) chunks to skip (high nibble) and then how many
27// to scan (low nibble).  A zero byte says that we've reached the end
28// of the pattern.
29//
30// All of these patterns start with 01 3x because the block header on
31// LP64 consists of an isa pointer (which we're supposed to scan for
32// some reason) followed by three words (2 ints, a function pointer,
33// and a descriptor pointer).
34
35// Test 1
36// Inline instruction for block variable layout: 0x0320 (3 strong 2 byref)
37// CHECK-LP64: Inline instruction for block variable layout: 0x0320
38    void (^b)() = ^{
39        byref_int = sh + ch+ch1+ch2 ;
40        x(bar);
41        x(baz);
42        x((id)strong_void_sta);
43        x(byref_bab);
44    };
45    b();
46
47// Test 2
48// Inline instruction for block variable layout: 0x0331 (3 strong 3 byref 1 weak)
49// CHECK-LP64: Inline instruction for block variable layout: 0x0331
50    void (^c)() = ^{
51        byref_int = sh + ch+ch1+ch2 ;
52        x(bar);
53        x(baz);
54        x((id)strong_void_sta);
55        x(wid);
56        bl_var1 = 0;
57        x(byref_bab);
58    };
59}
60
61@class NSString, NSNumber;
62void g() {
63  NSString *foo;
64   NSNumber *bar;
65   unsigned int bletch;
66   __weak id weak_delegate;
67  unsigned int i;
68  NSString *y;
69  NSString *z;
70// Inline instruction for block variable layout: 0x0401 (4 strong 0 byref 1 weak)
71// CHECK-LP64: Inline instruction for block variable layout: 0x0401
72  void (^c)() = ^{
73   int j = i + bletch;
74   x(foo);
75   x(bar);
76   x(weak_delegate);
77   x(y);
78   x(z);
79  };
80  c();
81}
82
83// Test 5 (unions/structs and their nesting):
84void h() {
85  struct S5 {
86    int i1;
87    __unsafe_unretained id o1;
88    struct V {
89     int i2;
90     __unsafe_unretained id o2;
91    } v1;
92    int i3;
93    union UI {
94        void * i1;
95        __unsafe_unretained id o1;
96        int i3;
97        __unsafe_unretained id o3;
98    }ui;
99  };
100
101  union U {
102        void * i1;
103        __unsafe_unretained id o1;
104        int i3;
105        __unsafe_unretained id o3;
106  }ui;
107
108  struct S5 s2;
109  union U u2;
110  __block id block_id;
111
112// 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
113  void (^c)() = ^{
114    x(s2.ui.o1);
115    x(u2.o1);
116    block_id = 0;
117  };
118  c();
119}
120
121// Test for array of stuff.
122void arr1() {
123  struct S {
124    __unsafe_unretained id unsafe_unretained_var[4];
125 } imported_s;
126
127// CHECK-LP64: block variable layout: BL_UNRETAINED:4, BL_OPERATOR:0
128    void (^c)() = ^{
129        x(imported_s.unsafe_unretained_var[2]);
130    };
131
132   c();
133}
134
135// Test2 for array of stuff.
136void arr2() {
137  struct S {
138   int a;
139    __unsafe_unretained id unsafe_unretained_var[4];
140 } imported_s;
141
142// CHECK-LP64: block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINED:4, BL_OPERATOR:0
143    void (^c)() = ^{
144        x(imported_s.unsafe_unretained_var[2]);
145    };
146
147   c();
148}
149
150// Test3 for array of stuff.
151void arr3() {
152  struct S {
153   int a;
154    __unsafe_unretained id unsafe_unretained_var[0];
155 } imported_s;
156
157// CHECK-LP64: block variable layout: BL_OPERATOR:0
158    void (^c)() = ^{
159      int i = imported_s.a;
160    };
161
162   c();
163}
164
165
166// Test4 for array of stuff.
167@class B;
168void arr4() {
169  struct S {
170    struct s0 {
171      __unsafe_unretained id s_f0;
172      __unsafe_unretained id s_f1;
173    } f0;
174
175    __unsafe_unretained id f1;
176
177    struct s1 {
178      int *f0;
179      __unsafe_unretained B *f1;
180    } f4[2][2];
181  } captured_s;
182
183// 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
184  void (^c)() = ^{
185      id i = captured_s.f0.s_f1;
186  };
187
188   c();
189}
190
191// Test1 bitfield in cpatured aggregate.
192void bf1() {
193  struct S {
194    int flag : 25;
195    int flag1: 7;
196    int flag2 :1;
197    int flag3: 7;
198    int flag4: 24;
199  } s;
200
201// CHECK-LP64: block variable layout: BL_OPERATOR:0
202  int (^c)() = ^{
203      return s.flag;
204  };
205  c();
206}
207
208// Test2 bitfield in cpatured aggregate.
209void bf2() {
210  struct S {
211    int flag : 1;
212  } s;
213
214// CHECK-LP64: block variable layout: BL_OPERATOR:0
215  int (^c)() = ^{
216      return s.flag;
217  };
218  c();
219}
220
221// Test3 bitfield in cpatured aggregate.
222void bf3() {
223
224     struct {
225        unsigned short _reserved : 16;
226
227        unsigned char _draggedNodesAreDeletable: 1;
228        unsigned char _draggedOutsideOutlineView : 1;
229        unsigned char _adapterRespondsTo_addRootPaths : 1;
230        unsigned char _adapterRespondsTo_moveDataNodes : 1;
231        unsigned char _adapterRespondsTo_removeRootDataNode : 1;
232        unsigned char _adapterRespondsTo_doubleClickDataNode : 1;
233        unsigned char _adapterRespondsTo_selectDataNode : 1;
234        unsigned char _adapterRespondsTo_textDidEndEditing : 1;
235        unsigned char _adapterRespondsTo_updateAndSaveRoots : 1;
236        unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1;
237        unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1;
238        unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1;
239        unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1;
240        unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1;
241
242        unsigned int _filler : 32;
243    } _flags;
244
245// CHECK-LP64: block variable layout: BL_OPERATOR:0
246  unsigned char (^c)() = ^{
247      return _flags._draggedNodesAreDeletable;
248  };
249
250   c();
251}
252
253// Test4 unnamed bitfield
254void bf4() {
255
256     struct {
257        unsigned short _reserved : 16;
258
259        unsigned char _draggedNodesAreDeletable: 1;
260        unsigned char _draggedOutsideOutlineView : 1;
261        unsigned char _adapterRespondsTo_addRootPaths : 1;
262        unsigned char _adapterRespondsTo_moveDataNodes : 1;
263        unsigned char _adapterRespondsTo_removeRootDataNode : 1;
264        unsigned char _adapterRespondsTo_doubleClickDataNode : 1;
265        unsigned char _adapterRespondsTo_selectDataNode : 1;
266        unsigned char _adapterRespondsTo_textDidEndEditing : 1;
267
268        unsigned long long : 64;
269
270        unsigned char _adapterRespondsTo_updateAndSaveRoots : 1;
271        unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1;
272        unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1;
273        unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1;
274        unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1;
275        unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1;
276
277        unsigned int _filler : 32;
278    } _flags;
279
280// CHECK-LP64: block variable layout: BL_OPERATOR:0
281  unsigned char (^c)() = ^{
282      return _flags._draggedNodesAreDeletable;
283  };
284
285   c();
286}
287
288
289
290// Test5 unnamed bitfield.
291void bf5() {
292     struct {
293        unsigned char flag : 1;
294        unsigned int  : 32;
295        unsigned char flag1 : 1;
296    } _flags;
297
298// CHECK-LP64: block variable layout: BL_OPERATOR:0
299  unsigned char (^c)() = ^{
300      return _flags.flag;
301  };
302
303   c();
304}
305
306
307// Test6 0 length bitfield.
308void bf6() {
309     struct {
310        unsigned char flag : 1;
311        unsigned int  : 0;
312        unsigned char flag1 : 1;
313    } _flags;
314
315// CHECK-LP64: block variable layout: BL_OPERATOR:0
316  unsigned char (^c)() = ^{
317      return _flags.flag;
318  };
319
320   c();
321}
322
323// Test7 large number of captured variables.
324void Test7() {
325    __weak id wid;
326    __weak id wid1, wid2, wid3, wid4;
327    __weak id wid5, wid6, wid7, wid8;
328    __weak id wid9, wid10, wid11, wid12;
329    __weak id wid13, wid14, wid15, wid16;
330    const id bar = (id) opaque_id();
331// CHECK-LP64: block variable layout: BL_STRONG:1, BL_WEAK:16, BL_OPERATOR:0
332    void (^b)() = ^{
333      x(bar);
334      x(wid1);
335      x(wid2);
336      x(wid3);
337      x(wid4);
338      x(wid5);
339      x(wid6);
340      x(wid7);
341      x(wid8);
342      x(wid9);
343      x(wid10);
344      x(wid11);
345      x(wid12);
346      x(wid13);
347      x(wid14);
348      x(wid15);
349      x(wid16);
350    };
351}
352
353
354// Test 8 very large number of captured variables.
355void Test8() {
356__weak id wid;
357    __weak id wid1, wid2, wid3, wid4;
358    __weak id wid5, wid6, wid7, wid8;
359    __weak id wid9, wid10, wid11, wid12;
360    __weak id wid13, wid14, wid15, wid16;
361    __weak id w1, w2, w3, w4;
362    __weak id w5, w6, w7, w8;
363    __weak id w9, w10, w11, w12;
364    __weak id w13, w14, w15, w16;
365    const id bar = (id) opaque_id();
366// CHECK-LP64: block variable layout: BL_STRONG:1, BL_WEAK:16, BL_WEAK:16, BL_WEAK:1, BL_OPERATOR:0
367    void (^b)() = ^{
368      x(bar);
369      x(wid1);
370      x(wid2);
371      x(wid3);
372      x(wid4);
373      x(wid5);
374      x(wid6);
375      x(wid7);
376      x(wid8);
377      x(wid9);
378      x(wid10);
379      x(wid11);
380      x(wid12);
381      x(wid13);
382      x(wid14);
383      x(wid15);
384      x(wid16);
385      x(w1);
386      x(w2);
387      x(w3);
388      x(w4);
389      x(w5);
390      x(w6);
391      x(w7);
392      x(w8);
393      x(w9);
394      x(w10);
395      x(w11);
396      x(w12);
397      x(w13);
398      x(w14);
399      x(w15);
400      x(w16);
401      x(wid);
402    };
403}
404