1 ; RUN: llc < %s -mtriple=s390x-linux-gnu| FileCheck %s 2 ; RUN: llc < %s -O0 -mtriple=s390x-linux-gnu | FileCheck --check-prefix=CHECK-O0 %s 3 4 declare i8* @malloc(i64) 5 declare 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". 10 define float @foo(%swift_error** swifterror %error_ptr_ref) { 11 ; CHECK-LABEL: foo: 12 ; CHECK: lghi %r2, 16 13 ; CHECK: brasl %r14, malloc 14 ; CHECK: mvi 8(%r2), 1 15 ; CHECK: lgr %r9, %r2 16 ; CHECK-O0-LABEL: foo: 17 ; CHECK-O0: lghi %r2, 16 18 ; CHECK-O0: brasl %r14, malloc 19 ; CHECK-O0: lgr %r9, %r2 20 ; CHECK-O0: mvi 8(%r2), 1 21 entry: 22 %call = call i8* @malloc(i64 16) 23 %call.0 = bitcast i8* %call to %swift_error* 24 store %swift_error* %call.0, %swift_error** %error_ptr_ref 25 %tmp = getelementptr inbounds i8, i8* %call, i64 8 26 store i8 1, i8* %tmp 27 ret float 1.0 28 } 29 30 ; "caller" calls "foo" that takes a swifterror parameter. 31 define float @caller(i8* %error_ref) { 32 ; CHECK-LABEL: caller: 33 ; Make a copy of error_ref because r2 is getting clobbered 34 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2 35 ; CHECK: lghi %r9, 0 36 ; CHECK: brasl %r14, foo 37 ; CHECK: %r2, %r9 38 ; CHECK: jlh 39 ; Access part of the error object and save it to error_ref 40 ; CHECK: lb %r[[REG2:[0-9]+]], 8(%r2) 41 ; CHECK: stc %r[[REG2]], 0(%r[[REG1]]) 42 ; CHECK: brasl %r14, free 43 ; CHECK-O0-LABEL: caller: 44 ; CHECK-O0: lghi %r9, 0 45 ; CHECK-O0: brasl %r14, foo 46 ; CHECK-O0: cghi %r9, 0 47 ; CHECK-O0: jlh 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 64 } 65 66 ; "caller2" is the caller of "foo", it calls "foo" inside a loop. 67 define float @caller2(i8* %error_ref) { 68 ; CHECK-LABEL: caller2: 69 ; Make a copy of error_ref because r2 is getting clobbered 70 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2 71 ; CHECK: lghi %r9, 0 72 ; CHECK: brasl %r14, foo 73 ; CHECK: cgijlh %r9, 0, 74 ; CHECK: ceb %f0, 75 ; CHECK: jnh 76 ; Access part of the error object and save it to error_ref 77 ; CHECK: lb %r[[REG2:[0-9]+]], 8(%r9) 78 ; CHECK: stc %r[[REG2]], 0(%r[[REG1]]) 79 ; CHECK: lgr %r2, %r9 80 ; CHECK: brasl %r14, free 81 ; CHECK-O0-LABEL: caller2: 82 ; CHECK-O0: lghi %r9, 0 83 ; CHECK-O0: brasl %r14, foo 84 ; CHECK-O0: cghi %r9, 0 85 ; CHECK-O0: jlh 86 entry: 87 %error_ptr_ref = alloca swifterror %swift_error* 88 br label %bb_loop 89 bb_loop: 90 store %swift_error* null, %swift_error** %error_ptr_ref 91 %call = call float @foo(%swift_error** swifterror %error_ptr_ref) 92 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref 93 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null 94 %tmp = bitcast %swift_error* %error_from_foo to i8* 95 br i1 %had_error_from_foo, label %handler, label %cont 96 cont: 97 %cmp = fcmp ogt float %call, 1.000000e+00 98 br i1 %cmp, label %bb_end, label %bb_loop 99 bb_end: 100 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 101 %t = load i8, i8* %v1 102 store i8 %t, i8* %error_ref 103 br label %handler 104 handler: 105 call void @free(i8* %tmp) 106 ret float 1.0 107 } 108 109 ; "foo_if" is a function that takes a swifterror parameter, it sets swifterror 110 ; under a certain condition. 111 define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) { 112 ; CHECK-LABEL: foo_if: 113 ; CHECK: cije %r2, 0 114 ; CHECK: lghi %r2, 16 115 ; CHECK: brasl %r14, malloc 116 ; CHECK: mvi 8(%r2), 1 117 ; CHECK: lgr %r9, %r2 118 ; CHECK-NOT: %r9 119 ; CHECK: br %r14 120 ; CHECK-O0-LABEL: foo_if: 121 ; CHECK-O0: chi %r2, 0 122 ; spill to stack 123 ; CHECK-O0: stg %r9, [[OFFS:[0-9]+]](%r15) 124 ; CHECK-O0: je 125 ; CHECK-O0: lghi %r2, 16 126 ; CHECK-O0: brasl %r14, malloc 127 ; CHECK-O0: lgr %r[[REG1:[0-9]+]], %r2 128 ; CHECK-O0: mvi 8(%r2), 1 129 ; CHECK-O0: lgr %r9, %r[[REG1]] 130 ; CHECK-O0: br %r14 131 ; reload from stack 132 ; CHECK-O0: lg %r[[REG2:[0-9]+]], [[OFFS]](%r15) 133 ; CHECK-O0: lgr %r9, %r[[REG2]] 134 ; CHECK-O0: br %r14 135 entry: 136 %cond = icmp ne i32 %cc, 0 137 br i1 %cond, label %gen_error, label %normal 138 139 gen_error: 140 %call = call i8* @malloc(i64 16) 141 %call.0 = bitcast i8* %call to %swift_error* 142 store %swift_error* %call.0, %swift_error** %error_ptr_ref 143 %tmp = getelementptr inbounds i8, i8* %call, i64 8 144 store i8 1, i8* %tmp 145 ret float 1.0 146 147 normal: 148 ret float 0.0 149 } 150 151 ; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror 152 ; under a certain condition inside a loop. 153 define float @foo_loop(%swift_error** swifterror %error_ptr_ref, i32 %cc, float %cc2) { 154 ; CHECK-LABEL: foo_loop: 155 ; CHECK: lr %r[[REG1:[0-9]+]], %r2 156 ; CHECK: cije %r[[REG1]], 0 157 ; CHECK: lghi %r2, 16 158 ; CHECK: brasl %r14, malloc 159 ; CHECK: mvi 8(%r2), 1 160 ; CHECK: ceb %f8, 161 ; CHECK: jnh 162 ; CHECK: lgr %r9, %r2 163 ; CHECK: br %r14 164 ; CHECK-O0-LABEL: foo_loop: 165 ; spill to stack 166 ; CHECK-O0: stg %r9, [[OFFS:[0-9]+]](%r15) 167 ; CHECK-O0: chi %r{{.*}}, 0 168 ; CHECK-O0: je 169 ; CHECK-O0: lghi %r2, 16 170 ; CHECK-O0: brasl %r14, malloc 171 ; CHECK-O0: lgr %r[[REG1:[0-9]+]], %r2 172 ; CHECK-O0: mvi 8(%r2), 1 173 ; CHECK-O0: jnh 174 ; reload from stack 175 ; CHECK-O0: lg %r[[REG2:[0-9]+]], [[OFFS:[0-9]+]](%r15) 176 ; CHECK-O0: lgr %r9, %r[[REG2]] 177 ; CHECK-O0: br %r14 178 entry: 179 br label %bb_loop 180 181 bb_loop: 182 %cond = icmp ne i32 %cc, 0 183 br i1 %cond, label %gen_error, label %bb_cont 184 185 gen_error: 186 %call = call i8* @malloc(i64 16) 187 %call.0 = bitcast i8* %call to %swift_error* 188 store %swift_error* %call.0, %swift_error** %error_ptr_ref 189 %tmp = getelementptr inbounds i8, i8* %call, i64 8 190 store i8 1, i8* %tmp 191 br label %bb_cont 192 193 bb_cont: 194 %cmp = fcmp ogt float %cc2, 1.000000e+00 195 br i1 %cmp, label %bb_end, label %bb_loop 196 bb_end: 197 ret float 0.0 198 } 199 200 %struct.S = type { i32, i32, i32, i32, i32, i32 } 201 202 ; "foo_sret" is a function that takes a swifterror parameter, it also has a sret 203 ; parameter. 204 define void @foo_sret(%struct.S* sret %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) { 205 ; CHECK-LABEL: foo_sret: 206 ; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2 207 ; CHECK-DAG: lr %r[[REG2:[0-9]+]], %r3 208 ; CHECK: lghi %r2, 16 209 ; CHECK: brasl %r14, malloc 210 ; CHECK: mvi 8(%r2), 1 211 ; CHECK: st %r[[REG2]], 4(%r[[REG1]]) 212 ; CHECK: lgr %r9, %r2 213 ; CHECK-NOT: %r9 214 ; CHECK: br %r14 215 216 ; CHECK-O0-LABEL: foo_sret: 217 ; CHECK-O0: lghi %r{{.*}}, 16 218 ; spill sret to stack 219 ; CHECK-O0: stg %r2, [[OFFS1:[0-9]+]](%r15) 220 ; CHECK-O0: lgr %r2, %r{{.*}} 221 ; CHECK-O0: st %r3, [[OFFS2:[0-9]+]](%r15) 222 ; CHECK-O0: brasl %r14, malloc 223 ; CHECK-O0: lgr {{.*}}, %r2 224 ; CHECK-O0: mvi 8(%r2), 1 225 ; CHECK-O0-DAG: lg %r[[REG1:[0-9]+]], [[OFFS1]](%r15) 226 ; CHECK-O0-DAG: l %r[[REG2:[0-9]+]], [[OFFS2]](%r15) 227 ; CHECK-O0: st %r[[REG2]], 4(%r[[REG1]]) 228 ; CHECK-O0: lgr %r9, {{.*}} 229 ; CHECK-O0: br %r14 230 entry: 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. 242 define float @caller3(i8* %error_ref) { 243 ; CHECK-LABEL: caller3: 244 ; Make a copy of error_ref because r2 is getting clobbered 245 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2 246 ; CHECK: lhi %r3, 1 247 ; CHECK: lghi %r9, 0 248 ; CHECK: brasl %r14, foo_sret 249 ; CHECK: jlh 250 ; Access part of the error object and save it to error_ref 251 ; CHECK: lb %r0, 8(%r2) 252 ; CHECK: stc %r0, 0(%r[[REG1]]) 253 ; CHECK: brasl %r14, free 254 255 ; CHECK-O0-LABEL: caller3: 256 ; CHECK-O0: lghi %r9, 0 257 ; CHECK-O0: lhi %r3, 1 258 ; CHECK-O0: stg %r2, {{.*}}(%r15) 259 ; CHECK-O0: lgr %r2, {{.*}} 260 ; CHECK-O0: brasl %r14, foo_sret 261 ; CHECK-O0: lgr {{.*}}, %r9 262 ; CHECK-O0: cghi %r9, 0 263 ; CHECK-O0: jlh 264 ; Access part of the error object and save it to error_ref 265 ; CHECK-O0: lb %r0, 8(%r{{.*}}) 266 ; CHECK-O0: stc %r0, 0(%r{{.*}}) 267 ; reload from stack 268 ; CHECK-O0: lg %r2, {{.*}}(%r15) 269 ; CHECK-O0: brasl %r14, free 270 entry: 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 279 cont: 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 284 handler: 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". 291 define float @caller_with_multiple_swifterror_values(i8* %error_ref, i8* %error_ref2) { 292 ; CHECK-LABEL: caller_with_multiple_swifterror_values: 293 ; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2 294 ; CHECK-DAG: lgr %r[[REG2:[0-9]+]], %r3 295 ; The first swifterror value: 296 ; CHECK: lghi %r9, 0 297 ; CHECK: brasl %r14, foo 298 ; CHECK: ltgr %r2, %r9 299 ; CHECK: jlh 300 ; Access part of the error object and save it to error_ref 301 ; CHECK: lb %r0, 8(%r2) 302 ; CHECK: stc %r0, 0(%r[[REG1]]) 303 ; CHECK: brasl %r14, free 304 305 ; The second swifterror value: 306 ; CHECK: lghi %r9, 0 307 ; CHECK: brasl %r14, foo 308 ; CHECK: ltgr %r2, %r9 309 ; CHECK: jlh 310 ; Access part of the error object and save it to error_ref 311 ; CHECK: lb %r0, 8(%r2) 312 ; CHECK: stc %r0, 0(%r[[REG2]]) 313 ; CHECK: brasl %r14, free 314 315 ; CHECK-O0-LABEL: caller_with_multiple_swifterror_values: 316 317 ; The first swifterror value: 318 ; CHECK-O0: lghi %r9, 0 319 ; CHECK-O0: brasl %r14, foo 320 ; CHECK-O0: jlh 321 322 ; The second swifterror value: 323 ; CHECK-O0: lghi %r9, 0 324 ; CHECK-O0: brasl %r14, foo 325 ; CHECK-O0: jlh 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) 341 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) 356 357 ret float 1.0 358 } 359