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