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