xref: /aosp_15_r20/external/clang/test/CodeGenObjC/block-var-layout.m (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 -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://12752901
4*67e74705SXin Li
5*67e74705SXin Listruct S {
6*67e74705SXin Li    int i1;
7*67e74705SXin Li    id o1;
8*67e74705SXin Li    struct V {
9*67e74705SXin Li     int i2;
10*67e74705SXin Li     id o2;
11*67e74705SXin Li    } v1;
12*67e74705SXin Li    int i3;
13*67e74705SXin Li    id o3;
14*67e74705SXin Li};
15*67e74705SXin Li
16*67e74705SXin Li__weak id wid;
17*67e74705SXin Livoid x(id y) {}
18*67e74705SXin Livoid y(int a) {}
19*67e74705SXin Li
20*67e74705SXin Liextern id opaque_id();
21*67e74705SXin Li
22*67e74705SXin Livoid f() {
23*67e74705SXin Li    __block int byref_int = 0;
24*67e74705SXin Li    char ch = 'a';
25*67e74705SXin Li    char ch1 = 'b';
26*67e74705SXin Li    char ch2 = 'c';
27*67e74705SXin Li    short sh = 2;
28*67e74705SXin Li    const id bar = (id) opaque_id();
29*67e74705SXin Li    id baz = 0;
30*67e74705SXin Li    __strong void *strong_void_sta;
31*67e74705SXin Li    __block id byref_bab = (id)0;
32*67e74705SXin Li    __block void *bl_var1;
33*67e74705SXin Li    int i; double dob;
34*67e74705SXin Li
35*67e74705SXin Li// The patterns here are a sequence of bytes, each saying first how
36*67e74705SXin Li// many sizeof(void*) chunks to skip (high nibble) and then how many
37*67e74705SXin Li// to scan (low nibble).  A zero byte says that we've reached the end
38*67e74705SXin Li// of the pattern.
39*67e74705SXin Li//
40*67e74705SXin Li// All of these patterns start with 01 3x because the block header on
41*67e74705SXin Li// LP64 consists of an isa pointer (which we're supposed to scan for
42*67e74705SXin Li// some reason) followed by three words (2 ints, a function pointer,
43*67e74705SXin Li// and a descriptor pointer).
44*67e74705SXin Li
45*67e74705SXin Li// FIXME: do these really have to be named L_OBJC_CLASS_NAME_xxx?
46*67e74705SXin Li// FIXME: sequences should never end in x0 00 instead of just 00
47*67e74705SXin Li
48*67e74705SXin Li// Test 1
49*67e74705SXin Li// byref int, short, char, char, char, id, id, strong void*, byref id
50*67e74705SXin Li// CHECK-LP64: block variable layout for block: 0x01, 0x35, 0x10, 0x00
51*67e74705SXin Li    void (^b)() = ^{
52*67e74705SXin Li        byref_int = sh + ch+ch1+ch2 ;
53*67e74705SXin Li        x(bar);
54*67e74705SXin Li        x(baz);
55*67e74705SXin Li        x((id)strong_void_sta);
56*67e74705SXin Li        x(byref_bab);
57*67e74705SXin Li    };
58*67e74705SXin Li    b();
59*67e74705SXin Li
60*67e74705SXin Li// Test 2
61*67e74705SXin Li// byref int, short, char, char, char, id, id, strong void*, byref void*, byref id
62*67e74705SXin Li// 01 36 10 00
63*67e74705SXin Li// CHECK-LP64: block variable layout for block: 0x01, 0x36, 0x10, 0x00
64*67e74705SXin Li    void (^c)() = ^{
65*67e74705SXin Li        byref_int = sh + ch+ch1+ch2 ;
66*67e74705SXin Li        x(bar);
67*67e74705SXin Li        x(baz);
68*67e74705SXin Li        x((id)strong_void_sta);
69*67e74705SXin Li        x(wid);
70*67e74705SXin Li        bl_var1 = 0;
71*67e74705SXin Li        x(byref_bab);
72*67e74705SXin Li    };
73*67e74705SXin Li    c();
74*67e74705SXin Li
75*67e74705SXin Li// Test 3
76*67e74705SXin Li// byref int, short, char, char, char, id, id, byref void*, int, double, byref id
77*67e74705SXin Li// 01 34 11 30 00
78*67e74705SXin Li// FIXME: we'd get a better format here if we sorted by scannability, not just alignment
79*67e74705SXin Li// CHECK-LP64: block variable layout for block: 0x01, 0x35, 0x30, 0x00
80*67e74705SXin Li    void (^d)() = ^{
81*67e74705SXin Li        byref_int = sh + ch+ch1+ch2 ;
82*67e74705SXin Li        x(bar);
83*67e74705SXin Li        x(baz);
84*67e74705SXin Li        x(wid);
85*67e74705SXin Li        bl_var1 = 0;
86*67e74705SXin Li        y(i + dob);
87*67e74705SXin Li        x(byref_bab);
88*67e74705SXin Li    };
89*67e74705SXin Li    d();
90*67e74705SXin Li
91*67e74705SXin Li// Test 4
92*67e74705SXin Li// struct S (int, id, int, id, int, id)
93*67e74705SXin Li// 01 41 11 11 00
94*67e74705SXin Li// CHECK-LP64: block variable layout for block: 0x01, 0x41, 0x11, 0x11, 0x00
95*67e74705SXin Li    struct S s2;
96*67e74705SXin Li    void (^e)() = ^{
97*67e74705SXin Li        x(s2.o1);
98*67e74705SXin Li    };
99*67e74705SXin Li    e();
100*67e74705SXin Li}
101*67e74705SXin Li
102*67e74705SXin Li// Test 5 (unions/structs and their nesting):
103*67e74705SXin Livoid Test5() {
104*67e74705SXin Li  struct S5 {
105*67e74705SXin Li    int i1;
106*67e74705SXin Li    id o1;
107*67e74705SXin Li    struct V {
108*67e74705SXin Li     int i2;
109*67e74705SXin Li     id o2;
110*67e74705SXin Li    } v1;
111*67e74705SXin Li    int i3;
112*67e74705SXin Li    union UI {
113*67e74705SXin Li        void * i1;
114*67e74705SXin Li        id o1;
115*67e74705SXin Li        int i3;
116*67e74705SXin Li        id o3;
117*67e74705SXin Li    }ui;
118*67e74705SXin Li  };
119*67e74705SXin Li
120*67e74705SXin Li  union U {
121*67e74705SXin Li        void * i1;
122*67e74705SXin Li        id o1;
123*67e74705SXin Li        int i3;
124*67e74705SXin Li        id o3;
125*67e74705SXin Li  }ui;
126*67e74705SXin Li
127*67e74705SXin Li  struct S5 s2;
128*67e74705SXin Li  union U u2;
129*67e74705SXin Li
130*67e74705SXin Li// struct s2 (int, id, int, id, int, id?), union u2 (id?)
131*67e74705SXin Li// 01 41 11 12 00
132*67e74705SXin Li// CHECK-LP64: block variable layout for block: 0x01, 0x41, 0x11, 0x12, 0x00
133*67e74705SXin Li  void (^c)() = ^{
134*67e74705SXin Li    x(s2.ui.o1);
135*67e74705SXin Li    x(u2.o1);
136*67e74705SXin Li  };
137*67e74705SXin Li  c();
138*67e74705SXin Li}
139*67e74705SXin Li
140*67e74705SXin Li// rdar: //8417746
141*67e74705SXin Livoid CFRelease(id);
142*67e74705SXin Livoid notifyBlock(id dependentBlock) {
143*67e74705SXin Li id singleObservationToken;
144*67e74705SXin Li id token;
145*67e74705SXin Li void (^b)();
146*67e74705SXin Li
147*67e74705SXin Li// id, id, void(^)()
148*67e74705SXin Li// 01 33 00
149*67e74705SXin Li// CHECK-LP64: block variable layout for block: 0x01, 0x33, 0x00
150*67e74705SXin Li void (^wrapperBlock)() = ^() {
151*67e74705SXin Li     CFRelease(singleObservationToken);
152*67e74705SXin Li     CFRelease(singleObservationToken);
153*67e74705SXin Li     CFRelease(token);
154*67e74705SXin Li     CFRelease(singleObservationToken);
155*67e74705SXin Li     b();
156*67e74705SXin Li    };
157*67e74705SXin Li wrapperBlock();
158*67e74705SXin Li}
159*67e74705SXin Li
160*67e74705SXin Livoid test_empty_block() {
161*67e74705SXin Li// 01 00
162*67e74705SXin Li// CHECK-LP64: block variable layout for block: 0x01, 0x30, 0x00
163*67e74705SXin Li  void (^wrapperBlock)() = ^() {
164*67e74705SXin Li  };
165*67e74705SXin Li wrapperBlock();
166*67e74705SXin Li}
167*67e74705SXin Li
168*67e74705SXin Li// rdar://16111839
169*67e74705SXin Litypedef union { char ch[8];  } SS;
170*67e74705SXin Litypedef struct { SS s[4]; } CS;
171*67e74705SXin Livoid test_union_in_layout() {
172*67e74705SXin Li  CS cs;
173*67e74705SXin Li  ^{ cs; };
174*67e74705SXin Li}
175