1; RUN: llc -mtriple=arm64-apple-darwin -mattr=+reserve-x18 < %s | FileCheck %s 2; RUN: llc -mtriple=arm64-apple-darwin -mattr=+reserve-x18 -fast-isel -fast-isel-abort=1 < %s | FileCheck %s 3; 4; Note: Print verbose stackmaps using -debug-only=stackmaps. 5 6; We are not getting the correct stack alignment when cross compiling for arm64. 7; So specify a datalayout here. 8target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 9 10; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps 11; CHECK-NEXT: __LLVM_StackMaps: 12; Header 13; CHECK-NEXT: .byte 3 14; CHECK-NEXT: .byte 0 15; CHECK-NEXT: .short 0 16; Num Functions 17; CHECK-NEXT: .long 11 18; Num LargeConstants 19; CHECK-NEXT: .long 3 20; Num Callsites 21; CHECK-NEXT: .long 11 22 23; Functions and stack size 24; CHECK-NEXT: .quad _constantargs 25; CHECK-NEXT: .quad 16 26; CHECK-NEXT: .quad 1 27; CHECK-NEXT: .quad _osrinline 28; CHECK-NEXT: .quad 32 29; CHECK-NEXT: .quad 1 30; CHECK-NEXT: .quad _osrcold 31; CHECK-NEXT: .quad 16 32; CHECK-NEXT: .quad 1 33; CHECK-NEXT: .quad _propertyRead 34; CHECK-NEXT: .quad 16 35; CHECK-NEXT: .quad 1 36; CHECK-NEXT: .quad _propertyWrite 37; CHECK-NEXT: .quad 16 38; CHECK-NEXT: .quad 1 39; CHECK-NEXT: .quad _jsVoidCall 40; CHECK-NEXT: .quad 16 41; CHECK-NEXT: .quad 1 42; CHECK-NEXT: .quad _jsIntCall 43; CHECK-NEXT: .quad 16 44; CHECK-NEXT: .quad 1 45; CHECK-NEXT: .quad _spilledValue 46; CHECK-NEXT: .quad 160 47; CHECK-NEXT: .quad 1 48; CHECK-NEXT: .quad _liveConstant 49; CHECK-NEXT: .quad 16 50; CHECK-NEXT: .quad 1 51; CHECK-NEXT: .quad _clobberLR 52; CHECK-NEXT: .quad 112 53; CHECK-NEXT: .quad 1 54; CHECK-NEXT: .quad _floats 55; CHECK-NEXT: .quad 32 56; CHECK-NEXT: .quad 1 57 58; Num LargeConstants 59; CHECK-NEXT: .quad 4294967295 60; CHECK-NEXT: .quad 4294967296 61; CHECK-NEXT: .quad 4294967297 62 63; Constant arguments 64; 65; CHECK-NEXT: .quad 1 66; CHECK-NEXT: .long L{{.*}}-_constantargs 67; CHECK-NEXT: .short 0 68; CHECK-NEXT: .short 6 69; SmallConstant 70; CHECK-NEXT: .byte 4 71; CHECK-NEXT: .byte 0 72; CHECK-NEXT: .short 8 73; CHECK-NEXT: .short 0 74; CHECK-NEXT: .short 0 75; CHECK-NEXT: .long 65535 76; SmallConstant 77; CHECK-NEXT: .byte 4 78; CHECK-NEXT: .byte 0 79; CHECK-NEXT: .short 8 80; CHECK-NEXT: .short 0 81; CHECK-NEXT: .short 0 82; CHECK-NEXT: .long 65536 83; LargeConstant at index 0 84; CHECK-NEXT: .byte 5 85; CHECK-NEXT: .byte 0 86; CHECK-NEXT: .short 8 87; CHECK-NEXT: .short 0 88; CHECK-NEXT: .short 0 89; CHECK-NEXT: .long 0 90; LargeConstant at index 1 91; CHECK-NEXT: .byte 5 92; CHECK-NEXT: .byte 0 93; CHECK-NEXT: .short 8 94; CHECK-NEXT: .short 0 95; CHECK-NEXT: .short 0 96; CHECK-NEXT: .long 1 97; SmallConstant 98; CHECK-NEXT: .byte 4 99; CHECK-NEXT: .byte 0 100; CHECK-NEXT: .short 8 101; CHECK-NEXT: .short 0 102; CHECK-NEXT: .short 0 103; CHECK-NEXT: .long 66 104; LargeConstant at index 2 105; CHECK-NEXT: .byte 5 106; CHECK-NEXT: .byte 0 107; CHECK-NEXT: .short 8 108; CHECK-NEXT: .short 0 109; CHECK-NEXT: .short 0 110; CHECK-NEXT: .long 2 111 112define void @constantargs() { 113entry: 114 %0 = inttoptr i64 244837814094590 to ptr 115 tail call void (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.void(i64 1, i32 20, ptr %0, i32 0, i64 65535, i64 65536, i64 4294967295, i64 4294967296, i128 66, i128 4294967297) 116 ret void 117} 118 119; Inline OSR Exit 120; 121; CHECK-LABEL: .long L{{.*}}-_osrinline 122; CHECK-NEXT: .short 0 123; CHECK-NEXT: .short 2 124; CHECK-NEXT: .byte 1 125; CHECK-NEXT: .byte 0 126; CHECK-NEXT: .short 8 127; CHECK-NEXT: .short {{[0-9]+}} 128; CHECK-NEXT: .short 0 129; CHECK-NEXT: .long 0 130; CHECK-NEXT: .byte 1 131; CHECK-NEXT: .byte 0 132; CHECK-NEXT: .short 8 133; CHECK-NEXT: .short {{[0-9]+}} 134; CHECK-NEXT: .short 0 135; CHECK-NEXT: .long 0 136define void @osrinline(i64 %a, i64 %b) { 137entry: 138 ; Runtime void->void call. 139 call void inttoptr (i64 244837814094590 to ptr)() 140 ; Followed by inline OSR patchpoint with 12-byte shadow and 2 live vars. 141 call void (i64, i32, ...) @llvm.experimental.stackmap(i64 3, i32 12, i64 %a, i64 %b) 142 ret void 143} 144 145; Cold OSR Exit 146; 147; 2 live variables in register. 148; 149; CHECK-LABEL: .long L{{.*}}-_osrcold 150; CHECK-NEXT: .short 0 151; CHECK-NEXT: .short 2 152; CHECK-NEXT: .byte 1 153; CHECK-NEXT: .byte 0 154; CHECK-NEXT: .short 8 155; CHECK-NEXT: .short {{[0-9]+}} 156; CHECK-NEXT: .short 0 157; CHECK-NEXT: .long 0 158; CHECK-NEXT: .byte 1 159; CHECK-NEXT: .byte 0 160; CHECK-NEXT: .short 8 161; CHECK-NEXT: .short {{[0-9]+}} 162; CHECK-NEXT: .short 0 163; CHECK-NEXT: .long 0 164define void @osrcold(i64 %a, i64 %b) { 165entry: 166 %test = icmp slt i64 %a, %b 167 br i1 %test, label %ret, label %cold 168cold: 169 ; OSR patchpoint with 12-byte nop-slide and 2 live vars. 170 %thunk = inttoptr i64 244837814094590 to ptr 171 call void (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.void(i64 4, i32 20, ptr %thunk, i32 0, i64 %a, i64 %b) 172 unreachable 173ret: 174 ret void 175} 176 177; Property Read 178; CHECK-LABEL: .long L{{.*}}-_propertyRead 179; CHECK-NEXT: .short 0 180; CHECK-NEXT: .short 0 181; 182; FIXME: There are currently no stackmap entries. After moving to 183; AnyRegCC, we will have entries for the object and return value. 184define i64 @propertyRead(ptr %obj) { 185entry: 186 %resolveRead = inttoptr i64 244837814094590 to ptr 187 %result = call i64 (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.i64(i64 5, i32 20, ptr %resolveRead, i32 1, ptr %obj) 188 %add = add i64 %result, 3 189 ret i64 %add 190} 191 192; Property Write 193; CHECK-LABEL: .long L{{.*}}-_propertyWrite 194; CHECK-NEXT: .short 0 195; CHECK-NEXT: .short 2 196; CHECK-NEXT: .byte 1 197; CHECK-NEXT: .byte 0 198; CHECK-NEXT: .short 8 199; CHECK-NEXT: .short {{[0-9]+}} 200; CHECK-NEXT: .short 0 201; CHECK-NEXT: .long 0 202; CHECK-NEXT: .byte 1 203; CHECK-NEXT: .byte 0 204; CHECK-NEXT: .short 8 205; CHECK-NEXT: .short {{[0-9]+}} 206; CHECK-NEXT: .short 0 207; CHECK-NEXT: .long 0 208define void @propertyWrite(i64 %dummy1, ptr %obj, i64 %dummy2, i64 %a) { 209entry: 210 %resolveWrite = inttoptr i64 244837814094590 to ptr 211 call anyregcc void (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.void(i64 6, i32 20, ptr %resolveWrite, i32 2, ptr %obj, i64 %a) 212 ret void 213} 214 215; Void JS Call 216; 217; 2 live variables in registers. 218; 219; CHECK-LABEL: .long L{{.*}}-_jsVoidCall 220; CHECK-NEXT: .short 0 221; CHECK-NEXT: .short 2 222; CHECK-NEXT: .byte 1 223; CHECK-NEXT: .byte 0 224; CHECK-NEXT: .short 8 225; CHECK-NEXT: .short {{[0-9]+}} 226; CHECK-NEXT: .short 0 227; CHECK-NEXT: .long 0 228; CHECK-NEXT: .byte 1 229; CHECK-NEXT: .byte 0 230; CHECK-NEXT: .short 8 231; CHECK-NEXT: .short {{[0-9]+}} 232; CHECK-NEXT: .short 0 233; CHECK-NEXT: .long 0 234define void @jsVoidCall(i64 %dummy1, ptr %obj, i64 %arg, i64 %l1, i64 %l2) { 235entry: 236 %resolveCall = inttoptr i64 244837814094590 to ptr 237 call void (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.void(i64 7, i32 20, ptr %resolveCall, i32 2, ptr %obj, i64 %arg, i64 %l1, i64 %l2) 238 ret void 239} 240 241; i64 JS Call 242; 243; 2 live variables in registers. 244; 245; CHECK-LABEL: .long L{{.*}}-_jsIntCall 246; CHECK-NEXT: .short 0 247; CHECK-NEXT: .short 2 248; CHECK-NEXT: .byte 1 249; CHECK-NEXT: .byte 0 250; CHECK-NEXT: .short 8 251; CHECK-NEXT: .short {{[0-9]+}} 252; CHECK-NEXT: .short 0 253; CHECK-NEXT: .long 0 254; CHECK-NEXT: .byte 1 255; CHECK-NEXT: .byte 0 256; CHECK-NEXT: .short 8 257; CHECK-NEXT: .short {{[0-9]+}} 258; CHECK-NEXT: .short 0 259; CHECK-NEXT: .long 0 260define i64 @jsIntCall(i64 %dummy1, ptr %obj, i64 %arg, i64 %l1, i64 %l2) { 261entry: 262 %resolveCall = inttoptr i64 244837814094590 to ptr 263 %result = call i64 (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.i64(i64 8, i32 20, ptr %resolveCall, i32 2, ptr %obj, i64 %arg, i64 %l1, i64 %l2) 264 %add = add i64 %result, 3 265 ret i64 %add 266} 267 268; Spilled stack map values. 269; 270; Verify 28 stack map entries. 271; 272; CHECK-LABEL: .long L{{.*}}-_spilledValue 273; CHECK-NEXT: .short 0 274; CHECK-NEXT: .short 28 275; 276; Check that at least one is a spilled entry from RBP. 277; Location: Indirect FP + ... 278; CHECK: .byte 3 279; CHECK-NEXT: .byte 0 280; CHECK-NEXT: .short 281; CHECK-NEXT: .short 29 282; CHECK-NEXT: .short 0 283; CHECK-NEXT: .long 284define void @spilledValue(i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16, i64 %l17, i64 %l18, i64 %l19, i64 %l20, i64 %l21, i64 %l22, i64 %l23, i64 %l24, i64 %l25, i64 %l26, i64 %l27) { 285entry: 286 call void (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.void(i64 11, i32 20, ptr null, i32 5, i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16, i64 %l17, i64 %l18, i64 %l19, i64 %l20, i64 %l21, i64 %l22, i64 %l23, i64 %l24, i64 %l25, i64 %l26, i64 %l27) 287 ret void 288} 289 290; Map a constant value. 291; 292; CHECK-LABEL: .long L{{.*}}-_liveConstant 293; CHECK-NEXT: .short 0 294; 1 location 295; CHECK-NEXT: .short 1 296; Loc 0: SmallConstant 297; CHECK-NEXT: .byte 4 298; CHECK-NEXT: .byte 0 299; CHECK-NEXT: .short 8 300; CHECK-NEXT: .short 0 301; CHECK-NEXT: .short 0 302; CHECK-NEXT: .long 33 303 304define void @liveConstant() { 305 tail call void (i64, i32, ...) @llvm.experimental.stackmap(i64 15, i32 8, i32 33) 306 ret void 307} 308 309; Map a value when LR is the only free register. 310; 311; CHECK-LABEL: .long L{{.*}}-_clobberLR 312; CHECK-NEXT: .short 0 313; 1 location 314; CHECK-NEXT: .short 1 315; Loc 0: Indirect FP (r29) - offset 316; CHECK-NEXT: .byte 3 317; CHECK-NEXT: .byte 0 318; CHECK-NEXT: .short 4 319; CHECK-NEXT: .short 29 320; CHECK-NEXT: .short 0 321; CHECK-NEXT: .long -{{[0-9]+}} 322define void @clobberLR(i32 %a) { 323 tail call void asm sideeffect "nop", "~{x0},~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7},~{x8},~{x9},~{x10},~{x11},~{x12},~{x13},~{x14},~{x15},~{x16},~{x17},~{x18},~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28},~{x29},~{x31}"() nounwind 324 tail call void (i64, i32, ...) @llvm.experimental.stackmap(i64 16, i32 8, i32 %a) 325 ret void 326} 327 328; CHECK-LABEL: .long L{{.*}}-_floats 329; CHECK-NEXT: .short 0 330; Num Locations 331; CHECK-NEXT: .short 6 332; Loc 0: constant float stored to FP register 333; CHECK-NEXT: .byte 1 334; CHECK-NEXT: .byte 0 335; CHECK-NEXT: .short 4 336; CHECK-NEXT: .short {{.*}} 337; CHECK-NEXT: .short 0 338; CHECK-NEXT: .long 0 339; Loc 0: constant double stored to FP register 340; CHECK-NEXT: .byte 1 341; CHECK-NEXT: .byte 0 342; CHECK-NEXT: .short 8 343; CHECK-NEXT: .short {{.*}} 344; CHECK-NEXT: .short 0 345; CHECK-NEXT: .long 0 346; Loc 1: float value in FP register 347; CHECK-NEXT: .byte 1 348; CHECK-NEXT: .byte 0 349; CHECK-NEXT: .short 4 350; CHECK-NEXT: .short {{.*}} 351; CHECK-NEXT: .short 0 352; CHECK-NEXT: .long 0 353; Loc 2: double value in FP register 354; CHECK-NEXT: .byte 1 355; CHECK-NEXT: .byte 0 356; CHECK-NEXT: .short 8 357; CHECK-NEXT: .short {{.*}} 358; CHECK-NEXT: .short 0 359; CHECK-NEXT: .long 0 360; Loc 3: float on stack 361; CHECK-NEXT: .byte 2 362; CHECK-NEXT: .byte 0 363; CHECK-NEXT: .short 8 364; CHECK-NEXT: .short {{.*}} 365; CHECK-NEXT: .short 0 366; CHECK-NEXT: .long -{{.*}} 367; Loc 4: double on stack 368; CHECK-NEXT: .byte 2 369; CHECK-NEXT: .byte 0 370; CHECK-NEXT: .short 8 371; CHECK-NEXT: .short {{.*}} 372; CHECK-NEXT: .short 0 373; CHECK-NEXT: .long -{{.*}} 374define void @floats(float %f, double %g) { 375 %ff = alloca float 376 %gg = alloca double 377 call void (i64, i32, ...) @llvm.experimental.stackmap(i64 888, i32 0, float 1.25, 378 double 1.5, float %f, double %g, ptr %ff, ptr %gg) 379 ret void 380} 381 382declare void @llvm.experimental.stackmap(i64, i32, ...) 383declare void @llvm.experimental.patchpoint.void(i64, i32, ptr, i32, ...) 384declare i64 @llvm.experimental.patchpoint.i64(i64, i32, ptr, i32, ...) 385