1 ; RUN: llc < %s -mtriple=s390x-linux-gnu -disable-block-placement | FileCheck %s
2 ; RUN: llc < %s -O0 -mtriple=s390x-linux-gnu -disable-block-placement | FileCheck --check-prefix=CHECK-O0 %s
4 declare ptr @malloc(i64)
5 declare void @free(ptr)
6 %swift_error = type {i64, i8}
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".
10 define float @foo(ptr swifterror %error_ptr_ref) {
13 ; CHECK: brasl %r14, malloc
14 ; CHECK: mvi 8(%r2), 1
16 ; CHECK-O0-LABEL: foo:
17 ; CHECK-O0: lghi %r2, 16
18 ; CHECK-O0: brasl %r14, malloc
19 ; CHECK-O0: lgr [[T0:%r[0-9]+]], %r2
20 ; CHECK-O0: mvi 8(%r2), 1
22 %call = call ptr @malloc(i64 16)
23 store ptr %call, ptr %error_ptr_ref
24 %tmp = getelementptr inbounds i8, ptr %call, i64 8
29 ; "caller" calls "foo" that takes a swifterror parameter.
30 define float @caller(ptr %error_ref) {
31 ; CHECK-LABEL: caller:
32 ; Make a copy of error_ref because r2 is getting clobbered
33 ; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2
34 ; CHECK-DAG: lghi %r9, 0
35 ; CHECK: brasl %r14, foo
38 ; Access part of the error object and save it to error_ref
39 ; CHECK: lb %r[[REG2:[0-9]+]], 8(%r2)
40 ; CHECK: stc %r[[REG2]], 0(%r[[REG1]])
41 ; CHECK: brasl %r14, free
42 ; CHECK-O0-LABEL: caller:
43 ; CHECK-O0: lghi %r9, 0
44 ; CHECK-O0: brasl %r14, foo
45 ; CHECK-O0: cghi %r9, 0
48 %error_ptr_ref = alloca swifterror ptr
49 store ptr null, ptr %error_ptr_ref
50 %call = call float @foo(ptr swifterror %error_ptr_ref)
51 %error_from_foo = load ptr, ptr %error_ptr_ref
52 %had_error_from_foo = icmp ne ptr %error_from_foo, null
53 br i1 %had_error_from_foo, label %handler, label %cont
55 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
57 store i8 %t, ptr %error_ref
60 call void @free(ptr %error_from_foo)
64 ; "caller2" is the caller of "foo", it calls "foo" inside a loop.
65 define float @caller2(ptr %error_ref) {
66 ; CHECK-LABEL: caller2:
67 ; Make a copy of error_ref because r2 is getting clobbered
68 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2
70 ; CHECK: brasl %r14, foo
71 ; CHECK: cgijlh %r9, 0,
74 ; Access part of the error object and save it to error_ref
75 ; CHECK: lb %r[[REG2:[0-9]+]], 8(%r9)
76 ; CHECK: stc %r[[REG2]], 0(%r[[REG1]])
78 ; CHECK: brasl %r14, free
79 ; CHECK-O0-LABEL: caller2:
80 ; CHECK-O0: lghi %r9, 0
81 ; CHECK-O0: brasl %r14, foo
82 ; CHECK-O0: cghi %r9, 0
85 %error_ptr_ref = alloca swifterror ptr
88 store ptr null, ptr %error_ptr_ref
89 %call = call float @foo(ptr swifterror %error_ptr_ref)
90 %error_from_foo = load ptr, ptr %error_ptr_ref
91 %had_error_from_foo = icmp ne ptr %error_from_foo, null
92 br i1 %had_error_from_foo, label %handler, label %cont
94 %cmp = fcmp ogt float %call, 1.000000e+00
95 br i1 %cmp, label %bb_end, label %bb_loop
97 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
99 store i8 %t, ptr %error_ref
102 call void @free(ptr %error_from_foo)
106 ; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
107 ; under a certain condition.
108 define float @foo_if(ptr swifterror %error_ptr_ref, i32 %cc) {
109 ; CHECK-LABEL: foo_if:
111 ; CHECK: lghi %r2, 16
112 ; CHECK: brasl %r14, malloc
113 ; CHECK: mvi 8(%r2), 1
114 ; CHECK: lgr %r9, %r2
117 ; CHECK-O0-LABEL: foo_if:
119 ; CHECK-O0: stg %r9, [[OFFS:[0-9]+]](%r15)
120 ; CHECK-O0: chi %r2, 0
122 ; CHECK-O0: lghi %r2, 16
123 ; CHECK-O0: brasl %r14, malloc
124 ; CHECK-O0: lgr %r9, %r2
125 ; CHECK-O0: mvi 8(%r2), 1
128 ; CHECK-O0: lg %r9, [[OFFS]](%r15)
131 %cond = icmp ne i32 %cc, 0
132 br i1 %cond, label %gen_error, label %normal
135 %call = call ptr @malloc(i64 16)
136 store ptr %call, ptr %error_ptr_ref
137 %tmp = getelementptr inbounds i8, ptr %call, i64 8
145 ; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
146 ; under a certain condition inside a loop.
147 define float @foo_loop(ptr swifterror %error_ptr_ref, i32 %cc, float %cc2) {
148 ; CHECK-LABEL: foo_loop:
149 ; CHECK: lr %r[[REG1:[0-9]+]], %r2
150 ; CHECK: cije %r[[REG1]], 0
151 ; CHECK: lghi %r2, 16
152 ; CHECK: brasl %r14, malloc
153 ; CHECK: mvi 8(%r2), 1
156 ; CHECK: lgr %r9, %r2
158 ; CHECK-O0-LABEL: foo_loop:
160 ; CHECK-O0: stg %r9, [[OFFS:[0-9]+]](%r15)
161 ; CHECK-O0: chi %r{{.*}}, 0
163 ; CHECK-O0: lghi %r2, 16
164 ; CHECK-O0: brasl %r14, malloc
165 ; CHECK-O0: lgr %r[[REG1:[0-9]+]], %r2
166 ; CHECK-O0: mvi 8(%r[[REG1]]), 1
169 ; CHECK-O0: lg %r9, [[OFFS:[0-9]+]](%r15)
175 %cond = icmp ne i32 %cc, 0
176 br i1 %cond, label %gen_error, label %bb_cont
179 %call = call ptr @malloc(i64 16)
180 store ptr %call, ptr %error_ptr_ref
181 %tmp = getelementptr inbounds i8, ptr %call, i64 8
186 %cmp = fcmp ogt float %cc2, 1.000000e+00
187 br i1 %cmp, label %bb_end, label %bb_loop
192 %struct.S = type { i32, i32, i32, i32, i32, i32 }
194 ; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
196 define void @foo_sret(ptr sret(%struct.S) %agg.result, i32 %val1, ptr swifterror %error_ptr_ref) {
197 ; CHECK-LABEL: foo_sret:
198 ; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2
199 ; CHECK-DAG: lr %r[[REG2:[0-9]+]], %r3
200 ; CHECK-DAG: lghi %r2, 16
201 ; CHECK: brasl %r14, malloc
202 ; CHECK: mvi 8(%r2), 1
203 ; CHECK: st %r[[REG2]], 4(%r[[REG1]])
204 ; CHECK: lgr %r9, %r2
208 ; CHECK-O0-LABEL: foo_sret:
209 ; spill sret to stack
210 ; CHECK-O0-DAG: stg %r2, [[OFFS1:[0-9]+]](%r15)
211 ; CHECK-O0-DAG: st %r3, [[OFFS2:[0-9]+]](%r15)
212 ; CHECK-O0: lghi %r2, 16
213 ; CHECK-O0: brasl %r14, malloc
214 ; CHECK-O0-DAG: lgr %r[[REG3:[0-9]+]], %r2
215 ; CHECK-O0-DAG: mvi 8(%r[[REG3]]), 1
216 ; CHECK-O0-DAG: lg %r[[REG1:[0-9]+]], [[OFFS1]](%r15)
217 ; CHECK-O0-DAG: lgr %r9, %r[[REG3]]
218 ; CHECK-O0-DAG: l %r[[REG2:[0-9]+]], [[OFFS2]](%r15)
219 ; CHECK-O0: st %r[[REG2]], 4(%r[[REG1]])
222 %call = call ptr @malloc(i64 16)
223 store ptr %call, ptr %error_ptr_ref
224 %tmp = getelementptr inbounds i8, ptr %call, i64 8
226 %v2 = getelementptr inbounds %struct.S, ptr %agg.result, i32 0, i32 1
227 store i32 %val1, ptr %v2
231 ; "caller3" calls "foo_sret" that takes a swifterror parameter.
232 define float @caller3(ptr %error_ref) {
233 ; CHECK-LABEL: caller3:
234 ; Make a copy of error_ref because r2 is getting clobbered
235 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2
238 ; CHECK: brasl %r14, foo_sret
240 ; Access part of the error object and save it to error_ref
241 ; CHECK: lb %r0, 8(%r2)
242 ; CHECK: stc %r0, 0(%r[[REG1]])
243 ; CHECK: brasl %r14, free
245 ; CHECK-O0-LABEL: caller3:
246 ; CHECK-O0: lghi %r9, 0
247 ; CHECK-O0: lhi %r3, 1
248 ; CHECK-O0: brasl %r14, foo_sret
249 ; CHECK-O0: lgr {{.*}}, %r9
250 ; CHECK-O0: cghi %r9, 0
252 ; Access part of the error object and save it to error_ref
253 ; CHECK-O0: lb %r0, 8(%r{{.*}})
254 ; CHECK-O0: stc %r0, 0(%r{{.*}})
256 ; CHECK-O0: lg %r2, {{.*}}(%r15)
257 ; CHECK-O0: brasl %r14, free
259 %s = alloca %struct.S, align 8
260 %error_ptr_ref = alloca swifterror ptr
261 store ptr null, ptr %error_ptr_ref
262 call void @foo_sret(ptr sret(%struct.S) %s, i32 1, ptr swifterror %error_ptr_ref)
263 %error_from_foo = load ptr, ptr %error_ptr_ref
264 %had_error_from_foo = icmp ne ptr %error_from_foo, null
265 br i1 %had_error_from_foo, label %handler, label %cont
267 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
268 %t = load i8, ptr %v1
269 store i8 %t, ptr %error_ref
272 call void @free(ptr %error_from_foo)
276 ; This is a caller with multiple swifterror values, it calls "foo" twice, each
277 ; time with a different swifterror value, from "alloca swifterror".
278 define float @caller_with_multiple_swifterror_values(ptr %error_ref, ptr %error_ref2) {
279 ; CHECK-LABEL: caller_with_multiple_swifterror_values:
280 ; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2
281 ; CHECK-DAG: lgr %r[[REG2:[0-9]+]], %r3
282 ; The first swifterror value:
283 ; CHECK-DAG: lghi %r9, 0
284 ; CHECK: brasl %r14, foo
285 ; CHECK: ltgr %r2, %r9
287 ; Access part of the error object and save it to error_ref
288 ; CHECK: lb %r0, 8(%r2)
289 ; CHECK: stc %r0, 0(%r[[REG1]])
290 ; CHECK: brasl %r14, free
292 ; The second swifterror value:
294 ; CHECK: brasl %r14, foo
295 ; CHECK: ltgr %r2, %r9
297 ; Access part of the error object and save it to error_ref
298 ; CHECK: lb %r0, 8(%r2)
299 ; CHECK: stc %r0, 0(%r[[REG2]])
300 ; CHECK: brasl %r14, free
302 ; CHECK-O0-LABEL: caller_with_multiple_swifterror_values:
304 ; The first swifterror value:
305 ; CHECK-O0: lghi %r9, 0
306 ; CHECK-O0: brasl %r14, foo
309 ; The second swifterror value:
310 ; CHECK-O0: lghi %r9, 0
311 ; CHECK-O0: brasl %r14, foo
314 %error_ptr_ref = alloca swifterror ptr
315 store ptr null, ptr %error_ptr_ref
316 %call = call float @foo(ptr swifterror %error_ptr_ref)
317 %error_from_foo = load ptr, ptr %error_ptr_ref
318 %had_error_from_foo = icmp ne ptr %error_from_foo, null
319 br i1 %had_error_from_foo, label %handler, label %cont
321 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
322 %t = load i8, ptr %v1
323 store i8 %t, ptr %error_ref
326 call void @free(ptr %error_from_foo)
328 %error_ptr_ref2 = alloca swifterror ptr
329 store ptr null, ptr %error_ptr_ref2
330 %call2 = call float @foo(ptr swifterror %error_ptr_ref2)
331 %error_from_foo2 = load ptr, ptr %error_ptr_ref2
332 %had_error_from_foo2 = icmp ne ptr %error_from_foo2, null
333 br i1 %had_error_from_foo2, label %handler2, label %cont2
335 %v2 = getelementptr inbounds %swift_error, ptr %error_from_foo2, i64 0, i32 1
336 %t2 = load i8, ptr %v2
337 store i8 %t2, ptr %error_ref2
340 call void @free(ptr %error_from_foo2)