1; RUN: llc < %s -verify-machineinstrs -stack-symbol-ordering=0 -mtriple="x86_64-pc-linux-gnu" | FileCheck %s 2; RUN: llc < %s -verify-machineinstrs -stack-symbol-ordering=0 -mtriple="x86_64-pc-unknown-elf" | FileCheck %s 3 4; This test is a sanity check to ensure statepoints are generating StackMap 5; sections correctly. This is not intended to be a rigorous test of the 6; StackMap format (see the stackmap tests for that). 7 8target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" 9 10declare zeroext i1 @return_i1() 11 12define i1 @test(i32 addrspace(1)* %ptr_base, i32 %arg) 13 gc "statepoint-example" { 14; CHECK-LABEL: test: 15; Do we see two spills for the local values and the store to the 16; alloca? 17; CHECK: subq $40, %rsp 18; CHECK: movq $0, 24(%rsp) 19; CHECK: movq %rdi, 16(%rsp) 20; CHECK: movq %rax, 8(%rsp) 21; CHECK: callq return_i1 22; CHECK: addq $40, %rsp 23; CHECK: retq 24entry: 25 %metadata1 = alloca i32 addrspace(1)*, i32 2, align 8 26 store i32 addrspace(1)* null, i32 addrspace(1)** %metadata1 27 %ptr_derived = getelementptr i32, i32 addrspace(1)* %ptr_base, i32 %arg 28 %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %ptr_base, i32 addrspace(1)* %ptr_derived, i32 addrspace(1)* null), "deopt" (i32 addrspace(1)* %ptr_base, i32 addrspace(1)* null)] 29 %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token) 30 %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 31 %b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 1) 32 %c = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 2, i32 2) 33; 34 ret i1 %call1 35} 36 37; This is similar to the previous test except that we have derived pointer as 38; argument to the function. Despite that this can not happen after the 39; RewriteSafepointForGC pass, lowering should be able to handle it anyway. 40define i1 @test_derived_arg(i32 addrspace(1)* %ptr_base, 41 i32 addrspace(1)* %ptr_derived) 42 gc "statepoint-example" { 43; CHECK-LABEL: test_derived_arg 44; Do we see two spills for the local values and the store to the 45; alloca? 46; CHECK: subq $40, %rsp 47; CHECK: movq $0, 24(%rsp) 48; CHECK: movq %rdi, 16(%rsp) 49; CHECK: movq %rsi, 8(%rsp) 50; CHECK: callq return_i1 51; CHECK: addq $40, %rsp 52; CHECK: retq 53entry: 54 %metadata1 = alloca i32 addrspace(1)*, i32 2, align 8 55 store i32 addrspace(1)* null, i32 addrspace(1)** %metadata1 56 %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %ptr_base, i32 addrspace(1)* %ptr_derived, i32 addrspace(1)* null), "deopt" (i32 addrspace(1)* %ptr_base, i32 addrspace(1)* null)] 57 %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token) 58 %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 59 %b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 1) 60 %c = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 2, i32 2) 61; 62 ret i1 %call1 63} 64 65; Simple test case to check that we emit the ID field correctly 66define i1 @test_id() gc "statepoint-example" { 67; CHECK-LABEL: test_id 68entry: 69 %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 237, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0) 70 %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token) 71 ret i1 %call1 72} 73 74; This test checks that when SP is changed in the function 75; (e.g. passing arguments on stack), the stack map entry 76; takes this adjustment into account. 77declare void @many_arg(i64, i64, i64, i64, i64, i64, i64, i64) 78 79define i32 @test_spadj(i32 addrspace(1)* %p) gc "statepoint-example" { 80 ; CHECK-LABEL: test_spadj 81 ; CHECK: movq %rdi, (%rsp) 82 ; CHECK: xorl %edi, %edi 83 ; CHECK: xorl %esi, %esi 84 ; CHECK: xorl %edx, %edx 85 ; CHECK: xorl %ecx, %ecx 86 ; CHECK: xorl %r8d, %r8d 87 ; CHECK: xorl %r9d, %r9d 88 ; CHECK: pushq $0 89 ; CHECK: pushq $0 90 ; CHECK: callq many_arg 91 ; CHECK: addq $16, %rsp 92 ; CHECK: movq (%rsp) 93 %statepoint_token = call token (i64, i32, void (i64, i64, i64, i64, i64, i64, i64, i64)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi64i64i64i64i64i64i64i64f(i64 0, i32 0, void (i64, i64, i64, i64, i64, i64, i64, i64)* @many_arg, i32 8, i32 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %p)] 94 %p.relocated = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %statepoint_token, i32 0, i32 0) ; (%p, %p) 95 %ld = load i32, i32 addrspace(1)* %p.relocated 96 ret i32 %ld 97} 98 99; Test that function arguments at fixed stack offset 100; can be directly encoded in the stack map, without 101; spilling. 102%struct = type { i64, i64, i64 } 103 104declare void @use(%struct*) 105 106define void @test_fixed_arg(%struct* byval(%struct) %x) gc "statepoint-example" { 107; CHECK-LABEL: test_fixed_arg 108; CHECK: pushq %rax 109; CHECK: leaq 16(%rsp), %rdi 110; Should not spill fixed stack address. 111; CHECK-NOT: movq %rdi, (%rsp) 112; CHECK: callq use 113; CHECK: popq %rax 114; CHECK: retq 115entry: 116 br label %bb 117 118bb: ; preds = %entry 119 %statepoint_token = call token (i64, i32, void (%struct*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp0s_structsf(i64 0, i32 0, void (%struct*)* @use, i32 1, i32 0, %struct* %x, i32 0, i32 0) ["deopt" (%struct* %x)] 120 ret void 121} 122 123declare token @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...) 124declare token @llvm.experimental.gc.statepoint.p0f_isVoidi64i64i64i64i64i64i64i64f(i64, i32, void (i64, i64, i64, i64, i64, i64, i64, i64)*, i32, i32, ...) 125declare token @llvm.experimental.gc.statepoint.p0f_isVoidp0s_structsf(i64, i32, void (%struct*)*, i32, i32, ...) 126declare i1 @llvm.experimental.gc.result.i1(token) 127declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) #3 128 129; CHECK-LABEL: .section .llvm_stackmaps 130; CHECK-NEXT: __LLVM_StackMaps: 131; Header 132; CHECK-NEXT: .byte 3 133; CHECK-NEXT: .byte 0 134; CHECK-NEXT: .short 0 135; Num Functions 136; CHECK-NEXT: .long 5 137; Num LargeConstants 138; CHECK-NEXT: .long 0 139; Num Callsites 140; CHECK-NEXT: .long 5 141 142; Functions and stack size 143; CHECK-NEXT: .quad test 144; CHECK-NEXT: .quad 40 145; CHECK-NEXT: .quad 1 146; CHECK-NEXT: .quad test_derived_arg 147; CHECK-NEXT: .quad 40 148; CHECK-NEXT: .quad 1 149; CHECK-NEXT: .quad test_id 150; CHECK-NEXT: .quad 8 151; CHECK-NEXT: .quad 1 152; CHECK-NEXT: .quad test_spadj 153; CHECK-NEXT: .quad 8 154; CHECK-NEXT: .quad 1 155; CHECK-NEXT: .quad test_fixed_arg 156; CHECK-NEXT: .quad 8 157; CHECK-NEXT: .quad 1 158 159; 160; test 161; 162 163; Statepoint ID 164; CHECK-NEXT: .quad 0 165 166; Callsites 167; Constant arguments 168; CHECK-NEXT: .long .Ltmp0-test 169; CHECK: .short 0 170; CHECK: .short 11 171; SmallConstant (0) 172; CHECK: .byte 4 173; CHECK-NEXT: .byte 0 174; CHECK: .short 8 175; CHECK: .short 0 176; CHECK-NEXT: .short 0 177; CHECK: .long 0 178; SmallConstant (0) 179; CHECK: .byte 4 180; CHECK-NEXT: .byte 0 181; CHECK: .short 8 182; CHECK: .short 0 183; CHECK-NEXT: .short 0 184; CHECK: .long 0 185; SmallConstant (2) 186; CHECK: .byte 4 187; CHECK-NEXT: .byte 0 188; CHECK: .short 8 189; CHECK: .short 0 190; CHECK-NEXT: .short 0 191; CHECK: .long 2 192; Indirect Spill Slot [RSP+0] 193; CHECK: .byte 3 194; CHECK-NEXT: .byte 0 195; CHECK: .short 8 196; CHECK: .short 7 197; CHECK-NEXT: .short 0 198; CHECK: .long 16 199; SmallConstant (0) 200; CHECK: .byte 4 201; CHECK-NEXT: .byte 0 202; CHECK: .short 8 203; CHECK: .short 0 204; CHECK-NEXT: .short 0 205; CHECK: .long 0 206; SmallConstant (0) 207; CHECK: .byte 4 208; CHECK-NEXT: .byte 0 209; CHECK: .short 8 210; CHECK: .short 0 211; CHECK-NEXT: .short 0 212; CHECK: .long 0 213; SmallConstant (0) 214; CHECK: .byte 4 215; CHECK-NEXT: .byte 0 216; CHECK: .short 8 217; CHECK: .short 0 218; CHECK-NEXT: .short 0 219; CHECK: .long 0 220; Indirect Spill Slot [RSP+16] 221; CHECK: .byte 3 222; CHECK-NEXT: .byte 0 223; CHECK: .short 8 224; CHECK: .short 7 225; CHECK-NEXT: .short 0 226; CHECK: .long 16 227; Indirect Spill Slot [RSP+8] 228; CHECK: .byte 3 229; CHECK-NEXT: .byte 0 230; CHECK: .short 8 231; CHECK: .short 7 232; CHECK-NEXT: .short 0 233; CHECK: .long 8 234; Indirect Spill Slot [RSP+16] 235; CHECK: .byte 3 236; CHECK-NEXT: .byte 0 237; CHECK: .short 8 238; CHECK: .short 7 239; CHECK-NEXT: .short 0 240; CHECK: .long 16 241; Indirect Spill Slot [RSP+16] 242; CHECK: .byte 3 243; CHECK-NEXT: .byte 0 244; CHECK: .short 8 245; CHECK: .short 7 246; CHECK-NEXT: .short 0 247; CHECK: .long 16 248 249; No Padding or LiveOuts 250; CHECK: .short 0 251; CHECK: .short 0 252; CHECK: .p2align 3 253 254; 255; test_derived_arg 256 257; Statepoint ID 258; CHECK-NEXT: .quad 0 259 260; Callsites 261; Constant arguments 262; CHECK-NEXT: .long .Ltmp1-test_derived_arg 263; CHECK: .short 0 264; CHECK: .short 11 265; SmallConstant (0) 266; CHECK: .byte 4 267; CHECK-NEXT: .byte 0 268; CHECK: .short 8 269; CHECK: .short 0 270; CHECK-NEXT: .short 0 271; CHECK: .long 0 272; SmallConstant (2) 273; CHECK: .byte 4 274; CHECK-NEXT: .byte 0 275; CHECK: .short 8 276; CHECK: .short 0 277; CHECK-NEXT: .short 0 278; CHECK: .long 2 279; Indirect Spill Slot [RSP+0] 280; CHECK: .byte 3 281; CHECK-NEXT: .byte 0 282; CHECK: .short 8 283; CHECK: .short 7 284; CHECK-NEXT: .short 0 285; CHECK: .long 16 286; SmallConstant (0) 287; CHECK: .byte 4 288; CHECK-NEXT: .byte 0 289; CHECK: .short 8 290; CHECK: .short 0 291; CHECK-NEXT: .short 0 292; CHECK: .long 0 293; SmallConstant (0) 294; CHECK: .byte 4 295; CHECK-NEXT: .byte 0 296; CHECK: .short 8 297; CHECK: .short 0 298; CHECK-NEXT: .short 0 299; CHECK: .long 0 300; SmallConstant (0) 301; CHECK: .byte 4 302; CHECK-NEXT: .byte 0 303; CHECK: .short 8 304; CHECK: .short 0 305; CHECK-NEXT: .short 0 306; CHECK: .long 0 307; Indirect Spill Slot [RSP+16] 308; CHECK: .byte 3 309; CHECK-NEXT: .byte 0 310; CHECK: .short 8 311; CHECK: .short 7 312; CHECK-NEXT: .short 0 313; CHECK: .long 16 314; Indirect Spill Slot [RSP+8] 315; CHECK: .byte 3 316; CHECK-NEXT: .byte 0 317; CHECK: .short 8 318; CHECK: .short 7 319; CHECK-NEXT: .short 0 320; CHECK: .long 8 321; Indirect Spill Slot [RSP+16] 322; CHECK: .byte 3 323; CHECK-NEXT: .byte 0 324; CHECK: .short 8 325; CHECK: .short 7 326; CHECK-NEXT: .short 0 327; CHECK: .long 16 328; Indirect Spill Slot [RSP+16] 329; CHECK: .byte 3 330; CHECK-NEXT: .byte 0 331; CHECK: .short 8 332; CHECK: .short 7 333; CHECK-NEXT: .short 0 334; CHECK: .long 16 335 336; No Padding or LiveOuts 337; CHECK: .short 0 338; CHECK: .short 0 339; CHECK: .p2align 3 340 341; Records for the test_id function: 342 343; The Statepoint ID: 344; CHECK-NEXT: .quad 237 345 346; Instruction Offset 347; CHECK-NEXT: .long .Ltmp2-test_id 348 349; Reserved: 350; CHECK: .short 0 351 352; NumLocations: 353; CHECK: .short 3 354 355; StkMapRecord[0]: 356; SmallConstant(0): 357; CHECK: .byte 4 358; CHECK-NEXT: .byte 0 359; CHECK: .short 8 360; CHECK: .short 0 361; CHECK-NEXT: .short 0 362; CHECK: .long 0 363 364; StkMapRecord[1]: 365; SmallConstant(0): 366; CHECK: .byte 4 367; CHECK-NEXT: .byte 0 368; CHECK: .short 8 369; CHECK: .short 0 370; CHECK-NEXT: .short 0 371; CHECK: .long 0 372 373; StkMapRecord[2]: 374; SmallConstant(0): 375; CHECK: .byte 4 376; CHECK-NEXT: .byte 0 377; CHECK: .short 8 378; CHECK: .short 0 379; CHECK-NEXT: .short 0 380; CHECK: .long 0 381 382; No padding or LiveOuts 383; CHECK: .short 0 384; CHECK: .short 0 385; CHECK: .p2align 3 386 387; 388; test_spadj 389 390; Statepoint ID 391; CHECK-NEXT: .quad 0 392 393; Instruction Offset 394; CHECK-NEXT: .long .Ltmp3-test_spadj 395 396; Reserved: 397; CHECK: .short 0 398 399; NumLocations: 400; CHECK: .short 5 401 402; StkMapRecord[0]: 403; SmallConstant(0): 404; CHECK: .byte 4 405; CHECK-NEXT: .byte 0 406; CHECK: .short 8 407; CHECK: .short 0 408; CHECK-NEXT: .short 0 409; CHECK: .long 0 410 411; StkMapRecord[1]: 412; SmallConstant(0): 413; CHECK: .byte 4 414; CHECK-NEXT: .byte 0 415; CHECK: .short 8 416; CHECK: .short 0 417; CHECK-NEXT: .short 0 418; CHECK: .long 0 419 420; StkMapRecord[2]: 421; SmallConstant(0): 422; CHECK: .byte 4 423; CHECK-NEXT: .byte 0 424; CHECK: .short 8 425; CHECK: .short 0 426; CHECK-NEXT: .short 0 427; CHECK: .long 0 428 429; StkMapRecord[3]: 430; Indirect Spill Slot [RSP+16] 431; CHECK: .byte 3 432; CHECK-NEXT: .byte 0 433; CHECK: .short 8 434; CHECK: .short 7 435; CHECK-NEXT: .short 0 436; CHECK: .long 16 437 438; StkMapRecord[4]: 439; Indirect Spill Slot [RSP+16] 440; CHECK: .byte 3 441; CHECK-NEXT: .byte 0 442; CHECK: .short 8 443; CHECK: .short 7 444; CHECK-NEXT: .short 0 445; CHECK: .long 16 446 447; No padding or LiveOuts 448; CHECK: .short 0 449; CHECK: .short 0 450; CHECK: .p2align 3 451 452; 453; test_fixed_arg 454 455; Statepoint ID 456; CHECK-NEXT: .quad 0 457 458; Instruction Offset 459; CHECK-NEXT: .long .Ltmp4-test_fixed_arg 460 461; Reserved: 462; CHECK: .short 0 463 464; NumLocations: 465; CHECK: .short 4 466 467; StkMapRecord[0]: 468; SmallConstant(0): 469; CHECK: .byte 4 470; CHECK-NEXT: .byte 0 471; CHECK: .short 8 472; CHECK: .short 0 473; CHECK-NEXT: .short 0 474; CHECK: .long 0 475 476; StkMapRecord[1]: 477; SmallConstant(0): 478; CHECK: .byte 4 479; CHECK-NEXT: .byte 0 480; CHECK: .short 8 481; CHECK: .short 0 482; CHECK-NEXT: .short 0 483; CHECK: .long 0 484 485; StkMapRecord[2]: 486; SmallConstant(1): 487; CHECK: .byte 4 488; CHECK-NEXT: .byte 0 489; CHECK: .short 8 490; CHECK: .short 0 491; CHECK-NEXT: .short 0 492; CHECK: .long 1 493 494; StkMapRecord[3]: 495; Direct RSP+16 496; CHECK: .byte 2 497; CHECK-NEXT: .byte 0 498; CHECK: .short 8 499; CHECK: .short 7 500; CHECK-NEXT: .short 0 501; CHECK: .long 16 502 503; No padding or LiveOuts 504; CHECK: .short 0 505; CHECK: .short 0 506; CHECK: .p2align 3 507