1*67e74705SXin Li // RUN: %clang_cc1 -triple arm64-linux-gnu -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=CHECK-LE %s
2*67e74705SXin Li // RUN: %clang_cc1 -triple aarch64_be-linux-gnu -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=CHECK-BE %s
3*67e74705SXin Li
4*67e74705SXin Li #include <stdarg.h>
5*67e74705SXin Li
6*67e74705SXin Li // Obviously there's more than one way to implement va_arg. This test should at
7*67e74705SXin Li // least prevent unintentional regressions caused by refactoring.
8*67e74705SXin Li
9*67e74705SXin Li va_list the_list;
10*67e74705SXin Li
simple_int(void)11*67e74705SXin Li int simple_int(void) {
12*67e74705SXin Li // CHECK-LABEL: define i32 @simple_int
13*67e74705SXin Li return va_arg(the_list, int);
14*67e74705SXin Li // CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 3)
15*67e74705SXin Li // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0
16*67e74705SXin Li // CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]
17*67e74705SXin Li
18*67e74705SXin Li // CHECK: [[VAARG_MAYBE_REG]]
19*67e74705SXin Li // CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8
20*67e74705SXin Li // CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 3)
21*67e74705SXin Li // CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0
22*67e74705SXin Li // CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]
23*67e74705SXin Li
24*67e74705SXin Li // CHECK: [[VAARG_IN_REG]]
25*67e74705SXin Li // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8*, i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 1)
26*67e74705SXin Li // CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[REG_TOP]], i32 [[GR_OFFS]]
27*67e74705SXin Li // CHECK-BE: [[REG_ADDR_ALIGNED:%[0-9]+]] = getelementptr inbounds i8, i8* [[REG_ADDR]], i64 4
28*67e74705SXin Li // CHECK-BE: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR_ALIGNED]] to i32*
29*67e74705SXin Li // CHECK-LE: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to i32*
30*67e74705SXin Li // CHECK: br label %[[VAARG_END:[a-z._0-9]+]]
31*67e74705SXin Li
32*67e74705SXin Li // CHECK: [[VAARG_ON_STACK]]
33*67e74705SXin Li // CHECK: [[STACK:%[a-z_0-9]+]] = load i8*, i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 0)
34*67e74705SXin Li // CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[STACK]], i64 8
35*67e74705SXin Li // CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 0)
36*67e74705SXin Li // CHECK-BE: [[STACK_ALIGNED:%[a-z_0-9]*]] = getelementptr inbounds i8, i8* [[STACK]], i64 4
37*67e74705SXin Li // CHECK-BE: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK_ALIGNED]] to i32*
38*67e74705SXin Li // CHECK-LE: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to i32*
39*67e74705SXin Li // CHECK: br label %[[VAARG_END]]
40*67e74705SXin Li
41*67e74705SXin Li // CHECK: [[VAARG_END]]
42*67e74705SXin Li // CHECK: [[ADDR:%[a-z._0-9]+]] = phi i32* [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ]
43*67e74705SXin Li // CHECK: [[RESULT:%[a-z_0-9]+]] = load i32, i32* [[ADDR]]
44*67e74705SXin Li // CHECK: ret i32 [[RESULT]]
45*67e74705SXin Li }
46*67e74705SXin Li
aligned_int(void)47*67e74705SXin Li __int128 aligned_int(void) {
48*67e74705SXin Li // CHECK-LABEL: define i128 @aligned_int
49*67e74705SXin Li return va_arg(the_list, __int128);
50*67e74705SXin Li // CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 3)
51*67e74705SXin Li // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0
52*67e74705SXin Li // CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]
53*67e74705SXin Li
54*67e74705SXin Li // CHECK: [[VAARG_MAYBE_REG]]
55*67e74705SXin Li // CHECK: [[ALIGN_REGOFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 15
56*67e74705SXin Li // CHECK: [[ALIGNED_REGOFFS:%[a-z_0-9]+]] = and i32 [[ALIGN_REGOFFS]], -16
57*67e74705SXin Li // CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[ALIGNED_REGOFFS]], 16
58*67e74705SXin Li // CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 3)
59*67e74705SXin Li // CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0
60*67e74705SXin Li // CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]
61*67e74705SXin Li
62*67e74705SXin Li // CHECK: [[VAARG_IN_REG]]
63*67e74705SXin Li // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8*, i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 1)
64*67e74705SXin Li // CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[REG_TOP]], i32 [[ALIGNED_REGOFFS]]
65*67e74705SXin Li // CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to i128*
66*67e74705SXin Li // CHECK: br label %[[VAARG_END:[a-z._0-9]+]]
67*67e74705SXin Li
68*67e74705SXin Li // CHECK: [[VAARG_ON_STACK]]
69*67e74705SXin Li // CHECK: [[STACK:%[a-z_0-9]+]] = load i8*, i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 0)
70*67e74705SXin Li // CHECK: [[STACKINT:%[a-z_0-9]+]] = ptrtoint i8* [[STACK]] to i64
71*67e74705SXin Li // CHECK: [[ALIGN_STACK:%[a-z_0-9]+]] = add i64 [[STACKINT]], 15
72*67e74705SXin Li // CHECK: [[ALIGNED_STACK_INT:%[a-z_0-9]+]] = and i64 [[ALIGN_STACK]], -16
73*67e74705SXin Li // CHECK: [[ALIGNED_STACK_PTR:%[a-z_0-9]+]] = inttoptr i64 [[ALIGNED_STACK_INT]] to i8*
74*67e74705SXin Li // CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[ALIGNED_STACK_PTR]], i64 16
75*67e74705SXin Li // CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 0)
76*67e74705SXin Li // CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[ALIGNED_STACK_PTR]] to i128*
77*67e74705SXin Li // CHECK: br label %[[VAARG_END]]
78*67e74705SXin Li
79*67e74705SXin Li // CHECK: [[VAARG_END]]
80*67e74705SXin Li // CHECK: [[ADDR:%[a-z._0-9]+]] = phi i128* [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ]
81*67e74705SXin Li // CHECK: [[RESULT:%[a-z_0-9]+]] = load i128, i128* [[ADDR]]
82*67e74705SXin Li // CHECK: ret i128 [[RESULT]]
83*67e74705SXin Li }
84*67e74705SXin Li
85*67e74705SXin Li struct bigstruct {
86*67e74705SXin Li int a[10];
87*67e74705SXin Li };
88*67e74705SXin Li
simple_indirect(void)89*67e74705SXin Li struct bigstruct simple_indirect(void) {
90*67e74705SXin Li // CHECK-LABEL: define void @simple_indirect
91*67e74705SXin Li return va_arg(the_list, struct bigstruct);
92*67e74705SXin Li // CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 3)
93*67e74705SXin Li // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0
94*67e74705SXin Li // CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]
95*67e74705SXin Li
96*67e74705SXin Li // CHECK: [[VAARG_MAYBE_REG]]
97*67e74705SXin Li // CHECK-NOT: and i32
98*67e74705SXin Li // CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8
99*67e74705SXin Li // CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 3)
100*67e74705SXin Li // CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0
101*67e74705SXin Li // CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]
102*67e74705SXin Li
103*67e74705SXin Li // CHECK: [[VAARG_IN_REG]]
104*67e74705SXin Li // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8*, i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 1)
105*67e74705SXin Li // CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[REG_TOP]], i32 [[GR_OFFS]]
106*67e74705SXin Li // CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to %struct.bigstruct**
107*67e74705SXin Li // CHECK: br label %[[VAARG_END:[a-z._0-9]+]]
108*67e74705SXin Li
109*67e74705SXin Li // CHECK: [[VAARG_ON_STACK]]
110*67e74705SXin Li // CHECK: [[STACK:%[a-z_0-9]+]] = load i8*, i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 0)
111*67e74705SXin Li // CHECK-NOT: and i64
112*67e74705SXin Li // CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[STACK]], i64 8
113*67e74705SXin Li // CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 0)
114*67e74705SXin Li // CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to %struct.bigstruct**
115*67e74705SXin Li // CHECK: br label %[[VAARG_END]]
116*67e74705SXin Li
117*67e74705SXin Li // CHECK: [[VAARG_END]]
118*67e74705SXin Li // CHECK: [[ADDR:%[a-z._0-9]+]] = phi %struct.bigstruct** [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ]
119*67e74705SXin Li // CHECK: load %struct.bigstruct*, %struct.bigstruct** [[ADDR]]
120*67e74705SXin Li }
121*67e74705SXin Li
122*67e74705SXin Li struct aligned_bigstruct {
123*67e74705SXin Li float a;
124*67e74705SXin Li long double b;
125*67e74705SXin Li };
126*67e74705SXin Li
simple_aligned_indirect(void)127*67e74705SXin Li struct aligned_bigstruct simple_aligned_indirect(void) {
128*67e74705SXin Li // CHECK-LABEL: define void @simple_aligned_indirect
129*67e74705SXin Li return va_arg(the_list, struct aligned_bigstruct);
130*67e74705SXin Li // CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 3)
131*67e74705SXin Li // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0
132*67e74705SXin Li // CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]
133*67e74705SXin Li
134*67e74705SXin Li // CHECK: [[VAARG_MAYBE_REG]]
135*67e74705SXin Li // CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8
136*67e74705SXin Li // CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 3)
137*67e74705SXin Li // CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0
138*67e74705SXin Li // CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]
139*67e74705SXin Li
140*67e74705SXin Li // CHECK: [[VAARG_IN_REG]]
141*67e74705SXin Li // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8*, i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 1)
142*67e74705SXin Li // CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[REG_TOP]], i32 [[GR_OFFS]]
143*67e74705SXin Li // CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to %struct.aligned_bigstruct**
144*67e74705SXin Li // CHECK: br label %[[VAARG_END:[a-z._0-9]+]]
145*67e74705SXin Li
146*67e74705SXin Li // CHECK: [[VAARG_ON_STACK]]
147*67e74705SXin Li // CHECK: [[STACK:%[a-z_0-9]+]] = load i8*, i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 0)
148*67e74705SXin Li // CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[STACK]], i64 8
149*67e74705SXin Li // CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 0)
150*67e74705SXin Li // CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to %struct.aligned_bigstruct**
151*67e74705SXin Li // CHECK: br label %[[VAARG_END]]
152*67e74705SXin Li
153*67e74705SXin Li // CHECK: [[VAARG_END]]
154*67e74705SXin Li // CHECK: [[ADDR:%[a-z._0-9]+]] = phi %struct.aligned_bigstruct** [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ]
155*67e74705SXin Li // CHECK: load %struct.aligned_bigstruct*, %struct.aligned_bigstruct** [[ADDR]]
156*67e74705SXin Li }
157*67e74705SXin Li
simple_double(void)158*67e74705SXin Li double simple_double(void) {
159*67e74705SXin Li // CHECK-LABEL: define double @simple_double
160*67e74705SXin Li return va_arg(the_list, double);
161*67e74705SXin Li // CHECK: [[VR_OFFS:%[a-z_0-9]+]] = load i32, i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 4)
162*67e74705SXin Li // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[VR_OFFS]], 0
163*67e74705SXin Li // CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG]]
164*67e74705SXin Li
165*67e74705SXin Li // CHECK: [[VAARG_MAYBE_REG]]
166*67e74705SXin Li // CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[VR_OFFS]], 16
167*67e74705SXin Li // CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 4)
168*67e74705SXin Li // CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0
169*67e74705SXin Li // CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]
170*67e74705SXin Li
171*67e74705SXin Li // CHECK: [[VAARG_IN_REG]]
172*67e74705SXin Li // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8*, i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 2)
173*67e74705SXin Li // CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[REG_TOP]], i32 [[VR_OFFS]]
174*67e74705SXin Li // CHECK-BE: [[REG_ADDR_ALIGNED:%[a-z_0-9]*]] = getelementptr inbounds i8, i8* [[REG_ADDR]], i64 8
175*67e74705SXin Li // CHECK-BE: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR_ALIGNED]] to double*
176*67e74705SXin Li // CHECK-LE: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to double*
177*67e74705SXin Li // CHECK: br label %[[VAARG_END:[a-z._0-9]+]]
178*67e74705SXin Li
179*67e74705SXin Li // CHECK: [[VAARG_ON_STACK]]
180*67e74705SXin Li // CHECK: [[STACK:%[a-z_0-9]+]] = load i8*, i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 0)
181*67e74705SXin Li // CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[STACK]], i64 8
182*67e74705SXin Li // CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 0)
183*67e74705SXin Li // CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to double*
184*67e74705SXin Li // CHECK: br label %[[VAARG_END]]
185*67e74705SXin Li
186*67e74705SXin Li // CHECK: [[VAARG_END]]
187*67e74705SXin Li // CHECK: [[ADDR:%[a-z._0-9]+]] = phi double* [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ]
188*67e74705SXin Li // CHECK: [[RESULT:%[a-z_0-9]+]] = load double, double* [[ADDR]]
189*67e74705SXin Li // CHECK: ret double [[RESULT]]
190*67e74705SXin Li }
191*67e74705SXin Li
192*67e74705SXin Li struct hfa {
193*67e74705SXin Li float a, b;
194*67e74705SXin Li };
195*67e74705SXin Li
simple_hfa(void)196*67e74705SXin Li struct hfa simple_hfa(void) {
197*67e74705SXin Li // CHECK-LABEL: define %struct.hfa @simple_hfa
198*67e74705SXin Li return va_arg(the_list, struct hfa);
199*67e74705SXin Li // CHECK: [[VR_OFFS:%[a-z_0-9]+]] = load i32, i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 4)
200*67e74705SXin Li // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[VR_OFFS]], 0
201*67e74705SXin Li // CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]
202*67e74705SXin Li
203*67e74705SXin Li // CHECK: [[VAARG_MAYBE_REG]]
204*67e74705SXin Li // CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[VR_OFFS]], 32
205*67e74705SXin Li // CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 4)
206*67e74705SXin Li // CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0
207*67e74705SXin Li // CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]
208*67e74705SXin Li
209*67e74705SXin Li // CHECK: [[VAARG_IN_REG]]
210*67e74705SXin Li // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8*, i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 2)
211*67e74705SXin Li // CHECK: [[FIRST_REG:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[REG_TOP]], i32 [[VR_OFFS]]
212*67e74705SXin Li // CHECK-LE: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[FIRST_REG]], i64 0
213*67e74705SXin Li // CHECK-BE: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[FIRST_REG]], i64 12
214*67e74705SXin Li // CHECK: [[EL_TYPED:%[a-z_0-9]+]] = bitcast i8* [[EL_ADDR]] to float*
215*67e74705SXin Li // CHECK: [[EL_TMPADDR:%[a-z_0-9]+]] = getelementptr inbounds [2 x float], [2 x float]* %[[TMP_HFA:[a-z_.0-9]+]], i64 0, i64 0
216*67e74705SXin Li // CHECK: [[EL:%[a-z_0-9]+]] = load float, float* [[EL_TYPED]]
217*67e74705SXin Li // CHECK: store float [[EL]], float* [[EL_TMPADDR]]
218*67e74705SXin Li // CHECK-LE: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[FIRST_REG]], i64 16
219*67e74705SXin Li // CHECK-BE: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[FIRST_REG]], i64 28
220*67e74705SXin Li // CHECK: [[EL_TYPED:%[a-z_0-9]+]] = bitcast i8* [[EL_ADDR]] to float*
221*67e74705SXin Li // CHECK: [[EL_TMPADDR:%[a-z_0-9]+]] = getelementptr inbounds [2 x float], [2 x float]* %[[TMP_HFA]], i64 0, i64 1
222*67e74705SXin Li // CHECK: [[EL:%[a-z_0-9]+]] = load float, float* [[EL_TYPED]]
223*67e74705SXin Li // CHECK: store float [[EL]], float* [[EL_TMPADDR]]
224*67e74705SXin Li // CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast [2 x float]* %[[TMP_HFA]] to %struct.hfa*
225*67e74705SXin Li // CHECK: br label %[[VAARG_END:[a-z_.0-9]+]]
226*67e74705SXin Li
227*67e74705SXin Li // CHECK: [[VAARG_ON_STACK]]
228*67e74705SXin Li // CHECK: [[STACK:%[a-z_0-9]+]] = load i8*, i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 0)
229*67e74705SXin Li // CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, i8* [[STACK]], i64 8
230*67e74705SXin Li // CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 0)
231*67e74705SXin Li // CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to %struct.hfa*
232*67e74705SXin Li // CHECK: br label %[[VAARG_END]]
233*67e74705SXin Li
234*67e74705SXin Li // CHECK: [[VAARG_END]]
235*67e74705SXin Li // CHECK: [[ADDR:%[a-z._0-9]+]] = phi %struct.hfa* [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ]
236*67e74705SXin Li }
237*67e74705SXin Li
check_start(int n,...)238*67e74705SXin Li void check_start(int n, ...) {
239*67e74705SXin Li // CHECK-LABEL: define void @check_start(i32 %n, ...)
240*67e74705SXin Li
241*67e74705SXin Li va_list the_list;
242*67e74705SXin Li va_start(the_list, n);
243*67e74705SXin Li // CHECK: [[THE_LIST:%[a-z_0-9]+]] = alloca %struct.__va_list
244*67e74705SXin Li // CHECK: [[VOIDP_THE_LIST:%[a-z_0-9]+]] = bitcast %struct.__va_list* [[THE_LIST]] to i8*
245*67e74705SXin Li // CHECK: call void @llvm.va_start(i8* [[VOIDP_THE_LIST]])
246*67e74705SXin Li }
247*67e74705SXin Li
248*67e74705SXin Li
249