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