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: movb $1, 8(%rax)
22 ; CHECK-O0: movq %{{.*}}, %r12
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
32 ; "caller" calls "foo" that takes a swifterror parameter.
33 define 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
39 ; Access part of the error object and save it to error_ref
40 ; CHECK-APPLE: movb 8(%rdi)
41 ; CHECK-APPLE: callq {{.*}}free
43 ; CHECK-O0-LABEL: caller:
45 ; CHECK-O0: movl %{{.*}}, %r12d
46 ; CHECK-O0: callq {{.*}}foo
49 %error_ptr_ref = alloca swifterror %swift_error*
50 store %swift_error* null, %swift_error** %error_ptr_ref
51 %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
52 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
53 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
54 %tmp = bitcast %swift_error* %error_from_foo to i8*
55 br i1 %had_error_from_foo, label %handler, label %cont
57 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
59 store i8 %t, i8* %error_ref
62 call void @free(i8* %tmp)
66 ; "caller2" is the caller of "foo", it calls "foo" inside a loop.
67 define float @caller2(i8* %error_ref) {
68 ; CHECK-APPLE-LABEL: caller2:
69 ; CHECK-APPLE: xorl %r12d, %r12d
70 ; CHECK-APPLE: callq {{.*}}foo
71 ; CHECK-APPLE: testq %r12, %r12
73 ; CHECK-APPLE: ucomiss
75 ; Access part of the error object and save it to error_ref
76 ; CHECK-APPLE: movb 8(%r12)
77 ; CHECK-APPLE: movq %r12, %rdi
78 ; CHECK-APPLE: callq {{.*}}free
80 ; CHECK-O0-LABEL: caller2:
82 ; CHECK-O0: movl %{{.*}}, %r12d
83 ; CHECK-O0: callq {{.*}}foo
84 ; CHECK-O0: movq %r12, [[ID:%[a-z]+]]
85 ; CHECK-O0: cmpq $0, %r12
88 %error_ptr_ref = alloca swifterror %swift_error*
91 store %swift_error* null, %swift_error** %error_ptr_ref
92 %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
93 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
94 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
95 %tmp = bitcast %swift_error* %error_from_foo to i8*
96 br i1 %had_error_from_foo, label %handler, label %cont
98 %cmp = fcmp ogt float %call, 1.000000e+00
99 br i1 %cmp, label %bb_end, label %bb_loop
101 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
102 %t = load i8, i8* %v1
103 store i8 %t, i8* %error_ref
106 call void @free(i8* %tmp)
110 ; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
111 ; under a certain condition.
112 define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) {
113 ; CHECK-APPLE-LABEL: foo_if:
114 ; CHECK-APPLE: testl %edi, %edi
116 ; CHECK-APPLE: movl $16, %edi
117 ; CHECK-APPLE: malloc
118 ; CHECK-APPLE: movb $1, 8(%rax)
119 ; CHECK-APPLE: movq %rax, %r12
120 ; CHECK-APPLE-NOT: %r12
123 ; CHECK-O0-LABEL: foo_if:
126 ; CHECK-O0: movq %r12, {{.*}}(%rsp)
128 ; CHECK-O0: movl $16,
130 ; CHECK-O0: movq %rax, [[ID:%[a-z]+]]
131 ; CHECK-O0-DAG: movb $1, 8(%rax)
132 ; CHECK-O0-DAG: movq [[ID]], %r12
135 ; CHECK-O0: movq {{.*}}(%rsp), [[REG:%[a-z]+]]
136 ; CHECK-O0: movq [[REG]], %r12
139 %cond = icmp ne i32 %cc, 0
140 br i1 %cond, label %gen_error, label %normal
143 %call = call i8* @malloc(i64 16)
144 %call.0 = bitcast i8* %call to %swift_error*
145 store %swift_error* %call.0, %swift_error** %error_ptr_ref
146 %tmp = getelementptr inbounds i8, i8* %call, i64 8
154 ; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
155 ; under a certain condition inside a loop.
156 define float @foo_loop(%swift_error** swifterror %error_ptr_ref, i32 %cc, float %cc2) {
157 ; CHECK-APPLE-LABEL: foo_loop:
158 ; CHECK-APPLE: movq %r12, %rax
161 ; CHECK-APPLE: movl $16, %edi
162 ; CHECK-APPLE: malloc
163 ; CHECK-APPLE: movb $1, 8(%rax)
164 ; CHECK-APPLE: ucomiss
166 ; CHECK-APPLE: movq %rax, %r12
169 ; CHECK-O0-LABEL: foo_loop:
171 ; CHECK-O0: movq %r12, {{.*}}(%rsp)
174 ; CHECK-O0: movl $16,
176 ; CHECK-O0: movq %rax, [[ID:%[a-z0-9]+]]
177 ; CHECK-O0: movb $1, 8([[ID]])
180 ; CHECK-O0: movq {{.*}}(%rsp), [[REG:%[a-z0-9]+]]
181 ; CHECK-O0: movq [[REG]], %r12
187 %cond = icmp ne i32 %cc, 0
188 br i1 %cond, label %gen_error, label %bb_cont
191 %call = call i8* @malloc(i64 16)
192 %call.0 = bitcast i8* %call to %swift_error*
193 store %swift_error* %call.0, %swift_error** %error_ptr_ref
194 %tmp = getelementptr inbounds i8, i8* %call, i64 8
199 %cmp = fcmp ogt float %cc2, 1.000000e+00
200 br i1 %cmp, label %bb_end, label %bb_loop
205 %struct.S = type { i32, i32, i32, i32, i32, i32 }
207 ; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
209 define void @foo_sret(%struct.S* sret %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) {
210 ; CHECK-APPLE-LABEL: foo_sret:
211 ; CHECK-APPLE: movq %rdi, %{{.*}}
212 ; CHECK-APPLE: movl $16, %edi
213 ; CHECK-APPLE: malloc
214 ; CHECK-APPLE: movb $1, 8(%rax)
215 ; CHECK-APPLE: movl %{{.*}}, 4(%{{.*}})
216 ; CHECK-APPLE: movq %rax, %r12
217 ; CHECK-APPLE: movq %{{.*}}, %rax
218 ; CHECK-APPLE-NOT: x19
220 ; CHECK-O0-LABEL: foo_sret:
221 ; CHECK-O0: movl $16,
222 ; spill sret to stack
223 ; CHECK-O0: movq %rdi,
224 ; CHECK-O0: movq {{.*}}, %rdi
226 ; CHECK-O0: movb $1, 8(%rax)
227 ; CHECK-O0: movl %{{.*}}, 4(%{{.*}})
228 ; CHECK-O0: movq %{{.*}}, %r12
229 ; reload sret from stack
230 ; CHECK-O0: movq {{.*}}(%rsp), %rax
233 %call = call i8* @malloc(i64 16)
234 %call.0 = bitcast i8* %call to %swift_error*
235 store %swift_error* %call.0, %swift_error** %error_ptr_ref
236 %tmp = getelementptr inbounds i8, i8* %call, i64 8
238 %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1
239 store i32 %val1, i32* %v2
243 ; "caller3" calls "foo_sret" that takes a swifterror parameter.
244 define float @caller3(i8* %error_ref) {
245 ; CHECK-APPLE-LABEL: caller3:
246 ; CHECK-APPLE: movl $1, %esi
247 ; CHECK-APPLE: xorl %r12d, %r12d
248 ; CHECK-APPLE: callq {{.*}}foo_sret
249 ; CHECK-APPLE: testq %r12, %r12
251 ; Access part of the error object and save it to error_ref
252 ; CHECK-APPLE: movb 8(%rdi),
253 ; CHECK-APPLE: movb %{{.*}},
254 ; CHECK-APPLE: callq {{.*}}free
256 ; CHECK-O0-LABEL: caller3:
258 ; CHECK-O0: movl {{.*}}, %r12d
259 ; CHECK-O0: movl $1, %esi
260 ; CHECK-O0: movq {{.*}}, %rdi
261 ; CHECK-O0: callq {{.*}}foo_sret
262 ; CHECK-O0: movq %r12,
265 ; Access part of the error object and save it to error_ref
266 ; CHECK-O0: movb 8(%{{.*}}),
267 ; CHECK-O0: movb %{{.*}},
269 ; CHECK-O0: movq {{.*}}(%rsp), %rdi
270 ; CHECK-O0: callq {{.*}}free
272 %s = alloca %struct.S, align 8
273 %error_ptr_ref = alloca swifterror %swift_error*
274 store %swift_error* null, %swift_error** %error_ptr_ref
275 call void @foo_sret(%struct.S* sret %s, i32 1, %swift_error** swifterror %error_ptr_ref)
276 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
277 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
278 %tmp = bitcast %swift_error* %error_from_foo to i8*
279 br i1 %had_error_from_foo, label %handler, label %cont
281 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
282 %t = load i8, i8* %v1
283 store i8 %t, i8* %error_ref
286 call void @free(i8* %tmp)
290 ; This is a caller with multiple swifterror values, it calls "foo" twice, each
291 ; time with a different swifterror value, from "alloca swifterror".
292 define float @caller_with_multiple_swifterror_values(i8* %error_ref, i8* %error_ref2) {
293 ; CHECK-APPLE-LABEL: caller_with_multiple_swifterror_values:
295 ; The first swifterror value:
296 ; CHECK-APPLE: xorl %r12d, %r12d
297 ; CHECK-APPLE: callq {{.*}}foo
298 ; CHECK-APPLE: testq %r12, %r12
300 ; Access part of the error object and save it to error_ref
301 ; CHECK-APPLE: movb 8(%rdi)
302 ; CHECK-APPLE: callq {{.*}}free
304 ; The second swifterror value:
305 ; CHECK-APPLE: xorl %r12d, %r12d
306 ; CHECK-APPLE: callq {{.*}}foo
307 ; CHECK-APPLE: testq %r12, %r12
309 ; Access part of the error object and save it to error_ref
310 ; CHECK-APPLE: movb 8(%rdi)
311 ; CHECK-APPLE: callq {{.*}}free
313 ; CHECK-O0-LABEL: caller_with_multiple_swifterror_values:
315 ; The first swifterror value:
317 ; CHECK-O0: movl %{{.*}}, %r12d
318 ; CHECK-O0: callq {{.*}}foo
321 ; The second swifterror value:
323 ; CHECK-O0: movl %{{.*}}, %r12d
324 ; CHECK-O0: callq {{.*}}foo
327 %error_ptr_ref = alloca swifterror %swift_error*
328 store %swift_error* null, %swift_error** %error_ptr_ref
329 %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
330 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
331 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
332 %tmp = bitcast %swift_error* %error_from_foo to i8*
333 br i1 %had_error_from_foo, label %handler, label %cont
335 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
336 %t = load i8, i8* %v1
337 store i8 %t, i8* %error_ref
340 call void @free(i8* %tmp)
342 %error_ptr_ref2 = alloca swifterror %swift_error*
343 store %swift_error* null, %swift_error** %error_ptr_ref2
344 %call2 = call float @foo(%swift_error** swifterror %error_ptr_ref2)
345 %error_from_foo2 = load %swift_error*, %swift_error** %error_ptr_ref2
346 %had_error_from_foo2 = icmp ne %swift_error* %error_from_foo2, null
347 %bitcast2 = bitcast %swift_error* %error_from_foo2 to i8*
348 br i1 %had_error_from_foo2, label %handler2, label %cont2
350 %v2 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo2, i64 0, i32 1
351 %t2 = load i8, i8* %v2
352 store i8 %t2, i8* %error_ref2
355 call void @free(i8* %bitcast2)
360 %swift.refcounted = type opaque
362 ; This test checks that we don't create bad phi nodes as part of swifterror
363 ; isel. We used to fail machine ir verification.
364 ; CHECK-APPLE: _swifterror_isel
365 ; CHECK-O0: _swifterror_isel
366 define void @swifterror_isel(%swift.refcounted*) {
368 %swifterror = alloca swifterror %swift_error*, align 8
369 br i1 undef, label %5, label %1
371 %2 = phi i16 [ %4, %1 ], [ undef, %entry ]
372 %3 = call i1 undef(i16 %2, %swift.refcounted* swiftself %0, %swift_error** nocapture swifterror %swifterror)
373 %4 = load i16, i16* undef, align 2
379 ; This tests the basic usage of a swifterror parameter with swiftcc.
380 define swiftcc float @foo_swiftcc(%swift_error** swifterror %error_ptr_ref) {
381 ; CHECK-APPLE-LABEL: foo_swiftcc:
382 ; CHECK-APPLE: movl $16, %edi
383 ; CHECK-APPLE: malloc
384 ; CHECK-APPLE: movb $1, 8(%rax)
385 ; CHECK-APPLE: movq %rax, %r12
387 ; CHECK-O0-LABEL: foo_swiftcc:
390 ; CHECK-O0: movb $1, 8(%rax)
391 ; CHECK-O0: movq %{{.*}}, %r12
393 %call = call i8* @malloc(i64 16)
394 %call.0 = bitcast i8* %call to %swift_error*
395 store %swift_error* %call.0, %swift_error** %error_ptr_ref
396 %tmp = getelementptr inbounds i8, i8* %call, i64 8
401 declare swiftcc float @moo(%swift_error** swifterror)
403 ; Test parameter forwarding.
404 define swiftcc float @forward_swifterror(%swift_error** swifterror %error_ptr_ref) {
405 ; CHECK-APPLE-LABEL: forward_swifterror:
406 ; CHECK-APPLE: pushq %rax
407 ; CHECK-APPLE: callq _moo
408 ; CHECK-APPLE: popq %rax
411 ; CHECK-O0-LABEL: forward_swifterror:
412 ; CHECK-O0: pushq %rax
413 ; CHECK-O0: callq _moo
414 ; CHECK-O0: popq %rax
418 %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref)
422 define swiftcc float @conditionally_forward_swifterror(%swift_error** swifterror %error_ptr_ref, i32 %cc) {
423 ; CHECK-APPLE-LABEL: conditionally_forward_swifterror:
424 ; CHECK-APPLE: pushq %rax
425 ; CHECK-APPLE: testl %edi, %edi
428 ; CHECK-APPLE: callq _moo
429 ; CHECK-APPLE: popq %rax
432 ; CHECK-APPLE: xorps %xmm0, %xmm0
433 ; CHECK-APPLE: popq %rax
436 ; CHECK-O0-LABEL: conditionally_forward_swifterror:
437 ; CHECK-O0: pushq [[REG1:%[a-z0-9]+]]
438 ; CHECK-O0: cmpl $0, %edi
439 ; CHECK-O0-DAG: movq %r12, (%rsp)
442 ; CHECK-O0: movq (%rsp), [[REG:%[a-z0-9]+]]
443 ; CHECK-O0: movq [[REG]], %r12
444 ; CHECK-O0: callq _moo
445 ; CHECK-O0: popq [[REG1]]
448 ; CHECK-O0: movq (%rsp), [[REG:%[a-z0-9]+]]
449 ; CHECK-O0: xorps %xmm0, %xmm0
450 ; CHECK-O0: movq [[REG]], %r12
451 ; CHECK-O0: popq [[REG1]]
454 %cond = icmp ne i32 %cc, 0
455 br i1 %cond, label %gen_error, label %normal
458 %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref)
465 ; Check that we don't blow up on tail calling swifterror argument functions.
466 define float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) {
468 %0 = tail call float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref)
471 define swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) {
473 %0 = tail call swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref)
477 ; Check that we can handle an empty function with swifterror argument.
478 ; CHECK-i386-LABEL: empty_swiftcc:
479 ; CHECK-i386: movl 4(%esp), %eax
480 ; CHECK-i386: movl 8(%esp), %edx
481 ; CHECK-i386: movl 12(%esp), %ecx
483 ; CHECK-APPLE-LABEL: empty_swiftcc:
484 ; CHECK-APPLE: movl %edx, %ecx
485 ; CHECK-APPLE-DAG: movl %edi, %eax
486 ; CHECK-APPLE-DAG: movl %esi, %edx
488 define swiftcc {i32, i32, i32} @empty_swiftcc({i32, i32, i32} , %swift_error** swifterror %error_ptr_ref) {
490 ret {i32, i32, i32} %0
493 ; Make sure we can handle the case when isel generates new machine basic blocks.
494 ; CHECK-APPLE-LABEL: dont_crash_on_new_isel_blocks:
495 ; CHECK-APPLE: pushq %rax
496 ; CHECK-APPLE: xorl %eax, %eax
497 ; CHECK-APPLE: testb %al, %al
499 ; CHECK-APPLE: callq *%rax
500 ; CHECK-APPLE: popq %rax
503 define swiftcc void @dont_crash_on_new_isel_blocks(%swift_error** nocapture swifterror, i1, i8**) {
506 br i1 %3, label %cont, label %falsebb
509 %4 = load i8*, i8** %2, align 8
513 tail call swiftcc void undef(%swift_error** nocapture swifterror %0)
517 ; CHECK-APPLE-LABEL: swifterror_clobber
518 ; CHECK-APPLE: movq %r12, [[REG:%.*]]
520 ; CHECK-APPLE: movq [[REG]], %r12
521 define swiftcc void @swifterror_clobber(%swift_error** nocapture swifterror %err) {
522 call void asm sideeffect "nop", "~{r12}"()
526 ; CHECK-APPLE-LABEL: swifterror_reg_clobber
527 ; CHECK-APPLE: pushq %r12
529 ; CHECK-APPLE: popq %r12
530 define swiftcc void @swifterror_reg_clobber(%swift_error** nocapture %err) {
531 call void asm sideeffect "nop", "~{r12}"()
535 ; CHECK-APPLE-LABEL: params_in_reg
536 ; Save callee save registers to store clobbered arugments.
537 ; CHECK-APPLE: pushq %rbp
538 ; CHECK-APPLE: pushq %r15
539 ; CHECK-APPLE: pushq %r14
540 ; Clobbered swiftself register.
541 ; CHECK-APPLE: pushq %r13
542 ; CHECK-APPLE: pushq %rbx
543 ; CHECK-APPLE: subq $48, %rsp
545 ; CHECK-APPLE: movq %r12, 32(%rsp)
546 ; CHECK-APPLE: movq %r13, 24(%rsp)
547 ; CHECK-APPLE: movq %r9, 16(%rsp)
548 ; CHECK-APPLE: movq %r8, 8(%rsp)
549 ; CHECK-APPLE: movq %rcx, %r14
550 ; CHECK-APPLE: movq %rdx, %r15
551 ; CHECK-APPLE: movq %rsi, %rbx
552 ; CHECK-APPLE: movq %rdi, %rbp
554 ; CHECK-APPLE: movl $1, %edi
555 ; CHECK-APPLE: movl $2, %esi
556 ; CHECK-APPLE: movl $3, %edx
557 ; CHECK-APPLE: movl $4, %ecx
558 ; CHECK-APPLE: movl $5, %r8d
559 ; CHECK-APPLE: movl $6, %r9d
560 ; CHECK-APPLE: xorl %r13d, %r13d
561 ; CHECK-APPLE: xorl %r12d, %r12d
562 ; CHECK-APPLE: callq _params_in_reg2
563 ; Setup second call with stored arguments.
564 ; CHECK-APPLE: movq %rbp, %rdi
565 ; CHECK-APPLE: movq %rbx, %rsi
566 ; CHECK-APPLE: movq %r15, %rdx
567 ; CHECK-APPLE: movq %r14, %rcx
568 ; CHECK-APPLE: movq 8(%rsp), %r8
569 ; CHECK-APPLE: movq 16(%rsp), %r9
570 ; CHECK-APPLE: movq 24(%rsp), %r13
571 ; CHECK-APPLE: movq 32(%rsp), %r12
572 ; CHECK-APPLE: callq _params_in_reg2
573 ; CHECK-APPLE: addq $48, %rsp
574 ; CHECK-APPLE: popq %rbx
575 ; CHECK-APPLE: popq %r13
576 ; CHECK-APPLE: popq %r14
577 ; CHECK-APPLE: popq %r15
578 ; CHECK-APPLE: popq %rbp
579 define swiftcc void @params_in_reg(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) {
580 %error_ptr_ref = alloca swifterror %swift_error*, align 8
581 store %swift_error* null, %swift_error** %error_ptr_ref
582 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)
583 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)
586 declare swiftcc void @params_in_reg2(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err)
588 ; CHECK-APPLE-LABEL: params_and_return_in_reg
589 ; CHECK-APPLE: pushq %rbp
590 ; CHECK-APPLE: pushq %r15
591 ; CHECK-APPLE: pushq %r14
592 ; CHECK-APPLE: pushq %r13
593 ; CHECK-APPLE: pushq %rbx
594 ; CHECK-APPLE: subq $48, %rsp
596 ; CHECK-APPLE: movq %r12, %r14
597 ; CHECK-APPLE: movq %r13, (%rsp)
598 ; CHECK-APPLE: movq %r9, 32(%rsp)
599 ; CHECK-APPLE: movq %r8, 24(%rsp)
600 ; CHECK-APPLE: movq %rcx, 16(%rsp)
601 ; CHECK-APPLE: movq %rdx, %r15
602 ; CHECK-APPLE: movq %rsi, %rbx
603 ; CHECK-APPLE: movq %rdi, %rbp
604 ; Setup call that clobbers all argument registers.
605 ; CHECK-APPLE: movl $1, %edi
606 ; CHECK-APPLE: movl $2, %esi
607 ; CHECK-APPLE: movl $3, %edx
608 ; CHECK-APPLE: movl $4, %ecx
609 ; CHECK-APPLE: movl $5, %r8d
610 ; CHECK-APPLE: movl $6, %r9d
611 ; CHECK-APPLE: xorl %r13d, %r13d
612 ; CHECK-APPLE: xorl %r12d, %r12d
613 ; CHECK-APPLE: callq _params_in_reg2
614 ; Store error_ptr_ref for later use.
615 ; CHECK-APPLE: movq %r12, 8(%rsp)
616 ; Restore original arguments.
617 ; CHECK-APPLE: movq %rbp, %rdi
618 ; CHECK-APPLE: movq %rbx, %rsi
619 ; CHECK-APPLE: movq %r15, %rdx
620 ; CHECK-APPLE: movq 16(%rsp), %rcx
621 ; CHECK-APPLE: movq 24(%rsp), %r8
622 ; CHECK-APPLE: movq 32(%rsp), %r9
623 ; CHECK-APPLE: movq (%rsp), %r13
624 ; CHECK-APPLE: movq %r14, %r12
625 ; CHECK-APPLE: callq _params_and_return_in_reg2
626 ; Store return values in callee saved registers.
627 ; CHECK-APPLE: movq %rax, %rbx
628 ; CHECK-APPLE: movq %rdx, %rbp
629 ; CHECK-APPLE: movq %rcx, %r15
630 ; CHECK-APPLE: movq %r8, %r14
631 ; Store the swifterror return value (%err).
632 ; CHECK-APPLE: movq %r12, (%rsp)
634 ; CHECK-APPLE: movl $1, %edi
635 ; CHECK-APPLE: movl $2, %esi
636 ; CHECK-APPLE: movl $3, %edx
637 ; CHECK-APPLE: movl $4, %ecx
638 ; CHECK-APPLE: movl $5, %r8d
639 ; CHECK-APPLE: movl $6, %r9d
640 ; CHECK-APPLE: xorl %r13d, %r13d
641 ; Restore the swifterror value of error_ptr_ref.
642 ; CHECK-APPLE: movq 8(%rsp), %r12
643 ; CHECK-APPLE: callq _params_in_reg2
644 ; Restore the return values of _params_and_return_in_reg2.
645 ; CHECK-APPLE: movq %rbx, %rax
646 ; CHECK-APPLE: movq %rbp, %rdx
647 ; CHECK-APPLE: movq %r15, %rcx
648 ; CHECK-APPLE: movq %r14, %r8
649 ; Restore the swiferror value of err.
650 ; CHECK-APPLE: movq (%rsp), %r12
651 ; CHECK-APPLE: addq $48, %rsp
652 ; CHECK-APPLE: popq %rbx
653 ; CHECK-APPLE: popq %r13
654 ; CHECK-APPLE: popq %r14
655 ; CHECK-APPLE: popq %r15
656 ; CHECK-APPLE: popq %rbp
657 define swiftcc { i64, i64, i64, i64} @params_and_return_in_reg(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) {
658 %error_ptr_ref = alloca swifterror %swift_error*, align 8
659 store %swift_error* null, %swift_error** %error_ptr_ref
660 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)
661 %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)
662 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)
663 ret { i64, i64, i64, i64 }%val
666 declare swiftcc { i64, i64, i64, i64 } @params_and_return_in_reg2(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err)
669 declare void @acallee(i8*)
671 ; Make sure we don't tail call if the caller returns a swifterror value. We
672 ; would have to move into the swifterror register before the tail call.
673 ; CHECK-APPLE: tailcall_from_swifterror:
674 ; CHECK-APPLE-NOT: jmp _acallee
675 ; CHECK-APPLE: callq _acallee
677 define swiftcc void @tailcall_from_swifterror(%swift_error** swifterror %error_ptr_ref) {
679 tail call void @acallee(i8* null)
683 ; Make sure we don't crash on this function during -O0.
684 ; We used to crash because we would insert an IMPLICIT_DEF for the swifterror at
685 ; beginning of the machine basic block but did not inform FastISel of the
686 ; inserted instruction. When computing the InsertPoint in the entry block
687 ; FastISel would choose an insertion point before the IMPLICIT_DEF causing a
689 declare hidden swiftcc i8* @testFunA()
693 define swiftcc void @dontCrash() {
695 %swifterror = alloca swifterror %swift_error*, align 8
696 store %swift_error* null, %swift_error** %swifterror, align 8
697 %a = call i8* @testFunA()
698 %b = bitcast i8* %a to %TSb*
699 %._value = getelementptr inbounds %TSb, %TSb* %b, i32 0, i32 0
700 %c = load i1, i1* %._value, align 1
701 br i1 %c, label %trueBB, label %falseBB
711 declare swiftcc void @foo2(%swift_error** swifterror)
713 ; Make sure we properly assign registers during fast-isel.
714 ; CHECK-O0-LABEL: testAssign
715 ; CHECK-O0: pushq %r12
716 ; CHECK-O0: xorl [[ZERO:%[a-z0-9]+]], [[ZERO]]
717 ; CHECK-O0: movl [[ZERO]], %r12d
718 ; CHECK-O0: callq _foo2
719 ; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]]
721 ; CHECK-O0: movq [[SLOT]], %rax
722 ; CHECK-O0: popq %r12
725 ; CHECK-APPLE-LABEL: testAssign
726 ; CHECK-APPLE: pushq %r12
727 ; CHECK-APPLE: xorl %r12d, %r12d
728 ; CHECK-APPLE: callq _foo2
729 ; CHECK-APPLE: movq %r12, %rax
730 ; CHECK-APPLE: popq %r12
733 define swiftcc %swift_error* @testAssign(i8* %error_ref) {
735 %error_ptr = alloca swifterror %swift_error*
736 store %swift_error* null, %swift_error** %error_ptr
737 call swiftcc void @foo2(%swift_error** swifterror %error_ptr)
741 %error = load %swift_error*, %swift_error** %error_ptr
742 ret %swift_error* %error
745 ; CHECK-O0-LABEL: testAssign2
746 ; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]]
748 ; CHECK-O0: movq [[SLOT]], %rax
749 ; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]]
750 ; CHECK-O0: movq [[SLOT2]], %r12
753 ; CHECK-APPLE-LABEL: testAssign2
754 ; CHECK-APPLE: movq %r12, %rax
756 define swiftcc %swift_error* @testAssign2(i8* %error_ref, %swift_error** swifterror %err) {
761 %error = load %swift_error*, %swift_error** %err
762 ret %swift_error* %error
765 ; CHECK-O0-LABEL: testAssign3
766 ; CHECK-O0: callq _foo2
767 ; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]]
768 ; CHECK-O0: movq [[SLOT]], %rax
769 ; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]]
770 ; CHECK-O0: movq [[SLOT2]], %r12
771 ; CHECK-O0: addq $24, %rsp
774 ; CHECK-APPLE-LABEL: testAssign3
775 ; CHECK-APPLE: callq _foo2
776 ; CHECK-APPLE: movq %r12, %rax
779 define swiftcc %swift_error* @testAssign3(i8* %error_ref, %swift_error** swifterror %err) {
781 call swiftcc void @foo2(%swift_error** swifterror %err)
785 %error = load %swift_error*, %swift_error** %err
786 ret %swift_error* %error
790 ; CHECK-O0-LABEL: testAssign4
791 ; CHECK-O0: callq _foo2
792 ; CHECK-O0: xorl %eax, %eax
793 ; CHECK-O0: movl %eax, %ecx
794 ; CHECK-O0: movq %rcx, [[SLOT:[-a-z0-9\(\)\%]*]]
795 ; CHECK-O0: movq [[SLOT]], %rax
796 ; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]]
797 ; CHECK-O0: movq [[SLOT2]], %r12
800 ; CHECK-APPLE-LABEL: testAssign4
801 ; CHECK-APPLE: callq _foo2
802 ; CHECK-APPLE: xorl %eax, %eax
803 ; CHECK-APPLE: xorl %r12d, %r12d
806 define swiftcc %swift_error* @testAssign4(i8* %error_ref, %swift_error** swifterror %err) {
808 call swiftcc void @foo2(%swift_error** swifterror %err)
809 store %swift_error* null, %swift_error** %err
813 %error = load %swift_error*, %swift_error** %err
814 ret %swift_error* %error