[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / CodeGen / X86 / swifterror.ll
blobac23473b8eccd0cd3ffaa9b2c7ac0ca4e4e68be7
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
14 ; CHECK-APPLE: malloc
15 ; CHECK-APPLE: movb $1, 8(%rax)
16 ; CHECK-APPLE: movq %rax, %r12
18 ; CHECK-O0-LABEL: foo:
19 ; CHECK-O0: movl $16
20 ; CHECK-O0: malloc
21 ; CHECK-O0: movq %{{.*}}, %r12
22 ; CHECK-O0: movb $1, 8(%rax)
24 entry:
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
29   store i8 1, i8* %tmp
30   ret float 1.0
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
39 ; CHECK-APPLE: jne
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:
45 ; CHECK-O0: xorl
46 ; CHECK-O0: movl %{{.*}}, %r12d
47 ; CHECK-O0: callq {{.*}}foo
48 ; CHECK-O0: jne
49 entry:
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
57 cont:
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
62 handler:
63   call void @free(i8* %tmp)
64   ret float 1.0
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
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
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
88 entry:
89   %error_ptr_ref = alloca swifterror %swift_error*
90   br label %bb_loop
91 bb_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
98 cont:
99   %cmp = fcmp ogt float %call, 1.000000e+00
100   br i1 %cmp, label %bb_end, label %bb_loop
101 bb_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
106 handler:
107   call void @free(i8* %tmp)
108   ret float 1.0
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
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
124 ; CHECK-O0-LABEL: foo_if:
125 ; spill to stack
126 ; CHECK-O0: movq %r12, {{.*}}(%rsp)
127 ; CHECK-O0: cmpl $0
128 ; CHECK-O0: je
129 ; CHECK-O0: movl $16,
130 ; CHECK-O0: malloc
131 ; CHECK-O0: movq %rax, %r12
132 ; CHECK-O0-DAG: movb $1, 8(%rax)
133 ; CHECK-O0: ret
134 ; reload from stack
135 ; CHECK-O0: movq {{.*}}(%rsp), %r12
136 ; CHECK-O0: ret
137 entry:
138   %cond = icmp ne i32 %cc, 0
139   br i1 %cond, label %gen_error, label %normal
141 gen_error:
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
146   store i8 1, i8* %tmp
147   ret float 1.0
149 normal:
150   ret float 0.0
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
158 ; CHECK-APPLE: testl
159 ; CHECK-APPLE: je
160 ; CHECK-APPLE: movl $16, %edi
161 ; CHECK-APPLE: malloc
162 ; CHECK-APPLE: movb $1, 8(%rax)
163 ; CHECK-APPLE: ucomiss
164 ; CHECK-APPLE: jbe
165 ; CHECK-APPLE: movq %rax, %r12
166 ; CHECK-APPLE: ret
168 ; CHECK-O0-LABEL: foo_loop:
169 ; spill to stack
170 ; CHECK-O0: movq %r12, {{.*}}(%rsp)
171 ; CHECK-O0: cmpl $0
172 ; CHECK-O0: je
173 ; CHECK-O0: movl $16,
174 ; CHECK-O0: malloc
175 ; CHECK-O0: movq %rax, [[ID:%[a-z0-9]+]]
176 ; CHECK-O0: movb $1, 8([[ID]])
177 ; CHECK-O0: jbe
178 ; reload from stack
179 ; CHECK-O0: movq {{.*}}(%rsp), %r12
180 ; CHECK-O0: ret
181 entry:
182   br label %bb_loop
184 bb_loop:
185   %cond = icmp ne i32 %cc, 0
186   br i1 %cond, label %gen_error, label %bb_cont
188 gen_error:
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
193   store i8 1, i8* %tmp
194   br label %bb_cont
196 bb_cont:
197   %cmp = fcmp ogt float %cc2, 1.000000e+00
198   br i1 %cmp, label %bb_end, label %bb_loop
199 bb_end:
200   ret float 0.0
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
206 ; parameter.
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,
222 ; CHECK-O0: malloc
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(%{{.*}})
228 ; CHECK-O0: ret
229 entry:
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
234   store i8 1, i8* %tmp
235   %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1
236   store i32 %val1, i32* %v2
237   ret void
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
247 ; CHECK-APPLE: jne
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:
254 ; CHECK-O0: xorl
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,
260 ; CHECK-O0: cmpq $0
261 ; CHECK-O0: jne
262 ; Access part of the error object and save it to error_ref
263 ; CHECK-O0: movb 8(%{{.*}}),
264 ; CHECK-O0: movb %{{.*}},
265 ; reload from stack
266 ; CHECK-O0: movq {{.*}}(%rsp), %rdi
267 ; CHECK-O0: callq {{.*}}free
268 entry:
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
277 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
281   br label %handler
282 handler:
283   call void @free(i8* %tmp)
284   ret float 1.0
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
296 ; CHECK-APPLE: jne
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
305 ; CHECK-APPLE: jne
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:
313 ; CHECK-O0: xorl
314 ; CHECK-O0: movl %{{.*}}, %r12d
315 ; CHECK-O0: callq {{.*}}foo
316 ; CHECK-O0: jne
318 ; The second swifterror value:
319 ; CHECK-O0: xorl
320 ; CHECK-O0: movl %{{.*}}, %r12d
321 ; CHECK-O0: callq {{.*}}foo
322 ; CHECK-O0: jne
323 entry:
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
331 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
335   br label %handler
336 handler:
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
346 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
350   br label %handler2
351 handler2:
352   call void @free(i8* %bitcast2)
354   ret float 1.0
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*) {
364 entry:
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
371   br label %1
373   ret void
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:
385 ; CHECK-O0: movl $16
386 ; CHECK-O0: malloc
387 ; CHECK-O0: movq %{{.*}}, %r12
388 ; CHECK-O0: movb $1, 8(%rax)
390 entry:
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
395   store i8 1, i8* %tmp
396   ret float 1.0
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
407 ; CHECK-APPLE: retq
409 ; CHECK-O0-LABEL: forward_swifterror:
410 ; CHECK-O0: pushq %rax
411 ; CHECK-O0:  callq _moo
412 ; CHECK-O0: popq %rax
413 ; CHECK-O0:  retq
415 entry:
416   %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref)
417   ret float %call
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
423 ; CHECK-APPLE:  je
425 ; CHECK-APPLE:  pushq %rax
426 ; CHECK-APPLE:  callq _moo
427 ; CHECK-APPLE:  popq %rax
428 ; CHECK-APPLE:  retq
430 ; CHECK-APPLE:  xorps %xmm0, %xmm0
431 ; CHECK-APPLE:  retq
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
437 ; CHECK-O0:  je
439 ; CHECK-O0:  movq (%rsp), %r12
440 ; CHECK-O0:  callq _moo
441 ; CHECK-O0:  popq [[REG1]]
442 ; CHECK-O0:  retq
444 ; CHECK-O0:  movq (%rsp), %r12
445 ; CHECK-O0:  xorps %xmm0, %xmm0
446 ; CHECK-O0:  popq [[REG1]]
447 ; CHECK-O0:  retq
448 entry:
449   %cond = icmp ne i32 %cc, 0
450   br i1 %cond, label %gen_error, label %normal
452 gen_error:
453   %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref)
454   ret float %call
456 normal:
457   ret float 0.0
460 ; Check that we don't blow up on tail calling swifterror argument functions.
461 define float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) {
462 entry:
463   %0 = tail call float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref)
464   ret float %0
466 define swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) {
467 entry:
468   %0 = tail call swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref)
469   ret float %0
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
477 ; CHECK-i386:  retl
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
482 ; CHECK-APPLE:  retq
483 define swiftcc {i32, i32, i32} @empty_swiftcc({i32, i32, i32} , %swift_error** swifterror %error_ptr_ref) {
484 entry:
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
492 ; CHECK-APPLE: jne
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**) {
500 entry:
501   %3 = or i1 false, %1
502   br i1 %3, label %cont, label %falsebb
504 falsebb:
505   %4 = load i8*, i8** %2, align 8
506   br label %cont
508 cont:
509   tail call swiftcc void undef(%swift_error** nocapture swifterror %0)
510   ret void
513 ; CHECK-APPLE-LABEL: swifterror_clobber
514 ; CHECK-APPLE: movq %r12, [[REG:%.*]]
515 ; CHECK-APPLE: nop
516 ; CHECK-APPLE: movq [[REG]], %r12
517 define swiftcc void @swifterror_clobber(%swift_error** nocapture swifterror %err) {
518   call void asm sideeffect "nop", "~{r12}"()
519   ret void
522 ; CHECK-APPLE-LABEL: swifterror_reg_clobber
523 ; CHECK-APPLE: pushq %r12
524 ; CHECK-APPLE: nop
525 ; CHECK-APPLE: popq  %r12
526 define swiftcc void @swifterror_reg_clobber(%swift_error** nocapture %err) {
527   call void asm sideeffect "nop", "~{r12}"()
528   ret void
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
540 ; Save arguments.
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
549 ; Setup call.
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)
580   ret void
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
591 ; Store arguments.
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)
629 ; Setup call.
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) {
674 entry:
675   tail call void @acallee(i8* null)
676   ret void
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
684 ; crash later on.
685 declare hidden swiftcc i8* @testFunA()
687 %TSb = type <{ i1 }>
689 define swiftcc void @dontCrash()  {
690 entry:
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
699 trueBB:
700   ret void
702 falseBB:
703   ret void
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
719 ; CHECK-O0:        retq
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
727 ; CHECK-APPLE:        retq
729 define swiftcc %swift_error* @testAssign(i8* %error_ref) {
730 entry:
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)
734   br label %a
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\(\)\%]*]]
743 ; CHECK-O0:        jmp
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
750 ; CHECK-APPLE:        retq
751 define swiftcc %swift_error* @testAssign2(i8* %error_ref, %swift_error** swifterror %err) {
752 entry:
753   br label %a
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
771 ; CHECK-APPLE:         retq
773 define swiftcc %swift_error* @testAssign3(i8* %error_ref, %swift_error** swifterror %err) {
774 entry:
775   call swiftcc void @foo2(%swift_error** swifterror %err)
776   br label %a
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
798 ; CHECK-APPLE:        retq
800 define swiftcc %swift_error* @testAssign4(i8* %error_ref, %swift_error** swifterror %err) {
801 entry:
802   call swiftcc void @foo2(%swift_error** swifterror %err)
803   store %swift_error* null, %swift_error** %err
804   br label %a
807   %error = load %swift_error*, %swift_error** %err
808   ret %swift_error* %error