• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-apple-darwin | FileCheck --check-prefix=CHECK-APPLE %s
2; RUN: llc -verify-machineinstrs -O0 < %s -mtriple=x86_64-apple-darwin | FileCheck --check-prefix=CHECK-O0 %s
3
4declare i8* @malloc(i64)
5declare void @free(i8*)
6%swift_error = type {i64, i8}
7
8; This tests the basic usage of a swifterror parameter. "foo" is the function
9; that takes a swifterror parameter and "caller" is the caller of "foo".
10define float @foo(%swift_error** swifterror %error_ptr_ref) {
11; CHECK-APPLE-LABEL: foo:
12; CHECK-APPLE: movl $16, %edi
13; CHECK-APPLE: malloc
14; CHECK-APPLE: movb $1, 8(%rax)
15; CHECK-APPLE: movq %rax, %r12
16
17; CHECK-O0-LABEL: foo:
18; CHECK-O0: movl $16
19; CHECK-O0: malloc
20; CHECK-O0: movb $1, 8(%rax)
21; CHECK-O0: movq %{{.*}}, %r12
22entry:
23  %call = call i8* @malloc(i64 16)
24  %call.0 = bitcast i8* %call to %swift_error*
25  store %swift_error* %call.0, %swift_error** %error_ptr_ref
26  %tmp = getelementptr inbounds i8, i8* %call, i64 8
27  store i8 1, i8* %tmp
28  ret float 1.0
29}
30
31; "caller" calls "foo" that takes a swifterror parameter.
32define float @caller(i8* %error_ref) {
33; CHECK-APPLE-LABEL: caller:
34; CHECK-APPLE: xorl %r12d, %r12d
35; CHECK-APPLE: callq {{.*}}foo
36; CHECK-APPLE: testq %r12, %r12
37; CHECK-APPLE: jne
38; Access part of the error object and save it to error_ref
39; CHECK-APPLE: movb 8(%r12)
40; CHECK-APPLE: movq %r12, %rdi
41; CHECK_APPLE: callq {{.*}}free
42
43; CHECK-O0-LABEL: caller:
44; CHECK-O0: xorl
45; CHECK-O0: movl %{{.*}}, %r12d
46; CHECK-O0: callq {{.*}}foo
47; CHECK-O0: jne
48entry:
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
56cont:
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
61handler:
62  call void @free(i8* %tmp)
63  ret float 1.0
64}
65
66; "caller2" is the caller of "foo", it calls "foo" inside a loop.
67define 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
79
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, [[ID]]
86; CHECK-O0: jne
87entry:
88  %error_ptr_ref = alloca swifterror %swift_error*
89  br label %bb_loop
90bb_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
97cont:
98  %cmp = fcmp ogt float %call, 1.000000e+00
99  br i1 %cmp, label %bb_end, label %bb_loop
100bb_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
105handler:
106  call void @free(i8* %tmp)
107  ret float 1.0
108}
109
110; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
111; under a certain condition.
112define 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
122
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), %r12
136; CHECK-O0: ret
137entry:
138  %cond = icmp ne i32 %cc, 0
139  br i1 %cond, label %gen_error, label %normal
140
141gen_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
148
149normal:
150  ret float 0.0
151}
152
153; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
154; under a certain condition inside a loop.
155define 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
167
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-z]+]]
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
181entry:
182  br label %bb_loop
183
184bb_loop:
185  %cond = icmp ne i32 %cc, 0
186  br i1 %cond, label %gen_error, label %bb_cont
187
188gen_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
195
196bb_cont:
197  %cmp = fcmp ogt float %cc2, 1.000000e+00
198  br i1 %cmp, label %bb_end, label %bb_loop
199bb_end:
200  ret float 0.0
201}
202
203%struct.S = type { i32, i32, i32, i32, i32, i32 }
204
205; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
206; parameter.
207define void @foo_sret(%struct.S* sret %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
217
218; CHECK-O0-LABEL: foo_sret:
219; CHECK-O0: movl $16,
220; spill sret to stack
221; CHECK-O0: movq %rdi,
222; CHECK-O0: movq {{.*}}, %rdi
223; CHECK-O0: malloc
224; CHECK-O0: movb $1, 8(%rax)
225; CHECK-O0: movl %{{.*}}, 4(%{{.*}})
226; CHECK-O0: movq %{{.*}}, %r12
227; reload sret from stack
228; CHECK-O0: movq {{.*}}(%rsp), %rax
229; CHECK-O0: ret
230entry:
231  %call = call i8* @malloc(i64 16)
232  %call.0 = bitcast i8* %call to %swift_error*
233  store %swift_error* %call.0, %swift_error** %error_ptr_ref
234  %tmp = getelementptr inbounds i8, i8* %call, i64 8
235  store i8 1, i8* %tmp
236  %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1
237  store i32 %val1, i32* %v2
238  ret void
239}
240
241; "caller3" calls "foo_sret" that takes a swifterror parameter.
242define float @caller3(i8* %error_ref) {
243; CHECK-APPLE-LABEL: caller3:
244; CHECK-APPLE: movl $1, %esi
245; CHECK-APPLE: xorl %r12d, %r12d
246; CHECK-APPLE: callq {{.*}}foo_sret
247; CHECK-APPLE: testq %r12, %r12
248; CHECK-APPLE: jne
249; Access part of the error object and save it to error_ref
250; CHECK-APPLE: movb 8(%r12),
251; CHECK-APPLE: movb %{{.*}},
252; CHECK-APPLE: movq %r12, %rdi
253; CHECK_APPLE: callq {{.*}}free
254
255; CHECK-O0-LABEL: caller3:
256; CHECK-O0: xorl
257; CHECK-O0: movl {{.*}}, %r12d
258; CHECK-O0: movl $1, %esi
259; CHECK-O0: movq {{.*}}, %rdi
260; CHECK-O0: callq {{.*}}foo_sret
261; CHECK-O0: movq %r12,
262; CHECK-O0: cmpq $0
263; CHECK-O0: jne
264; Access part of the error object and save it to error_ref
265; CHECK-O0: movb 8(%{{.*}}),
266; CHECK-O0: movb %{{.*}},
267; reload from stack
268; CHECK-O0: movq {{.*}}(%rsp), %rdi
269; CHECK-O0: callq {{.*}}free
270entry:
271  %s = alloca %struct.S, align 8
272  %error_ptr_ref = alloca swifterror %swift_error*
273  store %swift_error* null, %swift_error** %error_ptr_ref
274  call void @foo_sret(%struct.S* sret %s, i32 1, %swift_error** swifterror %error_ptr_ref)
275  %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
276  %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
277  %tmp = bitcast %swift_error* %error_from_foo to i8*
278  br i1 %had_error_from_foo, label %handler, label %cont
279cont:
280  %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
281  %t = load i8, i8* %v1
282  store i8 %t, i8* %error_ref
283  br label %handler
284handler:
285  call void @free(i8* %tmp)
286  ret float 1.0
287}
288
289; This is a caller with multiple swifterror values, it calls "foo" twice, each
290; time with a different swifterror value, from "alloca swifterror".
291define float @caller_with_multiple_swifterror_values(i8* %error_ref, i8* %error_ref2) {
292; CHECK-APPLE-LABEL: caller_with_multiple_swifterror_values:
293
294; The first swifterror value:
295; CHECK-APPLE: xorl %r12d, %r12d
296; CHECK-APPLE: callq {{.*}}foo
297; CHECK-APPLE: testq %r12, %r12
298; CHECK-APPLE: jne
299; Access part of the error object and save it to error_ref
300; CHECK-APPLE: movb 8(%r12)
301; CHECK-APPLE: movq %r12, %rdi
302; CHECK_APPLE: callq {{.*}}free
303
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(%r12)
311; CHECK-APPLE: movq %r12, %rdi
312; CHECK_APPLE: callq {{.*}}free
313
314; CHECK-O0-LABEL: caller_with_multiple_swifterror_values:
315
316; The first swifterror value:
317; CHECK-O0: xorl
318; CHECK-O0: movl %{{.*}}, %r12d
319; CHECK-O0: callq {{.*}}foo
320; CHECK-O0: jne
321
322; The second swifterror value:
323; CHECK-O0: xorl
324; CHECK-O0: movl %{{.*}}, %r12d
325; CHECK-O0: callq {{.*}}foo
326; CHECK-O0: jne
327entry:
328  %error_ptr_ref = alloca swifterror %swift_error*
329  store %swift_error* null, %swift_error** %error_ptr_ref
330  %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
331  %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
332  %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
333  %tmp = bitcast %swift_error* %error_from_foo to i8*
334  br i1 %had_error_from_foo, label %handler, label %cont
335cont:
336  %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
337  %t = load i8, i8* %v1
338  store i8 %t, i8* %error_ref
339  br label %handler
340handler:
341  call void @free(i8* %tmp)
342
343  %error_ptr_ref2 = alloca swifterror %swift_error*
344  store %swift_error* null, %swift_error** %error_ptr_ref2
345  %call2 = call float @foo(%swift_error** swifterror %error_ptr_ref2)
346  %error_from_foo2 = load %swift_error*, %swift_error** %error_ptr_ref2
347  %had_error_from_foo2 = icmp ne %swift_error* %error_from_foo2, null
348  %bitcast2 = bitcast %swift_error* %error_from_foo2 to i8*
349  br i1 %had_error_from_foo2, label %handler2, label %cont2
350cont2:
351  %v2 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo2, i64 0, i32 1
352  %t2 = load i8, i8* %v2
353  store i8 %t2, i8* %error_ref2
354  br label %handler2
355handler2:
356  call void @free(i8* %bitcast2)
357
358  ret float 1.0
359}
360