1; RUN: llc < %s | FileCheck %s 2; 3; Note: Print verbose stackmaps using -debug-only=stackmaps. 4 5; We are not getting the correct stack alignment when cross compiling for arm64. 6; So specify a datalayout here. 7target datalayout = "E-m:e-i64:64-n32:64" 8target triple = "powerpc64-unknown-linux-gnu" 9 10; CHECK-LABEL: constantargs: 11; CHECK: {{^}}.L[[constantargs_BEGIN:.*]]:{{$}} 12 13; CHECK-LABEL: osrinline: 14; CHECK: {{^}}.L[[osrinline_BEGIN:.*]]:{{$}} 15 16; CHECK-LABEL: osrcold: 17; CHECK: {{^}}.L[[osrcold_BEGIN:.*]]:{{$}} 18 19; CHECK-LABEL: propertyRead: 20; CHECK: {{^}}.L[[propertyRead_BEGIN:.*]]:{{$}} 21 22; CHECK-LABEL: propertyWrite: 23; CHECK: {{^}}.L[[propertyWrite_BEGIN:.*]]:{{$}} 24 25; CHECK-LABEL: jsVoidCall: 26; CHECK: {{^}}.L[[jsVoidCall_BEGIN:.*]]:{{$}} 27 28; CHECK-LABEL: jsIntCall: 29; CHECK: {{^}}.L[[jsIntCall_BEGIN:.*]]:{{$}} 30 31; CHECK-LABEL: spilledValue: 32; CHECK: {{^}}.L[[spilledValue_BEGIN:.*]]:{{$}} 33 34; CHECK-LABEL: spilledStackMapValue: 35; CHECK: {{^}}.L[[spilledStackMapValue_BEGIN:.*]]:{{$}} 36 37; CHECK-LABEL: liveConstant: 38; CHECK: {{^}}.L[[liveConstant_BEGIN:.*]]:{{$}} 39 40; CHECK-LABEL: clobberLR: 41; CHECK: {{^}}.L[[clobberLR_BEGIN:.*]]:{{$}} 42 43 44; CHECK-LABEL: .section .llvm_stackmaps 45; CHECK-NEXT: __LLVM_StackMaps: 46; Header 47; CHECK-NEXT: .byte 1 48; CHECK-NEXT: .byte 0 49; CHECK-NEXT: .short 0 50; Num Functions 51; CHECK-NEXT: .long 11 52; Num LargeConstants 53; CHECK-NEXT: .long 2 54; Num Callsites 55; CHECK-NEXT: .long 11 56 57; Functions and stack size 58; CHECK-NEXT: .quad constantargs 59; CHECK-NEXT: .quad 128 60; CHECK-NEXT: .quad osrinline 61; CHECK-NEXT: .quad 144 62; CHECK-NEXT: .quad osrcold 63; CHECK-NEXT: .quad 128 64; CHECK-NEXT: .quad propertyRead 65; CHECK-NEXT: .quad 128 66; CHECK-NEXT: .quad propertyWrite 67; CHECK-NEXT: .quad 128 68; CHECK-NEXT: .quad jsVoidCall 69; CHECK-NEXT: .quad 128 70; CHECK-NEXT: .quad jsIntCall 71; CHECK-NEXT: .quad 128 72; CHECK-NEXT: .quad spilledValue 73; CHECK-NEXT: .quad 304 74; CHECK-NEXT: .quad spilledStackMapValue 75; CHECK-NEXT: .quad 224 76; CHECK-NEXT: .quad liveConstant 77; CHECK-NEXT: .quad 64 78; CHECK-NEXT: .quad clobberLR 79; CHECK-NEXT: .quad 208 80 81; Num LargeConstants 82; CHECK-NEXT: .quad 4294967295 83; CHECK-NEXT: .quad 4294967296 84 85; Constant arguments 86; 87; CHECK-NEXT: .quad 1 88; CHECK-NEXT: .long .L{{.*}}-.L[[constantargs_BEGIN]] 89; CHECK-NEXT: .short 0 90; CHECK-NEXT: .short 4 91; SmallConstant 92; CHECK-NEXT: .byte 4 93; CHECK-NEXT: .byte 8 94; CHECK-NEXT: .short 0 95; CHECK-NEXT: .long 65535 96; SmallConstant 97; CHECK-NEXT: .byte 4 98; CHECK-NEXT: .byte 8 99; CHECK-NEXT: .short 0 100; CHECK-NEXT: .long 65536 101; SmallConstant 102; CHECK-NEXT: .byte 5 103; CHECK-NEXT: .byte 8 104; CHECK-NEXT: .short 0 105; CHECK-NEXT: .long 0 106; LargeConstant at index 0 107; CHECK-NEXT: .byte 5 108; CHECK-NEXT: .byte 8 109; CHECK-NEXT: .short 0 110; CHECK-NEXT: .long 1 111 112define void @constantargs() { 113entry: 114 %0 = inttoptr i64 244837814094590 to i8* 115 tail call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 1, i32 40, i8* %0, i32 0, i64 65535, i64 65536, i64 4294967295, i64 4294967296) 116 ret void 117} 118 119; Inline OSR Exit 120; 121; CHECK: .long .L{{.*}}-.L[[osrinline_BEGIN]] 122; CHECK-NEXT: .short 0 123; CHECK-NEXT: .short 2 124; CHECK-NEXT: .byte 1 125; CHECK-NEXT: .byte 8 126; CHECK-NEXT: .short {{[0-9]+}} 127; CHECK-NEXT: .long 0 128; CHECK-NEXT: .byte 1 129; CHECK-NEXT: .byte 8 130; CHECK-NEXT: .short {{[0-9]+}} 131; CHECK-NEXT: .long 0 132define void @osrinline(i64 %a, i64 %b) { 133entry: 134 ; Runtime void->void call. 135 call void inttoptr (i64 244837814094590 to void ()*)() 136 ; Followed by inline OSR patchpoint with 12-byte shadow and 2 live vars. 137 call void (i64, i32, ...) @llvm.experimental.stackmap(i64 3, i32 12, i64 %a, i64 %b) 138 ret void 139} 140 141; Cold OSR Exit 142; 143; 2 live variables in register. 144; 145; CHECK: .long .L{{.*}}-.L[[osrcold_BEGIN]] 146; CHECK-NEXT: .short 0 147; CHECK-NEXT: .short 2 148; CHECK-NEXT: .byte 1 149; CHECK-NEXT: .byte 8 150; CHECK-NEXT: .short {{[0-9]+}} 151; CHECK-NEXT: .long 0 152; CHECK-NEXT: .byte 1 153; CHECK-NEXT: .byte 8 154; CHECK-NEXT: .short {{[0-9]+}} 155; CHECK-NEXT: .long 0 156define void @osrcold(i64 %a, i64 %b) { 157entry: 158 %test = icmp slt i64 %a, %b 159 br i1 %test, label %ret, label %cold 160cold: 161 ; OSR patchpoint with 12-byte nop-slide and 2 live vars. 162 %thunk = inttoptr i64 244837814094590 to i8* 163 call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 4, i32 40, i8* %thunk, i32 0, i64 %a, i64 %b) 164 unreachable 165ret: 166 ret void 167} 168 169; Property Read 170; CHECK: .long .L{{.*}}-.L[[propertyRead_BEGIN]] 171; CHECK-NEXT: .short 0 172; CHECK-NEXT: .short 0 173; 174; FIXME: There are currently no stackmap entries. After moving to 175; AnyRegCC, we will have entries for the object and return value. 176define i64 @propertyRead(i64* %obj) { 177entry: 178 %resolveRead = inttoptr i64 244837814094590 to i8* 179 %result = call i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 5, i32 40, i8* %resolveRead, i32 1, i64* %obj) 180 %add = add i64 %result, 3 181 ret i64 %add 182} 183 184; Property Write 185; CHECK: .long .L{{.*}}-.L[[propertyWrite_BEGIN]] 186; CHECK-NEXT: .short 0 187; CHECK-NEXT: .short 2 188; CHECK-NEXT: .byte 1 189; CHECK-NEXT: .byte 8 190; CHECK-NEXT: .short {{[0-9]+}} 191; CHECK-NEXT: .long 0 192; CHECK-NEXT: .byte 1 193; CHECK-NEXT: .byte 8 194; CHECK-NEXT: .short {{[0-9]+}} 195; CHECK-NEXT: .long 0 196define void @propertyWrite(i64 %dummy1, i64* %obj, i64 %dummy2, i64 %a) { 197entry: 198 %resolveWrite = inttoptr i64 244837814094590 to i8* 199 call anyregcc void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 6, i32 40, i8* %resolveWrite, i32 2, i64* %obj, i64 %a) 200 ret void 201} 202 203; Void JS Call 204; 205; 2 live variables in registers. 206; 207; CHECK: .long .L{{.*}}-.L[[jsVoidCall_BEGIN]] 208; CHECK-NEXT: .short 0 209; CHECK-NEXT: .short 2 210; CHECK-NEXT: .byte 1 211; CHECK-NEXT: .byte 8 212; CHECK-NEXT: .short {{[0-9]+}} 213; CHECK-NEXT: .long 0 214; CHECK-NEXT: .byte 1 215; CHECK-NEXT: .byte 8 216; CHECK-NEXT: .short {{[0-9]+}} 217; CHECK-NEXT: .long 0 218define void @jsVoidCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) { 219entry: 220 %resolveCall = inttoptr i64 244837814094590 to i8* 221 call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 7, i32 40, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2) 222 ret void 223} 224 225; i64 JS Call 226; 227; 2 live variables in registers. 228; 229; CHECK: .long .L{{.*}}-.L[[jsIntCall_BEGIN]] 230; CHECK-NEXT: .short 0 231; CHECK-NEXT: .short 2 232; CHECK-NEXT: .byte 1 233; CHECK-NEXT: .byte 8 234; CHECK-NEXT: .short {{[0-9]+}} 235; CHECK-NEXT: .long 0 236; CHECK-NEXT: .byte 1 237; CHECK-NEXT: .byte 8 238; CHECK-NEXT: .short {{[0-9]+}} 239; CHECK-NEXT: .long 0 240define i64 @jsIntCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) { 241entry: 242 %resolveCall = inttoptr i64 244837814094590 to i8* 243 %result = call i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 8, i32 40, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2) 244 %add = add i64 %result, 3 245 ret i64 %add 246} 247 248; Spilled stack map values. 249; 250; Verify 28 stack map entries. 251; 252; CHECK: .long .L{{.*}}-.L[[spilledValue_BEGIN]] 253; CHECK-NEXT: .short 0 254; CHECK-NEXT: .short 28 255; 256; Check that at least one is a spilled entry from r31. 257; Location: Indirect FP + ... 258; CHECK: .byte 3 259; CHECK-NEXT: .byte 8 260; CHECK-NEXT: .short 31 261define 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) { 262entry: 263 call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 11, i32 40, 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) 264 ret void 265} 266 267; Spilled stack map values. 268; 269; Verify 30 stack map entries. 270; 271; CHECK: .long .L{{.*}}-.L[[spilledStackMapValue_BEGIN]] 272; CHECK-NEXT: .short 0 273; CHECK-NEXT: .short 30 274; 275; Check that at least one is a spilled entry from r31. 276; Location: Indirect FP + ... 277; CHECK: .byte 3 278; CHECK-NEXT: .byte 8 279; CHECK-NEXT: .short 31 280define 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) { 281entry: 282 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) 283 ret void 284} 285 286 287; Map a constant value. 288; 289; CHECK: .long .L{{.*}}-.L[[liveConstant_BEGIN]] 290; CHECK-NEXT: .short 0 291; 1 location 292; CHECK-NEXT: .short 1 293; Loc 0: SmallConstant 294; CHECK-NEXT: .byte 4 295; CHECK-NEXT: .byte 8 296; CHECK-NEXT: .short 0 297; CHECK-NEXT: .long 33 298 299define void @liveConstant() { 300 tail call void (i64, i32, ...) @llvm.experimental.stackmap(i64 15, i32 8, i32 33) 301 ret void 302} 303 304; Map a value when LR is the only free register. 305; 306; CHECK: .long .L{{.*}}-.L[[clobberLR_BEGIN]] 307; CHECK-NEXT: .short 0 308; 1 location 309; CHECK-NEXT: .short 1 310; Loc 0: Indirect FP (r31) - offset 311; CHECK-NEXT: .byte 3 312; CHECK-NEXT: .byte 4 313; CHECK-NEXT: .short 31 314; CHECK-NEXT: .long {{[0-9]+}} 315define void @clobberLR(i32 %a) { 316 tail call void asm sideeffect "nop", "~{r0},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r14},~{r15},~{r16},~{r17},~{r18},~{r19},~{r20},~{r21},~{r22},~{r23},~{r24},~{r25},~{r26},~{r27},~{r28},~{r29},~{r30},~{r31}"() nounwind 317 tail call void (i64, i32, ...) @llvm.experimental.stackmap(i64 16, i32 8, i32 %a) 318 ret void 319} 320 321declare void @llvm.experimental.stackmap(i64, i32, ...) 322declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...) 323declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...) 324