OSDN Git Service

[AArch64] Add a test for float argument passing to win64 vararg functions
[android-x86/external-llvm.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: sub     sp, 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: stp     x30, x8, [sp]
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: snprintf
106 ; CHECK: sub     sp,  sp, #96
107 ; CHECK: stp     x21, x20, [sp, #16]
108 ; CHECK: stp     x19, x30, [sp, #32]
109 ; CHECK: add     x8, sp, #56
110 ; CHECK: mov     x19, x2
111 ; CHECK: mov     x20, x1
112 ; CHECK: mov     x21, x0
113 ; CHECK: stp     x6, x7, [sp, #80]
114 ; CHECK: stp     x4, x5, [sp, #64]
115 ; CHECK: str     x3, [sp, #56]
116 ; CHECK: str     x8, [sp, #8]
117 ; CHECK: bl      __local_stdio_printf_options
118 ; CHECK: ldr     x8, [x0]
119 ; CHECK: add     x5, sp, #56
120 ; CHECK: mov     x1, x21
121 ; CHECK: mov     x2, x20
122 ; CHECK: orr     x0, x8, #0x2
123 ; CHECK: mov     x3, x19
124 ; CHECK: mov     x4, xzr
125 ; CHECK: bl      __stdio_common_vsprintf
126 ; CHECK: ldp     x19, x30, [sp, #32]
127 ; CHECK: ldp     x21, x20, [sp, #16]
128 ; CHECK: cmp     w0, #0
129 ; CHECK: csinv   w0, w0, wzr, ge
130 ; CHECK: add     sp, sp, #96
131 ; CHECK: ret
132 define i32 @snprintf(i8*, i64, i8*, ...) local_unnamed_addr #5 {
133   %4 = alloca i8*, align 8
134   %5 = bitcast i8** %4 to i8*
135   call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %5) #2
136   call void @llvm.va_start(i8* nonnull %5)
137   %6 = load i8*, i8** %4, align 8
138   %7 = call i64* @__local_stdio_printf_options() #2
139   %8 = load i64, i64* %7, align 8
140   %9 = or i64 %8, 2
141   %10 = call i32 @__stdio_common_vsprintf(i64 %9, i8* %0, i64 %1, i8* %2, i8* null, i8* %6) #2
142   %11 = icmp sgt i32 %10, -1
143   %12 = select i1 %11, i32 %10, i32 -1
144   call void @llvm.va_end(i8* nonnull %5)
145   call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %5) #2
146   ret i32 %12
147 }
148
149 ; CHECK-LABEL: fixed_params
150 ; CHECK: sub     sp,  sp, #32
151 ; CHECK: mov     w8,  w3
152 ; CHECK: mov     w9,  w2
153 ; CHECK: mov     w10, w1
154 ; CHECK: str     w4,  [sp]
155 ; CHECK: fmov    x1,  d0
156 ; CHECK: fmov    x3,  d1
157 ; CHECK: fmov    x5,  d2
158 ; CHECK: fmov    x7,  d3
159 ; CHECK: mov     w2,  w10
160 ; CHECK: mov     w4,  w9
161 ; CHECK: mov     w6,  w8
162 ; CHECK: str     x30, [sp, #16]
163 ; CHECK: str     d4,  [sp, #8]
164 ; CHECK: bl      varargs
165 ; CHECK: ldr     x30, [sp, #16]
166 ; CHECK: add     sp,  sp, #32
167 ; CHECK: ret
168 define void @fixed_params(i32, double, i32, double, i32, double, i32, double, i32, double) nounwind {
169   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)
170   ret void
171 }
172
173 declare void @varargs(i32, ...) local_unnamed_addr