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 %r[[REG1:[0-9]+]], %r2 20 ; CHECK-O0: mvi 8(%r2), 1 21 ; CHECK-O0: lgr %r9, %r[[REG1]] 22 entry: 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. 32 define float @caller(i8* %error_ref) { 33 ; CHECK-LABEL: caller: 34 ; Make a copy of error_ref because r2 is getting clobbered 35 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2 36 ; CHECK: lghi %r9, 0 37 ; CHECK: brasl %r14, foo 38 ; CHECK: cgijlh %r9, 0, 39 ; Access part of the error object and save it to error_ref 40 ; CHECK: lb %r[[REG2:[0-9]+]], 8(%r9) 41 ; CHECK: stc %r[[REG2]], 0(%r[[REG1]]) 42 ; CHECK: lgr %r2, %r9 43 ; CHECK: brasl %r14, free 44 ; CHECK-O0-LABEL: caller: 45 ; CHECK-O0: lghi %r9, 0 46 ; CHECK-O0: brasl %r14, foo 47 ; CHECK-O0: cghi %r9, 0 48 ; CHECK-O0: jlh 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 65 } 66 67 ; "caller2" is the caller of "foo", it calls "foo" inside a loop. 68 define float @caller2(i8* %error_ref) { 69 ; CHECK-LABEL: caller2: 70 ; Make a copy of error_ref because r2 is getting clobbered 71 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2 72 ; CHECK: lghi %r9, 0 73 ; CHECK: brasl %r14, foo 74 ; CHECK: cgijlh %r9, 0, 75 ; CHECK: ceb %f0, 76 ; CHECK: jnh 77 ; Access part of the error object and save it to error_ref 78 ; CHECK: lb %r[[REG2:[0-9]+]], 8(%r9) 79 ; CHECK: stc %r[[REG2]], 0(%r[[REG1]]) 80 ; CHECK: lgr %r2, %r9 81 ; CHECK: brasl %r14, free 82 ; CHECK-O0-LABEL: caller2: 83 ; CHECK-O0: lghi %r9, 0 84 ; CHECK-O0: brasl %r14, foo 85 ; CHECK-O0: cghi %r9, 0 86 ; CHECK-O0: jlh 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 108 } 109 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-LABEL: foo_if: 114 ; CHECK: cije %r2, 0 115 ; CHECK: lghi %r2, 16 116 ; CHECK: brasl %r14, malloc 117 ; CHECK: mvi 8(%r2), 1 118 ; CHECK: lgr %r9, %r2 119 ; CHECK-NOT: %r9 120 ; CHECK: br %r14 121 ; CHECK-O0-LABEL: foo_if: 122 ; CHECK-O0: chi %r2, 0 123 ; spill to stack 124 ; CHECK-O0: stg %r9, [[OFFS:[0-9]+]](%r15) 125 ; CHECK-O0: je 126 ; CHECK-O0: lghi %r2, 16 127 ; CHECK-O0: brasl %r14, malloc 128 ; CHECK-O0: lgr %r[[REG1:[0-9]+]], %r2 129 ; CHECK-O0: mvi 8(%r2), 1 130 ; CHECK-O0: lgr %r9, %r[[REG1]] 131 ; CHECK-O0: br %r14 132 ; reload from stack 133 ; CHECK-O0: lg %r9, [[OFFS]](%r15) 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 %r9, [[OFFS:[0-9]+]](%r15) 176 ; CHECK-O0: br %r14 177 entry: 178 br label %bb_loop 179 180 bb_loop: 181 %cond = icmp ne i32 %cc, 0 182 br i1 %cond, label %gen_error, label %bb_cont 183 184 gen_error: 185 %call = call i8* @malloc(i64 16) 186 %call.0 = bitcast i8* %call to %swift_error* 187 store %swift_error* %call.0, %swift_error** %error_ptr_ref 188 %tmp = getelementptr inbounds i8, i8* %call, i64 8 189 store i8 1, i8* %tmp 190 br label %bb_cont 191 192 bb_cont: 193 %cmp = fcmp ogt float %cc2, 1.000000e+00 194 br i1 %cmp, label %bb_end, label %bb_loop 195 bb_end: 196 ret float 0.0 197 } 198 199 %struct.S = type { i32, i32, i32, i32, i32, i32 } 200 201 ; "foo_sret" is a function that takes a swifterror parameter, it also has a sret 202 ; parameter. 203 define void @foo_sret(%struct.S* sret %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) { 204 ; CHECK-LABEL: foo_sret: 205 ; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2 206 ; CHECK-DAG: lr %r[[REG2:[0-9]+]], %r3 207 ; CHECK: lghi %r2, 16 208 ; CHECK: brasl %r14, malloc 209 ; CHECK: mvi 8(%r2), 1 210 ; CHECK: st %r[[REG2]], 4(%r[[REG1]]) 211 ; CHECK: lgr %r9, %r2 212 ; CHECK-NOT: %r9 213 ; CHECK: br %r14 214 215 ; CHECK-O0-LABEL: foo_sret: 216 ; CHECK-O0: lghi %r{{.*}}, 16 217 ; spill sret to stack 218 ; CHECK-O0: stg %r2, [[OFFS1:[0-9]+]](%r15) 219 ; CHECK-O0: lgr %r2, %r{{.*}} 220 ; CHECK-O0: st %r3, [[OFFS2:[0-9]+]](%r15) 221 ; CHECK-O0: brasl %r14, malloc 222 ; CHECK-O0: lgr {{.*}}, %r2 223 ; CHECK-O0: mvi 8(%r2), 1 224 ; CHECK-O0-DAG: lg %r[[REG1:[0-9]+]], [[OFFS1]](%r15) 225 ; CHECK-O0-DAG: l %r[[REG2:[0-9]+]], [[OFFS2]](%r15) 226 ; CHECK-O0: st %r[[REG2]], 4(%r[[REG1]]) 227 ; CHECK-O0: lgr %r9, {{.*}} 228 ; CHECK-O0: br %r14 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 238 } 239 240 ; "caller3" calls "foo_sret" that takes a swifterror parameter. 241 define float @caller3(i8* %error_ref) { 242 ; CHECK-LABEL: caller3: 243 ; Make a copy of error_ref because r2 is getting clobbered 244 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2 245 ; CHECK: lhi %r3, 1 246 ; CHECK: lghi %r9, 0 247 ; CHECK: brasl %r14, foo_sret 248 ; CHECK: cgijlh %r9, 0, 249 ; Access part of the error object and save it to error_ref 250 ; CHECK: lb %r0, 8(%r9) 251 ; CHECK: stc %r0, 0(%r[[REG1]]) 252 ; CHECK: lgr %r2, %r9 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: cgijlh %r9, 0, 299 ; Access part of the error object and save it to error_ref 300 ; CHECK: lb %r0, 8(%r9) 301 ; CHECK: stc %r0, 0(%r[[REG1]]) 302 ; CHECK: lgr %r2, %r9 303 ; CHECK: brasl %r14, free 304 305 ; The second swifterror value: 306 ; CHECK: lghi %r9, 0 307 ; CHECK: brasl %r14, foo 308 ; CHECK: cgijlh %r9, 0, 309 ; Access part of the error object and save it to error_ref 310 ; CHECK: lb %r0, 8(%r9) 311 ; CHECK: stc %r0, 0(%r[[REG2]]) 312 ; CHECK: lgr %r2, %r9 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