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