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