1; RUN: llc < %s -verify-machineinstrs -stack-symbol-ordering=0 -mtriple="x86_64-pc-linux-gnu" | FileCheck %s
2; RUN: llc < %s -verify-machineinstrs -stack-symbol-ordering=0 -mtriple="x86_64-pc-unknown-elf" | FileCheck %s
3
4; This test is a sanity check to ensure statepoints are generating StackMap
5; sections correctly.  This is not intended to be a rigorous test of the
6; StackMap format (see the stackmap tests for that).
7
8target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
9
10declare zeroext i1 @return_i1()
11
12define i1 @test(i32 addrspace(1)* %ptr_base, i32 %arg)
13  gc "statepoint-example" {
14; CHECK-LABEL: test:
15; Do we see two spills for the local values and the store to the
16; alloca?
17; CHECK: subq	$40, %rsp
18; CHECK: movq	$0,   24(%rsp)
19; CHECK: movq	%rdi, 16(%rsp)
20; CHECK: movq	%rax, 8(%rsp)
21; CHECK: callq return_i1
22; CHECK: addq	$40, %rsp
23; CHECK: retq
24entry:
25  %metadata1 = alloca i32 addrspace(1)*, i32 2, align 8
26  store i32 addrspace(1)* null, i32 addrspace(1)** %metadata1
27  %ptr_derived = getelementptr i32, i32 addrspace(1)* %ptr_base, i32 %arg
28  %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %ptr_base, i32 addrspace(1)* %ptr_derived, i32 addrspace(1)* null), "deopt" (i32 addrspace(1)* %ptr_base, i32 addrspace(1)* null)]
29  %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
30  %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0)
31  %b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 1)
32  %c = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 2, i32 2)
33;
34  ret i1 %call1
35}
36
37; This is similar to the previous test except that we have derived pointer as
38; argument to the function. Despite that this can not happen after the
39; RewriteSafepointForGC pass, lowering should be able to handle it anyway.
40define i1 @test_derived_arg(i32 addrspace(1)* %ptr_base,
41                            i32 addrspace(1)* %ptr_derived)
42  gc "statepoint-example" {
43; CHECK-LABEL: test_derived_arg
44; Do we see two spills for the local values and the store to the
45; alloca?
46; CHECK: subq	$40, %rsp
47; CHECK: movq	$0,   24(%rsp)
48; CHECK: movq	%rdi, 16(%rsp)
49; CHECK: movq	%rsi, 8(%rsp)
50; CHECK: callq return_i1
51; CHECK: addq	$40, %rsp
52; CHECK: retq
53entry:
54  %metadata1 = alloca i32 addrspace(1)*, i32 2, align 8
55  store i32 addrspace(1)* null, i32 addrspace(1)** %metadata1
56  %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %ptr_base, i32 addrspace(1)* %ptr_derived, i32 addrspace(1)* null), "deopt" (i32 addrspace(1)* %ptr_base, i32 addrspace(1)* null)]
57  %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
58  %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0)
59  %b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 1)
60  %c = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 2, i32 2)
61;
62  ret i1 %call1
63}
64
65; Simple test case to check that we emit the ID field correctly
66define i1 @test_id() gc "statepoint-example" {
67; CHECK-LABEL: test_id
68entry:
69  %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 237, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0)
70  %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
71  ret i1 %call1
72}
73
74; This test checks that when SP is changed in the function
75; (e.g. passing arguments on stack), the stack map entry
76; takes this adjustment into account.
77declare void @many_arg(i64, i64, i64, i64, i64, i64, i64, i64)
78
79define i32 @test_spadj(i32 addrspace(1)* %p) gc "statepoint-example" {
80  ; CHECK-LABEL: test_spadj
81  ; CHECK: movq %rdi, (%rsp)
82  ; CHECK: xorl %edi, %edi
83  ; CHECK: xorl %esi, %esi
84  ; CHECK: xorl %edx, %edx
85  ; CHECK: xorl %ecx, %ecx
86  ; CHECK: xorl %r8d, %r8d
87  ; CHECK: xorl %r9d, %r9d
88  ; CHECK: pushq $0
89  ; CHECK: pushq $0
90  ; CHECK: callq many_arg
91  ; CHECK: addq $16, %rsp
92  ; CHECK: movq (%rsp)
93  %statepoint_token = call token (i64, i32, void (i64, i64, i64, i64, i64, i64, i64, i64)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi64i64i64i64i64i64i64i64f(i64 0, i32 0, void (i64, i64, i64, i64, i64, i64, i64, i64)* @many_arg, i32 8, i32 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %p)]
94  %p.relocated = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %statepoint_token, i32 0, i32 0) ; (%p, %p)
95  %ld = load i32, i32 addrspace(1)* %p.relocated
96  ret i32 %ld
97}
98
99; Test that function arguments at fixed stack offset
100; can be directly encoded in the stack map, without
101; spilling.
102%struct = type { i64, i64, i64 }
103
104declare void @use(%struct*)
105
106define void @test_fixed_arg(%struct* byval(%struct) %x) gc "statepoint-example" {
107; CHECK-LABEL: test_fixed_arg
108; CHECK: pushq %rax
109; CHECK: leaq 16(%rsp), %rdi
110; Should not spill fixed stack address.
111; CHECK-NOT: movq %rdi, (%rsp)
112; CHECK: callq use
113; CHECK: popq %rax
114; CHECK: retq
115entry:
116  br label %bb
117
118bb:                                               ; preds = %entry
119  %statepoint_token = call token (i64, i32, void (%struct*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp0s_structsf(i64 0, i32 0, void (%struct*)* @use, i32 1, i32 0, %struct* %x, i32 0, i32 0) ["deopt" (%struct* %x)]
120  ret void
121}
122
123declare token @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...)
124declare token @llvm.experimental.gc.statepoint.p0f_isVoidi64i64i64i64i64i64i64i64f(i64, i32, void (i64, i64, i64, i64, i64, i64, i64, i64)*, i32, i32, ...)
125declare token @llvm.experimental.gc.statepoint.p0f_isVoidp0s_structsf(i64, i32, void (%struct*)*, i32, i32, ...)
126declare i1 @llvm.experimental.gc.result.i1(token)
127declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) #3
128
129; CHECK-LABEL: .section .llvm_stackmaps
130; CHECK-NEXT:  __LLVM_StackMaps:
131; Header
132; CHECK-NEXT:   .byte 3
133; CHECK-NEXT:   .byte 0
134; CHECK-NEXT:   .short 0
135; Num Functions
136; CHECK-NEXT:   .long 5
137; Num LargeConstants
138; CHECK-NEXT:   .long 0
139; Num Callsites
140; CHECK-NEXT:   .long 5
141
142; Functions and stack size
143; CHECK-NEXT:   .quad test
144; CHECK-NEXT:   .quad 40
145; CHECK-NEXT:   .quad 1
146; CHECK-NEXT:   .quad test_derived_arg
147; CHECK-NEXT:   .quad 40
148; CHECK-NEXT:   .quad 1
149; CHECK-NEXT:   .quad test_id
150; CHECK-NEXT:   .quad 8
151; CHECK-NEXT:   .quad 1
152; CHECK-NEXT:   .quad test_spadj
153; CHECK-NEXT:   .quad 8
154; CHECK-NEXT:   .quad 1
155; CHECK-NEXT:   .quad test_fixed_arg
156; CHECK-NEXT:   .quad 8
157; CHECK-NEXT:   .quad 1
158
159;
160; test
161;
162
163; Statepoint ID
164; CHECK-NEXT: .quad	0
165
166; Callsites
167; Constant arguments
168; CHECK-NEXT: .long	.Ltmp0-test
169; CHECK: .short	0
170; CHECK: .short	11
171; SmallConstant (0)
172; CHECK: .byte	4
173; CHECK-NEXT:   .byte   0
174; CHECK: .short 8
175; CHECK: .short	0
176; CHECK-NEXT:   .short  0
177; CHECK: .long	0
178; SmallConstant (0)
179; CHECK: .byte	4
180; CHECK-NEXT:   .byte   0
181; CHECK: .short 8
182; CHECK: .short	0
183; CHECK-NEXT:   .short  0
184; CHECK: .long	0
185; SmallConstant (2)
186; CHECK: .byte	4
187; CHECK-NEXT:   .byte   0
188; CHECK: .short 8
189; CHECK: .short	0
190; CHECK-NEXT:   .short  0
191; CHECK: .long	2
192; Indirect Spill Slot [RSP+0]
193; CHECK: .byte	3
194; CHECK-NEXT:   .byte   0
195; CHECK: .short 8
196; CHECK: .short	7
197; CHECK-NEXT:   .short  0
198; CHECK: .long	16
199; SmallConstant  (0)
200; CHECK: .byte	4
201; CHECK-NEXT:   .byte   0
202; CHECK: .short 8
203; CHECK: .short	0
204; CHECK-NEXT:   .short  0
205; CHECK: .long	0
206; SmallConstant  (0)
207; CHECK: .byte	4
208; CHECK-NEXT:   .byte   0
209; CHECK: .short 8
210; CHECK: .short	0
211; CHECK-NEXT:   .short  0
212; CHECK: .long	0
213; SmallConstant  (0)
214; CHECK: .byte	4
215; CHECK-NEXT:   .byte   0
216; CHECK: .short 8
217; CHECK: .short	0
218; CHECK-NEXT:   .short  0
219; CHECK: .long	0
220; Indirect Spill Slot [RSP+16]
221; CHECK: .byte	3
222; CHECK-NEXT:   .byte   0
223; CHECK: .short 8
224; CHECK: .short	7
225; CHECK-NEXT:   .short  0
226; CHECK: .long	16
227; Indirect Spill Slot [RSP+8]
228; CHECK: .byte	3
229; CHECK-NEXT:   .byte   0
230; CHECK: .short 8
231; CHECK: .short	7
232; CHECK-NEXT:   .short  0
233; CHECK: .long	8
234; Indirect Spill Slot [RSP+16]
235; CHECK: .byte	3
236; CHECK-NEXT:   .byte   0
237; CHECK: .short 8
238; CHECK: .short	7
239; CHECK-NEXT:   .short  0
240; CHECK: .long	16
241; Indirect Spill Slot [RSP+16]
242; CHECK: .byte	3
243; CHECK-NEXT:   .byte   0
244; CHECK: .short 8
245; CHECK: .short	7
246; CHECK-NEXT:   .short  0
247; CHECK: .long	16
248
249; No Padding or LiveOuts
250; CHECK: .short	0
251; CHECK: .short	0
252; CHECK: .p2align	3
253
254;
255; test_derived_arg
256
257; Statepoint ID
258; CHECK-NEXT: .quad	0
259
260; Callsites
261; Constant arguments
262; CHECK-NEXT: .long	.Ltmp1-test_derived_arg
263; CHECK: .short	0
264; CHECK: .short	11
265; SmallConstant (0)
266; CHECK: .byte	4
267; CHECK-NEXT:   .byte   0
268; CHECK: .short 8
269; CHECK: .short	0
270; CHECK-NEXT:   .short  0
271; CHECK: .long	0
272; SmallConstant (2)
273; CHECK: .byte	4
274; CHECK-NEXT:   .byte   0
275; CHECK: .short 8
276; CHECK: .short	0
277; CHECK-NEXT:   .short  0
278; CHECK: .long	2
279; Indirect Spill Slot [RSP+0]
280; CHECK: .byte	3
281; CHECK-NEXT:   .byte   0
282; CHECK: .short 8
283; CHECK: .short	7
284; CHECK-NEXT:   .short  0
285; CHECK: .long	16
286; SmallConstant  (0)
287; CHECK: .byte	4
288; CHECK-NEXT:   .byte   0
289; CHECK: .short 8
290; CHECK: .short	0
291; CHECK-NEXT:   .short  0
292; CHECK: .long	0
293; SmallConstant  (0)
294; CHECK: .byte	4
295; CHECK-NEXT:   .byte   0
296; CHECK: .short 8
297; CHECK: .short	0
298; CHECK-NEXT:   .short  0
299; CHECK: .long	0
300; SmallConstant  (0)
301; CHECK: .byte	4
302; CHECK-NEXT:   .byte   0
303; CHECK: .short 8
304; CHECK: .short	0
305; CHECK-NEXT:   .short  0
306; CHECK: .long	0
307; Indirect Spill Slot [RSP+16]
308; CHECK: .byte	3
309; CHECK-NEXT:   .byte   0
310; CHECK: .short 8
311; CHECK: .short	7
312; CHECK-NEXT:   .short  0
313; CHECK: .long	16
314; Indirect Spill Slot [RSP+8]
315; CHECK: .byte	3
316; CHECK-NEXT:   .byte   0
317; CHECK: .short 8
318; CHECK: .short	7
319; CHECK-NEXT:   .short  0
320; CHECK: .long	8
321; Indirect Spill Slot [RSP+16]
322; CHECK: .byte	3
323; CHECK-NEXT:   .byte   0
324; CHECK: .short 8
325; CHECK: .short	7
326; CHECK-NEXT:   .short  0
327; CHECK: .long	16
328; Indirect Spill Slot [RSP+16]
329; CHECK: .byte	3
330; CHECK-NEXT:   .byte   0
331; CHECK: .short 8
332; CHECK: .short	7
333; CHECK-NEXT:   .short  0
334; CHECK: .long	16
335
336; No Padding or LiveOuts
337; CHECK: .short	0
338; CHECK: .short	0
339; CHECK: .p2align	3
340
341; Records for the test_id function:
342
343; The Statepoint ID:
344; CHECK-NEXT: .quad	237
345
346; Instruction Offset
347; CHECK-NEXT: .long	.Ltmp2-test_id
348
349; Reserved:
350; CHECK: .short	0
351
352; NumLocations:
353; CHECK: .short	3
354
355; StkMapRecord[0]:
356; SmallConstant(0):
357; CHECK: .byte	4
358; CHECK-NEXT:   .byte   0
359; CHECK: .short 8
360; CHECK: .short	0
361; CHECK-NEXT:   .short  0
362; CHECK: .long	0
363
364; StkMapRecord[1]:
365; SmallConstant(0):
366; CHECK: .byte	4
367; CHECK-NEXT:   .byte   0
368; CHECK: .short 8
369; CHECK: .short	0
370; CHECK-NEXT:   .short  0
371; CHECK: .long	0
372
373; StkMapRecord[2]:
374; SmallConstant(0):
375; CHECK: .byte	4
376; CHECK-NEXT:   .byte   0
377; CHECK: .short 8
378; CHECK: .short	0
379; CHECK-NEXT:   .short  0
380; CHECK: .long	0
381
382; No padding or LiveOuts
383; CHECK: .short	0
384; CHECK: .short	0
385; CHECK: .p2align	3
386
387;
388; test_spadj
389
390; Statepoint ID
391; CHECK-NEXT: .quad	0
392
393; Instruction Offset
394; CHECK-NEXT: .long	.Ltmp3-test_spadj
395
396; Reserved:
397; CHECK: .short	0
398
399; NumLocations:
400; CHECK: .short	5
401
402; StkMapRecord[0]:
403; SmallConstant(0):
404; CHECK: .byte	4
405; CHECK-NEXT:   .byte   0
406; CHECK: .short 8
407; CHECK: .short	0
408; CHECK-NEXT:   .short  0
409; CHECK: .long	0
410
411; StkMapRecord[1]:
412; SmallConstant(0):
413; CHECK: .byte	4
414; CHECK-NEXT:   .byte   0
415; CHECK: .short 8
416; CHECK: .short	0
417; CHECK-NEXT:   .short  0
418; CHECK: .long	0
419
420; StkMapRecord[2]:
421; SmallConstant(0):
422; CHECK: .byte	4
423; CHECK-NEXT:   .byte   0
424; CHECK: .short 8
425; CHECK: .short	0
426; CHECK-NEXT:   .short  0
427; CHECK: .long	0
428
429; StkMapRecord[3]:
430; Indirect Spill Slot [RSP+16]
431; CHECK: .byte	3
432; CHECK-NEXT:   .byte   0
433; CHECK: .short 8
434; CHECK: .short	7
435; CHECK-NEXT:   .short  0
436; CHECK: .long	16
437
438; StkMapRecord[4]:
439; Indirect Spill Slot [RSP+16]
440; CHECK: .byte	3
441; CHECK-NEXT:   .byte   0
442; CHECK: .short 8
443; CHECK: .short	7
444; CHECK-NEXT:   .short  0
445; CHECK: .long	16
446
447; No padding or LiveOuts
448; CHECK: .short	0
449; CHECK: .short	0
450; CHECK: .p2align	3
451
452;
453; test_fixed_arg
454
455; Statepoint ID
456; CHECK-NEXT: .quad	0
457
458; Instruction Offset
459; CHECK-NEXT: .long	.Ltmp4-test_fixed_arg
460
461; Reserved:
462; CHECK: .short	0
463
464; NumLocations:
465; CHECK: .short	4
466
467; StkMapRecord[0]:
468; SmallConstant(0):
469; CHECK: .byte	4
470; CHECK-NEXT:   .byte   0
471; CHECK: .short 8
472; CHECK: .short	0
473; CHECK-NEXT:   .short  0
474; CHECK: .long	0
475
476; StkMapRecord[1]:
477; SmallConstant(0):
478; CHECK: .byte	4
479; CHECK-NEXT:   .byte   0
480; CHECK: .short 8
481; CHECK: .short	0
482; CHECK-NEXT:   .short  0
483; CHECK: .long	0
484
485; StkMapRecord[2]:
486; SmallConstant(1):
487; CHECK: .byte	4
488; CHECK-NEXT:   .byte   0
489; CHECK: .short 8
490; CHECK: .short	0
491; CHECK-NEXT:   .short  0
492; CHECK: .long	1
493
494; StkMapRecord[3]:
495; Direct RSP+16
496; CHECK: .byte	2
497; CHECK-NEXT:   .byte   0
498; CHECK: .short 8
499; CHECK: .short	7
500; CHECK-NEXT:   .short  0
501; CHECK: .long	16
502
503; No padding or LiveOuts
504; CHECK: .short	0
505; CHECK: .short	0
506; CHECK: .p2align	3
507