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