1 ; RUN: llc < %s -verify-machineinstrs -mtriple=x86_64-apple-darwin | FileCheck --check-prefix=CHECK-APPLE %s
2 ; RUN: llc < %s -verify-machineinstrs -mtriple=x86_64-apple-darwin -O0 | FileCheck --check-prefix=CHECK-O0 %s
3 ; RUN: llc < %s -verify-machineinstrs -mtriple=i386-apple-darwin | 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: subq $24, %rsp
438 ; CHECK-O0: movq %r12, [[REG1:%[a-z0-9]+]]
439 ; CHECK-O0: cmpl $0, %edi
440 ; CHECK-O0-DAG: movq [[REG1]], [[STK:[0-9]+]](%rsp)
441 ; CHECK-O0-DAG: movq %r12, [[STK2:[0-9]+]](%rsp)
444 ; CHECK-O0: movq [[STK2]](%rsp), [[REG:%[a-z0-9]+]]
445 ; CHECK-O0: movq [[REG]], %r12
446 ; CHECK-O0: callq _moo
447 ; CHECK-O0: addq $24, %rsp
450 ; CHECK-O0: movq [[STK2]](%rsp), [[REG:%[a-z0-9]+]]
451 ; CHECK-O0: xorps %xmm0, %xmm0
452 ; CHECK-O0: movq [[REG]], %r12
453 ; CHECK-O0: addq $24, %rsp
456 %cond = icmp ne i32 %cc, 0
457 br i1 %cond, label %gen_error, label %normal
460 %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref)
467 ; Check that we don't blow up on tail calling swifterror argument functions.
468 define float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) {
470 %0 = tail call float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref)
473 define swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) {
475 %0 = tail call swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref)
479 ; Check that we can handle an empty function with swifterror argument.
480 ; CHECK-i386-LABEL: empty_swiftcc:
481 ; CHECK-i386: movl 4(%esp), %eax
482 ; CHECK-i386: movl 8(%esp), %edx
483 ; CHECK-i386: movl 12(%esp), %ecx
485 ; CHECK-APPLE-LABEL: empty_swiftcc:
486 ; CHECK-APPLE: movl %edx, %ecx
487 ; CHECK-APPLE-DAG: movl %edi, %eax
488 ; CHECK-APPLE-DAG: movl %esi, %edx
490 define swiftcc {i32, i32, i32} @empty_swiftcc({i32, i32, i32} , %swift_error** swifterror %error_ptr_ref) {
492 ret {i32, i32, i32} %0
495 ; Make sure we can handle the case when isel generates new machine basic blocks.
496 ; CHECK-APPLE-LABEL: dont_crash_on_new_isel_blocks:
497 ; CHECK-APPLE: pushq %rax
498 ; CHECK-APPLE: xorl %eax, %eax
499 ; CHECK-APPLE: testb %al, %al
501 ; CHECK-APPLE: callq *%rax
502 ; CHECK-APPLE: popq %rax
505 define swiftcc void @dont_crash_on_new_isel_blocks(%swift_error** nocapture swifterror, i1, i8**) {
508 br i1 %3, label %cont, label %falsebb
511 %4 = load i8*, i8** %2, align 8
515 tail call swiftcc void undef(%swift_error** nocapture swifterror %0)
519 ; CHECK-APPLE-LABEL: swifterror_clobber
520 ; CHECK-APPLE: movq %r12, [[REG:%.*]]
522 ; CHECK-APPLE: movq [[REG]], %r12
523 define swiftcc void @swifterror_clobber(%swift_error** nocapture swifterror %err) {
524 call void asm sideeffect "nop", "~{r12}"()
528 ; CHECK-APPLE-LABEL: swifterror_reg_clobber
529 ; CHECK-APPLE: pushq %r12
531 ; CHECK-APPLE: popq %r12
532 define swiftcc void @swifterror_reg_clobber(%swift_error** nocapture %err) {
533 call void asm sideeffect "nop", "~{r12}"()
537 ; CHECK-APPLE-LABEL: params_in_reg
538 ; Save callee save registers to store clobbered arugments.
539 ; CHECK-APPLE: pushq %rbp
540 ; CHECK-APPLE: pushq %r15
541 ; CHECK-APPLE: pushq %r14
542 ; Clobbered swiftself register.
543 ; CHECK-APPLE: pushq %r13
544 ; CHECK-APPLE: pushq %rbx
545 ; CHECK-APPLE: subq $48, %rsp
547 ; CHECK-APPLE: movq %r12, 32(%rsp)
548 ; CHECK-APPLE: movq %r13, 24(%rsp)
549 ; CHECK-APPLE: movq %r9, 16(%rsp)
550 ; CHECK-APPLE: movq %r8, 8(%rsp)
551 ; CHECK-APPLE: movq %rcx, %r14
552 ; CHECK-APPLE: movq %rdx, %r15
553 ; CHECK-APPLE: movq %rsi, %rbx
554 ; CHECK-APPLE: movq %rdi, %rbp
556 ; CHECK-APPLE: movl $1, %edi
557 ; CHECK-APPLE: movl $2, %esi
558 ; CHECK-APPLE: movl $3, %edx
559 ; CHECK-APPLE: movl $4, %ecx
560 ; CHECK-APPLE: movl $5, %r8d
561 ; CHECK-APPLE: movl $6, %r9d
562 ; CHECK-APPLE: xorl %r13d, %r13d
563 ; CHECK-APPLE: xorl %r12d, %r12d
564 ; CHECK-APPLE: callq _params_in_reg2
565 ; Setup second call with stored arguments.
566 ; CHECK-APPLE: movq %rbp, %rdi
567 ; CHECK-APPLE: movq %rbx, %rsi
568 ; CHECK-APPLE: movq %r15, %rdx
569 ; CHECK-APPLE: movq %r14, %rcx
570 ; CHECK-APPLE: movq 8(%rsp), %r8
571 ; CHECK-APPLE: movq 16(%rsp), %r9
572 ; CHECK-APPLE: movq 24(%rsp), %r13
573 ; CHECK-APPLE: movq 32(%rsp), %r12
574 ; CHECK-APPLE: callq _params_in_reg2
575 ; CHECK-APPLE: addq $48, %rsp
576 ; CHECK-APPLE: popq %rbx
577 ; CHECK-APPLE: popq %r13
578 ; CHECK-APPLE: popq %r14
579 ; CHECK-APPLE: popq %r15
580 ; CHECK-APPLE: popq %rbp
581 define swiftcc void @params_in_reg(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) {
582 %error_ptr_ref = alloca swifterror %swift_error*, align 8
583 store %swift_error* null, %swift_error** %error_ptr_ref
584 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)
585 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)
588 declare swiftcc void @params_in_reg2(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err)
590 ; CHECK-APPLE-LABEL: params_and_return_in_reg
591 ; CHECK-APPLE: pushq %rbp
592 ; CHECK-APPLE: pushq %r15
593 ; CHECK-APPLE: pushq %r14
594 ; CHECK-APPLE: pushq %r13
595 ; CHECK-APPLE: pushq %rbx
596 ; CHECK-APPLE: subq $48, %rsp
598 ; CHECK-APPLE: movq %r12, %r14
599 ; CHECK-APPLE: movq %r13, (%rsp)
600 ; CHECK-APPLE: movq %r9, 32(%rsp)
601 ; CHECK-APPLE: movq %r8, 24(%rsp)
602 ; CHECK-APPLE: movq %rcx, 16(%rsp)
603 ; CHECK-APPLE: movq %rdx, %r15
604 ; CHECK-APPLE: movq %rsi, %rbx
605 ; CHECK-APPLE: movq %rdi, %rbp
606 ; Setup call that clobbers all argument registers.
607 ; CHECK-APPLE: movl $1, %edi
608 ; CHECK-APPLE: movl $2, %esi
609 ; CHECK-APPLE: movl $3, %edx
610 ; CHECK-APPLE: movl $4, %ecx
611 ; CHECK-APPLE: movl $5, %r8d
612 ; CHECK-APPLE: movl $6, %r9d
613 ; CHECK-APPLE: xorl %r13d, %r13d
614 ; CHECK-APPLE: xorl %r12d, %r12d
615 ; CHECK-APPLE: callq _params_in_reg2
616 ; Store error_ptr_ref for later use.
617 ; CHECK-APPLE: movq %r12, 8(%rsp)
618 ; Restore original arguments.
619 ; CHECK-APPLE: movq %rbp, %rdi
620 ; CHECK-APPLE: movq %rbx, %rsi
621 ; CHECK-APPLE: movq %r15, %rdx
622 ; CHECK-APPLE: movq 16(%rsp), %rcx
623 ; CHECK-APPLE: movq 24(%rsp), %r8
624 ; CHECK-APPLE: movq 32(%rsp), %r9
625 ; CHECK-APPLE: movq (%rsp), %r13
626 ; CHECK-APPLE: movq %r14, %r12
627 ; CHECK-APPLE: callq _params_and_return_in_reg2
628 ; Store return values in callee saved registers.
629 ; CHECK-APPLE: movq %rax, %rbx
630 ; CHECK-APPLE: movq %rdx, %rbp
631 ; CHECK-APPLE: movq %rcx, %r15
632 ; CHECK-APPLE: movq %r8, %r14
633 ; Store the swifterror return value (%err).
634 ; CHECK-APPLE: movq %r12, (%rsp)
636 ; CHECK-APPLE: movl $1, %edi
637 ; CHECK-APPLE: movl $2, %esi
638 ; CHECK-APPLE: movl $3, %edx
639 ; CHECK-APPLE: movl $4, %ecx
640 ; CHECK-APPLE: movl $5, %r8d
641 ; CHECK-APPLE: movl $6, %r9d
642 ; CHECK-APPLE: xorl %r13d, %r13d
643 ; Restore the swifterror value of error_ptr_ref.
644 ; CHECK-APPLE: movq 8(%rsp), %r12
645 ; CHECK-APPLE: callq _params_in_reg2
646 ; Restore the return values of _params_and_return_in_reg2.
647 ; CHECK-APPLE: movq %rbx, %rax
648 ; CHECK-APPLE: movq %rbp, %rdx
649 ; CHECK-APPLE: movq %r15, %rcx
650 ; CHECK-APPLE: movq %r14, %r8
651 ; Restore the swiferror value of err.
652 ; CHECK-APPLE: movq (%rsp), %r12
653 ; CHECK-APPLE: addq $48, %rsp
654 ; CHECK-APPLE: popq %rbx
655 ; CHECK-APPLE: popq %r13
656 ; CHECK-APPLE: popq %r14
657 ; CHECK-APPLE: popq %r15
658 ; CHECK-APPLE: popq %rbp
659 define swiftcc { i64, i64, i64, i64} @params_and_return_in_reg(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) {
660 %error_ptr_ref = alloca swifterror %swift_error*, align 8
661 store %swift_error* null, %swift_error** %error_ptr_ref
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 %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)
664 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)
665 ret { i64, i64, i64, i64 }%val
668 declare swiftcc { i64, i64, i64, i64 } @params_and_return_in_reg2(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err)
671 declare void @acallee(i8*)
673 ; Make sure we don't tail call if the caller returns a swifterror value. We
674 ; would have to move into the swifterror register before the tail call.
675 ; CHECK-APPLE: tailcall_from_swifterror:
676 ; CHECK-APPLE-NOT: jmp _acallee
677 ; CHECK-APPLE: callq _acallee
679 define swiftcc void @tailcall_from_swifterror(%swift_error** swifterror %error_ptr_ref) {
681 tail call void @acallee(i8* null)
685 ; Make sure we don't crash on this function during -O0.
686 ; We used to crash because we would insert an IMPLICIT_DEF for the swifterror at
687 ; beginning of the machine basic block but did not inform FastISel of the
688 ; inserted instruction. When computing the InsertPoint in the entry block
689 ; FastISel would choose an insertion point before the IMPLICIT_DEF causing a
691 declare hidden swiftcc i8* @testFunA()
695 define swiftcc void @dontCrash() {
697 %swifterror = alloca swifterror %swift_error*, align 8
698 store %swift_error* null, %swift_error** %swifterror, align 8
699 %a = call i8* @testFunA()
700 %b = bitcast i8* %a to %TSb*
701 %._value = getelementptr inbounds %TSb, %TSb* %b, i32 0, i32 0
702 %c = load i1, i1* %._value, align 1
703 br i1 %c, label %trueBB, label %falseBB
713 declare swiftcc void @foo2(%swift_error** swifterror)
715 ; Make sure we properly assign registers during fast-isel.
716 ; CHECK-O0-LABEL: testAssign
717 ; CHECK-O0: pushq %r12
718 ; CHECK-O0: xorl [[ZERO:%[a-z0-9]+]], [[ZERO]]
719 ; CHECK-O0: movl [[ZERO]], %r12d
720 ; CHECK-O0: callq _foo2
721 ; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]]
723 ; CHECK-O0: movq [[SLOT]], %rax
724 ; CHECK-O0: popq %r12
727 ; CHECK-APPLE-LABEL: testAssign
728 ; CHECK-APPLE: pushq %r12
729 ; CHECK-APPLE: xorl %r12d, %r12d
730 ; CHECK-APPLE: callq _foo2
731 ; CHECK-APPLE: movq %r12, %rax
732 ; CHECK-APPLE: popq %r12
735 define swiftcc %swift_error* @testAssign(i8* %error_ref) {
737 %error_ptr = alloca swifterror %swift_error*
738 store %swift_error* null, %swift_error** %error_ptr
739 call swiftcc void @foo2(%swift_error** swifterror %error_ptr)
743 %error = load %swift_error*, %swift_error** %error_ptr
744 ret %swift_error* %error
747 ; CHECK-O0-LABEL: testAssign2
748 ; CHECK-O0: movq %r12, {{.*}}
749 ; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]]
751 ; CHECK-O0: movq [[SLOT]], %rax
752 ; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]]
753 ; CHECK-O0: movq [[SLOT2]], %r12
756 ; CHECK-APPLE-LABEL: testAssign2
757 ; CHECK-APPLE: movq %r12, %rax
759 define swiftcc %swift_error* @testAssign2(i8* %error_ref, %swift_error** swifterror %err) {
764 %error = load %swift_error*, %swift_error** %err
765 ret %swift_error* %error
768 ; CHECK-O0-LABEL: testAssign3
769 ; CHECK-O0: callq _foo2
770 ; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]]
771 ; CHECK-O0: movq [[SLOT]], %rax
772 ; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]]
773 ; CHECK-O0: movq [[SLOT2]], %r12
774 ; CHECK-O0: addq $24, %rsp
777 ; CHECK-APPLE-LABEL: testAssign3
778 ; CHECK-APPLE: callq _foo2
779 ; CHECK-APPLE: movq %r12, %rax
782 define swiftcc %swift_error* @testAssign3(i8* %error_ref, %swift_error** swifterror %err) {
784 call swiftcc void @foo2(%swift_error** swifterror %err)
788 %error = load %swift_error*, %swift_error** %err
789 ret %swift_error* %error
793 ; CHECK-O0-LABEL: testAssign4
794 ; CHECK-O0: callq _foo2
795 ; CHECK-O0: xorl %ecx, %ecx
796 ; CHECK-O0: movl %ecx, %eax
797 ; CHECK-O0: movq %rax, [[SLOT:[-a-z0-9\(\)\%]*]]
798 ; CHECK-O0: movq [[SLOT]], %rax
799 ; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]]
800 ; CHECK-O0: movq [[SLOT2]], %r12
803 ; CHECK-APPLE-LABEL: testAssign4
804 ; CHECK-APPLE: callq _foo2
805 ; CHECK-APPLE: xorl %eax, %eax
806 ; CHECK-APPLE: xorl %r12d, %r12d
809 define swiftcc %swift_error* @testAssign4(i8* %error_ref, %swift_error** swifterror %err) {
811 call swiftcc void @foo2(%swift_error** swifterror %err)
812 store %swift_error* null, %swift_error** %err
816 %error = load %swift_error*, %swift_error** %err
817 ret %swift_error* %error