1; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-apple-darwin | FileCheck --check-prefix=CHECK-APPLE %s
2; RUN: llc -verify-machineinstrs -O0 < %s -mtriple=x86_64-apple-darwin | FileCheck --check-prefix=CHECK-O0 %s
3; RUN: llc -verify-machineinstrs < %s -mtriple=i386-apple-darwin | FileCheck --check-prefix=CHECK-i386 %s
4
5declare i8* @malloc(i64)
6declare void @free(i8*)
7%swift_error = type {i64, i8}
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: movl $16, %edi
14; CHECK-APPLE: malloc
15; CHECK-APPLE: movb $1, 8(%rax)
16; CHECK-APPLE: movq %rax, %r12
17
18; CHECK-O0-LABEL: foo:
19; CHECK-O0: movl $16
20; CHECK-O0: malloc
21; CHECK-O0: movb $1, 8(%rax)
22; CHECK-O0: movq %{{.*}}, %r12
23entry:
24  %call = call i8* @malloc(i64 16)
25  %call.0 = bitcast i8* %call to %swift_error*
26  store %swift_error* %call.0, %swift_error** %error_ptr_ref
27  %tmp = getelementptr inbounds i8, i8* %call, i64 8
28  store i8 1, i8* %tmp
29  ret float 1.0
30}
31
32; "caller" calls "foo" that takes a swifterror parameter.
33define float @caller(i8* %error_ref) {
34; CHECK-APPLE-LABEL: caller:
35; CHECK-APPLE: xorl %r12d, %r12d
36; CHECK-APPLE: callq {{.*}}foo
37; CHECK-APPLE: testq %r12, %r12
38; CHECK-APPLE: jne
39; Access part of the error object and save it to error_ref
40; CHECK-APPLE: movb 8(%r12)
41; CHECK-APPLE: movq %r12, %rdi
42; CHECK-APPLE: callq {{.*}}free
43
44; CHECK-O0-LABEL: caller:
45; CHECK-O0: xorl
46; CHECK-O0: movl %{{.*}}, %r12d
47; CHECK-O0: callq {{.*}}foo
48; CHECK-O0: jne
49entry:
50  %error_ptr_ref = alloca swifterror %swift_error*
51  store %swift_error* null, %swift_error** %error_ptr_ref
52  %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
53  %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
54  %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
55  %tmp = bitcast %swift_error* %error_from_foo to i8*
56  br i1 %had_error_from_foo, label %handler, label %cont
57cont:
58  %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
59  %t = load i8, i8* %v1
60  store i8 %t, i8* %error_ref
61  br label %handler
62handler:
63  call void @free(i8* %tmp)
64  ret float 1.0
65}
66
67; "caller2" is the caller of "foo", it calls "foo" inside a loop.
68define float @caller2(i8* %error_ref) {
69; CHECK-APPLE-LABEL: caller2:
70; CHECK-APPLE: xorl %r12d, %r12d
71; CHECK-APPLE: callq {{.*}}foo
72; CHECK-APPLE: testq %r12, %r12
73; CHECK-APPLE: jne
74; CHECK-APPLE: ucomiss
75; CHECK-APPLE: jbe
76; Access part of the error object and save it to error_ref
77; CHECK-APPLE: movb 8(%r12)
78; CHECK-APPLE: movq %r12, %rdi
79; CHECK-APPLE: callq {{.*}}free
80
81; CHECK-O0-LABEL: caller2:
82; CHECK-O0: xorl
83; CHECK-O0: movl %{{.*}}, %r12d
84; CHECK-O0: callq {{.*}}foo
85; CHECK-O0: movq %r12, [[ID:%[a-z]+]]
86; CHECK-O0: cmpq $0, %r12
87; CHECK-O0: jne
88entry:
89  %error_ptr_ref = alloca swifterror %swift_error*
90  br label %bb_loop
91bb_loop:
92  store %swift_error* null, %swift_error** %error_ptr_ref
93  %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
94  %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
95  %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
96  %tmp = bitcast %swift_error* %error_from_foo to i8*
97  br i1 %had_error_from_foo, label %handler, label %cont
98cont:
99  %cmp = fcmp ogt float %call, 1.000000e+00
100  br i1 %cmp, label %bb_end, label %bb_loop
101bb_end:
102  %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
103  %t = load i8, i8* %v1
104  store i8 %t, i8* %error_ref
105  br label %handler
106handler:
107  call void @free(i8* %tmp)
108  ret float 1.0
109}
110
111; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
112; under a certain condition.
113define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) {
114; CHECK-APPLE-LABEL: foo_if:
115; CHECK-APPLE: testl %edi, %edi
116; CHECK-APPLE: je
117; CHECK-APPLE: movl $16, %edi
118; CHECK-APPLE: malloc
119; CHECK-APPLE: movb $1, 8(%rax)
120; CHECK-APPLE: movq %rax, %r12
121; CHECK-APPLE-NOT: %r12
122; CHECK-APPLE: ret
123
124; CHECK-O0-LABEL: foo_if:
125; CHECK-O0: cmpl $0
126; spill to stack
127; CHECK-O0: movq %r12, {{.*}}(%rsp)
128; CHECK-O0: je
129; CHECK-O0: movl $16,
130; CHECK-O0: malloc
131; CHECK-O0: movq %rax, [[ID:%[a-z]+]]
132; CHECK-O0-DAG: movb $1, 8(%rax)
133; CHECK-O0-DAG: movq [[ID]], %r12
134; CHECK-O0: ret
135; reload from stack
136; CHECK-O0: movq {{.*}}(%rsp), [[REG:%[a-z]+]]
137; CHECK-O0: movq [[REG]], %r12
138; CHECK-O0: ret
139entry:
140  %cond = icmp ne i32 %cc, 0
141  br i1 %cond, label %gen_error, label %normal
142
143gen_error:
144  %call = call i8* @malloc(i64 16)
145  %call.0 = bitcast i8* %call to %swift_error*
146  store %swift_error* %call.0, %swift_error** %error_ptr_ref
147  %tmp = getelementptr inbounds i8, i8* %call, i64 8
148  store i8 1, i8* %tmp
149  ret float 1.0
150
151normal:
152  ret float 0.0
153}
154
155; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
156; under a certain condition inside a loop.
157define float @foo_loop(%swift_error** swifterror %error_ptr_ref, i32 %cc, float %cc2) {
158; CHECK-APPLE-LABEL: foo_loop:
159; CHECK-APPLE: movq %r12, %rax
160; CHECK-APPLE: testl
161; CHECK-APPLE: je
162; CHECK-APPLE: movl $16, %edi
163; CHECK-APPLE: malloc
164; CHECK-APPLE: movb $1, 8(%rax)
165; CHECK-APPLE: ucomiss
166; CHECK-APPLE: jbe
167; CHECK-APPLE: movq %rax, %r12
168; CHECK-APPLE: ret
169
170; CHECK-O0-LABEL: foo_loop:
171; spill to stack
172; CHECK-O0: movq %r12, {{.*}}(%rsp)
173; CHECK-O0: cmpl $0
174; CHECK-O0: je
175; CHECK-O0: movl $16,
176; CHECK-O0: malloc
177; CHECK-O0: movq %rax, [[ID:%[a-z0-9]+]]
178; CHECK-O0: movb $1, 8([[ID]])
179; CHECK-O0: jbe
180; reload from stack
181; CHECK-O0: movq {{.*}}(%rsp), [[REG:%[a-z0-9]+]]
182; CHECK-O0: movq [[REG]], %r12
183; CHECK-O0: ret
184entry:
185  br label %bb_loop
186
187bb_loop:
188  %cond = icmp ne i32 %cc, 0
189  br i1 %cond, label %gen_error, label %bb_cont
190
191gen_error:
192  %call = call i8* @malloc(i64 16)
193  %call.0 = bitcast i8* %call to %swift_error*
194  store %swift_error* %call.0, %swift_error** %error_ptr_ref
195  %tmp = getelementptr inbounds i8, i8* %call, i64 8
196  store i8 1, i8* %tmp
197  br label %bb_cont
198
199bb_cont:
200  %cmp = fcmp ogt float %cc2, 1.000000e+00
201  br i1 %cmp, label %bb_end, label %bb_loop
202bb_end:
203  ret float 0.0
204}
205
206%struct.S = type { i32, i32, i32, i32, i32, i32 }
207
208; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
209; parameter.
210define void @foo_sret(%struct.S* sret %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) {
211; CHECK-APPLE-LABEL: foo_sret:
212; CHECK-APPLE: movq %rdi, %{{.*}}
213; CHECK-APPLE: movl $16, %edi
214; CHECK-APPLE: malloc
215; CHECK-APPLE: movb $1, 8(%rax)
216; CHECK-APPLE: movl %{{.*}}, 4(%{{.*}})
217; CHECK-APPLE: movq %rax, %r12
218; CHECK-APPLE: movq %{{.*}}, %rax
219; CHECK-APPLE-NOT: x19
220
221; CHECK-O0-LABEL: foo_sret:
222; CHECK-O0: movl $16,
223; spill sret to stack
224; CHECK-O0: movq %rdi,
225; CHECK-O0: movq {{.*}}, %rdi
226; CHECK-O0: malloc
227; CHECK-O0: movb $1, 8(%rax)
228; CHECK-O0: movl %{{.*}}, 4(%{{.*}})
229; CHECK-O0: movq %{{.*}}, %r12
230; reload sret from stack
231; CHECK-O0: movq {{.*}}(%rsp), %rax
232; CHECK-O0: ret
233entry:
234  %call = call i8* @malloc(i64 16)
235  %call.0 = bitcast i8* %call to %swift_error*
236  store %swift_error* %call.0, %swift_error** %error_ptr_ref
237  %tmp = getelementptr inbounds i8, i8* %call, i64 8
238  store i8 1, i8* %tmp
239  %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1
240  store i32 %val1, i32* %v2
241  ret void
242}
243
244; "caller3" calls "foo_sret" that takes a swifterror parameter.
245define float @caller3(i8* %error_ref) {
246; CHECK-APPLE-LABEL: caller3:
247; CHECK-APPLE: movl $1, %esi
248; CHECK-APPLE: xorl %r12d, %r12d
249; CHECK-APPLE: callq {{.*}}foo_sret
250; CHECK-APPLE: testq %r12, %r12
251; CHECK-APPLE: jne
252; Access part of the error object and save it to error_ref
253; CHECK-APPLE: movb 8(%r12),
254; CHECK-APPLE: movb %{{.*}},
255; CHECK-APPLE: movq %r12, %rdi
256; CHECK-APPLE: callq {{.*}}free
257
258; CHECK-O0-LABEL: caller3:
259; CHECK-O0: xorl
260; CHECK-O0: movl {{.*}}, %r12d
261; CHECK-O0: movl $1, %esi
262; CHECK-O0: movq {{.*}}, %rdi
263; CHECK-O0: callq {{.*}}foo_sret
264; CHECK-O0: movq %r12,
265; CHECK-O0: cmpq $0
266; CHECK-O0: jne
267; Access part of the error object and save it to error_ref
268; CHECK-O0: movb 8(%{{.*}}),
269; CHECK-O0: movb %{{.*}},
270; reload from stack
271; CHECK-O0: movq {{.*}}(%rsp), %rdi
272; CHECK-O0: callq {{.*}}free
273entry:
274  %s = alloca %struct.S, align 8
275  %error_ptr_ref = alloca swifterror %swift_error*
276  store %swift_error* null, %swift_error** %error_ptr_ref
277  call void @foo_sret(%struct.S* sret %s, i32 1, %swift_error** swifterror %error_ptr_ref)
278  %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
279  %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
280  %tmp = bitcast %swift_error* %error_from_foo to i8*
281  br i1 %had_error_from_foo, label %handler, label %cont
282cont:
283  %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
284  %t = load i8, i8* %v1
285  store i8 %t, i8* %error_ref
286  br label %handler
287handler:
288  call void @free(i8* %tmp)
289  ret float 1.0
290}
291
292; This is a caller with multiple swifterror values, it calls "foo" twice, each
293; time with a different swifterror value, from "alloca swifterror".
294define float @caller_with_multiple_swifterror_values(i8* %error_ref, i8* %error_ref2) {
295; CHECK-APPLE-LABEL: caller_with_multiple_swifterror_values:
296
297; The first swifterror value:
298; CHECK-APPLE: xorl %r12d, %r12d
299; CHECK-APPLE: callq {{.*}}foo
300; CHECK-APPLE: testq %r12, %r12
301; CHECK-APPLE: jne
302; Access part of the error object and save it to error_ref
303; CHECK-APPLE: movb 8(%r12)
304; CHECK-APPLE: movq %r12, %rdi
305; CHECK-APPLE: callq {{.*}}free
306
307; The second swifterror value:
308; CHECK-APPLE: xorl %r12d, %r12d
309; CHECK-APPLE: callq {{.*}}foo
310; CHECK-APPLE: testq %r12, %r12
311; CHECK-APPLE: jne
312; Access part of the error object and save it to error_ref
313; CHECK-APPLE: movb 8(%r12)
314; CHECK-APPLE: movq %r12, %rdi
315; CHECK-APPLE: callq {{.*}}free
316
317; CHECK-O0-LABEL: caller_with_multiple_swifterror_values:
318
319; The first swifterror value:
320; CHECK-O0: xorl
321; CHECK-O0: movl %{{.*}}, %r12d
322; CHECK-O0: callq {{.*}}foo
323; CHECK-O0: jne
324
325; The second swifterror value:
326; CHECK-O0: xorl
327; CHECK-O0: movl %{{.*}}, %r12d
328; CHECK-O0: callq {{.*}}foo
329; CHECK-O0: jne
330entry:
331  %error_ptr_ref = alloca swifterror %swift_error*
332  store %swift_error* null, %swift_error** %error_ptr_ref
333  %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
334  %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
335  %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
336  %tmp = bitcast %swift_error* %error_from_foo to i8*
337  br i1 %had_error_from_foo, label %handler, label %cont
338cont:
339  %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
340  %t = load i8, i8* %v1
341  store i8 %t, i8* %error_ref
342  br label %handler
343handler:
344  call void @free(i8* %tmp)
345
346  %error_ptr_ref2 = alloca swifterror %swift_error*
347  store %swift_error* null, %swift_error** %error_ptr_ref2
348  %call2 = call float @foo(%swift_error** swifterror %error_ptr_ref2)
349  %error_from_foo2 = load %swift_error*, %swift_error** %error_ptr_ref2
350  %had_error_from_foo2 = icmp ne %swift_error* %error_from_foo2, null
351  %bitcast2 = bitcast %swift_error* %error_from_foo2 to i8*
352  br i1 %had_error_from_foo2, label %handler2, label %cont2
353cont2:
354  %v2 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo2, i64 0, i32 1
355  %t2 = load i8, i8* %v2
356  store i8 %t2, i8* %error_ref2
357  br label %handler2
358handler2:
359  call void @free(i8* %bitcast2)
360
361  ret float 1.0
362}
363
364%swift.refcounted = type opaque
365
366; This test checks that we don't create bad phi nodes as part of swifterror
367; isel. We used to fail machine ir verification.
368; CHECK-APPLE: _swifterror_isel
369; CHECK-O0: _swifterror_isel
370define void @swifterror_isel(%swift.refcounted*) {
371entry:
372  %swifterror = alloca swifterror %swift_error*, align 8
373  br i1 undef, label %5, label %1
374
375  %2 = phi i16 [ %4, %1 ], [ undef, %entry ]
376  %3 = call i1 undef(i16 %2, %swift.refcounted* swiftself %0, %swift_error** nocapture swifterror %swifterror)
377  %4 = load i16, i16* undef, align 2
378  br label %1
379
380  ret void
381}
382
383; This tests the basic usage of a swifterror parameter with swiftcc.
384define swiftcc float @foo_swiftcc(%swift_error** swifterror %error_ptr_ref) {
385; CHECK-APPLE-LABEL: foo_swiftcc:
386; CHECK-APPLE: movl $16, %edi
387; CHECK-APPLE: malloc
388; CHECK-APPLE: movb $1, 8(%rax)
389; CHECK-APPLE: movq %rax, %r12
390
391; CHECK-O0-LABEL: foo_swiftcc:
392; CHECK-O0: movl $16
393; CHECK-O0: malloc
394; CHECK-O0: movb $1, 8(%rax)
395; CHECK-O0: movq %{{.*}}, %r12
396entry:
397  %call = call i8* @malloc(i64 16)
398  %call.0 = bitcast i8* %call to %swift_error*
399  store %swift_error* %call.0, %swift_error** %error_ptr_ref
400  %tmp = getelementptr inbounds i8, i8* %call, i64 8
401  store i8 1, i8* %tmp
402  ret float 1.0
403}
404
405declare swiftcc float @moo(%swift_error** swifterror)
406
407; Test parameter forwarding.
408define swiftcc float @forward_swifterror(%swift_error** swifterror %error_ptr_ref) {
409; CHECK-APPLE-LABEL: forward_swifterror:
410; CHECK-APPLE: pushq %rax
411; CHECK-APPLE: callq _moo
412; CHECK-APPLE: popq %rax
413; CHECK-APPLE: retq
414
415; CHECK-O0-LABEL: forward_swifterror:
416; CHECK-O0: pushq %rax
417; CHECK-O0:  callq _moo
418; CHECK-O0: popq %rax
419; CHECK-O0:  retq
420
421entry:
422  %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref)
423  ret float %call
424}
425
426define swiftcc float @conditionally_forward_swifterror(%swift_error** swifterror %error_ptr_ref, i32 %cc) {
427; CHECK-APPLE-LABEL: conditionally_forward_swifterror:
428; CHECK-APPLE:  pushq %rax
429; CHECK-APPLE:	testl %edi, %edi
430; CHECK-APPLE:  je
431
432; CHECK-APPLE:  callq _moo
433; CHECK-APPLE:  popq %rax
434; CHECK-APPLE:  retq
435
436; CHECK-APPLE:  xorps %xmm0, %xmm0
437; CHECK-APPLE:  popq %rax
438; CHECK-APPLE:  retq
439
440; CHECK-O0-LABEL: conditionally_forward_swifterror:
441; CHECK-O0:  subq $24, %rsp
442; CHECK-O0:  movq %r12, [[REG1:%[a-z0-9]+]]
443; CHECK-O0:  cmpl $0, %edi
444; CHECK-O0-DAG:  movq [[REG1]], [[STK:[0-9]+]](%rsp)
445; CHECK-O0-DAG:  movq %r12, [[STK2:[0-9]+]](%rsp)
446; CHECK-O0:  je
447
448; CHECK-O0:  movq [[STK2]](%rsp), [[REG:%[a-z0-9]+]]
449; CHECK-O0:  movq [[REG]], %r12
450; CHECK-O0:  callq _moo
451; CHECK-O0:  addq $24, %rsp
452; CHECK-O0:  retq
453
454; CHECK-O0:  movq [[STK2]](%rsp), [[REG:%[a-z0-9]+]]
455; CHECK-O0:  xorps %xmm0, %xmm0
456; CHECK-O0:  movq [[REG]], %r12
457; CHECK-O0:  addq $24, %rsp
458; CHECK-O0:  retq
459entry:
460  %cond = icmp ne i32 %cc, 0
461  br i1 %cond, label %gen_error, label %normal
462
463gen_error:
464  %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref)
465  ret float %call
466
467normal:
468  ret float 0.0
469}
470
471; Check that we don't blow up on tail calling swifterror argument functions.
472define float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) {
473entry:
474  %0 = tail call float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref)
475  ret float %0
476}
477define swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) {
478entry:
479  %0 = tail call swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref)
480  ret float %0
481}
482
483; Check that we can handle an empty function with swifterror argument.
484; CHECK-i386-LABEL: empty_swiftcc:
485; CHECK-i386:  movl    4(%esp), %eax
486; CHECK-i386:  movl    8(%esp), %edx
487; CHECK-i386:  movl    12(%esp), %ecx
488; CHECK-i386:  retl
489; CHECK-APPLE-LABEL: empty_swiftcc:
490; CHECK-APPLE:  movl    %edx, %ecx
491; CHECK-APPLE:  movl    %edi, %eax
492; CHECK-APPLE:  movl    %esi, %edx
493; CHECK-APPLE:  retq
494define swiftcc {i32, i32, i32} @empty_swiftcc({i32, i32, i32} , %swift_error** swifterror %error_ptr_ref) {
495entry:
496  ret {i32, i32, i32} %0
497}
498
499; Make sure we can handle the case when isel generates new machine basic blocks.
500; CHECK-APPLE-LABEL: dont_crash_on_new_isel_blocks:
501; CHECK-APPLE: pushq   %rax
502; CHECK-APPLE: xorl    %eax, %eax
503; CHECK-APPLE: testb   %al, %al
504; CHECK-APPLE: jne
505; CHECK-APPLE: callq   *%rax
506; CHECK-APPLE: popq    %rax
507; CHECK-APPLE: ret
508
509define swiftcc void @dont_crash_on_new_isel_blocks(%swift_error** nocapture swifterror, i1, i8**) {
510entry:
511  %3 = or i1 false, %1
512  br i1 %3, label %cont, label %falsebb
513
514falsebb:
515  %4 = load i8*, i8** %2, align 8
516  br label %cont
517
518cont:
519  tail call swiftcc void undef(%swift_error** nocapture swifterror %0)
520  ret void
521}
522
523; CHECK-APPLE-LABEL: swifterror_clobber
524; CHECK-APPLE: movq %r12, [[REG:%.*]]
525; CHECK-APPLE: nop
526; CHECK-APPLE: movq [[REG]], %r12
527define swiftcc void @swifterror_clobber(%swift_error** nocapture swifterror %err) {
528  call void asm sideeffect "nop", "~{r12}"()
529  ret void
530}
531
532; CHECK-APPLE-LABEL: swifterror_reg_clobber
533; CHECK-APPLE: pushq %r12
534; CHECK-APPLE: nop
535; CHECK-APPLE: popq  %r12
536define swiftcc void @swifterror_reg_clobber(%swift_error** nocapture %err) {
537  call void asm sideeffect "nop", "~{r12}"()
538  ret void
539}
540
541; CHECK-APPLE-LABEL: params_in_reg
542; Save callee save registers to store clobbered arugments.
543; CHECK-APPLE:  pushq   %rbp
544; CHECK-APPLE:  pushq   %r15
545; CHECK-APPLE:  pushq   %r14
546; Clobbered swiftself register.
547; CHECK-APPLE:  pushq   %r13
548; CHECK-APPLE:  pushq   %rbx
549; CHECK-APPLE:  subq    $48, %rsp
550; Save arguments.
551; CHECK-APPLE:  movq    %r12, 32(%rsp)
552; CHECK-APPLE:  movq    %r13, 24(%rsp)
553; CHECK-APPLE:  movq    %r9, 16(%rsp)
554; CHECK-APPLE:  movq    %r8, 8(%rsp)
555; CHECK-APPLE:  movq    %rcx, %r14
556; CHECK-APPLE:  movq    %rdx, %r15
557; CHECK-APPLE:  movq    %rsi, %rbx
558; CHECK-APPLE:  movq    %rdi, %rbp
559; Setup call.
560; CHECK-APPLE:  movl    $1, %edi
561; CHECK-APPLE:  movl    $2, %esi
562; CHECK-APPLE:  movl    $3, %edx
563; CHECK-APPLE:  movl    $4, %ecx
564; CHECK-APPLE:  movl    $5, %r8d
565; CHECK-APPLE:  movl    $6, %r9d
566; CHECK-APPLE:  xorl    %r13d, %r13d
567; CHECK-APPLE:  xorl    %r12d, %r12d
568; CHECK-APPLE:  callq   _params_in_reg2
569; Setup second call with stored arguments.
570; CHECK-APPLE:  movq    %rbp, %rdi
571; CHECK-APPLE:  movq    %rbx, %rsi
572; CHECK-APPLE:  movq    %r15, %rdx
573; CHECK-APPLE:  movq    %r14, %rcx
574; CHECK-APPLE:  movq    8(%rsp), %r8
575; CHECK-APPLE:  movq    16(%rsp), %r9
576; CHECK-APPLE:  movq    24(%rsp), %r13
577; CHECK-APPLE:  movq    32(%rsp), %r12
578; CHECK-APPLE:  callq   _params_in_reg2
579; CHECK-APPLE:  addq    $48, %rsp
580; CHECK-APPLE:  popq    %rbx
581; CHECK-APPLE:  popq    %r13
582; CHECK-APPLE:  popq    %r14
583; CHECK-APPLE:  popq    %r15
584; CHECK-APPLE:  popq    %rbp
585define swiftcc void @params_in_reg(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) {
586  %error_ptr_ref = alloca swifterror %swift_error*, align 8
587  store %swift_error* null, %swift_error** %error_ptr_ref
588  call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
589  call swiftcc void @params_in_reg2(i64 %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i8* swiftself %6, %swift_error** nocapture swifterror %err)
590  ret void
591}
592declare swiftcc void @params_in_reg2(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err)
593
594; CHECK-APPLE-LABEL: params_and_return_in_reg
595; CHECK-APPLE:  pushq   %rbp
596; CHECK-APPLE:  pushq   %r15
597; CHECK-APPLE:  pushq   %r14
598; CHECK-APPLE:  pushq   %r13
599; CHECK-APPLE:  pushq   %rbx
600; CHECK-APPLE:  subq    $48, %rsp
601; Store arguments.
602; CHECK-APPLE:  movq    %r12, %r14
603; CHECK-APPLE:  movq    %r13, (%rsp)
604; CHECK-APPLE:  movq    %r9, 32(%rsp)
605; CHECK-APPLE:  movq    %r8, 24(%rsp)
606; CHECK-APPLE:  movq    %rcx, 16(%rsp)
607; CHECK-APPLE:  movq    %rdx, %r15
608; CHECK-APPLE:  movq    %rsi, %rbx
609; CHECK-APPLE:  movq    %rdi, %rbp
610; Setup call that clobbers all argument registers.
611; CHECK-APPLE:  movl    $1, %edi
612; CHECK-APPLE:  movl    $2, %esi
613; CHECK-APPLE:  movl    $3, %edx
614; CHECK-APPLE:  movl    $4, %ecx
615; CHECK-APPLE:  movl    $5, %r8d
616; CHECK-APPLE:  movl    $6, %r9d
617; CHECK-APPLE:  xorl    %r13d, %r13d
618; CHECK-APPLE:  xorl    %r12d, %r12d
619; CHECK-APPLE:  callq   _params_in_reg2
620; Store error_ptr_ref for later use.
621; CHECK-APPLE:  movq    %r12, 8(%rsp)
622; Restore original arguments.
623; CHECK-APPLE:  movq    %rbp, %rdi
624; CHECK-APPLE:  movq    %rbx, %rsi
625; CHECK-APPLE:  movq    %r15, %rdx
626; CHECK-APPLE:  movq    16(%rsp), %rcx
627; CHECK-APPLE:  movq    24(%rsp), %r8
628; CHECK-APPLE:  movq    32(%rsp), %r9
629; CHECK-APPLE:  movq    (%rsp), %r13
630; CHECK-APPLE:  movq    %r14, %r12
631; CHECK-APPLE:  callq   _params_and_return_in_reg2
632; Store return values in callee saved registers.
633; CHECK-APPLE:  movq    %rax, %rbx
634; CHECK-APPLE:  movq    %rdx, %rbp
635; CHECK-APPLE:  movq    %rcx, %r15
636; CHECK-APPLE:  movq    %r8, %r14
637; Store the swifterror return value (%err).
638; CHECK-APPLE:  movq    %r12, (%rsp)
639; Setup call.
640; CHECK-APPLE:  movl    $1, %edi
641; CHECK-APPLE:  movl    $2, %esi
642; CHECK-APPLE:  movl    $3, %edx
643; CHECK-APPLE:  movl    $4, %ecx
644; CHECK-APPLE:  movl    $5, %r8d
645; CHECK-APPLE:  movl    $6, %r9d
646; CHECK-APPLE:  xorl    %r13d, %r13d
647; Restore the swifterror value of error_ptr_ref.
648; CHECK-APPLE:  movq    8(%rsp), %r12
649; CHECK-APPLE:  callq   _params_in_reg2
650; Restore the return values of _params_and_return_in_reg2.
651; CHECK-APPLE:  movq    %rbx, %rax
652; CHECK-APPLE:  movq    %rbp, %rdx
653; CHECK-APPLE:  movq    %r15, %rcx
654; CHECK-APPLE:  movq    %r14, %r8
655; Restore the swiferror value of err.
656; CHECK-APPLE:  movq    (%rsp), %r12
657; CHECK-APPLE:  addq    $48, %rsp
658; CHECK-APPLE:  popq    %rbx
659; CHECK-APPLE:  popq    %r13
660; CHECK-APPLE:  popq    %r14
661; CHECK-APPLE:  popq    %r15
662; CHECK-APPLE:  popq    %rbp
663define swiftcc { i64, i64, i64, i64} @params_and_return_in_reg(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) {
664  %error_ptr_ref = alloca swifterror %swift_error*, align 8
665  store %swift_error* null, %swift_error** %error_ptr_ref
666  call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
667  %val = call swiftcc  { i64, i64, i64, i64 } @params_and_return_in_reg2(i64 %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i8* swiftself %6, %swift_error** nocapture swifterror %err)
668  call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
669  ret { i64, i64, i64, i64 }%val
670}
671
672declare swiftcc { i64, i64, i64, i64 } @params_and_return_in_reg2(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err)
673
674
675declare void @acallee(i8*)
676
677; Make sure we don't tail call if the caller returns a swifterror value. We
678; would have to move into the swifterror register before the tail call.
679; CHECK-APPLE: tailcall_from_swifterror:
680; CHECK-APPLE-NOT: jmp _acallee
681; CHECK-APPLE: callq _acallee
682
683define swiftcc void @tailcall_from_swifterror(%swift_error** swifterror %error_ptr_ref) {
684entry:
685  tail call void @acallee(i8* null)
686  ret void
687}
688
689; Make sure we don't crash on this function during -O0.
690; We used to crash because we would insert an IMPLICIT_DEF for the swifterror at
691; beginning of the machine basic block but did not inform FastISel of the
692; inserted instruction. When computing the InsertPoint in the entry block
693; FastISel would choose an insertion point before the IMPLICIT_DEF causing a
694; crash later on.
695declare hidden swiftcc i8* @testFunA()
696
697%TSb = type <{ i1 }>
698
699define swiftcc void @dontCrash()  {
700entry:
701  %swifterror = alloca swifterror %swift_error*, align 8
702  store %swift_error* null, %swift_error** %swifterror, align 8
703  %a = call i8* @testFunA()
704  %b = bitcast i8* %a to %TSb*
705  %._value = getelementptr inbounds %TSb, %TSb* %b, i32 0, i32 0
706  %c = load i1, i1* %._value, align 1
707  br i1 %c, label %trueBB, label %falseBB
708
709trueBB:
710  ret void
711
712falseBB:
713  ret void
714}
715