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