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