]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/CodeGen/AArch64/win64_vararg.ll
Vendor import of llvm release_50 branch r310316:
[FreeBSD/FreeBSD.git] / test / CodeGen / AArch64 / win64_vararg.ll
1 ; RUN: llc < %s -mtriple=aarch64-pc-win32 | FileCheck %s
2
3 define void @pass_va(i32 %count, ...) nounwind {
4 entry:
5 ; CHECK: str     x30, [sp, #-80]!
6 ; CHECK: add     x8, sp, #24
7 ; CHECK: add     x0, sp, #24
8 ; CHECK: stp     x6, x7, [sp, #64]
9 ; CHECK: stp     x4, x5, [sp, #48]
10 ; CHECK: stp     x2, x3, [sp, #32]
11 ; CHECK: str     x1, [sp, #24]
12 ; CHECK: str     x8, [sp, #8]
13 ; CHECK: bl      other_func
14 ; CHECK: ldr     x30, [sp], #80
15 ; CHECK: ret
16   %ap = alloca i8*, align 8
17   %ap1 = bitcast i8** %ap to i8*
18   call void @llvm.va_start(i8* %ap1)
19   %ap2 = load i8*, i8** %ap, align 8
20   call void @other_func(i8* %ap2)
21   ret void
22 }
23
24 declare void @other_func(i8*) local_unnamed_addr
25
26 declare void @llvm.va_start(i8*) nounwind
27 declare void @llvm.va_copy(i8*, i8*) nounwind
28
29 ; CHECK-LABEL: f9:
30 ; CHECK: sub     sp, sp, #16
31 ; CHECK: add     x8, sp, #24
32 ; CHECK: add     x0, sp, #24
33 ; CHECK: str     x8, [sp, #8]
34 ; CHECK: add     sp, sp, #16
35 ; CHECK: ret
36 define i8* @f9(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7, i64 %a8, ...) nounwind {
37 entry:
38   %ap = alloca i8*, align 8
39   %ap1 = bitcast i8** %ap to i8*
40   call void @llvm.va_start(i8* %ap1)
41   %ap2 = load i8*, i8** %ap, align 8
42   ret i8* %ap2
43 }
44
45 ; CHECK-LABEL: f8:
46 ; CHECK: sub     sp, sp, #16
47 ; CHECK: add     x8, sp, #16
48 ; CHECK: add     x0, sp, #16
49 ; CHECK: str     x8, [sp, #8]
50 ; CHECK: add     sp, sp, #16
51 ; CHECK: ret
52 define i8* @f8(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7, ...) nounwind {
53 entry:
54   %ap = alloca i8*, align 8
55   %ap1 = bitcast i8** %ap to i8*
56   call void @llvm.va_start(i8* %ap1)
57   %ap2 = load i8*, i8** %ap, align 8
58   ret i8* %ap2
59 }
60
61 ; CHECK-LABEL: f7:
62 ; CHECK: sub     sp, sp, #32
63 ; CHECK: add     x8, sp, #24
64 ; CHECK: str     x7, [sp, #24]
65 ; CHECK: add     x0, sp, #24
66 ; CHECK: str     x8, [sp, #8]
67 ; CHECK: add     sp, sp, #32
68 ; CHECK: ret
69 define i8* @f7(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, ...) nounwind {
70 entry:
71   %ap = alloca i8*, align 8
72   %ap1 = bitcast i8** %ap to i8*
73   call void @llvm.va_start(i8* %ap1)
74   %ap2 = load i8*, i8** %ap, align 8
75   ret i8* %ap2
76 }
77
78 ; CHECK-LABEL: copy1:
79 ; CHECK: sub     sp, sp, #80
80 ; CHECK: add     x8, sp, #24
81 ; CHECK: stp     x6, x7, [sp, #64]
82 ; CHECK: stp     x4, x5, [sp, #48]
83 ; CHECK: stp     x2, x3, [sp, #32]
84 ; CHECK: str     x1, [sp, #24]
85 ; CHECK: stp     x8, x8, [sp], #80
86 ; CHECK: ret
87 define void @copy1(i64 %a0, ...) nounwind {
88 entry:
89   %ap = alloca i8*, align 8
90   %cp = alloca i8*, align 8
91   %ap1 = bitcast i8** %ap to i8*
92   %cp1 = bitcast i8** %cp to i8*
93   call void @llvm.va_start(i8* %ap1)
94   call void @llvm.va_copy(i8* %cp1, i8* %ap1)
95   ret void
96 }
97
98 declare void @llvm.va_end(i8*)
99 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
100 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
101
102 declare i32 @__stdio_common_vsprintf(i64, i8*, i64, i8*, i8*, i8*) local_unnamed_addr #3
103 declare i64* @__local_stdio_printf_options() local_unnamed_addr #4
104
105 ; CHECK-LABEL: fp
106 ; CHECK: str     x21, [sp, #-96]!
107 ; CHECK: stp     x20, x19, [sp, #16]
108 ; CHECK: stp     x29, x30, [sp, #32]
109 ; CHECK: add     x29, sp, #32
110 ; CHECK: add     x8, x29, #24
111 ; CHECK: mov     x19, x2
112 ; CHECK: mov     x20, x1
113 ; CHECK: mov     x21, x0
114 ; CHECK: stp     x6, x7, [x29, #48]
115 ; CHECK: stp     x4, x5, [x29, #32]
116 ; CHECK: str     x3, [x29, #24]
117 ; CHECK: str     x8, [sp, #8]
118 ; CHECK: bl      __local_stdio_printf_options
119 ; CHECK: ldr     x8, [x0]
120 ; CHECK: add     x5, x29, #24
121 ; CHECK: mov     x1, x21
122 ; CHECK: mov     x2, x20
123 ; CHECK: orr     x0, x8, #0x2
124 ; CHECK: mov     x3, x19
125 ; CHECK: mov     x4, xzr
126 ; CHECK: bl      __stdio_common_vsprintf
127 ; CHECK: ldp     x29, x30, [sp, #32]
128 ; CHECK: ldp     x20, x19, [sp, #16]
129 ; CHECK: cmp     w0, #0
130 ; CHECK: csinv   w0, w0, wzr, ge
131 ; CHECK: ldr     x21, [sp], #96
132 ; CHECK: ret
133 define i32 @fp(i8*, i64, i8*, ...) local_unnamed_addr #6 {
134   %4 = alloca i8*, align 8
135   %5 = bitcast i8** %4 to i8*
136   call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %5) #2
137   call void @llvm.va_start(i8* nonnull %5)
138   %6 = load i8*, i8** %4, align 8
139   %7 = call i64* @__local_stdio_printf_options() #2
140   %8 = load i64, i64* %7, align 8
141   %9 = or i64 %8, 2
142   %10 = call i32 @__stdio_common_vsprintf(i64 %9, i8* %0, i64 %1, i8* %2, i8* null, i8* %6) #2
143   %11 = icmp sgt i32 %10, -1
144   %12 = select i1 %11, i32 %10, i32 -1
145   call void @llvm.va_end(i8* nonnull %5)
146   call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %5) #2
147   ret i32 %12
148 }
149
150 attributes #6 = { "no-frame-pointer-elim"="true" }
151
152 ; CHECK-LABEL: vla
153 ; CHECK: str     x23, [sp, #-112]!
154 ; CHECK: stp     x22, x21, [sp, #16]
155 ; CHECK: stp     x20, x19, [sp, #32]
156 ; CHECK: stp     x29, x30, [sp, #48]
157 ; CHECK: add     x29, sp, #48
158 ; CHECK: add     x8, x29, #16
159 ; CHECK: stur    x8, [x29, #-40]
160 ; CHECK: mov     w8, w0
161 ; CHECK: add     x8, x8, #15
162 ; CHECK: mov     x9, sp
163 ; CHECK: and     x8, x8, #0x1fffffff0
164 ; CHECK: sub     x20, x9, x8
165 ; CHECK: mov     x19, x1
166 ; CHECK: mov     x23, sp
167 ; CHECK: stp     x6, x7, [x29, #48]
168 ; CHECK: stp     x4, x5, [x29, #32]
169 ; CHECK: stp     x2, x3, [x29, #16]
170 ; CHECK: mov     sp, x20
171 ; CHECK: ldur    x21, [x29, #-40]
172 ; CHECK: sxtw    x22, w0
173 ; CHECK: bl      __local_stdio_printf_options
174 ; CHECK: ldr     x8, [x0]
175 ; CHECK: mov     x1, x20
176 ; CHECK: mov     x2, x22
177 ; CHECK: mov     x3, x19
178 ; CHECK: orr     x0, x8, #0x2
179 ; CHECK: mov     x4, xzr
180 ; CHECK: mov     x5, x21
181 ; CHECK: bl      __stdio_common_vsprintf
182 ; CHECK: mov     sp, x23
183 ; CHECK: sub     sp, x29, #48
184 ; CHECK: ldp     x29, x30, [sp, #48]
185 ; CHECK: ldp     x20, x19, [sp, #32]
186 ; CHECK: ldp     x22, x21, [sp, #16]
187 ; CHECK: ldr     x23, [sp], #112
188 ; CHECK: ret
189 define void @vla(i32, i8*, ...) local_unnamed_addr {
190   %3 = alloca i8*, align 8
191   %4 = bitcast i8** %3 to i8*
192   call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %4) #5
193   call void @llvm.va_start(i8* nonnull %4)
194   %5 = zext i32 %0 to i64
195   %6 = call i8* @llvm.stacksave()
196   %7 = alloca i8, i64 %5, align 1
197   %8 = load i8*, i8** %3, align 8
198   %9 = sext i32 %0 to i64
199   %10 = call i64* @__local_stdio_printf_options()
200   %11 = load i64, i64* %10, align 8
201   %12 = or i64 %11, 2
202   %13 = call i32 @__stdio_common_vsprintf(i64 %12, i8* nonnull %7, i64 %9, i8* %1, i8* null, i8* %8)
203   call void @llvm.va_end(i8* nonnull %4)
204   call void @llvm.stackrestore(i8* %6)
205   call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %4) #5
206   ret void
207 }
208
209 declare i8* @llvm.stacksave()
210 declare void @llvm.stackrestore(i8*)
211
212 ; CHECK-LABEL: snprintf
213 ; CHECK: sub     sp,  sp, #96
214 ; CHECK: stp     x21, x20, [sp, #16]
215 ; CHECK: stp     x19, x30, [sp, #32]
216 ; CHECK: add     x8, sp, #56
217 ; CHECK: mov     x19, x2
218 ; CHECK: mov     x20, x1
219 ; CHECK: mov     x21, x0
220 ; CHECK: stp     x6, x7, [sp, #80]
221 ; CHECK: stp     x4, x5, [sp, #64]
222 ; CHECK: str     x3, [sp, #56]
223 ; CHECK: str     x8, [sp, #8]
224 ; CHECK: bl      __local_stdio_printf_options
225 ; CHECK: ldr     x8, [x0]
226 ; CHECK: add     x5, sp, #56
227 ; CHECK: mov     x1, x21
228 ; CHECK: mov     x2, x20
229 ; CHECK: orr     x0, x8, #0x2
230 ; CHECK: mov     x3, x19
231 ; CHECK: mov     x4, xzr
232 ; CHECK: bl      __stdio_common_vsprintf
233 ; CHECK: ldp     x19, x30, [sp, #32]
234 ; CHECK: ldp     x21, x20, [sp, #16]
235 ; CHECK: cmp     w0, #0
236 ; CHECK: csinv   w0, w0, wzr, ge
237 ; CHECK: add     sp, sp, #96
238 ; CHECK: ret
239 define i32 @snprintf(i8*, i64, i8*, ...) local_unnamed_addr #5 {
240   %4 = alloca i8*, align 8
241   %5 = bitcast i8** %4 to i8*
242   call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %5) #2
243   call void @llvm.va_start(i8* nonnull %5)
244   %6 = load i8*, i8** %4, align 8
245   %7 = call i64* @__local_stdio_printf_options() #2
246   %8 = load i64, i64* %7, align 8
247   %9 = or i64 %8, 2
248   %10 = call i32 @__stdio_common_vsprintf(i64 %9, i8* %0, i64 %1, i8* %2, i8* null, i8* %6) #2
249   %11 = icmp sgt i32 %10, -1
250   %12 = select i1 %11, i32 %10, i32 -1
251   call void @llvm.va_end(i8* nonnull %5)
252   call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %5) #2
253   ret i32 %12
254 }