1; RUN: llc < %s -mtriple=x86_64-apple-darwin -disable-fp-elim | FileCheck %s 2; 3; Note: Print verbose stackmaps using -debug-only=stackmaps. 4 5; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps 6; CHECK-NEXT: __LLVM_StackMaps: 7; CHECK-NEXT: .long 0 8; Num LargeConstants 9; CHECK-NEXT: .long 1 10; CHECK-NEXT: .quad 4294967296 11; Num Callsites 12; CHECK-NEXT: .long 11 13 14; Constant arguments 15; 16; CHECK-NEXT: .long 1 17; CHECK-NEXT: .long L{{.*}}-_constantargs 18; CHECK-NEXT: .short 0 19; CHECK-NEXT: .short 4 20; SmallConstant 21; CHECK-NEXT: .byte 4 22; CHECK-NEXT: .byte 8 23; CHECK-NEXT: .short 0 24; CHECK-NEXT: .long 65535 25; SmallConstant 26; CHECK-NEXT: .byte 4 27; CHECK-NEXT: .byte 8 28; CHECK-NEXT: .short 0 29; CHECK-NEXT: .long 65536 30; SmallConstant 31; CHECK-NEXT: .byte 4 32; CHECK-NEXT: .byte 8 33; CHECK-NEXT: .short 0 34; CHECK-NEXT: .long -1 35; LargeConstant at index 0 36; CHECK-NEXT: .byte 5 37; CHECK-NEXT: .byte 8 38; CHECK-NEXT: .short 0 39; CHECK-NEXT: .long 0 40 41define void @constantargs() { 42entry: 43 %0 = inttoptr i64 12345 to i8* 44 tail call void (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i32 1, i32 15, i8* %0, i32 0, i64 65535, i64 65536, i64 4294967295, i64 4294967296) 45 ret void 46} 47 48; Inline OSR Exit 49; 50; CHECK-NEXT: .long 3 51; CHECK-NEXT: .long L{{.*}}-_osrinline 52; CHECK-NEXT: .short 0 53; CHECK-NEXT: .short 2 54; CHECK-NEXT: .byte 1 55; CHECK-NEXT: .byte 8 56; CHECK-NEXT: .short {{[0-9]+}} 57; CHECK-NEXT: .long 0 58; CHECK-NEXT: .byte 1 59; CHECK-NEXT: .byte 8 60; CHECK-NEXT: .short {{[0-9]+}} 61; CHECK-NEXT: .long 0 62define void @osrinline(i64 %a, i64 %b) { 63entry: 64 ; Runtime void->void call. 65 call void inttoptr (i64 -559038737 to void ()*)() 66 ; Followed by inline OSR patchpoint with 12-byte shadow and 2 live vars. 67 call void (i32, i32, ...)* @llvm.experimental.stackmap(i32 3, i32 12, i64 %a, i64 %b) 68 ret void 69} 70 71; Cold OSR Exit 72; 73; 2 live variables in register. 74; 75; CHECK-NEXT: .long 4 76; CHECK-NEXT: .long L{{.*}}-_osrcold 77; CHECK-NEXT: .short 0 78; CHECK-NEXT: .short 2 79; CHECK-NEXT: .byte 1 80; CHECK-NEXT: .byte 8 81; CHECK-NEXT: .short {{[0-9]+}} 82; CHECK-NEXT: .long 0 83; CHECK-NEXT: .byte 1 84; CHECK-NEXT: .byte 8 85; CHECK-NEXT: .short {{[0-9]+}} 86; CHECK-NEXT: .long 0 87define void @osrcold(i64 %a, i64 %b) { 88entry: 89 %test = icmp slt i64 %a, %b 90 br i1 %test, label %ret, label %cold 91cold: 92 ; OSR patchpoint with 12-byte nop-slide and 2 live vars. 93 %thunk = inttoptr i64 -559038737 to i8* 94 call void (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i32 4, i32 15, i8* %thunk, i32 0, i64 %a, i64 %b) 95 unreachable 96ret: 97 ret void 98} 99 100; Property Read 101; CHECK-NEXT: .long 5 102; CHECK-NEXT: .long L{{.*}}-_propertyRead 103; CHECK-NEXT: .short 0 104; CHECK-NEXT: .short 0 105; 106; FIXME: There are currently no stackmap entries. After moving to 107; AnyRegCC, we will have entries for the object and return value. 108define i64 @propertyRead(i64* %obj) { 109entry: 110 %resolveRead = inttoptr i64 -559038737 to i8* 111 %result = call i64 (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i32 5, i32 15, i8* %resolveRead, i32 1, i64* %obj) 112 %add = add i64 %result, 3 113 ret i64 %add 114} 115 116; Property Write 117; CHECK-NEXT: .long 6 118; CHECK-NEXT: .long L{{.*}}-_propertyWrite 119; CHECK-NEXT: .short 0 120; CHECK-NEXT: .short 0 121; 122; FIXME: There are currently no stackmap entries. After moving to 123; AnyRegCC, we will have entries for the object and return value. 124define void @propertyWrite(i64 %dummy1, i64* %obj, i64 %dummy2, i64 %a) { 125entry: 126 %resolveWrite = inttoptr i64 -559038737 to i8* 127 call void (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i32 6, i32 15, i8* %resolveWrite, i32 2, i64* %obj, i64 %a) 128 ret void 129} 130 131; Void JS Call 132; 133; 2 live variables in registers. 134; 135; CHECK-NEXT: .long 7 136; CHECK-NEXT: .long L{{.*}}-_jsVoidCall 137; CHECK-NEXT: .short 0 138; CHECK-NEXT: .short 2 139; CHECK-NEXT: .byte 1 140; CHECK-NEXT: .byte 8 141; CHECK-NEXT: .short {{[0-9]+}} 142; CHECK-NEXT: .long 0 143; CHECK-NEXT: .byte 1 144; CHECK-NEXT: .byte 8 145; CHECK-NEXT: .short {{[0-9]+}} 146; CHECK-NEXT: .long 0 147define void @jsVoidCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) { 148entry: 149 %resolveCall = inttoptr i64 -559038737 to i8* 150 call void (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i32 7, i32 15, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2) 151 ret void 152} 153 154; i64 JS Call 155; 156; 2 live variables in registers. 157; 158; CHECK: .long 8 159; CHECK-NEXT: .long L{{.*}}-_jsIntCall 160; CHECK-NEXT: .short 0 161; CHECK-NEXT: .short 2 162; CHECK-NEXT: .byte 1 163; CHECK-NEXT: .byte 8 164; CHECK-NEXT: .short {{[0-9]+}} 165; CHECK-NEXT: .long 0 166; CHECK-NEXT: .byte 1 167; CHECK-NEXT: .byte 8 168; CHECK-NEXT: .short {{[0-9]+}} 169; CHECK-NEXT: .long 0 170define i64 @jsIntCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) { 171entry: 172 %resolveCall = inttoptr i64 -559038737 to i8* 173 %result = call i64 (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i32 8, i32 15, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2) 174 %add = add i64 %result, 3 175 ret i64 %add 176} 177 178; Spilled stack map values. 179; 180; Verify 17 stack map entries. 181; 182; CHECK: .long 11 183; CHECK-NEXT: .long L{{.*}}-_spilledValue 184; CHECK-NEXT: .short 0 185; CHECK-NEXT: .short 17 186; 187; Check that at least one is a spilled entry from RBP. 188; Location: Indirect RBP + ... 189; CHECK: .byte 3 190; CHECK-NEXT: .byte 8 191; CHECK-NEXT: .short 6 192define 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) { 193entry: 194 call void (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i32 11, i32 15, 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) 195 ret void 196} 197 198; Spilled stack map values. 199; 200; Verify 17 stack map entries. 201; 202; CHECK: .long 12 203; CHECK-LABEL: .long L{{.*}}-_spilledStackMapValue 204; CHECK-NEXT: .short 0 205; CHECK-NEXT: .short 17 206; 207; Check that at least one is a spilled entry from RBP. 208; Location: Indirect RBP + ... 209; CHECK: .byte 3 210; CHECK-NEXT: .byte 8 211; CHECK-NEXT: .short 6 212define 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) { 213entry: 214 call void (i32, i32, ...)* @llvm.experimental.stackmap(i32 12, i32 15, 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) 215 ret void 216} 217 218; Spill a subregister stackmap operand. 219; 220; CHECK: .long 13 221; CHECK-LABEL: .long L{{.*}}-_spillSubReg 222; CHECK-NEXT: .short 0 223; 4 locations 224; CHECK-NEXT: .short 1 225; 226; Check that the subregister operand is a 4-byte spill. 227; Location: Indirect, 4-byte, RBP + ... 228; CHECK: .byte 3 229; CHECK-NEXT: .byte 4 230; CHECK-NEXT: .short 6 231define void @spillSubReg(i64 %arg) #0 { 232bb: 233 br i1 undef, label %bb1, label %bb2 234 235bb1: 236 unreachable 237 238bb2: 239 %tmp = load i64* inttoptr (i64 140685446136880 to i64*) 240 br i1 undef, label %bb16, label %bb17 241 242bb16: 243 unreachable 244 245bb17: 246 %tmp32 = trunc i64 %tmp to i32 247 br i1 undef, label %bb60, label %bb61 248 249bb60: 250 tail call void asm sideeffect "nop", "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() nounwind 251 tail call void (i32, i32, ...)* @llvm.experimental.stackmap(i32 13, i32 5, i32 %tmp32) 252 unreachable 253 254bb61: 255 unreachable 256} 257 258; Map a single byte subregister. There is no DWARF register number, so 259; we expect the register to be encoded with the proper size and spill offset. We don't know which 260; 261; CHECK: .long 14 262; CHECK-LABEL: .long L{{.*}}-_subRegOffset 263; CHECK-NEXT: .short 0 264; 2 locations 265; CHECK-NEXT: .short 2 266; 267; Check that the subregister operands are 1-byte spills. 268; Location 0: Register, 4-byte, AL 269; CHECK-NEXT: .byte 1 270; CHECK-NEXT: .byte 1 271; CHECK-NEXT: .short 0 272; CHECK-NEXT: .long 0 273; 274; Location 1: Register, 4-byte, BL 275; CHECK-NEXT: .byte 1 276; CHECK-NEXT: .byte 1 277; CHECK-NEXT: .short 3 278; CHECK-NEXT: .long 0 279define void @subRegOffset(i16 %arg) { 280 %v = mul i16 %arg, 5 281 %a0 = trunc i16 %v to i8 282 tail call void asm sideeffect "nop", "~{bx}"() nounwind 283 %arghi = lshr i16 %v, 8 284 %a1 = trunc i16 %arghi to i8 285 tail call void asm sideeffect "nop", "~{cx},~{dx},~{bp},~{si},~{di},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() nounwind 286 tail call void (i32, i32, ...)* @llvm.experimental.stackmap(i32 14, i32 5, i8 %a0, i8 %a1) 287 ret void 288} 289 290declare void @llvm.experimental.stackmap(i32, i32, ...) 291declare void @llvm.experimental.patchpoint.void(i32, i32, i8*, i32, ...) 292declare i64 @llvm.experimental.patchpoint.i64(i32, i32, i8*, i32, ...) 293