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 LargeConstants
9; CHECK-NEXT:   .long   1
10; CHECK-NEXT:   .quad   4294967296
11; Num Callsites
12; CHECK-NEXT:   .long   18
13
14; Constant arguments
15;
16; CHECK-NEXT:   .quad   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 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 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-LABEL:  .long   L{{.*}}-_osrinline
51; CHECK-NEXT:   .short  0
52; CHECK-NEXT:   .short  2
53; CHECK-NEXT:   .byte   1
54; CHECK-NEXT:   .byte   8
55; CHECK-NEXT:   .short  {{[0-9]+}}
56; CHECK-NEXT:   .long   0
57; CHECK-NEXT:   .byte   1
58; CHECK-NEXT:   .byte   8
59; CHECK-NEXT:   .short  {{[0-9]+}}
60; CHECK-NEXT:   .long  0
61define void @osrinline(i64 %a, i64 %b) {
62entry:
63  ; Runtime void->void call.
64  call void inttoptr (i64 -559038737 to void ()*)()
65  ; Followed by inline OSR patchpoint with 12-byte shadow and 2 live vars.
66  call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 3, i32 12, i64 %a, i64 %b)
67  ret void
68}
69
70; Cold OSR Exit
71;
72; 2 live variables in register.
73;
74; CHECK-LABEL:  .long   L{{.*}}-_osrcold
75; CHECK-NEXT:   .short  0
76; CHECK-NEXT:   .short  2
77; CHECK-NEXT:   .byte   1
78; CHECK-NEXT:   .byte   8
79; CHECK-NEXT:   .short  {{[0-9]+}}
80; CHECK-NEXT:   .long   0
81; CHECK-NEXT:   .byte   1
82; CHECK-NEXT:   .byte   8
83; CHECK-NEXT:   .short  {{[0-9]+}}
84; CHECK-NEXT:   .long   0
85define void @osrcold(i64 %a, i64 %b) {
86entry:
87  %test = icmp slt i64 %a, %b
88  br i1 %test, label %ret, label %cold
89cold:
90  ; OSR patchpoint with 12-byte nop-slide and 2 live vars.
91  %thunk = inttoptr i64 -559038737 to i8*
92  call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 4, i32 15, i8* %thunk, i32 0, i64 %a, i64 %b)
93  unreachable
94ret:
95  ret void
96}
97
98; Property Read
99; CHECK-LABEL:  .long   L{{.*}}-_propertyRead
100; CHECK-NEXT:   .short  0
101; CHECK-NEXT:   .short  2
102; CHECK-NEXT:   .byte   1
103; CHECK-NEXT:   .byte   8
104; CHECK-NEXT:   .short  {{[0-9]+}}
105; CHECK-NEXT:   .long   0
106; CHECK-NEXT:   .byte   1
107; CHECK-NEXT:   .byte   8
108; CHECK-NEXT:   .short  {{[0-9]+}}
109; CHECK-NEXT:   .long   0
110define i64 @propertyRead(i64* %obj) {
111entry:
112  %resolveRead = inttoptr i64 -559038737 to i8*
113  %result = call anyregcc i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 5, i32 15, i8* %resolveRead, i32 1, i64* %obj)
114  %add = add i64 %result, 3
115  ret i64 %add
116}
117
118; Property Write
119; CHECK-LABEL:  .long   L{{.*}}-_propertyWrite
120; CHECK-NEXT:   .short  0
121; CHECK-NEXT:   .short  2
122; CHECK-NEXT:   .byte   1
123; CHECK-NEXT:   .byte   8
124; CHECK-NEXT:   .short  {{[0-9]+}}
125; CHECK-NEXT:   .long   0
126; CHECK-NEXT:   .byte   1
127; CHECK-NEXT:   .byte   8
128; CHECK-NEXT:   .short  {{[0-9]+}}
129; CHECK-NEXT:   .long   0
130define void @propertyWrite(i64 %dummy1, i64* %obj, i64 %dummy2, i64 %a) {
131entry:
132  %resolveWrite = inttoptr i64 -559038737 to i8*
133  call anyregcc void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 6, i32 15, i8* %resolveWrite, i32 2, i64* %obj, i64 %a)
134  ret void
135}
136
137; Void JS Call
138;
139; 2 live variables in registers.
140;
141; CHECK-LABEL:  .long   L{{.*}}-_jsVoidCall
142; CHECK-NEXT:   .short  0
143; CHECK-NEXT:   .short  2
144; CHECK-NEXT:   .byte   1
145; CHECK-NEXT:   .byte   8
146; CHECK-NEXT:   .short  {{[0-9]+}}
147; CHECK-NEXT:   .long   0
148; CHECK-NEXT:   .byte   1
149; CHECK-NEXT:   .byte   8
150; CHECK-NEXT:   .short  {{[0-9]+}}
151; CHECK-NEXT:   .long   0
152define void @jsVoidCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) {
153entry:
154  %resolveCall = inttoptr i64 -559038737 to i8*
155  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)
156  ret void
157}
158
159; i64 JS Call
160;
161; 2 live variables in registers.
162;
163; CHECK-LABEL:  .long   L{{.*}}-_jsIntCall
164; CHECK-NEXT:   .short  0
165; CHECK-NEXT:   .short  2
166; CHECK-NEXT:   .byte   1
167; CHECK-NEXT:   .byte   8
168; CHECK-NEXT:   .short  {{[0-9]+}}
169; CHECK-NEXT:   .long   0
170; CHECK-NEXT:   .byte   1
171; CHECK-NEXT:   .byte   8
172; CHECK-NEXT:   .short  {{[0-9]+}}
173; CHECK-NEXT:   .long   0
174define i64 @jsIntCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) {
175entry:
176  %resolveCall = inttoptr i64 -559038737 to i8*
177  %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)
178  %add = add i64 %result, 3
179  ret i64 %add
180}
181
182; Spilled stack map values.
183;
184; Verify 17 stack map entries.
185;
186; CHECK-LABEL:  .long L{{.*}}-_spilledValue
187; CHECK-NEXT:   .short 0
188; CHECK-NEXT:   .short 17
189;
190; Check that at least one is a spilled entry from RBP.
191; Location: Indirect RBP + ...
192; CHECK:        .byte 3
193; CHECK-NEXT:   .byte 8
194; CHECK-NEXT:   .short 6
195define 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) {
196entry:
197  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)
198  ret void
199}
200
201; Spilled stack map values.
202;
203; Verify 17 stack map entries.
204;
205; CHECK-LABEL:  .long L{{.*}}-_spilledStackMapValue
206; CHECK-NEXT:   .short 0
207; CHECK-NEXT:   .short 17
208;
209; Check that at least one is a spilled entry from RBP.
210; Location: Indirect RBP + ...
211; CHECK:        .byte 3
212; CHECK-NEXT:   .byte 8
213; CHECK-NEXT:   .short 6
214define 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) {
215entry:
216  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)
217  ret void
218}
219
220; Spill a subregister stackmap operand.
221;
222; CHECK-LABEL:  .long L{{.*}}-_spillSubReg
223; CHECK-NEXT:   .short 0
224; 4 locations
225; CHECK-NEXT:   .short 1
226;
227; Check that the subregister operand is a 4-byte spill.
228; Location: Indirect, 4-byte, RBP + ...
229; CHECK:        .byte 3
230; CHECK-NEXT:   .byte 4
231; CHECK-NEXT:   .short 6
232define void @spillSubReg(i64 %arg) #0 {
233bb:
234  br i1 undef, label %bb1, label %bb2
235
236bb1:
237  unreachable
238
239bb2:
240  %tmp = load i64* inttoptr (i64 140685446136880 to i64*)
241  br i1 undef, label %bb16, label %bb17
242
243bb16:
244  unreachable
245
246bb17:
247  %tmp32 = trunc i64 %tmp to i32
248  br i1 undef, label %bb60, label %bb61
249
250bb60:
251  tail call void asm sideeffect "nop", "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() nounwind
252  tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 13, i32 5, i32 %tmp32)
253  unreachable
254
255bb61:
256  unreachable
257}
258
259; Map a single byte subregister. There is no DWARF register number, so
260; we expect the register to be encoded with the proper size and spill offset. We don't know which
261;
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 (i64, i32, ...)* @llvm.experimental.stackmap(i64 14, i32 5, i8 %a0, i8 %a1)
287  ret void
288}
289
290; Map a constant value.
291;
292; CHECK-LABEL:  .long L{{.*}}-_liveConstant
293; CHECK-NEXT:   .short 0
294; 1 location
295; CHECK-NEXT:   .short 1
296; Loc 0: SmallConstant
297; CHECK-NEXT:   .byte   4
298; CHECK-NEXT:   .byte   8
299; CHECK-NEXT:   .short  0
300; CHECK-NEXT:   .long   33
301
302define void @liveConstant() {
303  tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 15, i32 5, i32 33)
304  ret void
305}
306
307; Directly map an alloca's address.
308;
309; Callsite 16
310; CHECK-LABEL:  .long L{{.*}}-_directFrameIdx
311; CHECK-NEXT:   .short 0
312; 1 location
313; CHECK-NEXT:   .short	1
314; Loc 0: Direct RBP - ofs
315; CHECK-NEXT:   .byte	2
316; CHECK-NEXT:   .byte	8
317; CHECK-NEXT:   .short	6
318; CHECK-NEXT:   .long
319
320; Callsite 17
321; CHECK-LABEL:  .long	L{{.*}}-_directFrameIdx
322; CHECK-NEXT:   .short	0
323; 2 locations
324; CHECK-NEXT:   .short	2
325; Loc 0: Direct RBP - ofs
326; CHECK-NEXT:   .byte	2
327; CHECK-NEXT:   .byte	8
328; CHECK-NEXT:   .short	6
329; CHECK-NEXT:   .long
330; Loc 1: Direct RBP - ofs
331; CHECK-NEXT:   .byte	2
332; CHECK-NEXT:   .byte	8
333; CHECK-NEXT:   .short	6
334; CHECK-NEXT:   .long
335define void @directFrameIdx() {
336entry:
337  %metadata1 = alloca i64, i32 3, align 8
338  store i64 11, i64* %metadata1
339  store i64 12, i64* %metadata1
340  store i64 13, i64* %metadata1
341  call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 16, i32 0, i64* %metadata1)
342  %metadata2 = alloca i8, i32 4, align 8
343  %metadata3 = alloca i16, i32 4, align 8
344  call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 17, i32 5, i8* null, i32 0, i8* %metadata2, i16* %metadata3)
345  ret void
346}
347
348; Test a 64-bit ID.
349;
350; CHECK:        .quad 4294967295
351; CHECK-LABEL:  .long L{{.*}}-_longid
352; CHECK:        .quad 4294967296
353; CHECK-LABEL:  .long L{{.*}}-_longid
354; CHECK:        .quad 9223372036854775807
355; CHECK-LABEL:  .long L{{.*}}-_longid
356; CHECK:        .quad -1
357; CHECK-LABEL:  .long L{{.*}}-_longid
358define void @longid() {
359entry:
360  tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 4294967295, i32 0, i8* null, i32 0)
361  tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 4294967296, i32 0, i8* null, i32 0)
362  tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 9223372036854775807, i32 0, i8* null, i32 0)
363  tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 -1, i32 0, i8* null, i32 0)
364  ret void
365}
366
367declare void @llvm.experimental.stackmap(i64, i32, ...)
368declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)
369declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)
370