Use Align for TFL::TransientStackAlignment
[llvm-core.git] / test / CodeGen / X86 / swifterror.ll
blobc3732295209782a775dd38d08ab8daa988dda6a0
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: movb $1, 8(%rax)
22 ; CHECK-O0: movq %{{.*}}, %r12
23 entry:
24   %call = call i8* @malloc(i64 16)
25   %call.0 = bitcast i8* %call to %swift_error*
26   store %swift_error* %call.0, %swift_error** %error_ptr_ref
27   %tmp = getelementptr inbounds i8, i8* %call, i64 8
28   store i8 1, i8* %tmp
29   ret float 1.0
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
38 ; CHECK-APPLE: jne
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:
44 ; CHECK-O0: xorl
45 ; CHECK-O0: movl %{{.*}}, %r12d
46 ; CHECK-O0: callq {{.*}}foo
47 ; CHECK-O0: jne
48 entry:
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
56 cont:
57   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
58   %t = load i8, i8* %v1
59   store i8 %t, i8* %error_ref
60   br label %handler
61 handler:
62   call void @free(i8* %tmp)
63   ret float 1.0
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
72 ; CHECK-APPLE: jne
73 ; CHECK-APPLE: ucomiss
74 ; CHECK-APPLE: jbe
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:
81 ; CHECK-O0: xorl
82 ; CHECK-O0: movl %{{.*}}, %r12d
83 ; CHECK-O0: callq {{.*}}foo
84 ; CHECK-O0: movq %r12, [[ID:%[a-z]+]]
85 ; CHECK-O0: cmpq $0, %r12
86 ; CHECK-O0: jne
87 entry:
88   %error_ptr_ref = alloca swifterror %swift_error*
89   br label %bb_loop
90 bb_loop:
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
97 cont:
98   %cmp = fcmp ogt float %call, 1.000000e+00
99   br i1 %cmp, label %bb_end, label %bb_loop
100 bb_end:
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
104   br label %handler
105 handler:
106   call void @free(i8* %tmp)
107   ret float 1.0
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
115 ; CHECK-APPLE: je
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
121 ; CHECK-APPLE: ret
123 ; CHECK-O0-LABEL: foo_if:
124 ; CHECK-O0: cmpl $0
125 ; spill to stack
126 ; CHECK-O0: movq %r12, {{.*}}(%rsp)
127 ; CHECK-O0: je
128 ; CHECK-O0: movl $16,
129 ; CHECK-O0: malloc
130 ; CHECK-O0: movq %rax, [[ID:%[a-z]+]]
131 ; CHECK-O0-DAG: movb $1, 8(%rax)
132 ; CHECK-O0-DAG: movq [[ID]], %r12
133 ; CHECK-O0: ret
134 ; reload from stack
135 ; CHECK-O0: movq {{.*}}(%rsp), [[REG:%[a-z]+]]
136 ; CHECK-O0: movq [[REG]], %r12
137 ; CHECK-O0: ret
138 entry:
139   %cond = icmp ne i32 %cc, 0
140   br i1 %cond, label %gen_error, label %normal
142 gen_error:
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
147   store i8 1, i8* %tmp
148   ret float 1.0
150 normal:
151   ret float 0.0
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
159 ; CHECK-APPLE: testl
160 ; CHECK-APPLE: je
161 ; CHECK-APPLE: movl $16, %edi
162 ; CHECK-APPLE: malloc
163 ; CHECK-APPLE: movb $1, 8(%rax)
164 ; CHECK-APPLE: ucomiss
165 ; CHECK-APPLE: jbe
166 ; CHECK-APPLE: movq %rax, %r12
167 ; CHECK-APPLE: ret
169 ; CHECK-O0-LABEL: foo_loop:
170 ; spill to stack
171 ; CHECK-O0: movq %r12, {{.*}}(%rsp)
172 ; CHECK-O0: cmpl $0
173 ; CHECK-O0: je
174 ; CHECK-O0: movl $16,
175 ; CHECK-O0: malloc
176 ; CHECK-O0: movq %rax, [[ID:%[a-z0-9]+]]
177 ; CHECK-O0: movb $1, 8([[ID]])
178 ; CHECK-O0: jbe
179 ; reload from stack
180 ; CHECK-O0: movq {{.*}}(%rsp), [[REG:%[a-z0-9]+]]
181 ; CHECK-O0: movq [[REG]], %r12
182 ; CHECK-O0: ret
183 entry:
184   br label %bb_loop
186 bb_loop:
187   %cond = icmp ne i32 %cc, 0
188   br i1 %cond, label %gen_error, label %bb_cont
190 gen_error:
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
195   store i8 1, i8* %tmp
196   br label %bb_cont
198 bb_cont:
199   %cmp = fcmp ogt float %cc2, 1.000000e+00
200   br i1 %cmp, label %bb_end, label %bb_loop
201 bb_end:
202   ret float 0.0
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
208 ; parameter.
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
225 ; CHECK-O0: malloc
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
231 ; CHECK-O0: ret
232 entry:
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
237   store i8 1, i8* %tmp
238   %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1
239   store i32 %val1, i32* %v2
240   ret void
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
250 ; CHECK-APPLE: jne
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:
257 ; CHECK-O0: xorl
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,
263 ; CHECK-O0: cmpq $0
264 ; CHECK-O0: jne
265 ; Access part of the error object and save it to error_ref
266 ; CHECK-O0: movb 8(%{{.*}}),
267 ; CHECK-O0: movb %{{.*}},
268 ; reload from stack
269 ; CHECK-O0: movq {{.*}}(%rsp), %rdi
270 ; CHECK-O0: callq {{.*}}free
271 entry:
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
280 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
284   br label %handler
285 handler:
286   call void @free(i8* %tmp)
287   ret float 1.0
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
299 ; CHECK-APPLE: jne
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
308 ; CHECK-APPLE: jne
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:
316 ; CHECK-O0: xorl
317 ; CHECK-O0: movl %{{.*}}, %r12d
318 ; CHECK-O0: callq {{.*}}foo
319 ; CHECK-O0: jne
321 ; The second swifterror value:
322 ; CHECK-O0: xorl
323 ; CHECK-O0: movl %{{.*}}, %r12d
324 ; CHECK-O0: callq {{.*}}foo
325 ; CHECK-O0: jne
326 entry:
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
334 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
338   br label %handler
339 handler:
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
349 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
353   br label %handler2
354 handler2:
355   call void @free(i8* %bitcast2)
357   ret float 1.0
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*) {
367 entry:
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
374   br label %1
376   ret void
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:
388 ; CHECK-O0: movl $16
389 ; CHECK-O0: malloc
390 ; CHECK-O0: movb $1, 8(%rax)
391 ; CHECK-O0: movq %{{.*}}, %r12
392 entry:
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
397   store i8 1, i8* %tmp
398   ret float 1.0
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
409 ; CHECK-APPLE: retq
411 ; CHECK-O0-LABEL: forward_swifterror:
412 ; CHECK-O0: pushq %rax
413 ; CHECK-O0:  callq _moo
414 ; CHECK-O0: popq %rax
415 ; CHECK-O0:  retq
417 entry:
418   %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref)
419   ret float %call
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
426 ; CHECK-APPLE:  je
428 ; CHECK-APPLE:  callq _moo
429 ; CHECK-APPLE:  popq %rax
430 ; CHECK-APPLE:  retq
432 ; CHECK-APPLE:  xorps %xmm0, %xmm0
433 ; CHECK-APPLE:  popq %rax
434 ; CHECK-APPLE:  retq
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)
440 ; CHECK-O0:  je
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]]
446 ; CHECK-O0:  retq
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]]
452 ; CHECK-O0:  retq
453 entry:
454   %cond = icmp ne i32 %cc, 0
455   br i1 %cond, label %gen_error, label %normal
457 gen_error:
458   %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref)
459   ret float %call
461 normal:
462   ret float 0.0
465 ; Check that we don't blow up on tail calling swifterror argument functions.
466 define float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) {
467 entry:
468   %0 = tail call float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref)
469   ret float %0
471 define swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) {
472 entry:
473   %0 = tail call swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref)
474   ret float %0
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
482 ; CHECK-i386:  retl
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
487 ; CHECK-APPLE:  retq
488 define swiftcc {i32, i32, i32} @empty_swiftcc({i32, i32, i32} , %swift_error** swifterror %error_ptr_ref) {
489 entry:
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
498 ; CHECK-APPLE: jne
499 ; CHECK-APPLE: callq   *%rax
500 ; CHECK-APPLE: popq    %rax
501 ; CHECK-APPLE: ret
503 define swiftcc void @dont_crash_on_new_isel_blocks(%swift_error** nocapture swifterror, i1, i8**) {
504 entry:
505   %3 = or i1 false, %1
506   br i1 %3, label %cont, label %falsebb
508 falsebb:
509   %4 = load i8*, i8** %2, align 8
510   br label %cont
512 cont:
513   tail call swiftcc void undef(%swift_error** nocapture swifterror %0)
514   ret void
517 ; CHECK-APPLE-LABEL: swifterror_clobber
518 ; CHECK-APPLE: movq %r12, [[REG:%.*]]
519 ; CHECK-APPLE: nop
520 ; CHECK-APPLE: movq [[REG]], %r12
521 define swiftcc void @swifterror_clobber(%swift_error** nocapture swifterror %err) {
522   call void asm sideeffect "nop", "~{r12}"()
523   ret void
526 ; CHECK-APPLE-LABEL: swifterror_reg_clobber
527 ; CHECK-APPLE: pushq %r12
528 ; CHECK-APPLE: nop
529 ; CHECK-APPLE: popq  %r12
530 define swiftcc void @swifterror_reg_clobber(%swift_error** nocapture %err) {
531   call void asm sideeffect "nop", "~{r12}"()
532   ret void
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
544 ; Save arguments.
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
553 ; Setup call.
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)
584   ret void
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
595 ; Store arguments.
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)
633 ; Setup call.
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) {
678 entry:
679   tail call void @acallee(i8* null)
680   ret void
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
688 ; crash later on.
689 declare hidden swiftcc i8* @testFunA()
691 %TSb = type <{ i1 }>
693 define swiftcc void @dontCrash()  {
694 entry:
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
703 trueBB:
704   ret void
706 falseBB:
707   ret void
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
723 ; CHECK-O0:        retq
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
731 ; CHECK-APPLE:        retq
733 define swiftcc %swift_error* @testAssign(i8* %error_ref) {
734 entry:
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)
738   br label %a
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\(\)\%]*]]
747 ; CHECK-O0:        jmp
748 ; CHECK-O0:        movq    [[SLOT]], %rax
749 ; CHECK-O0:        movq    %rax, [[SLOT2:[-a-z0-9\(\)\%]*]]
750 ; CHECK-O0:        movq    [[SLOT2]], %r12
751 ; CHECK-O0:        retq
753 ; CHECK-APPLE-LABEL: testAssign2
754 ; CHECK-APPLE:        movq    %r12, %rax
755 ; CHECK-APPLE:        retq
756 define swiftcc %swift_error* @testAssign2(i8* %error_ref, %swift_error** swifterror %err) {
757 entry:
758   br label %a
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
772 ; CHECK-O0:        retq
774 ; CHECK-APPLE-LABEL: testAssign3
775 ; CHECK-APPLE:         callq   _foo2
776 ; CHECK-APPLE:         movq    %r12, %rax
777 ; CHECK-APPLE:         retq
779 define swiftcc %swift_error* @testAssign3(i8* %error_ref, %swift_error** swifterror %err) {
780 entry:
781   call swiftcc void @foo2(%swift_error** swifterror %err)
782   br label %a
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
798 ; CHECK-O0:        retq
800 ; CHECK-APPLE-LABEL: testAssign4
801 ; CHECK-APPLE:        callq   _foo2
802 ; CHECK-APPLE:        xorl    %eax, %eax
803 ; CHECK-APPLE:        xorl    %r12d, %r12d
804 ; CHECK-APPLE:        retq
806 define swiftcc %swift_error* @testAssign4(i8* %error_ref, %swift_error** swifterror %err) {
807 entry:
808   call swiftcc void @foo2(%swift_error** swifterror %err)
809   store %swift_error* null, %swift_error** %err
810   br label %a
813   %error = load %swift_error*, %swift_error** %err
814   ret %swift_error* %error