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 12 18; Num LargeConstants 19; CHECK-NEXT: .long 3 20; Num Callsites 21; CHECK-NEXT: .long 12 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 _spilledStackMapValue 49; CHECK-NEXT: .quad 128 50; CHECK-NEXT: .quad 1 51; CHECK-NEXT: .quad _liveConstant 52; CHECK-NEXT: .quad 16 53; CHECK-NEXT: .quad 1 54; CHECK-NEXT: .quad _clobberLR 55; CHECK-NEXT: .quad 112 56; CHECK-NEXT: .quad 1 57; CHECK-NEXT: .quad _floats 58; CHECK-NEXT: .quad 32 59; CHECK-NEXT: .quad 1 60 61; Num LargeConstants 62; CHECK-NEXT: .quad 4294967295 63; CHECK-NEXT: .quad 4294967296 64; CHECK-NEXT: .quad 4294967297 65 66; Constant arguments 67; 68; CHECK-NEXT: .quad 1 69; CHECK-NEXT: .long L{{.*}}-_constantargs 70; CHECK-NEXT: .short 0 71; CHECK-NEXT: .short 6 72; SmallConstant 73; CHECK-NEXT: .byte 4 74; CHECK-NEXT: .byte 0 75; CHECK-NEXT: .short 8 76; CHECK-NEXT: .short 0 77; CHECK-NEXT: .short 0 78; CHECK-NEXT: .long 65535 79; SmallConstant 80; CHECK-NEXT: .byte 4 81; CHECK-NEXT: .byte 0 82; CHECK-NEXT: .short 8 83; CHECK-NEXT: .short 0 84; CHECK-NEXT: .short 0 85; CHECK-NEXT: .long 65536 86; LargeConstant at index 0 87; CHECK-NEXT: .byte 5 88; CHECK-NEXT: .byte 0 89; CHECK-NEXT: .short 8 90; CHECK-NEXT: .short 0 91; CHECK-NEXT: .short 0 92; CHECK-NEXT: .long 0 93; LargeConstant at index 1 94; CHECK-NEXT: .byte 5 95; CHECK-NEXT: .byte 0 96; CHECK-NEXT: .short 8 97; CHECK-NEXT: .short 0 98; CHECK-NEXT: .short 0 99; CHECK-NEXT: .long 1 100; SmallConstant 101; CHECK-NEXT: .byte 4 102; CHECK-NEXT: .byte 0 103; CHECK-NEXT: .short 8 104; CHECK-NEXT: .short 0 105; CHECK-NEXT: .short 0 106; CHECK-NEXT: .long 66 107; LargeConstant at index 2 108; CHECK-NEXT: .byte 5 109; CHECK-NEXT: .byte 0 110; CHECK-NEXT: .short 8 111; CHECK-NEXT: .short 0 112; CHECK-NEXT: .short 0 113; CHECK-NEXT: .long 2 114 115define void @constantargs() { 116entry: 117 %0 = inttoptr i64 244837814094590 to i8* 118 tail call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 1, i32 20, i8* %0, i32 0, i64 65535, i64 65536, i64 4294967295, i64 4294967296, i128 66, i128 4294967297) 119 ret void 120} 121 122; Inline OSR Exit 123; 124; CHECK-LABEL: .long L{{.*}}-_osrinline 125; CHECK-NEXT: .short 0 126; CHECK-NEXT: .short 2 127; CHECK-NEXT: .byte 1 128; CHECK-NEXT: .byte 0 129; CHECK-NEXT: .short 8 130; CHECK-NEXT: .short {{[0-9]+}} 131; CHECK-NEXT: .short 0 132; CHECK-NEXT: .long 0 133; CHECK-NEXT: .byte 1 134; CHECK-NEXT: .byte 0 135; CHECK-NEXT: .short 8 136; CHECK-NEXT: .short {{[0-9]+}} 137; CHECK-NEXT: .short 0 138; CHECK-NEXT: .long 0 139define void @osrinline(i64 %a, i64 %b) { 140entry: 141 ; Runtime void->void call. 142 call void inttoptr (i64 244837814094590 to void ()*)() 143 ; Followed by inline OSR patchpoint with 12-byte shadow and 2 live vars. 144 call void (i64, i32, ...) @llvm.experimental.stackmap(i64 3, i32 12, i64 %a, i64 %b) 145 ret void 146} 147 148; Cold OSR Exit 149; 150; 2 live variables in register. 151; 152; CHECK-LABEL: .long L{{.*}}-_osrcold 153; CHECK-NEXT: .short 0 154; CHECK-NEXT: .short 2 155; CHECK-NEXT: .byte 1 156; CHECK-NEXT: .byte 0 157; CHECK-NEXT: .short 8 158; CHECK-NEXT: .short {{[0-9]+}} 159; CHECK-NEXT: .short 0 160; CHECK-NEXT: .long 0 161; CHECK-NEXT: .byte 1 162; CHECK-NEXT: .byte 0 163; CHECK-NEXT: .short 8 164; CHECK-NEXT: .short {{[0-9]+}} 165; CHECK-NEXT: .short 0 166; CHECK-NEXT: .long 0 167define void @osrcold(i64 %a, i64 %b) { 168entry: 169 %test = icmp slt i64 %a, %b 170 br i1 %test, label %ret, label %cold 171cold: 172 ; OSR patchpoint with 12-byte nop-slide and 2 live vars. 173 %thunk = inttoptr i64 244837814094590 to i8* 174 call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 4, i32 20, i8* %thunk, i32 0, i64 %a, i64 %b) 175 unreachable 176ret: 177 ret void 178} 179 180; Property Read 181; CHECK-LABEL: .long L{{.*}}-_propertyRead 182; CHECK-NEXT: .short 0 183; CHECK-NEXT: .short 0 184; 185; FIXME: There are currently no stackmap entries. After moving to 186; AnyRegCC, we will have entries for the object and return value. 187define i64 @propertyRead(i64* %obj) { 188entry: 189 %resolveRead = inttoptr i64 244837814094590 to i8* 190 %result = call i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 5, i32 20, i8* %resolveRead, i32 1, i64* %obj) 191 %add = add i64 %result, 3 192 ret i64 %add 193} 194 195; Property Write 196; CHECK-LABEL: .long L{{.*}}-_propertyWrite 197; CHECK-NEXT: .short 0 198; CHECK-NEXT: .short 2 199; CHECK-NEXT: .byte 1 200; CHECK-NEXT: .byte 0 201; CHECK-NEXT: .short 8 202; CHECK-NEXT: .short {{[0-9]+}} 203; CHECK-NEXT: .short 0 204; CHECK-NEXT: .long 0 205; CHECK-NEXT: .byte 1 206; CHECK-NEXT: .byte 0 207; CHECK-NEXT: .short 8 208; CHECK-NEXT: .short {{[0-9]+}} 209; CHECK-NEXT: .short 0 210; CHECK-NEXT: .long 0 211define void @propertyWrite(i64 %dummy1, i64* %obj, i64 %dummy2, i64 %a) { 212entry: 213 %resolveWrite = inttoptr i64 244837814094590 to i8* 214 call anyregcc void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 6, i32 20, i8* %resolveWrite, i32 2, i64* %obj, i64 %a) 215 ret void 216} 217 218; Void JS Call 219; 220; 2 live variables in registers. 221; 222; CHECK-LABEL: .long L{{.*}}-_jsVoidCall 223; CHECK-NEXT: .short 0 224; CHECK-NEXT: .short 2 225; CHECK-NEXT: .byte 1 226; CHECK-NEXT: .byte 0 227; CHECK-NEXT: .short 8 228; CHECK-NEXT: .short {{[0-9]+}} 229; CHECK-NEXT: .short 0 230; CHECK-NEXT: .long 0 231; CHECK-NEXT: .byte 1 232; CHECK-NEXT: .byte 0 233; CHECK-NEXT: .short 8 234; CHECK-NEXT: .short {{[0-9]+}} 235; CHECK-NEXT: .short 0 236; CHECK-NEXT: .long 0 237define void @jsVoidCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) { 238entry: 239 %resolveCall = inttoptr i64 244837814094590 to i8* 240 call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 7, i32 20, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2) 241 ret void 242} 243 244; i64 JS Call 245; 246; 2 live variables in registers. 247; 248; CHECK-LABEL: .long L{{.*}}-_jsIntCall 249; CHECK-NEXT: .short 0 250; CHECK-NEXT: .short 2 251; CHECK-NEXT: .byte 1 252; CHECK-NEXT: .byte 0 253; CHECK-NEXT: .short 8 254; CHECK-NEXT: .short {{[0-9]+}} 255; CHECK-NEXT: .short 0 256; CHECK-NEXT: .long 0 257; CHECK-NEXT: .byte 1 258; CHECK-NEXT: .byte 0 259; CHECK-NEXT: .short 8 260; CHECK-NEXT: .short {{[0-9]+}} 261; CHECK-NEXT: .short 0 262; CHECK-NEXT: .long 0 263define i64 @jsIntCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) { 264entry: 265 %resolveCall = inttoptr i64 244837814094590 to i8* 266 %result = call i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 8, i32 20, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2) 267 %add = add i64 %result, 3 268 ret i64 %add 269} 270 271; Spilled stack map values. 272; 273; Verify 28 stack map entries. 274; 275; CHECK-LABEL: .long L{{.*}}-_spilledValue 276; CHECK-NEXT: .short 0 277; CHECK-NEXT: .short 28 278; 279; Check that at least one is a spilled entry from RBP. 280; Location: Indirect FP + ... 281; CHECK: .byte 3 282; CHECK-NEXT: .byte 0 283; CHECK-NEXT: .short 284; CHECK-NEXT: .short 29 285; CHECK-NEXT: .short 0 286; CHECK-NEXT: .long 287define 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) { 288entry: 289 call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 11, i32 20, i8* 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) 290 ret void 291} 292 293; Spilled stack map values. 294; 295; Verify 23 stack map entries. 296; 297; CHECK-LABEL: .long L{{.*}}-_spilledStackMapValue 298; CHECK-NEXT: .short 0 299; CHECK-NEXT: .short 30 300; 301; Check that at least one is a spilled entry from RBP. 302; Location: Indirect FP + ... 303; CHECK: .byte 3 304; CHECK-NEXT: .byte 0 305; CHECK-NEXT: .short 306; CHECK-NEXT: .short 29 307; CHECK-NEXT: .short 0 308; CHECK-NEXT: .long 309define webkit_jscc void @spilledStackMapValue(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, i64 %l28, i64 %l29) { 310entry: 311 call void (i64, i32, ...) @llvm.experimental.stackmap(i64 12, i32 16, 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, i64 %l28, i64 %l29) 312 ret void 313} 314 315 316; Map a constant value. 317; 318; CHECK-LABEL: .long L{{.*}}-_liveConstant 319; CHECK-NEXT: .short 0 320; 1 location 321; CHECK-NEXT: .short 1 322; Loc 0: SmallConstant 323; CHECK-NEXT: .byte 4 324; CHECK-NEXT: .byte 0 325; CHECK-NEXT: .short 8 326; CHECK-NEXT: .short 0 327; CHECK-NEXT: .short 0 328; CHECK-NEXT: .long 33 329 330define void @liveConstant() { 331 tail call void (i64, i32, ...) @llvm.experimental.stackmap(i64 15, i32 8, i32 33) 332 ret void 333} 334 335; Map a value when LR is the only free register. 336; 337; CHECK-LABEL: .long L{{.*}}-_clobberLR 338; CHECK-NEXT: .short 0 339; 1 location 340; CHECK-NEXT: .short 1 341; Loc 0: Indirect FP (r29) - offset 342; CHECK-NEXT: .byte 3 343; CHECK-NEXT: .byte 0 344; CHECK-NEXT: .short 4 345; CHECK-NEXT: .short 29 346; CHECK-NEXT: .short 0 347; CHECK-NEXT: .long -{{[0-9]+}} 348define void @clobberLR(i32 %a) { 349 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 350 tail call void (i64, i32, ...) @llvm.experimental.stackmap(i64 16, i32 8, i32 %a) 351 ret void 352} 353 354; CHECK-LABEL: .long L{{.*}}-_floats 355; CHECK-NEXT: .short 0 356; Num Locations 357; CHECK-NEXT: .short 6 358; Loc 0: constant float stored to FP register 359; CHECK-NEXT: .byte 1 360; CHECK-NEXT: .byte 0 361; CHECK-NEXT: .short 4 362; CHECK-NEXT: .short {{.*}} 363; CHECK-NEXT: .short 0 364; CHECK-NEXT: .long 0 365; Loc 0: constant double stored to FP register 366; CHECK-NEXT: .byte 1 367; CHECK-NEXT: .byte 0 368; CHECK-NEXT: .short 8 369; CHECK-NEXT: .short {{.*}} 370; CHECK-NEXT: .short 0 371; CHECK-NEXT: .long 0 372; Loc 1: float value in FP register 373; CHECK-NEXT: .byte 1 374; CHECK-NEXT: .byte 0 375; CHECK-NEXT: .short 4 376; CHECK-NEXT: .short {{.*}} 377; CHECK-NEXT: .short 0 378; CHECK-NEXT: .long 0 379; Loc 2: double value in FP register 380; CHECK-NEXT: .byte 1 381; CHECK-NEXT: .byte 0 382; CHECK-NEXT: .short 8 383; CHECK-NEXT: .short {{.*}} 384; CHECK-NEXT: .short 0 385; CHECK-NEXT: .long 0 386; Loc 3: float on stack 387; CHECK-NEXT: .byte 2 388; CHECK-NEXT: .byte 0 389; CHECK-NEXT: .short 8 390; CHECK-NEXT: .short {{.*}} 391; CHECK-NEXT: .short 0 392; CHECK-NEXT: .long -{{.*}} 393; Loc 4: double on stack 394; CHECK-NEXT: .byte 2 395; CHECK-NEXT: .byte 0 396; CHECK-NEXT: .short 8 397; CHECK-NEXT: .short {{.*}} 398; CHECK-NEXT: .short 0 399; CHECK-NEXT: .long -{{.*}} 400define void @floats(float %f, double %g) { 401 %ff = alloca float 402 %gg = alloca double 403 call void (i64, i32, ...) @llvm.experimental.stackmap(i64 888, i32 0, float 1.25, 404 double 1.5, float %f, double %g, float* %ff, double* %gg) 405 ret void 406} 407 408declare void @llvm.experimental.stackmap(i64, i32, ...) 409declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...) 410declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...) 411