1 // RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-unknown-unknown -fblocks %s -emit-llvm -o - | FileCheck %s -check-prefix=UNINIT
2 // RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=pattern %s -emit-llvm -o - | FileCheck %s -check-prefix=PATTERN
3 // RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s -check-prefix=ZERO
4 
5 // None of the synthesized globals should contain `undef`.
6 // PATTERN-NOT: undef
7 // ZERO-NOT: undef
8 
9 template<typename T> void used(T &) noexcept;
10 
11 extern "C" {
12 
13 // UNINIT-LABEL:  test_selfinit(
14 // ZERO-LABEL:    test_selfinit(
15 // ZERO: store i32 0, i32* %self, align 4, !annotation [[AUTO_INIT:!.+]]
16 // PATTERN-LABEL: test_selfinit(
17 // PATTERN: store i32 -1431655766, i32* %self, align 4, !annotation [[AUTO_INIT:!.+]]
test_selfinit()18 void test_selfinit() {
19   int self = self + 1;
20   used(self);
21 }
22 
23 // UNINIT-LABEL:  test_block(
24 // ZERO-LABEL:    test_block(
25 // ZERO: store i32 0, i32* %block, align 4, !annotation [[AUTO_INIT:!.+]]
26 // PATTERN-LABEL: test_block(
27 // PATTERN: store i32 -1431655766, i32* %block, align 4, !annotation [[AUTO_INIT:!.+]]
test_block()28 void test_block() {
29   __block int block;
30   used(block);
31 }
32 
33 // Using the variable being initialized is typically UB in C, but for blocks we
34 // can be nice: they imply extra book-keeping and we can do the auto-init before
35 // any of said book-keeping.
36 //
37 // UNINIT-LABEL:  test_block_self_init(
38 // ZERO-LABEL:    test_block_self_init(
39 // ZERO:          %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
40 // ZERO:          %captured1 = getelementptr inbounds %struct.__block_byref_captured, %struct.__block_byref_captured* %captured, i32 0, i32 4
41 // ZERO-NEXT:     store %struct.XYZ* null, %struct.XYZ** %captured1, align 8, !annotation [[AUTO_INIT:!.+]]
42 // ZERO:          %call = call %struct.XYZ* @create(
43 // PATTERN-LABEL: test_block_self_init(
44 // PATTERN:       %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
45 // PATTERN:       %captured1 = getelementptr inbounds %struct.__block_byref_captured, %struct.__block_byref_captured* %captured, i32 0, i32 4
46 // PATTERN-NEXT:  store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8, !annotation [[AUTO_INIT:!.+]]
47 // PATTERN:       %call = call %struct.XYZ* @create(
48 using Block = void (^)();
49 typedef struct XYZ {
50   Block block;
51 } * xyz_t;
test_block_self_init()52 void test_block_self_init() {
53   extern xyz_t create(Block block);
54   __block xyz_t captured = create(^() {
55     used(captured);
56   });
57 }
58 
59 // Capturing with escape after initialization is also an edge case.
60 //
61 // UNINIT-LABEL:  test_block_captures_self_after_init(
62 // ZERO-LABEL:    test_block_captures_self_after_init(
63 // ZERO:          %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
64 // ZERO:          %captured1 = getelementptr inbounds %struct.__block_byref_captured.1, %struct.__block_byref_captured.1* %captured, i32 0, i32 4
65 // ZERO-NEXT:     store %struct.XYZ* null, %struct.XYZ** %captured1, align 8, !annotation [[AUTO_INIT:!.+]]
66 // ZERO:          %call = call %struct.XYZ* @create(
67 // PATTERN-LABEL: test_block_captures_self_after_init(
68 // PATTERN:       %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
69 // PATTERN:       %captured1 = getelementptr inbounds %struct.__block_byref_captured.1, %struct.__block_byref_captured.1* %captured, i32 0, i32 4
70 // PATTERN-NEXT:  store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8, !annotation [[AUTO_INIT:!.+]]
71 // PATTERN:       %call = call %struct.XYZ* @create(
test_block_captures_self_after_init()72 void test_block_captures_self_after_init() {
73   extern xyz_t create(Block block);
74   __block xyz_t captured;
75   captured = create(^() {
76     used(captured);
77   });
78 }
79 
80 // This type of code is currently not handled by zero / pattern initialization.
81 // The test will break when that is fixed.
82 // UNINIT-LABEL:  test_goto_unreachable_value(
83 // ZERO-LABEL:    test_goto_unreachable_value(
84 // ZERO-NOT: store {{.*}}%oops
85 // PATTERN-LABEL: test_goto_unreachable_value(
86 // PATTERN-NOT: store {{.*}}%oops
test_goto_unreachable_value()87 void test_goto_unreachable_value() {
88   goto jump;
89   int oops;
90  jump:
91   used(oops);
92 }
93 
94 // This type of code is currently not handled by zero / pattern initialization.
95 // The test will break when that is fixed.
96 // UNINIT-LABEL:  test_goto(
97 // ZERO-LABEL:    test_goto(
98 // ZERO: if.then:
99 // ZERO: br label %jump
100 // ZERO: store i32 0, i32* %oops, align 4, !annotation [[AUTO_INIT:!.+]]
101 // ZERO: br label %jump
102 // ZERO: jump:
103 // PATTERN-LABEL: test_goto(
104 // PATTERN: if.then:
105 // PATTERN: br label %jump
106 // PATTERN: store i32 -1431655766, i32* %oops, align 4, !annotation [[AUTO_INIT:!.+]]
107 // PATTERN: br label %jump
108 // PATTERN: jump:
test_goto(int i)109 void test_goto(int i) {
110   if (i)
111     goto jump;
112   int oops;
113  jump:
114   used(oops);
115 }
116 
117 // This type of code is currently not handled by zero / pattern initialization.
118 // The test will break when that is fixed.
119 // UNINIT-LABEL:  test_switch(
120 // ZERO-LABEL:    test_switch(
121 // ZERO:      sw.bb:
122 // ZERO-NEXT: store i32 0, i32* %oops, align 4, !annotation [[AUTO_INIT:!.+]]
123 // ZERO:      sw.bb1:
124 // ZERO-NEXT: call void @{{.*}}used
125 // PATTERN-LABEL: test_switch(
126 // PATTERN:      sw.bb:
127 // PATTERN-NEXT: store i32 -1431655766, i32* %oops, align 4, !annotation [[AUTO_INIT:!.+]]
128 // PATTERN:      sw.bb1:
129 // PATTERN-NEXT: call void @{{.*}}used
test_switch(int i)130 void test_switch(int i) {
131   switch (i) {
132   case 0:
133     int oops;
134     break;
135   case 1:
136     used(oops);
137   }
138 }
139 
140 // UNINIT-LABEL:  test_vla(
141 // ZERO-LABEL:    test_vla(
142 // ZERO:  %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 4
143 // ZERO:  call void @llvm.memset{{.*}}(i8* align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]]
144 // PATTERN-LABEL: test_vla(
145 // PATTERN:  %vla.iszerosized = icmp eq i64 %{{.*}}, 0
146 // PATTERN:  br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop
147 // PATTERN: vla-setup.loop:
148 // PATTERN:  %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 4
149 // PATTERN:  %vla.begin = bitcast i32* %vla to i8*
150 // PATTERN:  %vla.end = getelementptr inbounds i8, i8* %vla.begin, i64 %[[SIZE]]
151 // PATTERN:  br label %vla-init.loop
152 // PATTERN: vla-init.loop:
153 // PATTERN:  %vla.cur = phi i8* [ %vla.begin, %vla-setup.loop ], [ %vla.next, %vla-init.loop ]
154 // PATTERN:  call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_vla.vla {{.*}}), !annotation [[AUTO_INIT:!.+]]
155 // PATTERN:  %vla.next = getelementptr inbounds i8, i8* %vla.cur, i64 4
156 // PATTERN:  %vla-init.isdone = icmp eq i8* %vla.next, %vla.end
157 // PATTERN:  br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop
158 // PATTERN: vla-init.cont:
159 // PATTERN:  call void @{{.*}}used
test_vla(int size)160 void test_vla(int size) {
161   // Variable-length arrays can't have a zero size according to C11 6.7.6.2/5.
162   // Neither can they be negative-sized.
163   //
164   // We don't use the former fact because some code creates zero-sized VLAs and
165   // doesn't use them. clang makes these share locations with other stack
166   // values, which leads to initialization of the wrong values.
167   //
168   // We rely on the later fact because it generates better code.
169   //
170   // Both cases are caught by UBSan.
171   int vla[size];
172   int *ptr = vla;
173   used(ptr);
174 }
175 
176 // UNINIT-LABEL:  test_alloca(
177 // ZERO-LABEL:    test_alloca(
178 // ZERO:          %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64
179 // ZERO-NEXT:     %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align [[ALIGN:[0-9]+]]
180 // ZERO-NEXT:     call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %[[ALLOCA]], i8 0, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]]
181 // PATTERN-LABEL: test_alloca(
182 // PATTERN:       %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64
183 // PATTERN-NEXT:  %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align [[ALIGN:[0-9]+]]
184 // PATTERN-NEXT:  call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %[[ALLOCA]], i8 -86, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]]
test_alloca(int size)185 void test_alloca(int size) {
186   void *ptr = __builtin_alloca(size);
187   used(ptr);
188 }
189 
190 // UNINIT-LABEL:  test_alloca_with_align(
191 // ZERO-LABEL:    test_alloca_with_align(
192 // ZERO:          %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64
193 // ZERO-NEXT:     %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128
194 // ZERO-NEXT:     call void @llvm.memset{{.*}}(i8* align 128 %[[ALLOCA]], i8 0, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]]
195 // PATTERN-LABEL: test_alloca_with_align(
196 // PATTERN:       %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64
197 // PATTERN-NEXT:  %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128
198 // PATTERN-NEXT:  call void @llvm.memset{{.*}}(i8* align 128 %[[ALLOCA]], i8 -86, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]]
test_alloca_with_align(int size)199 void test_alloca_with_align(int size) {
200   void *ptr = __builtin_alloca_with_align(size, 1024);
201   used(ptr);
202 }
203 
204 // UNINIT-LABEL:  test_alloca_uninitialized(
205 // ZERO-LABEL:    test_alloca_uninitialized(
206 // ZERO:          %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64
207 // ZERO-NEXT:     %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align [[ALIGN:[0-9]+]]
208 // ZERO-NOT:      call void @llvm.memset
209 // PATTERN-LABEL: test_alloca_uninitialized(
210 // PATTERN:       %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64
211 // PATTERN-NEXT:  %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align [[ALIGN:[0-9]+]]
212 // PATTERN-NOT:   call void @llvm.memset
test_alloca_uninitialized(int size)213 void test_alloca_uninitialized(int size) {
214   void *ptr = __builtin_alloca_uninitialized(size);
215   used(ptr);
216 }
217 
218 // UNINIT-LABEL:  test_alloca_with_align_uninitialized(
219 // ZERO-LABEL:    test_alloca_with_align_uninitialized(
220 // ZERO:          %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64
221 // ZERO-NEXT:     %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128
222 // ZERO-NOT:      call void @llvm.memset
223 // PATTERN-LABEL: test_alloca_with_align_uninitialized(
224 // PATTERN:       %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64
225 // PATTERN-NEXT:  %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128
226 // PATTERN-NOT:   call void @llvm.memset
test_alloca_with_align_uninitialized(int size)227 void test_alloca_with_align_uninitialized(int size) {
228   void *ptr = __builtin_alloca_with_align_uninitialized(size, 1024);
229   used(ptr);
230 }
231 
232 // UNINIT-LABEL:  test_struct_vla(
233 // ZERO-LABEL:    test_struct_vla(
234 // ZERO:  %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16
235 // ZERO:  call void @llvm.memset{{.*}}(i8* align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]]
236 // PATTERN-LABEL: test_struct_vla(
237 // PATTERN:  %vla.iszerosized = icmp eq i64 %{{.*}}, 0
238 // PATTERN:  br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop
239 // PATTERN: vla-setup.loop:
240 // PATTERN:  %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16
241 // PATTERN:  %vla.begin = bitcast %struct.anon* %vla to i8*
242 // PATTERN:  %vla.end = getelementptr inbounds i8, i8* %vla.begin, i64 %[[SIZE]]
243 // PATTERN:  br label %vla-init.loop
244 // PATTERN: vla-init.loop:
245 // PATTERN:  %vla.cur = phi i8* [ %vla.begin, %vla-setup.loop ], [ %vla.next, %vla-init.loop ]
246 // PATTERN:  call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_struct_vla.vla {{.*}}), !annotation [[AUTO_INIT:!.+]]
247 // PATTERN:  %vla.next = getelementptr inbounds i8, i8* %vla.cur, i64 16
248 // PATTERN:  %vla-init.isdone = icmp eq i8* %vla.next, %vla.end
249 // PATTERN:  br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop
250 // PATTERN: vla-init.cont:
251 // PATTERN:  call void @{{.*}}used
test_struct_vla(int size)252 void test_struct_vla(int size) {
253   // Same as above, but with a struct that doesn't just memcpy.
254   struct {
255     float f;
256     char c;
257     void *ptr;
258   } vla[size];
259   void *ptr = static_cast<void*>(vla);
260   used(ptr);
261 }
262 
263 // UNINIT-LABEL:  test_zsa(
264 // ZERO-LABEL:    test_zsa(
265 // ZERO: %zsa = alloca [0 x i32], align 4
266 // ZERO-NOT: %zsa
267 // ZERO:  call void @{{.*}}used
268 // PATTERN-LABEL: test_zsa(
269 // PATTERN: %zsa = alloca [0 x i32], align 4
270 // PATTERN-NOT: %zsa
271 // PATTERN:  call void @{{.*}}used
test_zsa(int size)272 void test_zsa(int size) {
273   // Technically not valid, but as long as clang accepts them we should do
274   // something sensible (i.e. not store to the zero-size array).
275   int zsa[0];
276   used(zsa);
277 }
278 
279 // UNINIT-LABEL:  test_huge_uninit(
280 // ZERO-LABEL:    test_huge_uninit(
281 // ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536, {{.*}}), !annotation [[AUTO_INIT:!.+]]
282 // PATTERN-LABEL: test_huge_uninit(
283 // PATTERN: call void @llvm.memset{{.*}}, i8 -86, i64 65536, {{.*}}), !annotation [[AUTO_INIT:!.+]]
test_huge_uninit()284 void test_huge_uninit() {
285   // We can't emit this as an inline constant to a store instruction because
286   // SDNode hits an internal size limit.
287   char big[65536];
288   used(big);
289 }
290 
291 // UNINIT-LABEL:  test_huge_small_init(
292 // ZERO-LABEL:    test_huge_small_init(
293 // ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536,
294 // ZERO-NOT: !annotation
295 // ZERO: store i8 97,
296 // ZERO: store i8 98,
297 // ZERO: store i8 99,
298 // ZERO: store i8 100,
299 // PATTERN-LABEL: test_huge_small_init(
300 // PATTERN: call void @llvm.memset{{.*}}, i8 0, i64 65536,
301 // PATTERN-NOT: !annotation
302 // PATTERN: store i8 97,
303 // PATTERN: store i8 98,
304 // PATTERN: store i8 99,
305 // PATTERN: store i8 100,
test_huge_small_init()306 void test_huge_small_init() {
307   char big[65536] = { 'a', 'b', 'c', 'd' };
308   used(big);
309 }
310 
311 // UNINIT-LABEL:  test_huge_larger_init(
312 // ZERO-LABEL:    test_huge_larger_init(
313 // ZERO:  call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, {{.*}}, i64 65536,
314 // ZERO-NOT: !annotation
315 // PATTERN-LABEL: test_huge_larger_init(
316 // PATTERN:  call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, {{.*}}, i64 65536,
317 // PATTERN-NOT: !annotation
test_huge_larger_init()318 void test_huge_larger_init() {
319   char big[65536] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
320   used(big);
321 }
322 
323 } // extern "C"
324 
325 // CHECK: [[AUTO_INIT]] = !{ !"auto-init" }
326