xref: /llvm-project/llvm/test/CodeGen/AArch64/win64_vararg.ll (revision db158c7c830807caeeb0691739c41f1d522029e9)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=aarch64-pc-win32 | FileCheck %s
3
4define void @pass_va(i32 %count, ...) nounwind {
5; CHECK-LABEL: pass_va:
6; CHECK:       // %bb.0: // %entry
7; CHECK-NEXT:    str x30, [sp, #-80]! // 8-byte Folded Spill
8; CHECK-NEXT:    add x8, sp, #24
9; CHECK-NEXT:    add x0, sp, #24
10; CHECK-NEXT:    stp x1, x2, [sp, #24]
11; CHECK-NEXT:    stp x3, x4, [sp, #40]
12; CHECK-NEXT:    stp x5, x6, [sp, #56]
13; CHECK-NEXT:    str x7, [sp, #72]
14; CHECK-NEXT:    str x8, [sp, #8]
15; CHECK-NEXT:    bl other_func
16; CHECK-NEXT:    ldr x30, [sp], #80 // 8-byte Folded Reload
17; CHECK-NEXT:    ret
18entry:
19  %ap = alloca ptr, align 8
20  call void @llvm.va_start(ptr %ap)
21  %ap2 = load ptr, ptr %ap, align 8
22  call void @other_func(ptr %ap2)
23  ret void
24}
25
26declare void @other_func(ptr) local_unnamed_addr
27
28declare void @llvm.va_start(ptr) nounwind
29declare void @llvm.va_copy(ptr, ptr) nounwind
30
31define ptr @f9(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7, i64 %a8, ...) nounwind {
32; CHECK-LABEL: f9:
33; CHECK:       // %bb.0: // %entry
34; CHECK-NEXT:    sub sp, sp, #16
35; CHECK-NEXT:    add x8, sp, #24
36; CHECK-NEXT:    add x0, sp, #24
37; CHECK-NEXT:    str x8, [sp, #8]
38; CHECK-NEXT:    add sp, sp, #16
39; CHECK-NEXT:    ret
40entry:
41  %ap = alloca ptr, align 8
42  call void @llvm.va_start(ptr %ap)
43  %ap2 = load ptr, ptr %ap, align 8
44  ret ptr %ap2
45}
46
47define ptr @f8(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7, ...) nounwind {
48; CHECK-LABEL: f8:
49; CHECK:       // %bb.0: // %entry
50; CHECK-NEXT:    sub sp, sp, #16
51; CHECK-NEXT:    add x8, sp, #16
52; CHECK-NEXT:    add x0, sp, #16
53; CHECK-NEXT:    str x8, [sp, #8]
54; CHECK-NEXT:    add sp, sp, #16
55; CHECK-NEXT:    ret
56entry:
57  %ap = alloca ptr, align 8
58  call void @llvm.va_start(ptr %ap)
59  %ap2 = load ptr, ptr %ap, align 8
60  ret ptr %ap2
61}
62
63define ptr @f7(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, ...) nounwind {
64; CHECK-LABEL: f7:
65; CHECK:       // %bb.0: // %entry
66; CHECK-NEXT:    sub sp, sp, #32
67; CHECK-NEXT:    add x8, sp, #24
68; CHECK-NEXT:    add x0, sp, #24
69; CHECK-NEXT:    str x7, [sp, #24]
70; CHECK-NEXT:    str x8, [sp, #8]
71; CHECK-NEXT:    add sp, sp, #32
72; CHECK-NEXT:    ret
73entry:
74  %ap = alloca ptr, align 8
75  call void @llvm.va_start(ptr %ap)
76  %ap2 = load ptr, ptr %ap, align 8
77  ret ptr %ap2
78}
79
80define void @copy1(i64 %a0, ...) nounwind {
81; CHECK-LABEL: copy1:
82; CHECK:       // %bb.0: // %entry
83; CHECK-NEXT:    sub sp, sp, #80
84; CHECK-NEXT:    add x8, sp, #24
85; CHECK-NEXT:    stp x1, x2, [sp, #24]
86; CHECK-NEXT:    stp x3, x4, [sp, #40]
87; CHECK-NEXT:    stp x5, x6, [sp, #56]
88; CHECK-NEXT:    str x7, [sp, #72]
89; CHECK-NEXT:    stp x8, x8, [sp], #80
90; CHECK-NEXT:    ret
91entry:
92  %ap = alloca ptr, align 8
93  %cp = alloca ptr, align 8
94  call void @llvm.va_start(ptr %ap)
95  call void @llvm.va_copy(ptr %cp, ptr %ap)
96  ret void
97}
98
99declare void @llvm.va_end(ptr)
100declare void @llvm.lifetime.start.p0(i64, ptr nocapture) #1
101declare void @llvm.lifetime.end.p0(i64, ptr nocapture) #1
102
103declare i32 @__stdio_common_vsprintf(i64, ptr, i64, ptr, ptr, ptr) local_unnamed_addr #3
104declare ptr @__local_stdio_printf_options() local_unnamed_addr #4
105
106define i32 @fp(ptr, i64, ptr, ...) local_unnamed_addr #6 {
107; CHECK-LABEL: fp:
108; CHECK:       .seh_proc fp
109; CHECK-NEXT:  // %bb.0:
110; CHECK-NEXT:    stp x19, x20, [sp, #-96]! // 16-byte Folded Spill
111; CHECK-NEXT:    .seh_save_regp_x x19, 96
112; CHECK-NEXT:    str x21, [sp, #16] // 8-byte Folded Spill
113; CHECK-NEXT:    .seh_save_reg x21, 16
114; CHECK-NEXT:    stp x29, x30, [sp, #24] // 16-byte Folded Spill
115; CHECK-NEXT:    .seh_save_fplr 24
116; CHECK-NEXT:    add x29, sp, #24
117; CHECK-NEXT:    .seh_add_fp 24
118; CHECK-NEXT:    .seh_endprologue
119; CHECK-NEXT:    add x8, x29, #32
120; CHECK-NEXT:    mov x19, x2
121; CHECK-NEXT:    mov x20, x1
122; CHECK-NEXT:    mov x21, x0
123; CHECK-NEXT:    stp x3, x4, [x29, #32]
124; CHECK-NEXT:    stp x5, x6, [x29, #48]
125; CHECK-NEXT:    str x7, [x29, #64]
126; CHECK-NEXT:    str x8, [x29, #16]
127; CHECK-NEXT:    bl __local_stdio_printf_options
128; CHECK-NEXT:    ldr x8, [x0]
129; CHECK-NEXT:    add x5, x29, #32
130; CHECK-NEXT:    mov x1, x21
131; CHECK-NEXT:    mov x2, x20
132; CHECK-NEXT:    mov x3, x19
133; CHECK-NEXT:    mov x4, xzr
134; CHECK-NEXT:    orr x0, x8, #0x2
135; CHECK-NEXT:    bl __stdio_common_vsprintf
136; CHECK-NEXT:    cmp w0, #0
137; CHECK-NEXT:    csinv w0, w0, wzr, ge
138; CHECK-NEXT:    .seh_startepilogue
139; CHECK-NEXT:    ldp x29, x30, [sp, #24] // 16-byte Folded Reload
140; CHECK-NEXT:    .seh_save_fplr 24
141; CHECK-NEXT:    ldr x21, [sp, #16] // 8-byte Folded Reload
142; CHECK-NEXT:    .seh_save_reg x21, 16
143; CHECK-NEXT:    ldp x19, x20, [sp], #96 // 16-byte Folded Reload
144; CHECK-NEXT:    .seh_save_regp_x x19, 96
145; CHECK-NEXT:    .seh_endepilogue
146; CHECK-NEXT:    ret
147; CHECK-NEXT:    .seh_endfunclet
148; CHECK-NEXT:    .seh_endproc
149  %4 = alloca ptr, align 8
150  call void @llvm.lifetime.start.p0(i64 8, ptr nonnull %4) #2
151  call void @llvm.va_start(ptr nonnull %4)
152  %5 = load ptr, ptr %4, align 8
153  %6 = call ptr @__local_stdio_printf_options() #2
154  %7 = load i64, ptr %6, align 8
155  %8 = or i64 %7, 2
156  %9 = call i32 @__stdio_common_vsprintf(i64 %8, ptr %0, i64 %1, ptr %2, ptr null, ptr %5) #2
157  %10 = icmp sgt i32 %9, -1
158  %11 = select i1 %10, i32 %9, i32 -1
159  call void @llvm.va_end(ptr nonnull %4)
160  call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %4) #2
161  ret i32 %11
162}
163
164attributes #6 = { "frame-pointer"="all" }
165
166define void @vla(i32, ptr, ...) local_unnamed_addr {
167; CHECK-LABEL: vla:
168; CHECK:       .seh_proc vla
169; CHECK-NEXT:  // %bb.0:
170; CHECK-NEXT:    stp x19, x20, [sp, #-112]! // 16-byte Folded Spill
171; CHECK-NEXT:    .seh_save_regp_x x19, 112
172; CHECK-NEXT:    stp x21, x22, [sp, #16] // 16-byte Folded Spill
173; CHECK-NEXT:    .seh_save_regp x21, 16
174; CHECK-NEXT:    str x23, [sp, #32] // 8-byte Folded Spill
175; CHECK-NEXT:    .seh_save_reg x23, 32
176; CHECK-NEXT:    stp x29, x30, [sp, #40] // 16-byte Folded Spill
177; CHECK-NEXT:    .seh_save_fplr 40
178; CHECK-NEXT:    add x29, sp, #40
179; CHECK-NEXT:    .seh_add_fp 40
180; CHECK-NEXT:    .seh_endprologue
181; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
182; CHECK-NEXT:    add x8, x29, #24
183; CHECK-NEXT:    mov w9, w0
184; CHECK-NEXT:    mov x19, x1
185; CHECK-NEXT:    str x8, [x29, #16]
186; CHECK-NEXT:    add x8, x9, #15
187; CHECK-NEXT:    mov x23, sp
188; CHECK-NEXT:    lsr x15, x8, #4
189; CHECK-NEXT:    stp x2, x3, [x29, #24]
190; CHECK-NEXT:    stp x4, x5, [x29, #40]
191; CHECK-NEXT:    stp x6, x7, [x29, #56]
192; CHECK-NEXT:    bl __chkstk
193; CHECK-NEXT:    sub x20, sp, x15, lsl #4
194; CHECK-NEXT:    mov sp, x20
195; CHECK-NEXT:    ldr x21, [x29, #16]
196; CHECK-NEXT:    sxtw x22, w0
197; CHECK-NEXT:    bl __local_stdio_printf_options
198; CHECK-NEXT:    ldr x8, [x0]
199; CHECK-NEXT:    mov x1, x20
200; CHECK-NEXT:    mov x2, x22
201; CHECK-NEXT:    mov x3, x19
202; CHECK-NEXT:    mov x4, xzr
203; CHECK-NEXT:    mov x5, x21
204; CHECK-NEXT:    orr x0, x8, #0x2
205; CHECK-NEXT:    bl __stdio_common_vsprintf
206; CHECK-NEXT:    mov sp, x23
207; CHECK-NEXT:    .seh_startepilogue
208; CHECK-NEXT:    sub sp, x29, #40
209; CHECK-NEXT:    .seh_add_fp 40
210; CHECK-NEXT:    ldp x29, x30, [sp, #40] // 16-byte Folded Reload
211; CHECK-NEXT:    .seh_save_fplr 40
212; CHECK-NEXT:    ldr x23, [sp, #32] // 8-byte Folded Reload
213; CHECK-NEXT:    .seh_save_reg x23, 32
214; CHECK-NEXT:    ldp x21, x22, [sp, #16] // 16-byte Folded Reload
215; CHECK-NEXT:    .seh_save_regp x21, 16
216; CHECK-NEXT:    ldp x19, x20, [sp], #112 // 16-byte Folded Reload
217; CHECK-NEXT:    .seh_save_regp_x x19, 112
218; CHECK-NEXT:    .seh_endepilogue
219; CHECK-NEXT:    ret
220; CHECK-NEXT:    .seh_endfunclet
221; CHECK-NEXT:    .seh_endproc
222  %3 = alloca ptr, align 8
223  call void @llvm.lifetime.start.p0(i64 8, ptr nonnull %3) #5
224  call void @llvm.va_start(ptr nonnull %3)
225  %4 = zext i32 %0 to i64
226  %5 = call ptr @llvm.stacksave()
227  %6 = alloca i8, i64 %4, align 1
228  %7 = load ptr, ptr %3, align 8
229  %8 = sext i32 %0 to i64
230  %9 = call ptr @__local_stdio_printf_options()
231  %10 = load i64, ptr %9, align 8
232  %11 = or i64 %10, 2
233  %12 = call i32 @__stdio_common_vsprintf(i64 %11, ptr nonnull %6, i64 %8, ptr %1, ptr null, ptr %7)
234  call void @llvm.va_end(ptr nonnull %3)
235  call void @llvm.stackrestore(ptr %5)
236  call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %3) #5
237  ret void
238}
239
240declare ptr @llvm.stacksave()
241declare void @llvm.stackrestore(ptr)
242
243define i32 @snprintf(ptr, i64, ptr, ...) local_unnamed_addr #5 {
244; CHECK-LABEL: snprintf:
245; CHECK:       .seh_proc snprintf
246; CHECK-NEXT:  // %bb.0:
247; CHECK-NEXT:    sub sp, sp, #96
248; CHECK-NEXT:    .seh_stackalloc 96
249; CHECK-NEXT:    stp x19, x20, [sp, #16] // 16-byte Folded Spill
250; CHECK-NEXT:    .seh_save_regp x19, 16
251; CHECK-NEXT:    stp x21, x30, [sp, #32] // 16-byte Folded Spill
252; CHECK-NEXT:    .seh_save_lrpair x21, 32
253; CHECK-NEXT:    .seh_endprologue
254; CHECK-NEXT:    add x8, sp, #56
255; CHECK-NEXT:    mov x19, x2
256; CHECK-NEXT:    mov x20, x1
257; CHECK-NEXT:    mov x21, x0
258; CHECK-NEXT:    stp x3, x4, [sp, #56]
259; CHECK-NEXT:    stp x5, x6, [sp, #72]
260; CHECK-NEXT:    str x7, [sp, #88]
261; CHECK-NEXT:    str x8, [sp, #8]
262; CHECK-NEXT:    bl __local_stdio_printf_options
263; CHECK-NEXT:    ldr x8, [x0]
264; CHECK-NEXT:    add x5, sp, #56
265; CHECK-NEXT:    mov x1, x21
266; CHECK-NEXT:    mov x2, x20
267; CHECK-NEXT:    mov x3, x19
268; CHECK-NEXT:    mov x4, xzr
269; CHECK-NEXT:    orr x0, x8, #0x2
270; CHECK-NEXT:    bl __stdio_common_vsprintf
271; CHECK-NEXT:    cmp w0, #0
272; CHECK-NEXT:    csinv w0, w0, wzr, ge
273; CHECK-NEXT:    .seh_startepilogue
274; CHECK-NEXT:    ldp x21, x30, [sp, #32] // 16-byte Folded Reload
275; CHECK-NEXT:    .seh_save_lrpair x21, 32
276; CHECK-NEXT:    ldp x19, x20, [sp, #16] // 16-byte Folded Reload
277; CHECK-NEXT:    .seh_save_regp x19, 16
278; CHECK-NEXT:    add sp, sp, #96
279; CHECK-NEXT:    .seh_stackalloc 96
280; CHECK-NEXT:    .seh_endepilogue
281; CHECK-NEXT:    ret
282; CHECK-NEXT:    .seh_endfunclet
283; CHECK-NEXT:    .seh_endproc
284  %4 = alloca ptr, align 8
285  call void @llvm.lifetime.start.p0(i64 8, ptr nonnull %4) #2
286  call void @llvm.va_start(ptr nonnull %4)
287  %5 = load ptr, ptr %4, align 8
288  %6 = call ptr @__local_stdio_printf_options() #2
289  %7 = load i64, ptr %6, align 8
290  %8 = or i64 %7, 2
291  %9 = call i32 @__stdio_common_vsprintf(i64 %8, ptr %0, i64 %1, ptr %2, ptr null, ptr %5) #2
292  %10 = icmp sgt i32 %9, -1
293  %11 = select i1 %10, i32 %9, i32 -1
294  call void @llvm.va_end(ptr nonnull %4)
295  call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %4) #2
296  ret i32 %11
297}
298
299define void @fixed_params(i32, double, i32, double, i32, double, i32, double, i32, double) nounwind {
300; CHECK-LABEL: fixed_params:
301; CHECK:       // %bb.0:
302; CHECK-NEXT:    sub sp, sp, #32
303; CHECK-NEXT:    mov w8, w4
304; CHECK-NEXT:    mov w6, w3
305; CHECK-NEXT:    mov w4, w2
306; CHECK-NEXT:    mov w2, w1
307; CHECK-NEXT:    fmov x1, d0
308; CHECK-NEXT:    fmov x3, d1
309; CHECK-NEXT:    fmov x5, d2
310; CHECK-NEXT:    fmov x7, d3
311; CHECK-NEXT:    str x30, [sp, #16] // 8-byte Folded Spill
312; CHECK-NEXT:    str d4, [sp, #8]
313; CHECK-NEXT:    str w8, [sp]
314; CHECK-NEXT:    bl varargs
315; CHECK-NEXT:    ldr x30, [sp, #16] // 8-byte Folded Reload
316; CHECK-NEXT:    add sp, sp, #32
317; CHECK-NEXT:    ret
318  tail call void (i32, ...) @varargs(i32 %0, double %1, i32 %2, double %3, i32 %4, double %5, i32 %6, double %7, i32 %8, double %9)
319  ret void
320}
321
322declare void @varargs(i32, ...) local_unnamed_addr
323