1 ; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-apple-darwin -disable-block-placement | FileCheck --check-prefix=CHECK-APPLE %s
2 ; RUN: llc -verify-machineinstrs -O0 < %s -mtriple=x86_64-apple-darwin -disable-block-placement | FileCheck --check-prefix=CHECK-O0 %s
3 ; RUN: llc -verify-machineinstrs < %s -mtriple=i386-apple-darwin -disable-block-placement | FileCheck --check-prefix=CHECK-i386 %s
5 declare i8* @malloc(i64)
6 declare void @free(i8*)
7 %swift_error = type {i64, i8}
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".
11 define float @foo(%swift_error** swifterror %error_ptr_ref) {
12 ; CHECK-APPLE-LABEL: foo:
13 ; CHECK-APPLE: movl $16, %edi
15 ; CHECK-APPLE: movb $1, 8(%rax)
16 ; CHECK-APPLE: movq %rax, %r12
18 ; CHECK-O0-LABEL: foo:
21 ; CHECK-O0: movq %{{.*}}, %r12
22 ; CHECK-O0: movb $1, 8(%rax)
25 %call = call i8* @malloc(i64 16)
26 %call.0 = bitcast i8* %call to %swift_error*
27 store %swift_error* %call.0, %swift_error** %error_ptr_ref
28 %tmp = getelementptr inbounds i8, i8* %call, i64 8
33 ; "caller" calls "foo" that takes a swifterror parameter.
34 define float @caller(i8* %error_ref) {
35 ; CHECK-APPLE-LABEL: caller:
36 ; CHECK-APPLE: xorl %r12d, %r12d
37 ; CHECK-APPLE: callq {{.*}}foo
38 ; CHECK-APPLE: testq %r12, %r12
40 ; Access part of the error object and save it to error_ref
41 ; CHECK-APPLE: movb 8(%rdi)
42 ; CHECK-APPLE: callq {{.*}}free
44 ; CHECK-O0-LABEL: caller:
46 ; CHECK-O0: movl %{{.*}}, %r12d
47 ; CHECK-O0: callq {{.*}}foo
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
58 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
60 store i8 %t, i8* %error_ref
63 call void @free(i8* %tmp)
67 ; "caller2" is the caller of "foo", it calls "foo" inside a loop.
68 define 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
74 ; CHECK-APPLE: ucomiss
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
81 ; CHECK-O0-LABEL: caller2:
83 ; CHECK-O0: movl %{{.*}}, %r12d
84 ; CHECK-O0: callq {{.*}}foo
85 ; CHECK-O0: movq %r12, [[ID:%[a-z]+]]
86 ; CHECK-O0: cmpq $0, %r12
89 %error_ptr_ref = alloca swifterror %swift_error*
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
99 %cmp = fcmp ogt float %call, 1.000000e+00
100 br i1 %cmp, label %bb_end, label %bb_loop
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
107 call void @free(i8* %tmp)
111 ; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
112 ; under a certain condition.
113 define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) {
114 ; CHECK-APPLE-LABEL: foo_if:
115 ; CHECK-APPLE: testl %edi, %edi
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
124 ; CHECK-O0-LABEL: foo_if:
126 ; CHECK-O0: movq %r12, {{.*}}(%rsp)
129 ; CHECK-O0: movl $16,
131 ; CHECK-O0: movq %rax, %r12
132 ; CHECK-O0-DAG: movb $1, 8(%rax)
135 ; CHECK-O0: movq {{.*}}(%rsp), %r12
138 %cond = icmp ne i32 %cc, 0
139 br i1 %cond, label %gen_error, label %normal
142 %call = call i8* @malloc(i64 16)
143 %call.0 = bitcast i8* %call to %swift_error*
144 store %swift_error* %call.0, %swift_error** %error_ptr_ref
145 %tmp = getelementptr inbounds i8, i8* %call, i64 8
153 ; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
154 ; under a certain condition inside a loop.
155 define float @foo_loop(%swift_error** swifterror %error_ptr_ref, i32 %cc, float %cc2) {
156 ; CHECK-APPLE-LABEL: foo_loop:
157 ; CHECK-APPLE: movq %r12, %rax
160 ; CHECK-APPLE: movl $16, %edi
161 ; CHECK-APPLE: malloc
162 ; CHECK-APPLE: movb $1, 8(%rax)
163 ; CHECK-APPLE: ucomiss
165 ; CHECK-APPLE: movq %rax, %r12
168 ; CHECK-O0-LABEL: foo_loop:
170 ; CHECK-O0: movq %r12, {{.*}}(%rsp)
173 ; CHECK-O0: movl $16,
175 ; CHECK-O0: movq %rax, [[ID:%[a-z0-9]+]]
176 ; CHECK-O0: movb $1, 8([[ID]])
179 ; CHECK-O0: movq {{.*}}(%rsp), %r12
185 %cond = icmp ne i32 %cc, 0
186 br i1 %cond, label %gen_error, label %bb_cont
189 %call = call i8* @malloc(i64 16)
190 %call.0 = bitcast i8* %call to %swift_error*
191 store %swift_error* %call.0, %swift_error** %error_ptr_ref
192 %tmp = getelementptr inbounds i8, i8* %call, i64 8
197 %cmp = fcmp ogt float %cc2, 1.000000e+00
198 br i1 %cmp, label %bb_end, label %bb_loop
203 %struct.S = type { i32, i32, i32, i32, i32, i32 }
205 ; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
207 define void @foo_sret(%struct.S* sret(%struct.S) %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) {
208 ; CHECK-APPLE-LABEL: foo_sret:
209 ; CHECK-APPLE: movq %rdi, %{{.*}}
210 ; CHECK-APPLE: movl $16, %edi
211 ; CHECK-APPLE: malloc
212 ; CHECK-APPLE: movb $1, 8(%rax)
213 ; CHECK-APPLE: movl %{{.*}}, 4(%{{.*}})
214 ; CHECK-APPLE: movq %rax, %r12
215 ; CHECK-APPLE: movq %{{.*}}, %rax
216 ; CHECK-APPLE-NOT: x19
218 ; CHECK-O0-LABEL: foo_sret:
219 ; spill sret to stack
220 ; CHECK-O0: movq %rdi,
221 ; CHECK-O0: movl $16,
223 ; reload sret from stack
224 ; CHECK-O0: movq {{.*}}(%rsp), %rax
225 ; CHECK-O0: movq %{{.*}}, %r12
226 ; CHECK-O0: movb $1, 8(%rcx)
227 ; CHECK-O0: movl %{{.*}}, 4(%{{.*}})
230 %call = call i8* @malloc(i64 16)
231 %call.0 = bitcast i8* %call to %swift_error*
232 store %swift_error* %call.0, %swift_error** %error_ptr_ref
233 %tmp = getelementptr inbounds i8, i8* %call, i64 8
235 %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1
236 store i32 %val1, i32* %v2
240 ; "caller3" calls "foo_sret" that takes a swifterror parameter.
241 define float @caller3(i8* %error_ref) {
242 ; CHECK-APPLE-LABEL: caller3:
243 ; CHECK-APPLE: movl $1, %esi
244 ; CHECK-APPLE: xorl %r12d, %r12d
245 ; CHECK-APPLE: callq {{.*}}foo_sret
246 ; CHECK-APPLE: testq %r12, %r12
248 ; Access part of the error object and save it to error_ref
249 ; CHECK-APPLE: movb 8(%rdi),
250 ; CHECK-APPLE: movb %{{.*}},
251 ; CHECK-APPLE: callq {{.*}}free
253 ; CHECK-O0-LABEL: caller3:
255 ; CHECK-O0: movl {{.*}}, %r12d
256 ; CHECK-O0: leaq {{.*}}, %rdi
257 ; CHECK-O0: movl $1, %esi
258 ; CHECK-O0: callq {{.*}}foo_sret
259 ; CHECK-O0: movq %r12,
262 ; Access part of the error object and save it to error_ref
263 ; CHECK-O0: movb 8(%{{.*}}),
264 ; CHECK-O0: movb %{{.*}},
266 ; CHECK-O0: movq {{.*}}(%rsp), %rdi
267 ; CHECK-O0: callq {{.*}}free
269 %s = alloca %struct.S, align 8
270 %error_ptr_ref = alloca swifterror %swift_error*
271 store %swift_error* null, %swift_error** %error_ptr_ref
272 call void @foo_sret(%struct.S* sret(%struct.S) %s, i32 1, %swift_error** swifterror %error_ptr_ref)
273 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
274 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
275 %tmp = bitcast %swift_error* %error_from_foo to i8*
276 br i1 %had_error_from_foo, label %handler, label %cont
278 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
279 %t = load i8, i8* %v1
280 store i8 %t, i8* %error_ref
283 call void @free(i8* %tmp)
287 ; This is a caller with multiple swifterror values, it calls "foo" twice, each
288 ; time with a different swifterror value, from "alloca swifterror".
289 define float @caller_with_multiple_swifterror_values(i8* %error_ref, i8* %error_ref2) {
290 ; CHECK-APPLE-LABEL: caller_with_multiple_swifterror_values:
292 ; The first swifterror value:
293 ; CHECK-APPLE: xorl %r12d, %r12d
294 ; CHECK-APPLE: callq {{.*}}foo
295 ; CHECK-APPLE: testq %r12, %r12
297 ; Access part of the error object and save it to error_ref
298 ; CHECK-APPLE: movb 8(%rdi)
299 ; CHECK-APPLE: callq {{.*}}free
301 ; The second swifterror value:
302 ; CHECK-APPLE: xorl %r12d, %r12d
303 ; CHECK-APPLE: callq {{.*}}foo
304 ; CHECK-APPLE: testq %r12, %r12
306 ; Access part of the error object and save it to error_ref
307 ; CHECK-APPLE: movb 8(%rdi)
308 ; CHECK-APPLE: callq {{.*}}free
310 ; CHECK-O0-LABEL: caller_with_multiple_swifterror_values:
312 ; The first swifterror value:
314 ; CHECK-O0: movl %{{.*}}, %r12d
315 ; CHECK-O0: callq {{.*}}foo
318 ; The second swifterror value:
320 ; CHECK-O0: movl %{{.*}}, %r12d
321 ; CHECK-O0: callq {{.*}}foo
324 %error_ptr_ref = alloca swifterror %swift_error*
325 store %swift_error* null, %swift_error** %error_ptr_ref
326 %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
327 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
328 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
329 %tmp = bitcast %swift_error* %error_from_foo to i8*
330 br i1 %had_error_from_foo, label %handler, label %cont
332 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
333 %t = load i8, i8* %v1
334 store i8 %t, i8* %error_ref
337 call void @free(i8* %tmp)
339 %error_ptr_ref2 = alloca swifterror %swift_error*
340 store %swift_error* null, %swift_error** %error_ptr_ref2
341 %call2 = call float @foo(%swift_error** swifterror %error_ptr_ref2)
342 %error_from_foo2 = load %swift_error*, %swift_error** %error_ptr_ref2
343 %had_error_from_foo2 = icmp ne %swift_error* %error_from_foo2, null
344 %bitcast2 = bitcast %swift_error* %error_from_foo2 to i8*
345 br i1 %had_error_from_foo2, label %handler2, label %cont2
347 %v2 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo2, i64 0, i32 1
348 %t2 = load i8, i8* %v2
349 store i8 %t2, i8* %error_ref2
352 call void @free(i8* %bitcast2)
357 %swift.refcounted = type opaque
359 ; This test checks that we don't create bad phi nodes as part of swifterror
360 ; isel. We used to fail machine ir verification.
361 ; CHECK-APPLE: _swifterror_isel
362 ; CHECK-O0: _swifterror_isel
363 define void @swifterror_isel(%swift.refcounted*) {
365 %swifterror = alloca swifterror %swift_error*, align 8
366 br i1 undef, label %5, label %1
368 %2 = phi i16 [ %4, %1 ], [ undef, %entry ]
369 %3 = call i1 undef(i16 %2, %swift.refcounted* swiftself %0, %swift_error** nocapture swifterror %swifterror)
370 %4 = load i16, i16* undef, align 2
376 ; This tests the basic usage of a swifterror parameter with swiftcc.
377 define swiftcc float @foo_swiftcc(%swift_error** swifterror %error_ptr_ref) {
378 ; CHECK-APPLE-LABEL: foo_swiftcc:
379 ; CHECK-APPLE: movl $16, %edi
380 ; CHECK-APPLE: malloc
381 ; CHECK-APPLE: movb $1, 8(%rax)
382 ; CHECK-APPLE: movq %rax, %r12
384 ; CHECK-O0-LABEL: foo_swiftcc:
387 ; CHECK-O0: movq %{{.*}}, %r12
388 ; CHECK-O0: movb $1, 8(%rax)
391 %call = call i8* @malloc(i64 16)
392 %call.0 = bitcast i8* %call to %swift_error*
393 store %swift_error* %call.0, %swift_error** %error_ptr_ref
394 %tmp = getelementptr inbounds i8, i8* %call, i64 8
399 declare swiftcc float @moo(%swift_error** swifterror)
401 ; Test parameter forwarding.
402 define swiftcc float @forward_swifterror(%swift_error** swifterror %error_ptr_ref) {
403 ; CHECK-APPLE-LABEL: forward_swifterror:
404 ; CHECK-APPLE: pushq %rax
405 ; CHECK-APPLE: callq _moo
406 ; CHECK-APPLE: popq %rax
409 ; CHECK-O0-LABEL: forward_swifterror:
410 ; CHECK-O0: pushq %rax
411 ; CHECK-O0: callq _moo
412 ; CHECK-O0: popq %rax
416 %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref)
420 define swiftcc float @conditionally_forward_swifterror(%swift_error** swifterror %error_ptr_ref, i32 %cc) {
421 ; CHECK-APPLE-LABEL: conditionally_forward_swifterror:
422 ; CHECK-APPLE: testl %edi, %edi
425 ; CHECK-APPLE: pushq %rax
426 ; CHECK-APPLE: callq _moo
427 ; CHECK-APPLE: popq %rax
430 ; CHECK-APPLE: xorps %xmm0, %xmm0
433 ; CHECK-O0-LABEL: conditionally_forward_swifterror:
434 ; CHECK-O0: pushq [[REG1:%[a-z0-9]+]]
435 ; CHECK-O0-DAG: movq %r12, (%rsp)
436 ; CHECK-O0: cmpl $0, %edi
439 ; CHECK-O0: movq (%rsp), %r12
440 ; CHECK-O0: callq _moo
441 ; CHECK-O0: popq [[REG1]]
444 ; CHECK-O0: movq (%rsp), %r12
445 ; CHECK-O0: xorps %xmm0, %xmm0
446 ; CHECK-O0: popq [[REG1]]
449 %cond = icmp ne i32 %cc, 0
450 br i1 %cond, label %gen_error, label %normal
453 %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref)
460 ; Check that we don't blow up on tail calling swifterror argument functions.
461 define float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) {
463 %0 = tail call float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref)
466 define swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) {
468 %0 = tail call swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref)
472 ; Check that we can handle an empty function with swifterror argument.
473 ; CHECK-i386-LABEL: empty_swiftcc:
474 ; CHECK-i386: movl 4(%esp), %eax
475 ; CHECK-i386: movl 8(%esp), %edx
476 ; CHECK-i386: movl 12(%esp), %ecx
478 ; CHECK-APPLE-LABEL: empty_swiftcc:
479 ; CHECK-APPLE: movl %edx, %ecx
480 ; CHECK-APPLE-DAG: movl %edi, %eax
481 ; CHECK-APPLE-DAG: movl %esi, %edx
483 define swiftcc {i32, i32, i32} @empty_swiftcc({i32, i32, i32} , %swift_error** swifterror %error_ptr_ref) {
485 ret {i32, i32, i32} %0
488 ; Make sure we can handle the case when isel generates new machine basic blocks.
489 ; CHECK-APPLE-LABEL: dont_crash_on_new_isel_blocks:
490 ; CHECK-APPLE: xorl %eax, %eax
491 ; CHECK-APPLE: testb %al, %al
493 ; CHECK-APPLE: pushq %rax
494 ; CHECK-APPLE-NEXT: .cfi_def_cfa_offset 16
495 ; CHECK-APPLE-NEXT: callq *%rax
496 ; CHECK-APPLE-NEXT: popq %rax
497 ; CHECK-APPLE-NEXT: ret
499 define swiftcc void @dont_crash_on_new_isel_blocks(%swift_error** nocapture swifterror, i1, i8**) {
502 br i1 %3, label %cont, label %falsebb
505 %4 = load i8*, i8** %2, align 8
509 tail call swiftcc void undef(%swift_error** nocapture swifterror %0)
513 ; CHECK-APPLE-LABEL: swifterror_clobber
514 ; CHECK-APPLE: movq %r12, [[REG:%.*]]
516 ; CHECK-APPLE: movq [[REG]], %r12
517 define swiftcc void @swifterror_clobber(%swift_error** nocapture swifterror %err) {
518 call void asm sideeffect "nop", "~{r12}"()
522 ; CHECK-APPLE-LABEL: swifterror_reg_clobber
523 ; CHECK-APPLE: pushq %r12
525 ; CHECK-APPLE: popq %r12
526 define swiftcc void @swifterror_reg_clobber(%swift_error** nocapture %err) {
527 call void asm sideeffect "nop", "~{r12}"()
531 ; CHECK-APPLE-LABEL: params_in_reg
532 ; Save callee save registers to store clobbered arguments.
533 ; CHECK-APPLE: pushq %rbp
534 ; CHECK-APPLE: pushq %r15
535 ; CHECK-APPLE: pushq %r14
536 ; Clobbered swiftself register.
537 ; CHECK-APPLE: pushq %r13
538 ; CHECK-APPLE: pushq %rbx
539 ; CHECK-APPLE: subq $48, %rsp
541 ; CHECK-APPLE: movq %r12, 32(%rsp)
542 ; CHECK-APPLE: movq %r13, 24(%rsp)
543 ; CHECK-APPLE: movq %r9, 16(%rsp)
544 ; CHECK-APPLE: movq %r8, 8(%rsp)
545 ; CHECK-APPLE: movq %rcx, %r14
546 ; CHECK-APPLE: movq %rdx, %r15
547 ; CHECK-APPLE: movq %rsi, %rbx
548 ; CHECK-APPLE: movq %rdi, %rbp
550 ; CHECK-APPLE: movl $1, %edi
551 ; CHECK-APPLE: movl $2, %esi
552 ; CHECK-APPLE: movl $3, %edx
553 ; CHECK-APPLE: movl $4, %ecx
554 ; CHECK-APPLE: movl $5, %r8d
555 ; CHECK-APPLE: movl $6, %r9d
556 ; CHECK-APPLE: xorl %r13d, %r13d
557 ; CHECK-APPLE: xorl %r12d, %r12d
558 ; CHECK-APPLE: callq _params_in_reg2
559 ; Setup second call with stored arguments.
560 ; CHECK-APPLE: movq %rbp, %rdi
561 ; CHECK-APPLE: movq %rbx, %rsi
562 ; CHECK-APPLE: movq %r15, %rdx
563 ; CHECK-APPLE: movq %r14, %rcx
564 ; CHECK-APPLE: movq 8(%rsp), %r8
565 ; CHECK-APPLE: movq 16(%rsp), %r9
566 ; CHECK-APPLE: movq 24(%rsp), %r13
567 ; CHECK-APPLE: movq 32(%rsp), %r12
568 ; CHECK-APPLE: callq _params_in_reg2
569 ; CHECK-APPLE: addq $48, %rsp
570 ; CHECK-APPLE: popq %rbx
571 ; CHECK-APPLE: popq %r13
572 ; CHECK-APPLE: popq %r14
573 ; CHECK-APPLE: popq %r15
574 ; CHECK-APPLE: popq %rbp
575 define swiftcc void @params_in_reg(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) {
576 %error_ptr_ref = alloca swifterror %swift_error*, align 8
577 store %swift_error* null, %swift_error** %error_ptr_ref
578 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)
579 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)
582 declare swiftcc void @params_in_reg2(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err)
584 ; CHECK-APPLE-LABEL: params_and_return_in_reg
585 ; CHECK-APPLE: pushq %rbp
586 ; CHECK-APPLE: pushq %r15
587 ; CHECK-APPLE: pushq %r14
588 ; CHECK-APPLE: pushq %r13
589 ; CHECK-APPLE: pushq %rbx
590 ; CHECK-APPLE: subq $48, %rsp
592 ; CHECK-APPLE: movq %r12, %r14
593 ; CHECK-APPLE: movq %r13, (%rsp)
594 ; CHECK-APPLE: movq %r9, 32(%rsp)
595 ; CHECK-APPLE: movq %r8, 24(%rsp)
596 ; CHECK-APPLE: movq %rcx, 16(%rsp)
597 ; CHECK-APPLE: movq %rdx, %r15
598 ; CHECK-APPLE: movq %rsi, %rbx
599 ; CHECK-APPLE: movq %rdi, %rbp
600 ; Setup call that clobbers all argument registers.
601 ; CHECK-APPLE: movl $1, %edi
602 ; CHECK-APPLE: movl $2, %esi
603 ; CHECK-APPLE: movl $3, %edx
604 ; CHECK-APPLE: movl $4, %ecx
605 ; CHECK-APPLE: movl $5, %r8d
606 ; CHECK-APPLE: movl $6, %r9d
607 ; CHECK-APPLE: xorl %r13d, %r13d
608 ; CHECK-APPLE: xorl %r12d, %r12d
609 ; CHECK-APPLE: callq _params_in_reg2
610 ; Store error_ptr_ref for later use.
611 ; CHECK-APPLE: movq %r12, 8(%rsp)
612 ; Restore original arguments.
613 ; CHECK-APPLE: movq %rbp, %rdi
614 ; CHECK-APPLE: movq %rbx, %rsi
615 ; CHECK-APPLE: movq %r15, %rdx
616 ; CHECK-APPLE: movq 16(%rsp), %rcx
617 ; CHECK-APPLE: movq 24(%rsp), %r8
618 ; CHECK-APPLE: movq 32(%rsp), %r9
619 ; CHECK-APPLE: movq (%rsp), %r13
620 ; CHECK-APPLE: movq %r14, %r12
621 ; CHECK-APPLE: callq _params_and_return_in_reg2
622 ; Store return values in callee saved registers.
623 ; CHECK-APPLE: movq %rax, %rbx
624 ; CHECK-APPLE: movq %rdx, %rbp
625 ; CHECK-APPLE: movq %rcx, %r15
626 ; CHECK-APPLE: movq %r8, %r14
627 ; Store the swifterror return value (%err).
628 ; CHECK-APPLE: movq %r12, (%rsp)
630 ; CHECK-APPLE: movl $1, %edi
631 ; CHECK-APPLE: movl $2, %esi
632 ; CHECK-APPLE: movl $3, %edx
633 ; CHECK-APPLE: movl $4, %ecx
634 ; CHECK-APPLE: movl $5, %r8d
635 ; CHECK-APPLE: movl $6, %r9d
636 ; CHECK-APPLE: xorl %r13d, %r13d
637 ; Restore the swifterror value of error_ptr_ref.
638 ; CHECK-APPLE: movq 8(%rsp), %r12
639 ; CHECK-APPLE: callq _params_in_reg2
640 ; Restore the return values of _params_and_return_in_reg2.
641 ; CHECK-APPLE: movq %rbx, %rax
642 ; CHECK-APPLE: movq %rbp, %rdx
643 ; CHECK-APPLE: movq %r15, %rcx
644 ; CHECK-APPLE: movq %r14, %r8
645 ; Restore the swiferror value of err.
646 ; CHECK-APPLE: movq (%rsp), %r12
647 ; CHECK-APPLE: addq $48, %rsp
648 ; CHECK-APPLE: popq %rbx
649 ; CHECK-APPLE: popq %r13
650 ; CHECK-APPLE: popq %r14
651 ; CHECK-APPLE: popq %r15
652 ; CHECK-APPLE: popq %rbp
653 define swiftcc { i64, i64, i64, i64} @params_and_return_in_reg(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) {
654 %error_ptr_ref = alloca swifterror %swift_error*, align 8
655 store %swift_error* null, %swift_error** %error_ptr_ref
656 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)
657 %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)
658 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)
659 ret { i64, i64, i64, i64 }%val
662 declare swiftcc { i64, i64, i64, i64 } @params_and_return_in_reg2(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err)
665 declare void @acallee(i8*)
667 ; Make sure we don't tail call if the caller returns a swifterror value. We
668 ; would have to move into the swifterror register before the tail call.
669 ; CHECK-APPLE: tailcall_from_swifterror:
670 ; CHECK-APPLE-NOT: jmp _acallee
671 ; CHECK-APPLE: callq _acallee
673 define swiftcc void @tailcall_from_swifterror(%swift_error** swifterror %error_ptr_ref) {
675 tail call void @acallee(i8* null)
679 ; Make sure we don't crash on this function during -O0.
680 ; We used to crash because we would insert an IMPLICIT_DEF for the swifterror at
681 ; beginning of the machine basic block but did not inform FastISel of the
682 ; inserted instruction. When computing the InsertPoint in the entry block
683 ; FastISel would choose an insertion point before the IMPLICIT_DEF causing a
685 declare hidden swiftcc i8* @testFunA()
689 define swiftcc void @dontCrash() {
691 %swifterror = alloca swifterror %swift_error*, align 8
692 store %swift_error* null, %swift_error** %swifterror, align 8
693 %a = call i8* @testFunA()
694 %b = bitcast i8* %a to %TSb*
695 %._value = getelementptr inbounds %TSb, %TSb* %b, i32 0, i32 0
696 %c = load i1, i1* %._value, align 1
697 br i1 %c, label %trueBB, label %falseBB
707 declare swiftcc void @foo2(%swift_error** swifterror)
709 ; Make sure we properly assign registers during fast-isel.
710 ; CHECK-O0-LABEL: testAssign
711 ; CHECK-O0: pushq %r12
712 ; CHECK-O0: xorl [[ZERO:%[a-z0-9]+]], [[ZERO]]
713 ; CHECK-O0: movl [[ZERO]], %r12d
714 ; CHECK-O0: callq _foo2
715 ; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]]
717 ; CHECK-O0: movq [[SLOT]], %rax
718 ; CHECK-O0: popq %r12
721 ; CHECK-APPLE-LABEL: testAssign
722 ; CHECK-APPLE: pushq %r12
723 ; CHECK-APPLE: xorl %r12d, %r12d
724 ; CHECK-APPLE: callq _foo2
725 ; CHECK-APPLE: movq %r12, %rax
726 ; CHECK-APPLE: popq %r12
729 define swiftcc %swift_error* @testAssign(i8* %error_ref) {
731 %error_ptr = alloca swifterror %swift_error*
732 store %swift_error* null, %swift_error** %error_ptr
733 call swiftcc void @foo2(%swift_error** swifterror %error_ptr)
737 %error = load %swift_error*, %swift_error** %error_ptr
738 ret %swift_error* %error
741 ; CHECK-O0-LABEL: testAssign2
742 ; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]]
744 ; CHECK-O0: movq [[SLOT]], %r12
745 ; CHECK-O0-NEXT: movq %r12, %rax
746 ; CHECK-O0-NEXT: retq
748 ; CHECK-APPLE-LABEL: testAssign2
749 ; CHECK-APPLE: movq %r12, %rax
751 define swiftcc %swift_error* @testAssign2(i8* %error_ref, %swift_error** swifterror %err) {
756 %error = load %swift_error*, %swift_error** %err
757 ret %swift_error* %error
760 ; CHECK-O0-LABEL: testAssign3
761 ; CHECK-O0: callq _foo2
762 ; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]]
763 ; CHECK-O0: movq [[SLOT]], %r12
764 ; CHECK-O0-NEXT: movq %r12, %rax
765 ; CHECK-O0-NEXT: popq %rcx
766 ; CHECK-O0-NEXT: retq
768 ; CHECK-APPLE-LABEL: testAssign3
769 ; CHECK-APPLE: callq _foo2
770 ; CHECK-APPLE: movq %r12, %rax
773 define swiftcc %swift_error* @testAssign3(i8* %error_ref, %swift_error** swifterror %err) {
775 call swiftcc void @foo2(%swift_error** swifterror %err)
779 %error = load %swift_error*, %swift_error** %err
780 ret %swift_error* %error
784 ; CHECK-O0-LABEL: testAssign4
785 ; CHECK-O0: callq _foo2
786 ; CHECK-O0: xorl %eax, %eax
787 ; CHECK-O0: ## kill: def $rax killed $eax
788 ; CHECK-O0: movq %rax, [[SLOT:[-a-z0-9\(\)\%]*]]
789 ; CHECK-O0: movq [[SLOT]], %r12
790 ; CHECK-O0-NEXT: movq %r12, %rax
791 ; CHECK-O0-NEXT: popq %rcx
792 ; CHECK-O0-NEXT: retq
794 ; CHECK-APPLE-LABEL: testAssign4
795 ; CHECK-APPLE: callq _foo2
796 ; CHECK-APPLE: xorl %eax, %eax
797 ; CHECK-APPLE: xorl %r12d, %r12d
800 define swiftcc %swift_error* @testAssign4(i8* %error_ref, %swift_error** swifterror %err) {
802 call swiftcc void @foo2(%swift_error** swifterror %err)
803 store %swift_error* null, %swift_error** %err
807 %error = load %swift_error*, %swift_error** %err
808 ret %swift_error* %error