1; RUN: llc -verify-machineinstrs < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-APPLE --check-prefix=CHECK-ARMV7 %s
2; RUN: llc -verify-machineinstrs -O0 < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-O0 %s
3
4declare i8* @malloc(i64)
5declare void @free(i8*)
6%swift_error = type { i64, i8 }
7%struct.S = type { i32, i32, i32, i32, i32, i32 }
8
9; This tests the basic usage of a swifterror parameter. "foo" is the function
10; that takes a swifterror parameter and "caller" is the caller of "foo".
11define float @foo(%swift_error** swifterror %error_ptr_ref) {
12; CHECK-APPLE-LABEL: foo:
13; CHECK-APPLE: mov r0, #16
14; CHECK-APPLE: malloc
15; CHECK-APPLE-DAG: mov [[ID:r[0-9]+]], #1
16; CHECK-APPLE-DAG: mov r6, r{{.*}}
17; CHECK-APPLE-DAG: strb [[ID]], [r{{.*}}, #8]
18
19; CHECK-O0-LABEL: foo:
20; CHECK-O0: mov r{{.*}}, #16
21; CHECK-O0: malloc
22; CHECK-O0: mov [[ID2:r[0-9]+]], r0
23; CHECK-O0: mov [[ID:r[0-9]+]], #1
24; CHECK-O0: strb [[ID]], [r0, #8]
25; CHECK-O0: mov r6, [[ID2]]
26entry:
27  %call = call i8* @malloc(i64 16)
28  %call.0 = bitcast i8* %call to %swift_error*
29  store %swift_error* %call.0, %swift_error** %error_ptr_ref
30  %tmp = getelementptr inbounds i8, i8* %call, i64 8
31  store i8 1, i8* %tmp
32  ret float 1.0
33}
34
35; "caller" calls "foo" that takes a swifterror parameter.
36define float @caller(i8* %error_ref) {
37; CHECK-APPLE-LABEL: caller:
38; CHECK-APPLE-DAG: mov [[ID:r[0-9]+]], r0
39; CHECK-APPLE-DAG: mov r6, #0
40; CHECK-APPLE: bl {{.*}}foo
41; CHECK-APPLE: cmp r6, #0
42; Access part of the error object and save it to error_ref
43; CHECK-APPLE: ldrbeq [[CODE:r[0-9]+]], [r6, #8]
44; CHECK-APPLE: strbeq [[CODE]], [{{.*}}[[ID]]]
45; CHECK-APPLE: mov r0, r6
46; CHECK-APPLE: bl {{.*}}free
47
48; CHECK-O0-LABEL: caller:
49; spill r0
50; CHECK-O0-DAG: mov r6, #0
51; CHECK-O0-DAG: str r0, [sp, [[SLOT:#[0-9]+]]
52; CHECK-O0: bl {{.*}}foo
53; CHECK-O0: mov [[TMP:r[0-9]+]], r6
54; CHECK-O0: str [[TMP]], [sp]
55; CHECK-O0: bne
56; CHECK-O0: ldrb [[CODE:r[0-9]+]], [r0, #8]
57; CHECK-O0: ldr     [[ID:r[0-9]+]], [sp, [[SLOT]]]
58; CHECK-O0: strb [[CODE]], [{{.*}}[[ID]]]
59; reload r0
60; CHECK-O0: ldr r0, [sp]
61; CHECK-O0: free
62entry:
63  %error_ptr_ref = alloca swifterror %swift_error*
64  store %swift_error* null, %swift_error** %error_ptr_ref
65  %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
66  %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
67  %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
68  %tmp = bitcast %swift_error* %error_from_foo to i8*
69  br i1 %had_error_from_foo, label %handler, label %cont
70cont:
71  %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
72  %t = load i8, i8* %v1
73  store i8 %t, i8* %error_ref
74  br label %handler
75handler:
76  call void @free(i8* %tmp)
77  ret float 1.0
78}
79
80; "caller2" is the caller of "foo", it calls "foo" inside a loop.
81define float @caller2(i8* %error_ref) {
82; CHECK-APPLE-LABEL: caller2:
83; CHECK-APPLE-DAG: mov [[ID:r[0-9]+]], r0
84; CHECK-APPLE-DAG: mov r6, #0
85; CHECK-APPLE: bl {{.*}}foo
86; CHECK-APPLE: cmp r6, #0
87; CHECK-APPLE: bne
88; Access part of the error object and save it to error_ref
89; CHECK-APPLE: ldrb [[CODE:r[0-9]+]], [r6, #8]
90; CHECK-APPLE: strb [[CODE]], [{{.*}}[[ID]]]
91; CHECK-APPLE: mov r0, r6
92; CHECK-APPLE: bl {{.*}}free
93
94; CHECK-O0-LABEL: caller2:
95; spill r0
96; CHECK-O0-DAG: str r0,
97; CHECK-O0-DAG: mov r6, #0
98; CHECK-O0: bl {{.*}}foo
99; CHECK-O0: mov r{{.*}}, r6
100; CHECK-O0: str r0, [sp]
101; CHECK-O0: bne
102; CHECK-O0: ble
103; CHECK-O0: ldrb [[CODE:r[0-9]+]], [r0, #8]
104; reload r0
105; CHECK-O0: ldr [[ID:r[0-9]+]],
106; CHECK-O0: strb [[CODE]], [{{.*}}[[ID]]]
107; CHECK-O0: ldr r0, [sp]
108; CHECK-O0: free
109entry:
110  %error_ptr_ref = alloca swifterror %swift_error*
111  br label %bb_loop
112bb_loop:
113  store %swift_error* null, %swift_error** %error_ptr_ref
114  %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
115  %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
116  %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
117  %tmp = bitcast %swift_error* %error_from_foo to i8*
118  br i1 %had_error_from_foo, label %handler, label %cont
119cont:
120  %cmp = fcmp ogt float %call, 1.000000e+00
121  br i1 %cmp, label %bb_end, label %bb_loop
122bb_end:
123  %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
124  %t = load i8, i8* %v1
125  store i8 %t, i8* %error_ref
126  br label %handler
127handler:
128  call void @free(i8* %tmp)
129  ret float 1.0
130}
131
132; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
133; under a certain condition.
134define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) {
135; CHECK-APPLE-LABEL: foo_if:
136; CHECK-APPLE: cmp r0, #0
137; CHECK-APPLE: eq
138; CHECK-APPLE: mov r0, #16
139; CHECK-APPLE: malloc
140; CHECK-APPLE: mov [[ID:r[0-9]+]], #1
141; CHECK-APPLE-DAG: mov r6, r{{.*}}
142; CHECK-APPLE-DAG: strb [[ID]], [r{{.*}}, #8]
143
144; CHECK-O0-LABEL: foo_if:
145; CHECK-O0: cmp r0, #0
146; spill to stack
147; CHECK-O0: str r6
148; CHECK-O0: beq
149; CHECK-O0: mov r0, #16
150; CHECK-O0: malloc
151; CHECK-O0: mov [[ID:r[0-9]+]], r0
152; CHECK-O0: mov [[ID2:[a-z0-9]+]], #1
153; CHECK-O0: strb [[ID2]], [r0, #8]
154; CHECK-O0: mov r6, [[ID]]
155; reload from stack
156; CHECK-O0: ldr r6
157entry:
158  %cond = icmp ne i32 %cc, 0
159  br i1 %cond, label %gen_error, label %normal
160
161gen_error:
162  %call = call i8* @malloc(i64 16)
163  %call.0 = bitcast i8* %call to %swift_error*
164  store %swift_error* %call.0, %swift_error** %error_ptr_ref
165  %tmp = getelementptr inbounds i8, i8* %call, i64 8
166  store i8 1, i8* %tmp
167  ret float 1.0
168
169normal:
170  ret float 0.0
171}
172
173; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
174; under a certain condition inside a loop.
175define float @foo_loop(%swift_error** swifterror %error_ptr_ref, i32 %cc, float %cc2) {
176; CHECK-APPLE-LABEL: foo_loop:
177; CHECK-APPLE: mov [[CODE:r[0-9]+]], r0
178; swifterror is kept in a register
179; CHECK-APPLE: mov [[ID:r[0-9]+]], r6
180; CHECK-APPLE: cmp [[CODE]], #0
181; CHECK-APPLE: beq
182; CHECK-APPLE: mov r0, #16
183; CHECK-APPLE: malloc
184; CHECK-APPLE: strb r{{.*}}, [{{.*}}[[ID]], #8]
185; CHECK-APPLE: ble
186; CHECK-APPLE: mov r6, [[ID]]
187
188; CHECK-O0-LABEL: foo_loop:
189; CHECK-O0: mov r{{.*}}, r6
190; CHECK-O0: cmp r{{.*}}, #0
191; CHECK-O0: beq
192; CHECK-O0-DAG: movw r{{.*}}, #1
193; CHECK-O0-DAG: mov r{{.*}}, #16
194; CHECK-O0: malloc
195; CHECK-O0-DAG: mov [[ID:r[0-9]+]], r0
196; CHECK-O0-DAG: ldr [[ID2:r[0-9]+]], [sp{{.*}}]
197; CHECK-O0: strb [[ID2]], [{{.*}}[[ID]], #8]
198; spill r0
199; CHECK-O0: str r0, [sp{{.*}}]
200; CHECK-O0: vcmpe
201; CHECK-O0: ble
202; reload from stack
203; CHECK-O0: ldr r6
204entry:
205  br label %bb_loop
206
207bb_loop:
208  %cond = icmp ne i32 %cc, 0
209  br i1 %cond, label %gen_error, label %bb_cont
210
211gen_error:
212  %call = call i8* @malloc(i64 16)
213  %call.0 = bitcast i8* %call to %swift_error*
214  store %swift_error* %call.0, %swift_error** %error_ptr_ref
215  %tmp = getelementptr inbounds i8, i8* %call, i64 8
216  store i8 1, i8* %tmp
217  br label %bb_cont
218
219bb_cont:
220  %cmp = fcmp ogt float %cc2, 1.000000e+00
221  br i1 %cmp, label %bb_end, label %bb_loop
222bb_end:
223  ret float 0.0
224}
225
226; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
227; parameter.
228define void @foo_sret(%struct.S* sret %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) {
229; CHECK-APPLE-LABEL: foo_sret:
230; CHECK-APPLE: mov [[SRET:r[0-9]+]], r0
231; CHECK-APPLE: mov r0, #16
232; CHECK-APPLE: malloc
233; CHECK-APPLE: mov [[REG:r[0-9]+]], #1
234; CHECK-APPLE-DAG: mov r6, r0
235; CHECK-APPLE-DAG: strb [[REG]], [r0, #8]
236; CHECK-APPLE-DAG: str r{{.*}}, [{{.*}}[[SRET]], #4]
237
238; CHECK-O0-LABEL: foo_sret:
239; CHECK-O0: mov r{{.*}}, #16
240; spill to stack: sret and val1
241; CHECK-O0-DAG: str r0
242; CHECK-O0-DAG: str r1
243; CHECK-O0: malloc
244; CHECK-O0: mov [[ID:r[0-9]+]], #1
245; CHECK-O0: strb [[ID]], [r0, #8]
246; reload from stack: sret and val1
247; CHECK-O0: ldr
248; CHECK-O0: ldr
249; CHECK-O0: str r{{.*}}, [{{.*}}, #4]
250; CHECK-O0: mov r6
251entry:
252  %call = call i8* @malloc(i64 16)
253  %call.0 = bitcast i8* %call to %swift_error*
254  store %swift_error* %call.0, %swift_error** %error_ptr_ref
255  %tmp = getelementptr inbounds i8, i8* %call, i64 8
256  store i8 1, i8* %tmp
257  %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1
258  store i32 %val1, i32* %v2
259  ret void
260}
261
262; "caller3" calls "foo_sret" that takes a swifterror parameter.
263define float @caller3(i8* %error_ref) {
264; CHECK-APPLE-LABEL: caller3:
265; CHECK-APPLE: mov [[ID:r[0-9]+]], r0
266; CHECK-APPLE: mov r6, #0
267; CHECK-APPLE: bl {{.*}}foo_sret
268; CHECK-APPLE: cmp r6, #0
269; Access part of the error object and save it to error_ref
270; CHECK-APPLE: ldrbeq [[CODE:r[0-9]+]], [r6, #8]
271; CHECK-APPLE: strbeq [[CODE]], [{{.*}}[[ID]]]
272; CHECK-APPLE: mov r0, r6
273; CHECK-APPLE: bl {{.*}}free
274
275; CHECK-O0-LABEL: caller3:
276; CHECK-O0-DAG: mov r6, #0
277; CHECK-O0-DAG: mov r0
278; CHECK-O0-DAG: mov r1
279; CHECK-O0: bl {{.*}}foo_sret
280; CHECK-O0: mov [[ID2:r[0-9]+]], r6
281; CHECK-O0: cmp r6
282; CHECK-O0: str [[ID2]], [sp[[SLOT:.*]]]
283; CHECK-O0: bne
284; Access part of the error object and save it to error_ref
285; CHECK-O0: ldrb [[CODE:r[0-9]+]]
286; CHECK-O0: ldr [[ID:r[0-9]+]]
287; CHECK-O0: strb [[CODE]], [{{.*}}[[ID]]]
288; CHECK-O0: ldr r0, [sp[[SLOT]]
289; CHECK-O0: bl {{.*}}free
290entry:
291  %s = alloca %struct.S, align 8
292  %error_ptr_ref = alloca swifterror %swift_error*
293  store %swift_error* null, %swift_error** %error_ptr_ref
294  call void @foo_sret(%struct.S* sret %s, i32 1, %swift_error** swifterror %error_ptr_ref)
295  %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
296  %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
297  %tmp = bitcast %swift_error* %error_from_foo to i8*
298  br i1 %had_error_from_foo, label %handler, label %cont
299cont:
300  %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
301  %t = load i8, i8* %v1
302  store i8 %t, i8* %error_ref
303  br label %handler
304handler:
305  call void @free(i8* %tmp)
306  ret float 1.0
307}
308
309; "foo_vararg" is a function that takes a swifterror parameter, it also has
310; variable number of arguments.
311declare void @llvm.va_start(i8*) nounwind
312define float @foo_vararg(%swift_error** swifterror %error_ptr_ref, ...) {
313; CHECK-APPLE-LABEL: foo_vararg:
314; CHECK-APPLE: mov r0, #16
315; CHECK-APPLE: malloc
316; CHECK-APPLE: mov [[REG:r[0-9]+]], r0
317; CHECK-APPLE: mov [[ID:r[0-9]+]], #1
318; CHECK-APPLE-DAG: strb [[ID]], [{{.*}}[[REG]], #8]
319; CHECK-APPLE-DAG: mov r6, [[REG]]
320
321entry:
322  %call = call i8* @malloc(i64 16)
323  %call.0 = bitcast i8* %call to %swift_error*
324  store %swift_error* %call.0, %swift_error** %error_ptr_ref
325  %tmp = getelementptr inbounds i8, i8* %call, i64 8
326  store i8 1, i8* %tmp
327
328  %args = alloca i8*, align 8
329  %a10 = alloca i32, align 4
330  %a11 = alloca i32, align 4
331  %a12 = alloca i32, align 4
332  %v10 = bitcast i8** %args to i8*
333  call void @llvm.va_start(i8* %v10)
334  %v11 = va_arg i8** %args, i32
335  store i32 %v11, i32* %a10, align 4
336  %v12 = va_arg i8** %args, i32
337  store i32 %v12, i32* %a11, align 4
338  %v13 = va_arg i8** %args, i32
339  store i32 %v13, i32* %a12, align 4
340
341  ret float 1.0
342}
343
344; "caller4" calls "foo_vararg" that takes a swifterror parameter.
345define float @caller4(i8* %error_ref) {
346; CHECK-APPLE-LABEL: caller4:
347; CHECK-APPLE: mov [[ID:r[0-9]+]], r0
348; CHECK-APPLE: mov r6, #0
349; CHECK-APPLE: bl {{.*}}foo_vararg
350; CHECK-APPLE: cmp r6, #0
351; Access part of the error object and save it to error_ref
352; CHECK-APPLE: ldrbeq [[CODE:r[0-9]+]], [r6, #8]
353; CHECK-APPLE: strbeq [[CODE]], [{{.*}}[[ID]]]
354; CHECK-APPLE: mov r0, r6
355; CHECK-APPLE: bl {{.*}}free
356entry:
357  %error_ptr_ref = alloca swifterror %swift_error*
358  store %swift_error* null, %swift_error** %error_ptr_ref
359
360  %a10 = alloca i32, align 4
361  %a11 = alloca i32, align 4
362  %a12 = alloca i32, align 4
363  store i32 10, i32* %a10, align 4
364  store i32 11, i32* %a11, align 4
365  store i32 12, i32* %a12, align 4
366  %v10 = load i32, i32* %a10, align 4
367  %v11 = load i32, i32* %a11, align 4
368  %v12 = load i32, i32* %a12, align 4
369
370  %call = call float (%swift_error**, ...) @foo_vararg(%swift_error** swifterror %error_ptr_ref, i32 %v10, i32 %v11, i32 %v12)
371  %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
372  %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
373  %tmp = bitcast %swift_error* %error_from_foo to i8*
374  br i1 %had_error_from_foo, label %handler, label %cont
375
376cont:
377  %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
378  %t = load i8, i8* %v1
379  store i8 %t, i8* %error_ref
380  br label %handler
381handler:
382  call void @free(i8* %tmp)
383  ret float 1.0
384}
385
386; Check that we don't blow up on tail calling swifterror argument functions.
387define float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) {
388entry:
389  %0 = tail call float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref)
390  ret float %0
391}
392define swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) {
393entry:
394  %0 = tail call swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref)
395  ret float %0
396}
397
398; CHECK-APPLE-LABEL: swifterror_clobber
399; CHECK-APPLE: mov [[REG:r[0-9]+]], r6
400; CHECK-APPLE: nop
401; CHECK-APPLE: mov r6, [[REG]]
402define swiftcc void @swifterror_clobber(%swift_error** nocapture swifterror %err) {
403  call void asm sideeffect "nop", "~{r6}"()
404  ret void
405}
406
407; CHECK-APPLE-LABEL: swifterror_reg_clobber
408; CHECK-APPLE: push {{.*}}r6
409; CHECK-APPLE: nop
410; CHECK-APPLE: pop  {{.*}}r6
411define swiftcc void @swifterror_reg_clobber(%swift_error** nocapture %err) {
412  call void asm sideeffect "nop", "~{r6}"()
413  ret void
414}
415
416; CHECK-ARMV7-LABEL: _params_in_reg
417; Store callee saved registers excluding swifterror.
418; CHECK-ARMV7:  push    {r4, r5, r7, r8, r10, r11, lr}
419; Store swiftself (r10) and swifterror (r6).
420; CHECK-ARMV7-DAG:  str     r6, [s[[STK1:.*]]]
421; CHECK-ARMV7-DAG:  str     r10, [s[[STK2:.*]]]
422; Store arguments.
423; CHECK-ARMV7:  mov     r4, r3
424; CHECK-ARMV7:  mov     r5, r2
425; CHECK-ARMV7:  mov     r8, r1
426; CHECK-ARMV7:  mov     r11, r0
427; Setup call.
428; CHECK-ARMV7:  mov     r0, #1
429; CHECK-ARMV7:  mov     r1, #2
430; CHECK-ARMV7:  mov     r2, #3
431; CHECK-ARMV7:  mov     r3, #4
432; CHECK-ARMV7:  mov     r10, #0
433; CHECK-ARMV7:  mov     r6, #0
434; CHECK-ARMV7:  bl      _params_in_reg2
435; Restore original arguments.
436; CHECK-ARMV7-DAG:  ldr     r10, [s[[STK2]]]
437; CHECK-ARMV7-DAG:  ldr     r6, [s[[STK1]]]
438; CHECK-ARMV7:  mov     r0, r11
439; CHECK-ARMV7:  mov     r1, r8
440; CHECK-ARMV7:  mov     r2, r5
441; CHECK-ARMV7:  mov     r3, r4
442; CHECK-ARMV7:  bl      _params_in_reg2
443; CHECK-ARMV7:  pop     {r4, r5, r7,  r8, r10, r11, pc}
444define swiftcc void @params_in_reg(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err) {
445  %error_ptr_ref = alloca swifterror %swift_error*, align 8
446  store %swift_error* null, %swift_error** %error_ptr_ref
447  call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
448  call swiftcc void @params_in_reg2(i32 %0, i32 %1, i32 %2, i32 %3, i8* swiftself %4, %swift_error** nocapture swifterror %err)
449  ret void
450}
451declare swiftcc void @params_in_reg2(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err)
452
453; CHECK-ARMV7-LABEL: params_and_return_in_reg
454; CHECK-ARMV7:  push    {r4, r5, r7, r8, r10, r11, lr}
455; Store swifterror and swiftself
456; CHECK-ARMV7:  mov     r4, r6
457; CHECK-ARMV7:  str     r10, [s[[STK1:.*]]]
458; Store arguments.
459; CHECK-ARMV7:  str     r3, [s[[STK2:.*]]]
460; CHECK-ARMV7:  mov     r5, r2
461; CHECK-ARMV7:  mov     r8, r1
462; CHECK-ARMV7:  mov     r11, r0
463; Setup call.
464; CHECK-ARMV7:  mov     r0, #1
465; CHECK-ARMV7:  mov     r1, #2
466; CHECK-ARMV7:  mov     r2, #3
467; CHECK-ARMV7:  mov     r3, #4
468; CHECK-ARMV7:  mov     r10, #0
469; CHECK-ARMV7:  mov     r6, #0
470; CHECK-ARMV7:  bl      _params_in_reg2
471; Restore original arguments.
472; CHECK-ARMV7:  ldr     r3, [s[[STK2]]]
473; CHECK-ARMV7:  ldr     r10, [s[[STK1]]]
474; Store %error_ptr_ref;
475; CHECK-ARMV7:  str     r6, [s[[STK3:.*]]]
476; Restore original arguments.
477; CHECK-ARMV7:  mov     r0, r11
478; CHECK-ARMV7:  mov     r1, r8
479; CHECK-ARMV7:  mov     r2, r5
480; CHECK-ARMV7:  mov     r6, r4
481; CHECK-ARMV7:  bl      _params_and_return_in_reg2
482; Store swifterror return %err;
483; CHECK-ARMV7:  str     r6, [s[[STK1]]]
484; Load swifterror value %error_ptr_ref.
485; CHECK-ARMV7:  ldr     r6, [s[[STK3]]]
486; Save return values.
487; CHECK-ARMV7:  mov     r5, r0
488; CHECK-ARMV7:  mov     r4, r1
489; CHECK-ARMV7:  mov     r8, r2
490; CHECK-ARMV7:  mov     r11, r3
491; Setup call.
492; CHECK-ARMV7:  mov     r0, #1
493; CHECK-ARMV7:  mov     r1, #2
494; CHECK-ARMV7:  mov     r2, #3
495; CHECK-ARMV7:  mov     r3, #4
496; CHECK-ARMV7:  mov     r10, #0
497; CHECK-ARMV7:  bl      _params_in_reg2
498; Load swifterror %err;
499; CHECK-ARMV7:  ldr     r6, [s[[STK1]]]
500; Restore return values for returning.
501; CHECK-ARMV7:  mov     r0, r5
502; CHECK-ARMV7:  mov     r1, r4
503; CHECK-ARMV7:  mov     r2, r8
504; CHECK-ARMV7:  mov     r3, r11
505; CHECK-ARMV7:  pop     {r4, r5, r7, r8, r10, r11, pc}
506define swiftcc { i32, i32, i32, i32} @params_and_return_in_reg(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err) {
507  %error_ptr_ref = alloca swifterror %swift_error*, align 8
508  store %swift_error* null, %swift_error** %error_ptr_ref
509  call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
510  %val = call swiftcc  { i32, i32, i32, i32 } @params_and_return_in_reg2(i32 %0, i32 %1, i32 %2, i32 %3, i8* swiftself %4, %swift_error** nocapture swifterror %err)
511  call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
512  ret { i32, i32, i32, i32 }%val
513}
514
515declare swiftcc { i32, i32, i32, i32 } @params_and_return_in_reg2(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err)
516