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 3; RUN: opt -passes=safe-stack -safe-stack-coloring=1 -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s 4; RUN: opt -passes=safe-stack -safe-stack-coloring=1 -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s 5 6; x and y share the stack slot. 7define void @f() safestack { 8; CHECK-LABEL: define void @f 9entry: 10; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 11; CHECK: getelementptr i8, ptr %[[USP]], i32 -16 12 13 %x = alloca i32, align 4 14 %y = alloca i32, align 4 15 %z = alloca i32, align 4 16 17 call void @llvm.lifetime.start.p0(i64 -1, ptr %z) 18 call void @llvm.lifetime.start.p0(i64 -1, ptr %x) 19 20; CHECK: getelementptr i8, ptr %[[USP]], i32 -4 21 call void @capture32(ptr %x) 22 call void @llvm.lifetime.end.p0(i64 -1, ptr %x) 23 call void @llvm.lifetime.start.p0(i64 -1, ptr %y) 24 25; CHECK: getelementptr i8, ptr %[[USP]], i32 -4 26 call void @capture32(ptr %y) 27 call void @llvm.lifetime.end.p0(i64 -1, ptr %y) 28 29; CHECK: getelementptr i8, ptr %[[USP]], i32 -8 30 call void @capture32(ptr %z) 31 call void @llvm.lifetime.end.p0(i64 -1, ptr %z) 32 33 ret void 34} 35 36define void @no_markers() safestack { 37; CHECK-LABEL: define void @no_markers( 38entry: 39; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 40; CHECK: getelementptr i8, ptr %[[USP]], i32 -16 41 42 %x = alloca i32, align 4 43 %y = alloca i32, align 4 44 45 call void @llvm.lifetime.start.p0(i64 -1, ptr %x) 46 47; CHECK: getelementptr i8, ptr %[[USP]], i32 -4 48 call void @capture32(ptr %x) 49 call void @llvm.lifetime.end.p0(i64 -1, ptr %x) 50 51; CHECK: getelementptr i8, ptr %[[USP]], i32 -8 52 call void @capture32(ptr %y) 53 54 ret void 55} 56 57; x and y can't share memory, but they can split z's storage. 58define void @g() safestack { 59; CHECK-LABEL: define void @g 60entry: 61; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 62; CHECK: getelementptr i8, ptr %[[USP]], i32 -16 63 64 %x = alloca i32, align 4 65 %y = alloca i32, align 4 66 %z = alloca i64, align 4 67 68 call void @llvm.lifetime.start.p0(i64 -1, ptr %x) 69 call void @llvm.lifetime.start.p0(i64 -1, ptr %y) 70 71; CHECK: getelementptr i8, ptr %[[USP]], i32 -4 72 call void @capture32(ptr %x) 73 call void @llvm.lifetime.end.p0(i64 -1, ptr %x) 74 75; CHECK: getelementptr i8, ptr %[[USP]], i32 -8 76 call void @capture32(ptr %y) 77 call void @llvm.lifetime.end.p0(i64 -1, ptr %y) 78 call void @llvm.lifetime.start.p0(i64 -1, ptr %z) 79 80; CHECK: getelementptr i8, ptr %[[USP]], i32 -8 81 call void @capture64(ptr %z) 82 call void @llvm.lifetime.end.p0(i64 -1, ptr %z) 83 84 ret void 85} 86 87; Both y and z fit in x's alignment gap. 88define void @h() safestack { 89; CHECK-LABEL: define void @h 90entry: 91; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 92; CHECK: getelementptr i8, ptr %[[USP]], i32 -16 93 94 %x = alloca i32, align 16 95 %z = alloca i64, align 4 96 %y = alloca i32, align 4 97 98 call void @llvm.lifetime.start.p0(i64 -1, ptr %x) 99 call void @llvm.lifetime.start.p0(i64 -1, ptr %y) 100 call void @llvm.lifetime.start.p0(i64 -1, ptr %z) 101 102; CHECK: getelementptr i8, ptr %[[USP]], i32 -16 103 call void @capture32(ptr %x) 104 105; CHECK: getelementptr i8, ptr %[[USP]], i32 -12 106 call void @capture32(ptr %y) 107 108; CHECK: getelementptr i8, ptr %[[USP]], i32 -8 109 call void @capture64(ptr %z) 110 111 call void @llvm.lifetime.end.p0(i64 -1, ptr %x) 112 call void @llvm.lifetime.end.p0(i64 -1, ptr %y) 113 call void @llvm.lifetime.end.p0(i64 -1, ptr %z) 114 115 ret void 116} 117 118; void f(bool a, bool b) { 119; long x1, x2; capture64(&x1); capture64(&x2); 120; if (a) { 121; long y; capture64(&y); 122; if (b) { 123; long y1; capture64(&y1); 124; } else { 125; long y2; capture64(&y2); 126; } 127; } else { 128; long z; capture64(&z); 129; if (b) { 130; long z1; capture64(&z1); 131; } else { 132; long z2; capture64(&z2); 133; } 134; } 135; } 136; Everything fits in 4 x 64-bit slots. 137define void @i(i1 zeroext %a, i1 zeroext %b) safestack { 138; CHECK-LABEL: define void @i 139entry: 140; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 141; CHECK-NEXT: getelementptr i8, ptr %[[USP]], i32 -32 142 %x1 = alloca i64, align 8 143 %x2 = alloca i64, align 8 144 %y = alloca i64, align 8 145 %y1 = alloca i64, align 8 146 %y2 = alloca i64, align 8 147 %z = alloca i64, align 8 148 %z1 = alloca i64, align 8 149 %z2 = alloca i64, align 8 150 call void @llvm.lifetime.start.p0(i64 -1, ptr %x1) 151 call void @llvm.lifetime.start.p0(i64 -1, ptr %x2) 152; CHECK: getelementptr i8, ptr %[[USP]], i32 -8 153; CHECK: call void @capture64( 154 call void @capture64(ptr nonnull %x1) 155; CHECK: getelementptr i8, ptr %[[USP]], i32 -16 156; CHECK: call void @capture64( 157 call void @capture64(ptr nonnull %x2) 158 br i1 %a, label %if.then, label %if.else4 159 160if.then: ; preds = %entry 161 call void @llvm.lifetime.start.p0(i64 -1, ptr %y) 162; CHECK: getelementptr i8, ptr %[[USP]], i32 -24 163; CHECK: call void @capture64( 164 call void @capture64(ptr nonnull %y) 165 br i1 %b, label %if.then3, label %if.else 166 167if.then3: ; preds = %if.then 168 call void @llvm.lifetime.start.p0(i64 -1, ptr %y1) 169; CHECK: getelementptr i8, ptr %[[USP]], i32 -32 170; CHECK: call void @capture64( 171 call void @capture64(ptr nonnull %y1) 172 call void @llvm.lifetime.end.p0(i64 -1, ptr %y1) 173 br label %if.end 174 175if.else: ; preds = %if.then 176 call void @llvm.lifetime.start.p0(i64 -1, ptr %y2) 177; CHECK: getelementptr i8, ptr %[[USP]], i32 -32 178; CHECK: call void @capture64( 179 call void @capture64(ptr nonnull %y2) 180 call void @llvm.lifetime.end.p0(i64 -1, ptr %y2) 181 br label %if.end 182 183if.end: ; preds = %if.else, %if.then3 184 call void @llvm.lifetime.end.p0(i64 -1, ptr %y) 185 br label %if.end9 186 187if.else4: ; preds = %entry 188 call void @llvm.lifetime.start.p0(i64 -1, ptr %z) 189; CHECK: getelementptr i8, ptr %[[USP]], i32 -24 190; CHECK: call void @capture64( 191 call void @capture64(ptr nonnull %z) 192 br i1 %b, label %if.then6, label %if.else7 193 194if.then6: ; preds = %if.else4 195 call void @llvm.lifetime.start.p0(i64 -1, ptr %z1) 196; CHECK: getelementptr i8, ptr %[[USP]], i32 -32 197; CHECK: call void @capture64( 198 call void @capture64(ptr nonnull %z1) 199 call void @llvm.lifetime.end.p0(i64 -1, ptr %z1) 200 br label %if.end8 201 202if.else7: ; preds = %if.else4 203 call void @llvm.lifetime.start.p0(i64 -1, ptr %z2) 204; CHECK: getelementptr i8, ptr %[[USP]], i32 -32 205; CHECK: call void @capture64( 206 call void @capture64(ptr nonnull %z2) 207 call void @llvm.lifetime.end.p0(i64 -1, ptr %z2) 208 br label %if.end8 209 210if.end8: ; preds = %if.else7, %if.then6 211 call void @llvm.lifetime.end.p0(i64 -1, ptr %z) 212 br label %if.end9 213 214if.end9: ; preds = %if.end8, %if.end 215 call void @llvm.lifetime.end.p0(i64 -1, ptr %x2) 216 call void @llvm.lifetime.end.p0(i64 -1, ptr %x1) 217 ret void 218} 219 220; lifetime for x ends in 2 different BBs 221define void @no_merge1(i1 %d) safestack { 222; CHECK-LABEL: define void @no_merge1( 223entry: 224; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 225; CHECK-NEXT: getelementptr i8, ptr %[[USP]], i32 -16 226 %x = alloca i32, align 4 227 %y = alloca i32, align 4 228 call void @llvm.lifetime.start.p0(i64 -1, ptr %x) 229; CHECK: getelementptr i8, ptr %[[USP]], i32 -4 230; CHECK: call void @capture32( 231 call void @capture32(ptr %x) 232 br i1 %d, label %bb2, label %bb3 233bb2: 234 call void @llvm.lifetime.start.p0(i64 -1, ptr %y) 235; CHECK: getelementptr i8, ptr %[[USP]], i32 -8 236; CHECK: call void @capture32( 237 call void @capture32(ptr %y) 238 call void @llvm.lifetime.end.p0(i64 -1, ptr %y) 239 call void @llvm.lifetime.end.p0(i64 -1, ptr %x) 240 ret void 241bb3: 242 call void @llvm.lifetime.end.p0(i64 -1, ptr %x) 243 ret void 244} 245 246define void @merge1(i1 %d) safestack { 247; CHECK-LABEL: define void @merge1( 248entry: 249; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 250; CHECK-NEXT: getelementptr i8, ptr %[[USP]], i32 -16 251 %x = alloca i32, align 4 252 %y = alloca i32, align 4 253 call void @llvm.lifetime.start.p0(i64 -1, ptr %x) 254; CHECK: getelementptr i8, ptr %[[USP]], i32 -4 255; CHECK: call void @capture32( 256 call void @capture32(ptr %x) 257 call void @llvm.lifetime.end.p0(i64 -1, ptr %x) 258 br i1 %d, label %bb2, label %bb3 259bb2: 260 call void @llvm.lifetime.start.p0(i64 -1, ptr %y) 261; CHECK: getelementptr i8, ptr %[[USP]], i32 -4 262; CHECK: call void @capture32( 263 call void @capture32(ptr %y) 264 call void @llvm.lifetime.end.p0(i64 -1, ptr %y) 265 ret void 266bb3: 267 ret void 268} 269 270; Missing lifetime.end 271define void @merge2_noend(i1 %d) safestack { 272; CHECK-LABEL: define void @merge2_noend( 273entry: 274; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 275; CHECK-NEXT: getelementptr i8, ptr %[[USP]], i32 -16 276 %x = alloca i32, align 4 277 %y = alloca i32, align 4 278 call void @llvm.lifetime.start.p0(i64 -1, ptr %x) 279; CHECK: getelementptr i8, ptr %[[USP]], i32 -4 280; CHECK: call void @capture32( 281 call void @capture32(ptr %x) 282 call void @llvm.lifetime.end.p0(i64 -1, ptr %x) 283 br i1 %d, label %bb2, label %bb3 284bb2: 285 call void @llvm.lifetime.start.p0(i64 -1, ptr %y) 286; CHECK: getelementptr i8, ptr %[[USP]], i32 -4 287; CHECK: call void @capture32( 288 call void @capture32(ptr %y) 289 ret void 290bb3: 291 ret void 292} 293 294; Missing lifetime.end 295define void @merge3_noend(i1 %d) safestack { 296; CHECK-LABEL: define void @merge3_noend( 297entry: 298; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 299; CHECK-NEXT: getelementptr i8, ptr %[[USP]], i32 -16 300 %x = alloca i32, align 4 301 %y = alloca i32, align 4 302 call void @llvm.lifetime.start.p0(i64 -1, ptr %x) 303; CHECK: getelementptr i8, ptr %[[USP]], i32 -4 304; CHECK: call void @capture32( 305 call void @capture32(ptr %x) 306 br i1 %d, label %bb2, label %bb3 307bb2: 308 call void @llvm.lifetime.end.p0(i64 -1, ptr %x) 309 call void @llvm.lifetime.start.p0(i64 -1, ptr %y) 310; CHECK: getelementptr i8, ptr %[[USP]], i32 -4 311; CHECK: call void @capture32( 312 call void @capture32(ptr %y) 313 ret void 314bb3: 315 ret void 316} 317 318; Missing lifetime.start 319define void @nomerge4_nostart(i1 %d) safestack { 320; CHECK-LABEL: define void @nomerge4_nostart( 321entry: 322; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 323; CHECK-NEXT: getelementptr i8, ptr %[[USP]], i32 -16 324 %x = alloca i32, align 4 325 %y = alloca i32, align 4 326; CHECK: getelementptr i8, ptr %[[USP]], i32 -4 327; CHECK: call void @capture32( 328 call void @capture32(ptr %x) 329 call void @llvm.lifetime.end.p0(i64 -1, ptr %x) 330 br i1 %d, label %bb2, label %bb3 331bb2: 332 call void @llvm.lifetime.start.p0(i64 -1, ptr %y) 333; CHECK: getelementptr i8, ptr %[[USP]], i32 -8 334; CHECK: call void @capture32( 335 call void @capture32(ptr %y) 336 ret void 337bb3: 338 ret void 339} 340 341define void @array_merge() safestack { 342; CHECK-LABEL: define void @array_merge( 343entry: 344; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 345; CHECK-NEXT: getelementptr i8, ptr %[[USP]], i32 -800 346 %A.i1 = alloca [100 x i32], align 4 347 %B.i2 = alloca [100 x i32], align 4 348 %A.i = alloca [100 x i32], align 4 349 %B.i = alloca [100 x i32], align 4 350 call void @llvm.lifetime.start.p0(i64 -1, ptr %A.i) 351 call void @llvm.lifetime.start.p0(i64 -1, ptr %B.i) 352; CHECK: getelementptr i8, ptr %[[USP]], i32 -400 353; CHECK: call void @capture100x32( 354 call void @capture100x32(ptr %A.i) 355; CHECK: getelementptr i8, ptr %[[USP]], i32 -800 356; CHECK: call void @capture100x32( 357 call void @capture100x32(ptr %B.i) 358 call void @llvm.lifetime.end.p0(i64 -1, ptr %A.i) 359 call void @llvm.lifetime.end.p0(i64 -1, ptr %B.i) 360 call void @llvm.lifetime.start.p0(i64 -1, ptr %A.i1) 361 call void @llvm.lifetime.start.p0(i64 -1, ptr %B.i2) 362; CHECK: getelementptr i8, ptr %[[USP]], i32 -400 363; CHECK: call void @capture100x32( 364 call void @capture100x32(ptr %A.i1) 365; CHECK: getelementptr i8, ptr %[[USP]], i32 -800 366; CHECK: call void @capture100x32( 367 call void @capture100x32(ptr %B.i2) 368 call void @llvm.lifetime.end.p0(i64 -1, ptr %A.i1) 369 call void @llvm.lifetime.end.p0(i64 -1, ptr %B.i2) 370 ret void 371} 372 373define void @myCall_pr15707() safestack { 374; CHECK-LABEL: define void @myCall_pr15707( 375entry: 376; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 377; CHECK-NEXT: getelementptr i8, ptr %[[USP]], i32 -200000 378 %buf1 = alloca i8, i32 100000, align 16 379 %buf2 = alloca i8, i32 100000, align 16 380 381 call void @llvm.lifetime.start.p0(i64 -1, ptr %buf1) 382 call void @llvm.lifetime.end.p0(i64 -1, ptr %buf1) 383 384 call void @llvm.lifetime.start.p0(i64 -1, ptr %buf1) 385 call void @llvm.lifetime.start.p0(i64 -1, ptr %buf2) 386 call void @capture8(ptr %buf1) 387 call void @capture8(ptr %buf2) 388 ret void 389} 390 391; Check that we don't assert and crash even when there are allocas 392; outside the declared lifetime regions. 393define void @bad_range() safestack { 394; CHECK-LABEL: define void @bad_range( 395entry: 396; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 397; A.i and B.i unsafe, not merged 398; CHECK-NEXT: getelementptr i8, ptr %[[USP]], i32 -800 399; A.i1 and B.i2 safe 400; CHECK: = alloca [100 x i32], align 4 401; CHECK: = alloca [100 x i32], align 4 402 403 %A.i1 = alloca [100 x i32], align 4 404 %B.i2 = alloca [100 x i32], align 4 405 %A.i = alloca [100 x i32], align 4 406 %B.i = alloca [100 x i32], align 4 407 call void @llvm.lifetime.start.p0(i64 -1, ptr %A.i) nounwind 408 call void @llvm.lifetime.start.p0(i64 -1, ptr %B.i) nounwind 409 call void @capture100x32(ptr %A.i) 410 call void @capture100x32(ptr %B.i) 411 call void @llvm.lifetime.end.p0(i64 -1, ptr %A.i) nounwind 412 call void @llvm.lifetime.end.p0(i64 -1, ptr %B.i) nounwind 413 br label %block2 414 415block2: 416 ; I am used outside the marked lifetime. 417 call void @capture100x32(ptr %A.i) 418 call void @capture100x32(ptr %B.i) 419 ret void 420} 421 422%struct.Klass = type { i32, i32 } 423 424define i32 @shady_range(i32 %argc, ptr nocapture %argv) safestack { 425; CHECK-LABEL: define i32 @shady_range( 426entry: 427; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 428; CHECK-NEXT: getelementptr i8, ptr %[[USP]], i32 -64 429 %a.i = alloca [4 x %struct.Klass], align 16 430 %b.i = alloca [4 x %struct.Klass], align 16 431 ; I am used outside the lifetime zone below: 432 call void @llvm.lifetime.start.p0(i64 -1, ptr %a.i) 433 call void @llvm.lifetime.start.p0(i64 -1, ptr %b.i) 434 call void @capture8(ptr %a.i) 435 call void @capture8(ptr %b.i) 436 %z3 = load i32, ptr %a.i, align 16 437 call void @llvm.lifetime.end.p0(i64 -1, ptr %a.i) 438 call void @llvm.lifetime.end.p0(i64 -1, ptr %b.i) 439 ret i32 %z3 440} 441 442define void @end_loop() safestack { 443; CHECK-LABEL: define void @end_loop() 444entry: 445; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 446; CHECK-NEXT: getelementptr i8, ptr %[[USP]], i32 -16 447 %x = alloca i8, align 4 448 call void @llvm.lifetime.start.p0(i64 4, ptr %x) nounwind 449 br label %l2 450 451l2: 452 call void @capture8(ptr %x) 453 call void @llvm.lifetime.end.p0(i64 4, ptr %x) nounwind 454 br label %l2 455} 456 457; Check that @x and @y get distinct stack slots => @x lifetime does not break 458; when control re-enters l2. 459define void @start_loop() safestack { 460; CHECK-LABEL: define void @start_loop() 461entry: 462; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 463; CHECK-NEXT: getelementptr i8, ptr %[[USP]], i32 -16 464 %x = alloca i8, align 4 465 %y = alloca i8, align 4 466 call void @llvm.lifetime.start.p0(i64 4, ptr %x) nounwind 467 br label %l2 468 469l2: 470; CHECK: getelementptr i8, ptr %[[USP]], i32 -8 471 call void @llvm.lifetime.start.p0(i64 4, ptr %y) nounwind 472 call void @capture8(ptr %y) 473 call void @llvm.lifetime.end.p0(i64 4, ptr %y) nounwind 474 475; CHECK: getelementptr i8, ptr %[[USP]], i32 -4 476 call void @llvm.lifetime.start.p0(i64 4, ptr %x) nounwind 477 call void @capture8(ptr %x) 478 br label %l2 479} 480 481; This test checks for a bug where the stack coloring algorithm was not tracking 482; the live range of allocas through phi instructions, so it did not consider 483; alloca and alloca2 to be live at the same time. As a result it was using 484; the same stack slot for both allocas. To ensure this bug isn't present, we 485; check that there are 64 bytes allocated for the unsafe stack which is enough 486; space for both allocas. 487; CHECK-LABEL: @stack_coloring_liveness_bug 488define void @stack_coloring_liveness_bug(i32 %arg0) #0 { 489entry: 490; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr 491; CHECK-NEXT: getelementptr i8, ptr %[[USP]], i32 -64 492 %alloca = alloca [32 x i8], align 16 493 %alloca2 = alloca [32 x i8], align 16 494 %cond = icmp eq i32 %arg0, 0 495 br i1 %cond, label %if, label %else 496 497if: 498 br label %end 499 500else: 501; CHECK: getelementptr i8, ptr %[[USP]], i32 -32 502 call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %alloca) 503 call void @capture8(ptr %alloca) 504 call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %alloca) 505 br label %end 506 507end: 508; CHECK: getelementptr i8, ptr %[[USP]], i32 -64 509 %alloca.end = phi ptr [ %alloca, %if], [%alloca, %else] 510 call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %alloca2) 511 call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %alloca.end) 512 call void @capture2_8(ptr %alloca2, ptr %alloca.end) 513 call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %alloca2) 514 call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %alloca.end) 515 ret void 516} 517 518attributes #0 = { safestack } 519 520declare void @llvm.lifetime.start.p0(i64, ptr nocapture) 521declare void @llvm.lifetime.end.p0(i64, ptr nocapture) 522declare void @capture8(ptr) 523declare void @capture32(ptr) 524declare void @capture64(ptr) 525declare void @capture100x32(ptr) 526declare void @capture2_8(ptr, ptr) 527