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 2 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 2 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 _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 58; Num LargeConstants 59; CHECK-NEXT: .quad 4294967295 60; CHECK-NEXT: .quad 4294967296 61 62; Constant arguments 63; 64; CHECK-NEXT: .quad 1 65; CHECK-NEXT: .long L{{.*}}-_constantargs 66; CHECK-NEXT: .short 0 67; CHECK-NEXT: .short 4 68; SmallConstant 69; CHECK-NEXT: .byte 4 70; CHECK-NEXT: .byte 8 71; CHECK-NEXT: .short 0 72; CHECK-NEXT: .long 65535 73; SmallConstant 74; CHECK-NEXT: .byte 4 75; CHECK-NEXT: .byte 8 76; CHECK-NEXT: .short 0 77; CHECK-NEXT: .long 65536 78; SmallConstant 79; CHECK-NEXT: .byte 5 80; CHECK-NEXT: .byte 8 81; CHECK-NEXT: .short 0 82; CHECK-NEXT: .long 0 83; LargeConstant at index 0 84; CHECK-NEXT: .byte 5 85; CHECK-NEXT: .byte 8 86; CHECK-NEXT: .short 0 87; CHECK-NEXT: .long 1 88 89define void @constantargs() { 90entry: 91 %0 = inttoptr i64 244837814094590 to i8* 92 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) 93 ret void 94} 95 96; Inline OSR Exit 97; 98; CHECK-LABEL: .long L{{.*}}-_osrinline 99; CHECK-NEXT: .short 0 100; CHECK-NEXT: .short 2 101; CHECK-NEXT: .byte 1 102; CHECK-NEXT: .byte 8 103; CHECK-NEXT: .short {{[0-9]+}} 104; CHECK-NEXT: .long 0 105; CHECK-NEXT: .byte 1 106; CHECK-NEXT: .byte 8 107; CHECK-NEXT: .short {{[0-9]+}} 108; CHECK-NEXT: .long 0 109define void @osrinline(i64 %a, i64 %b) { 110entry: 111 ; Runtime void->void call. 112 call void inttoptr (i64 244837814094590 to void ()*)() 113 ; Followed by inline OSR patchpoint with 12-byte shadow and 2 live vars. 114 call void (i64, i32, ...) @llvm.experimental.stackmap(i64 3, i32 12, i64 %a, i64 %b) 115 ret void 116} 117 118; Cold OSR Exit 119; 120; 2 live variables in register. 121; 122; CHECK-LABEL: .long L{{.*}}-_osrcold 123; CHECK-NEXT: .short 0 124; CHECK-NEXT: .short 2 125; CHECK-NEXT: .byte 1 126; CHECK-NEXT: .byte 8 127; CHECK-NEXT: .short {{[0-9]+}} 128; CHECK-NEXT: .long 0 129; CHECK-NEXT: .byte 1 130; CHECK-NEXT: .byte 8 131; CHECK-NEXT: .short {{[0-9]+}} 132; CHECK-NEXT: .long 0 133define void @osrcold(i64 %a, i64 %b) { 134entry: 135 %test = icmp slt i64 %a, %b 136 br i1 %test, label %ret, label %cold 137cold: 138 ; OSR patchpoint with 12-byte nop-slide and 2 live vars. 139 %thunk = inttoptr i64 244837814094590 to i8* 140 call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 4, i32 20, i8* %thunk, i32 0, i64 %a, i64 %b) 141 unreachable 142ret: 143 ret void 144} 145 146; Property Read 147; CHECK-LABEL: .long L{{.*}}-_propertyRead 148; CHECK-NEXT: .short 0 149; CHECK-NEXT: .short 0 150; 151; FIXME: There are currently no stackmap entries. After moving to 152; AnyRegCC, we will have entries for the object and return value. 153define i64 @propertyRead(i64* %obj) { 154entry: 155 %resolveRead = inttoptr i64 244837814094590 to i8* 156 %result = call i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 5, i32 20, i8* %resolveRead, i32 1, i64* %obj) 157 %add = add i64 %result, 3 158 ret i64 %add 159} 160 161; Property Write 162; CHECK-LABEL: .long L{{.*}}-_propertyWrite 163; CHECK-NEXT: .short 0 164; CHECK-NEXT: .short 2 165; CHECK-NEXT: .byte 1 166; CHECK-NEXT: .byte 8 167; CHECK-NEXT: .short {{[0-9]+}} 168; CHECK-NEXT: .long 0 169; CHECK-NEXT: .byte 1 170; CHECK-NEXT: .byte 8 171; CHECK-NEXT: .short {{[0-9]+}} 172; CHECK-NEXT: .long 0 173define void @propertyWrite(i64 %dummy1, i64* %obj, i64 %dummy2, i64 %a) { 174entry: 175 %resolveWrite = inttoptr i64 244837814094590 to i8* 176 call anyregcc void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 6, i32 20, i8* %resolveWrite, i32 2, i64* %obj, i64 %a) 177 ret void 178} 179 180; Void JS Call 181; 182; 2 live variables in registers. 183; 184; CHECK-LABEL: .long L{{.*}}-_jsVoidCall 185; CHECK-NEXT: .short 0 186; CHECK-NEXT: .short 2 187; CHECK-NEXT: .byte 1 188; CHECK-NEXT: .byte 8 189; CHECK-NEXT: .short {{[0-9]+}} 190; CHECK-NEXT: .long 0 191; CHECK-NEXT: .byte 1 192; CHECK-NEXT: .byte 8 193; CHECK-NEXT: .short {{[0-9]+}} 194; CHECK-NEXT: .long 0 195define void @jsVoidCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) { 196entry: 197 %resolveCall = inttoptr i64 244837814094590 to i8* 198 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) 199 ret void 200} 201 202; i64 JS Call 203; 204; 2 live variables in registers. 205; 206; CHECK-LABEL: .long L{{.*}}-_jsIntCall 207; CHECK-NEXT: .short 0 208; CHECK-NEXT: .short 2 209; CHECK-NEXT: .byte 1 210; CHECK-NEXT: .byte 8 211; CHECK-NEXT: .short {{[0-9]+}} 212; CHECK-NEXT: .long 0 213; CHECK-NEXT: .byte 1 214; CHECK-NEXT: .byte 8 215; CHECK-NEXT: .short {{[0-9]+}} 216; CHECK-NEXT: .long 0 217define i64 @jsIntCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) { 218entry: 219 %resolveCall = inttoptr i64 244837814094590 to i8* 220 %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) 221 %add = add i64 %result, 3 222 ret i64 %add 223} 224 225; Spilled stack map values. 226; 227; Verify 28 stack map entries. 228; 229; CHECK-LABEL: .long L{{.*}}-_spilledValue 230; CHECK-NEXT: .short 0 231; CHECK-NEXT: .short 28 232; 233; Check that at least one is a spilled entry from RBP. 234; Location: Indirect FP + ... 235; CHECK: .byte 3 236; CHECK-NEXT: .byte 8 237; CHECK-NEXT: .short 29 238define 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) { 239entry: 240 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) 241 ret void 242} 243 244; Spilled stack map values. 245; 246; Verify 23 stack map entries. 247; 248; CHECK-LABEL: .long L{{.*}}-_spilledStackMapValue 249; CHECK-NEXT: .short 0 250; CHECK-NEXT: .short 30 251; 252; Check that at least one is a spilled entry from RBP. 253; Location: Indirect FP + ... 254; CHECK: .byte 3 255; CHECK-NEXT: .byte 8 256; CHECK-NEXT: .short 29 257define 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) { 258entry: 259 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) 260 ret void 261} 262 263 264; Map a constant value. 265; 266; CHECK-LABEL: .long L{{.*}}-_liveConstant 267; CHECK-NEXT: .short 0 268; 1 location 269; CHECK-NEXT: .short 1 270; Loc 0: SmallConstant 271; CHECK-NEXT: .byte 4 272; CHECK-NEXT: .byte 8 273; CHECK-NEXT: .short 0 274; CHECK-NEXT: .long 33 275 276define void @liveConstant() { 277 tail call void (i64, i32, ...) @llvm.experimental.stackmap(i64 15, i32 8, i32 33) 278 ret void 279} 280 281; Map a value when LR is the only free register. 282; 283; CHECK-LABEL: .long L{{.*}}-_clobberLR 284; CHECK-NEXT: .short 0 285; 1 location 286; CHECK-NEXT: .short 1 287; Loc 0: Indirect FP (r29) - offset 288; CHECK-NEXT: .byte 3 289; CHECK-NEXT: .byte 4 290; CHECK-NEXT: .short 29 291; CHECK-NEXT: .long -{{[0-9]+}} 292define void @clobberLR(i32 %a) { 293 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 294 tail call void (i64, i32, ...) @llvm.experimental.stackmap(i64 16, i32 8, i32 %a) 295 ret void 296} 297 298declare void @llvm.experimental.stackmap(i64, i32, ...) 299declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...) 300declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...) 301