1 ; RUN: opt -safe-stack -safe-stack-coloring=1 -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
2 ; RUN: opt -safe-stack -safe-stack-coloring=1 -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
4 ; x and y share the stack slot.
5 define void @f() safestack {
6 ; CHECK-LABEL: define void @f
8 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
9 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -16
11 %x = alloca i32, align 4
12 %y = alloca i32, align 4
13 %z = alloca i32, align 4
14 %x0 = bitcast i32* %x to i8*
15 %y0 = bitcast i32* %y to i8*
16 %z0 = bitcast i32* %z to i8*
18 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %z0)
19 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
21 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -4
22 call void @capture32(i32* %x)
23 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
24 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
26 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -4
27 call void @capture32(i32* %y)
28 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
30 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -8
31 call void @capture32(i32* %z)
32 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %z0)
37 define void @no_markers() safestack {
38 ; CHECK-LABEL: define void @no_markers(
40 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
41 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -16
43 %x = alloca i32, align 4
44 %y = alloca i32, align 4
45 %x0 = bitcast i32* %x to i8*
47 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
49 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -4
50 call void @capture32(i32* %x)
51 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
53 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -8
54 call void @capture32(i32* %y)
59 ; x and y can't share memory, but they can split z's storage.
60 define void @g() safestack {
61 ; CHECK-LABEL: define void @g
63 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
64 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -16
66 %x = alloca i32, align 4
67 %y = alloca i32, align 4
68 %z = alloca i64, align 4
69 %x0 = bitcast i32* %x to i8*
70 %y0 = bitcast i32* %y to i8*
71 %z0 = bitcast i64* %z to i8*
73 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
74 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
76 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -4
77 call void @capture32(i32* %x)
78 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
80 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -8
81 call void @capture32(i32* %y)
82 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
83 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %z0)
85 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -8
86 call void @capture64(i64* %z)
87 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %z0)
92 ; Both y and z fit in x's alignment gap.
93 define void @h() safestack {
94 ; CHECK-LABEL: define void @h
96 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
97 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -16
99 %x = alloca i32, align 16
100 %z = alloca i64, align 4
101 %y = alloca i32, align 4
102 %x0 = bitcast i32* %x to i8*
103 %y0 = bitcast i32* %y to i8*
104 %z0 = bitcast i64* %z to i8*
106 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
107 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
108 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %z0)
110 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -16
111 call void @capture32(i32* %x)
113 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -12
114 call void @capture32(i32* %y)
116 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -8
117 call void @capture64(i64* %z)
119 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
120 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
121 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %z0)
126 ; void f(bool a, bool b) {
127 ; long x1, x2; capture64(&x1); capture64(&x2);
129 ; long y; capture64(&y);
131 ; long y1; capture64(&y1);
133 ; long y2; capture64(&y2);
136 ; long z; capture64(&z);
138 ; long z1; capture64(&z1);
140 ; long z2; capture64(&z2);
144 ; Everything fits in 4 x 64-bit slots.
145 define void @i(i1 zeroext %a, i1 zeroext %b) safestack {
146 ; CHECK-LABEL: define void @i
148 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
149 ; CHECK-NEXT: getelementptr i8, i8* %[[USP]], i32 -32
150 %x1 = alloca i64, align 8
151 %x2 = alloca i64, align 8
152 %y = alloca i64, align 8
153 %y1 = alloca i64, align 8
154 %y2 = alloca i64, align 8
155 %z = alloca i64, align 8
156 %z1 = alloca i64, align 8
157 %z2 = alloca i64, align 8
158 %0 = bitcast i64* %x1 to i8*
159 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %0)
160 %1 = bitcast i64* %x2 to i8*
161 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %1)
162 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -8
163 ; CHECK: call void @capture64(
164 call void @capture64(i64* nonnull %x1)
165 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -16
166 ; CHECK: call void @capture64(
167 call void @capture64(i64* nonnull %x2)
168 br i1 %a, label %if.then, label %if.else4
170 if.then: ; preds = %entry
171 %2 = bitcast i64* %y to i8*
172 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %2)
173 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -24
174 ; CHECK: call void @capture64(
175 call void @capture64(i64* nonnull %y)
176 br i1 %b, label %if.then3, label %if.else
178 if.then3: ; preds = %if.then
179 %3 = bitcast i64* %y1 to i8*
180 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %3)
181 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -32
182 ; CHECK: call void @capture64(
183 call void @capture64(i64* nonnull %y1)
184 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %3)
187 if.else: ; preds = %if.then
188 %4 = bitcast i64* %y2 to i8*
189 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %4)
190 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -32
191 ; CHECK: call void @capture64(
192 call void @capture64(i64* nonnull %y2)
193 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %4)
196 if.end: ; preds = %if.else, %if.then3
197 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %2)
200 if.else4: ; preds = %entry
201 %5 = bitcast i64* %z to i8*
202 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %5)
203 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -24
204 ; CHECK: call void @capture64(
205 call void @capture64(i64* nonnull %z)
206 br i1 %b, label %if.then6, label %if.else7
208 if.then6: ; preds = %if.else4
209 %6 = bitcast i64* %z1 to i8*
210 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %6)
211 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -32
212 ; CHECK: call void @capture64(
213 call void @capture64(i64* nonnull %z1)
214 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %6)
217 if.else7: ; preds = %if.else4
218 %7 = bitcast i64* %z2 to i8*
219 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7)
220 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -32
221 ; CHECK: call void @capture64(
222 call void @capture64(i64* nonnull %z2)
223 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %7)
226 if.end8: ; preds = %if.else7, %if.then6
227 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %5)
230 if.end9: ; preds = %if.end8, %if.end
231 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %1)
232 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %0)
236 ; lifetime for x ends in 2 different BBs
237 define void @no_merge1(i1 %d) safestack {
238 ; CHECK-LABEL: define void @no_merge1(
240 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
241 ; CHECK-NEXT: getelementptr i8, i8* %[[USP]], i32 -16
242 %x = alloca i32, align 4
243 %y = alloca i32, align 4
244 %x0 = bitcast i32* %x to i8*
245 %y0 = bitcast i32* %y to i8*
246 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
247 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -4
248 ; CHECK: call void @capture32(
249 call void @capture32(i32* %x)
250 br i1 %d, label %bb2, label %bb3
252 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
253 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -8
254 ; CHECK: call void @capture32(
255 call void @capture32(i32* %y)
256 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
257 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
260 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
264 define void @merge1(i1 %d) safestack {
265 ; CHECK-LABEL: define void @merge1(
267 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
268 ; CHECK-NEXT: getelementptr i8, i8* %[[USP]], i32 -16
269 %x = alloca i32, align 4
270 %y = alloca i32, align 4
271 %x0 = bitcast i32* %x to i8*
272 %y0 = bitcast i32* %y to i8*
273 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
274 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -4
275 ; CHECK: call void @capture32(
276 call void @capture32(i32* %x)
277 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
278 br i1 %d, label %bb2, label %bb3
280 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
281 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -4
282 ; CHECK: call void @capture32(
283 call void @capture32(i32* %y)
284 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
290 ; Missing lifetime.end
291 define void @merge2_noend(i1 %d) safestack {
292 ; CHECK-LABEL: define void @merge2_noend(
294 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
295 ; CHECK-NEXT: getelementptr i8, i8* %[[USP]], i32 -16
296 %x = alloca i32, align 4
297 %y = alloca i32, align 4
298 %x0 = bitcast i32* %x to i8*
299 %y0 = bitcast i32* %y to i8*
300 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
301 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -4
302 ; CHECK: call void @capture32(
303 call void @capture32(i32* %x)
304 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
305 br i1 %d, label %bb2, label %bb3
307 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
308 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -4
309 ; CHECK: call void @capture32(
310 call void @capture32(i32* %y)
316 ; Missing lifetime.end
317 define void @merge3_noend(i1 %d) safestack {
318 ; CHECK-LABEL: define void @merge3_noend(
320 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
321 ; CHECK-NEXT: getelementptr i8, i8* %[[USP]], i32 -16
322 %x = alloca i32, align 4
323 %y = alloca i32, align 4
324 %x0 = bitcast i32* %x to i8*
325 %y0 = bitcast i32* %y to i8*
326 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
327 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -4
328 ; CHECK: call void @capture32(
329 call void @capture32(i32* %x)
330 br i1 %d, label %bb2, label %bb3
332 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
333 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
334 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -4
335 ; CHECK: call void @capture32(
336 call void @capture32(i32* %y)
342 ; Missing lifetime.start
343 define void @nomerge4_nostart(i1 %d) safestack {
344 ; CHECK-LABEL: define void @nomerge4_nostart(
346 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
347 ; CHECK-NEXT: getelementptr i8, i8* %[[USP]], i32 -16
348 %x = alloca i32, align 4
349 %y = alloca i32, align 4
350 %x0 = bitcast i32* %x to i8*
351 %y0 = bitcast i32* %y to i8*
352 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -4
353 ; CHECK: call void @capture32(
354 call void @capture32(i32* %x)
355 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
356 br i1 %d, label %bb2, label %bb3
358 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
359 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -8
360 ; CHECK: call void @capture32(
361 call void @capture32(i32* %y)
367 define void @array_merge() safestack {
368 ; CHECK-LABEL: define void @array_merge(
370 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
371 ; CHECK-NEXT: getelementptr i8, i8* %[[USP]], i32 -800
372 %A.i1 = alloca [100 x i32], align 4
373 %B.i2 = alloca [100 x i32], align 4
374 %A.i = alloca [100 x i32], align 4
375 %B.i = alloca [100 x i32], align 4
376 %0 = bitcast [100 x i32]* %A.i to i8*
377 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %0)
378 %1 = bitcast [100 x i32]* %B.i to i8*
379 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %1)
380 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -400
381 ; CHECK: call void @capture100x32(
382 call void @capture100x32([100 x i32]* %A.i)
383 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -800
384 ; CHECK: call void @capture100x32(
385 call void @capture100x32([100 x i32]* %B.i)
386 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %0)
387 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %1)
388 %2 = bitcast [100 x i32]* %A.i1 to i8*
389 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %2)
390 %3 = bitcast [100 x i32]* %B.i2 to i8*
391 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %3)
392 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -400
393 ; CHECK: call void @capture100x32(
394 call void @capture100x32([100 x i32]* %A.i1)
395 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -800
396 ; CHECK: call void @capture100x32(
397 call void @capture100x32([100 x i32]* %B.i2)
398 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %2)
399 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %3)
403 define void @myCall_pr15707() safestack {
404 ; CHECK-LABEL: define void @myCall_pr15707(
406 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
407 ; CHECK-NEXT: getelementptr i8, i8* %[[USP]], i32 -200000
408 %buf1 = alloca i8, i32 100000, align 16
409 %buf2 = alloca i8, i32 100000, align 16
411 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %buf1)
412 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %buf1)
414 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %buf1)
415 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %buf2)
416 call void @capture8(i8* %buf1)
417 call void @capture8(i8* %buf2)
421 ; Check that we don't assert and crash even when there are allocas
422 ; outside the declared lifetime regions.
423 define void @bad_range() safestack {
424 ; CHECK-LABEL: define void @bad_range(
426 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
427 ; A.i and B.i unsafe, not merged
428 ; CHECK-NEXT: getelementptr i8, i8* %[[USP]], i32 -800
430 ; CHECK: = alloca [100 x i32], align 4
431 ; CHECK: = alloca [100 x i32], align 4
433 %A.i1 = alloca [100 x i32], align 4
434 %B.i2 = alloca [100 x i32], align 4
435 %A.i = alloca [100 x i32], align 4
436 %B.i = alloca [100 x i32], align 4
437 %0 = bitcast [100 x i32]* %A.i to i8*
438 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %0) nounwind
439 %1 = bitcast [100 x i32]* %B.i to i8*
440 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %1) nounwind
441 call void @capture100x32([100 x i32]* %A.i)
442 call void @capture100x32([100 x i32]* %B.i)
443 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %0) nounwind
444 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %1) nounwind
448 ; I am used outside the marked lifetime.
449 call void @capture100x32([100 x i32]* %A.i)
450 call void @capture100x32([100 x i32]* %B.i)
454 %struct.Klass = type { i32, i32 }
456 define i32 @shady_range(i32 %argc, i8** nocapture %argv) safestack {
457 ; CHECK-LABEL: define i32 @shady_range(
459 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
460 ; CHECK-NEXT: getelementptr i8, i8* %[[USP]], i32 -64
461 %a.i = alloca [4 x %struct.Klass], align 16
462 %b.i = alloca [4 x %struct.Klass], align 16
463 %a8 = bitcast [4 x %struct.Klass]* %a.i to i8*
464 %b8 = bitcast [4 x %struct.Klass]* %b.i to i8*
465 ; I am used outside the lifetime zone below:
466 %z2 = getelementptr inbounds [4 x %struct.Klass], [4 x %struct.Klass]* %a.i, i64 0, i64 0, i32 0
467 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a8)
468 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %b8)
469 call void @capture8(i8* %a8)
470 call void @capture8(i8* %b8)
471 %z3 = load i32, i32* %z2, align 16
472 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %a8)
473 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %b8)
477 define void @end_loop() safestack {
478 ; CHECK-LABEL: define void @end_loop()
480 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
481 ; CHECK-NEXT: getelementptr i8, i8* %[[USP]], i32 -16
482 %x = alloca i8, align 4
483 call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) nounwind
487 call void @capture8(i8* %x)
488 call void @llvm.lifetime.end.p0i8(i64 4, i8* %x) nounwind
492 ; Check that @x and @y get distinct stack slots => @x lifetime does not break
493 ; when control re-enters l2.
494 define void @start_loop() safestack {
495 ; CHECK-LABEL: define void @start_loop()
497 ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
498 ; CHECK-NEXT: getelementptr i8, i8* %[[USP]], i32 -16
499 %x = alloca i8, align 4
500 %y = alloca i8, align 4
501 call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) nounwind
505 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -8
506 call void @llvm.lifetime.start.p0i8(i64 4, i8* %y) nounwind
507 call void @capture8(i8* %y)
508 call void @llvm.lifetime.end.p0i8(i64 4, i8* %y) nounwind
510 ; CHECK: getelementptr i8, i8* %[[USP]], i32 -4
511 call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) nounwind
512 call void @capture8(i8* %x)
516 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
517 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
518 declare void @capture8(i8*)
519 declare void @capture32(i32*)
520 declare void @capture64(i64*)
521 declare void @capture100x32([100 x i32]*)