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