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