1; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7 -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 Functions
9; CHECK-NEXT:   .long 15
10; CHECK-NEXT:   .long _constantargs
11; CHECK-NEXT:   .long 8
12; CHECK-NEXT:   .long _osrinline
13; CHECK-NEXT:   .long 24
14; CHECK-NEXT:   .long _osrcold
15; CHECK-NEXT:   .long 8
16; CHECK-NEXT:   .long _propertyRead
17; CHECK-NEXT:   .long 8
18; CHECK-NEXT:   .long _propertyWrite
19; CHECK-NEXT:   .long 8
20; CHECK-NEXT:   .long _jsVoidCall
21; CHECK-NEXT:   .long 8
22; CHECK-NEXT:   .long _jsIntCall
23; CHECK-NEXT:   .long 8
24; CHECK-NEXT:   .long _spilledValue
25; CHECK-NEXT:   .long 56
26; CHECK-NEXT:   .long _spilledStackMapValue
27; CHECK-NEXT:   .long 56
28; CHECK-NEXT:   .long _spillSubReg
29; CHECK-NEXT:   .long 56
30; CHECK-NEXT:   .long _subRegOffset
31; CHECK-NEXT:   .long 56
32; CHECK-NEXT:   .long _liveConstant
33; CHECK-NEXT:   .long 8
34; CHECK-NEXT:   .long _directFrameIdx
35; CHECK-NEXT:   .long 56
36; CHECK-NEXT:   .long _longid
37; CHECK-NEXT:   .long 8
38; CHECK-NEXT:   .long _clobberScratch
39; CHECK-NEXT:   .long 56
40; Num LargeConstants
41; CHECK-NEXT:   .long   3
42; CHECK-NEXT:   .quad   2147483648
43; CHECK-NEXT:   .quad   4294967295
44; CHECK-NEXT:   .quad   4294967296
45; Num Callsites
46; CHECK-NEXT:   .long   19
47
48; Constant arguments
49;
50; CHECK-NEXT:   .quad   1
51; CHECK-NEXT:   .long   L{{.*}}-_constantargs
52; CHECK-NEXT:   .short  0
53; CHECK-NEXT:   .short  12
54; SmallConstant
55; CHECK-NEXT:   .byte   4
56; CHECK-NEXT:   .byte   8
57; CHECK-NEXT:   .short  0
58; CHECK-NEXT:   .long   -1
59; SmallConstant
60; CHECK-NEXT:   .byte   4
61; CHECK-NEXT:   .byte   8
62; CHECK-NEXT:   .short  0
63; CHECK-NEXT:   .long   -1
64; SmallConstant
65; CHECK-NEXT:   .byte   4
66; CHECK-NEXT:   .byte   8
67; CHECK-NEXT:   .short  0
68; CHECK-NEXT:   .long   65536
69; SmallConstant
70; CHECK-NEXT:   .byte   4
71; CHECK-NEXT:   .byte   8
72; CHECK-NEXT:   .short  0
73; CHECK-NEXT:   .long   2000000000
74; SmallConstant
75; CHECK-NEXT:   .byte   4
76; CHECK-NEXT:   .byte   8
77; CHECK-NEXT:   .short  0
78; CHECK-NEXT:   .long   2147483647
79; SmallConstant
80; CHECK-NEXT:   .byte   4
81; CHECK-NEXT:   .byte   8
82; CHECK-NEXT:   .short  0
83; CHECK-NEXT:   .long   -1
84; SmallConstant
85; CHECK-NEXT:   .byte   4
86; CHECK-NEXT:   .byte   8
87; CHECK-NEXT:   .short  0
88; CHECK-NEXT:   .long   -1
89; SmallConstant
90; CHECK-NEXT:   .byte   4
91; CHECK-NEXT:   .byte   8
92; CHECK-NEXT:   .short  0
93; CHECK-NEXT:   .long   0
94; LargeConstant at index 0
95; CHECK-NEXT:   .byte   5
96; CHECK-NEXT:   .byte   8
97; CHECK-NEXT:   .short  0
98; CHECK-NEXT:   .long   0
99; LargeConstant at index 1
100; CHECK-NEXT:   .byte   5
101; CHECK-NEXT:   .byte   8
102; CHECK-NEXT:   .short  0
103; CHECK-NEXT:   .long   1
104; LargeConstant at index 2
105; CHECK-NEXT:   .byte   5
106; CHECK-NEXT:   .byte   8
107; CHECK-NEXT:   .short  0
108; CHECK-NEXT:   .long   2
109; SmallConstant
110; CHECK-NEXT:   .byte   4
111; CHECK-NEXT:   .byte   8
112; CHECK-NEXT:   .short  0
113; CHECK-NEXT:   .long   -1
114
115define void @constantargs() {
116entry:
117  %0 = inttoptr i64 12345 to i8*
118  tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 1, i32 15, i8* %0, i32 0, i16 65535, i16 -1, i32 65536, i32 2000000000, i32 2147483647, i32 -1, i32 4294967295, i32 4294967296, i64 2147483648, i64 4294967295, i64 4294967296, i64 -1)
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   8
129; CHECK-NEXT:   .short  {{[0-9]+}}
130; CHECK-NEXT:   .long   0
131; CHECK-NEXT:   .byte   1
132; CHECK-NEXT:   .byte   8
133; CHECK-NEXT:   .short  {{[0-9]+}}
134; CHECK-NEXT:   .long  0
135define void @osrinline(i64 %a, i64 %b) {
136entry:
137  ; Runtime void->void call.
138  call void inttoptr (i64 -559038737 to void ()*)()
139  ; Followed by inline OSR patchpoint with 12-byte shadow and 2 live vars.
140  call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 3, i32 12, i64 %a, i64 %b)
141  ret void
142}
143
144; Cold OSR Exit
145;
146; 2 live variables in register.
147;
148; CHECK-LABEL:  .long   L{{.*}}-_osrcold
149; CHECK-NEXT:   .short  0
150; CHECK-NEXT:   .short  2
151; CHECK-NEXT:   .byte   1
152; CHECK-NEXT:   .byte   8
153; CHECK-NEXT:   .short  {{[0-9]+}}
154; CHECK-NEXT:   .long   0
155; CHECK-NEXT:   .byte   1
156; CHECK-NEXT:   .byte   8
157; CHECK-NEXT:   .short  {{[0-9]+}}
158; CHECK-NEXT:   .long   0
159define void @osrcold(i64 %a, i64 %b) {
160entry:
161  %test = icmp slt i64 %a, %b
162  br i1 %test, label %ret, label %cold
163cold:
164  ; OSR patchpoint with 12-byte nop-slide and 2 live vars.
165  %thunk = inttoptr i64 -559038737 to i8*
166  call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 4, i32 15, i8* %thunk, i32 0, i64 %a, i64 %b)
167  unreachable
168ret:
169  ret void
170}
171
172; Property Read
173; CHECK-LABEL:  .long   L{{.*}}-_propertyRead
174; CHECK-NEXT:   .short  0
175; CHECK-NEXT:   .short  2
176; CHECK-NEXT:   .byte   1
177; CHECK-NEXT:   .byte   8
178; CHECK-NEXT:   .short  {{[0-9]+}}
179; CHECK-NEXT:   .long   0
180; CHECK-NEXT:   .byte   1
181; CHECK-NEXT:   .byte   8
182; CHECK-NEXT:   .short  {{[0-9]+}}
183; CHECK-NEXT:   .long   0
184define i64 @propertyRead(i64* %obj) {
185entry:
186  %resolveRead = inttoptr i64 -559038737 to i8*
187  %result = call anyregcc i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 5, i32 15, i8* %resolveRead, i32 1, i64* %obj)
188  %add = add i64 %result, 3
189  ret i64 %add
190}
191
192; Property Write
193; CHECK-LABEL:  .long   L{{.*}}-_propertyWrite
194; CHECK-NEXT:   .short  0
195; CHECK-NEXT:   .short  2
196; CHECK-NEXT:   .byte   1
197; CHECK-NEXT:   .byte   8
198; CHECK-NEXT:   .short  {{[0-9]+}}
199; CHECK-NEXT:   .long   0
200; CHECK-NEXT:   .byte   1
201; CHECK-NEXT:   .byte   8
202; CHECK-NEXT:   .short  {{[0-9]+}}
203; CHECK-NEXT:   .long   0
204define void @propertyWrite(i64 %dummy1, i64* %obj, i64 %dummy2, i64 %a) {
205entry:
206  %resolveWrite = inttoptr i64 -559038737 to i8*
207  call anyregcc void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 6, i32 15, i8* %resolveWrite, i32 2, i64* %obj, i64 %a)
208  ret void
209}
210
211; Void JS Call
212;
213; 2 live variables in registers.
214;
215; CHECK-LABEL:  .long   L{{.*}}-_jsVoidCall
216; CHECK-NEXT:   .short  0
217; CHECK-NEXT:   .short  2
218; CHECK-NEXT:   .byte   1
219; CHECK-NEXT:   .byte   8
220; CHECK-NEXT:   .short  {{[0-9]+}}
221; CHECK-NEXT:   .long   0
222; CHECK-NEXT:   .byte   1
223; CHECK-NEXT:   .byte   8
224; CHECK-NEXT:   .short  {{[0-9]+}}
225; CHECK-NEXT:   .long   0
226define void @jsVoidCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) {
227entry:
228  %resolveCall = inttoptr i64 -559038737 to i8*
229  call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 7, i32 15, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2)
230  ret void
231}
232
233; i64 JS Call
234;
235; 2 live variables in registers.
236;
237; CHECK-LABEL:  .long   L{{.*}}-_jsIntCall
238; CHECK-NEXT:   .short  0
239; CHECK-NEXT:   .short  2
240; CHECK-NEXT:   .byte   1
241; CHECK-NEXT:   .byte   8
242; CHECK-NEXT:   .short  {{[0-9]+}}
243; CHECK-NEXT:   .long   0
244; CHECK-NEXT:   .byte   1
245; CHECK-NEXT:   .byte   8
246; CHECK-NEXT:   .short  {{[0-9]+}}
247; CHECK-NEXT:   .long   0
248define i64 @jsIntCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) {
249entry:
250  %resolveCall = inttoptr i64 -559038737 to i8*
251  %result = call i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 8, i32 15, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2)
252  %add = add i64 %result, 3
253  ret i64 %add
254}
255
256; Spilled stack map values.
257;
258; Verify 17 stack map entries.
259;
260; CHECK-LABEL:  .long L{{.*}}-_spilledValue
261; CHECK-NEXT:   .short 0
262; CHECK-NEXT:   .short 17
263;
264; Check that at least one is a spilled entry from RBP.
265; Location: Indirect RBP + ...
266; CHECK:        .byte 3
267; CHECK-NEXT:   .byte 8
268; CHECK-NEXT:   .short 6
269define 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) {
270entry:
271  call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 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)
272  ret void
273}
274
275; Spilled stack map values.
276;
277; Verify 17 stack map entries.
278;
279; CHECK-LABEL:  .long L{{.*}}-_spilledStackMapValue
280; CHECK-NEXT:   .short 0
281; CHECK-NEXT:   .short 17
282;
283; Check that at least one is a spilled entry from RBP.
284; Location: Indirect RBP + ...
285; CHECK:        .byte 3
286; CHECK-NEXT:   .byte 8
287; CHECK-NEXT:   .short 6
288define 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) {
289entry:
290  call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 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)
291  ret void
292}
293
294; Spill a subregister stackmap operand.
295;
296; CHECK-LABEL:  .long L{{.*}}-_spillSubReg
297; CHECK-NEXT:   .short 0
298; 4 locations
299; CHECK-NEXT:   .short 1
300;
301; Check that the subregister operand is a 4-byte spill.
302; Location: Indirect, 4-byte, RBP + ...
303; CHECK:        .byte 3
304; CHECK-NEXT:   .byte 4
305; CHECK-NEXT:   .short 6
306define void @spillSubReg(i64 %arg) #0 {
307bb:
308  br i1 undef, label %bb1, label %bb2
309
310bb1:
311  unreachable
312
313bb2:
314  %tmp = load i64* inttoptr (i64 140685446136880 to i64*)
315  br i1 undef, label %bb16, label %bb17
316
317bb16:
318  unreachable
319
320bb17:
321  %tmp32 = trunc i64 %tmp to i32
322  br i1 undef, label %bb60, label %bb61
323
324bb60:
325  tail call void asm sideeffect "nop", "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() nounwind
326  tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 13, i32 5, i32 %tmp32)
327  unreachable
328
329bb61:
330  unreachable
331}
332
333; Map a single byte subregister. There is no DWARF register number, so
334; we expect the register to be encoded with the proper size and spill offset. We don't know which
335;
336; CHECK-LABEL:  .long L{{.*}}-_subRegOffset
337; CHECK-NEXT:   .short 0
338; 2 locations
339; CHECK-NEXT:   .short 2
340;
341; Check that the subregister operands are 1-byte spills.
342; Location 0: Register, 4-byte, AL
343; CHECK-NEXT:   .byte 1
344; CHECK-NEXT:   .byte 1
345; CHECK-NEXT:   .short 0
346; CHECK-NEXT:   .long 0
347;
348; Location 1: Register, 4-byte, BL
349; CHECK-NEXT:   .byte 1
350; CHECK-NEXT:   .byte 1
351; CHECK-NEXT:   .short 3
352; CHECK-NEXT:   .long 0
353define void @subRegOffset(i16 %arg) {
354  %v = mul i16 %arg, 5
355  %a0 = trunc i16 %v to i8
356  tail call void asm sideeffect "nop", "~{bx}"() nounwind
357  %arghi = lshr i16 %v, 8
358  %a1 = trunc i16 %arghi to i8
359  tail call void asm sideeffect "nop", "~{cx},~{dx},~{bp},~{si},~{di},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() nounwind
360  tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 14, i32 5, i8 %a0, i8 %a1)
361  ret void
362}
363
364; Map a constant value.
365;
366; CHECK-LABEL:  .long L{{.*}}-_liveConstant
367; CHECK-NEXT:   .short 0
368; 1 location
369; CHECK-NEXT:   .short 1
370; Loc 0: SmallConstant
371; CHECK-NEXT:   .byte   4
372; CHECK-NEXT:   .byte   8
373; CHECK-NEXT:   .short  0
374; CHECK-NEXT:   .long   33
375
376define void @liveConstant() {
377  tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 15, i32 5, i32 33)
378  ret void
379}
380
381; Directly map an alloca's address.
382;
383; Callsite 16
384; CHECK-LABEL:  .long L{{.*}}-_directFrameIdx
385; CHECK-NEXT:   .short 0
386; 1 location
387; CHECK-NEXT:   .short	1
388; Loc 0: Direct RBP - ofs
389; CHECK-NEXT:   .byte	2
390; CHECK-NEXT:   .byte	8
391; CHECK-NEXT:   .short	6
392; CHECK-NEXT:   .long
393
394; Callsite 17
395; CHECK-LABEL:  .long	L{{.*}}-_directFrameIdx
396; CHECK-NEXT:   .short	0
397; 2 locations
398; CHECK-NEXT:   .short	2
399; Loc 0: Direct RBP - ofs
400; CHECK-NEXT:   .byte	2
401; CHECK-NEXT:   .byte	8
402; CHECK-NEXT:   .short	6
403; CHECK-NEXT:   .long
404; Loc 1: Direct RBP - ofs
405; CHECK-NEXT:   .byte	2
406; CHECK-NEXT:   .byte	8
407; CHECK-NEXT:   .short	6
408; CHECK-NEXT:   .long
409define void @directFrameIdx() {
410entry:
411  %metadata1 = alloca i64, i32 3, align 8
412  store i64 11, i64* %metadata1
413  store i64 12, i64* %metadata1
414  store i64 13, i64* %metadata1
415  call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 16, i32 0, i64* %metadata1)
416  %metadata2 = alloca i8, i32 4, align 8
417  %metadata3 = alloca i16, i32 4, align 8
418  call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 17, i32 5, i8* null, i32 0, i8* %metadata2, i16* %metadata3)
419  ret void
420}
421
422; Test a 64-bit ID.
423;
424; CHECK:        .quad 4294967295
425; CHECK-LABEL:  .long L{{.*}}-_longid
426; CHECK:        .quad 4294967296
427; CHECK-LABEL:  .long L{{.*}}-_longid
428; CHECK:        .quad 9223372036854775807
429; CHECK-LABEL:  .long L{{.*}}-_longid
430; CHECK:        .quad -1
431; CHECK-LABEL:  .long L{{.*}}-_longid
432define void @longid() {
433entry:
434  tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 4294967295, i32 0, i8* null, i32 0)
435  tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 4294967296, i32 0, i8* null, i32 0)
436  tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 9223372036854775807, i32 0, i8* null, i32 0)
437  tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 -1, i32 0, i8* null, i32 0)
438  ret void
439}
440
441; Map a value when R11 is the only free register.
442; The scratch register should not be used for a live stackmap value.
443;
444; CHECK-LABEL:  .long L{{.*}}-_clobberScratch
445; CHECK-NEXT:   .short 0
446; 1 location
447; CHECK-NEXT:   .short 1
448; Loc 0: Indirect fp - offset
449; CHECK-NEXT:   .byte   3
450; CHECK-NEXT:   .byte   4
451; CHECK-NEXT:   .short  6
452; CHECK-NEXT:   .long   -{{[0-9]+}}
453define void @clobberScratch(i32 %a) {
454  tail call void asm sideeffect "nop", "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di},~{r8},~{r9},~{r10},~{r12},~{r13},~{r14},~{r15}"() nounwind
455  tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 16, i32 8, i32 %a)
456  ret void
457}
458
459declare void @llvm.experimental.stackmap(i64, i32, ...)
460declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)
461declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)
462