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 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-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]] 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-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 49entry: 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 57cont: 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 62handler: 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. 68define 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 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-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 135entry: 136 %cond = icmp ne i32 %cc, 0 137 br i1 %cond, label %gen_error, label %normal 138 139gen_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 147normal: 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. 153define 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 177entry: 178 br label %bb_loop 179 180bb_loop: 181 %cond = icmp ne i32 %cc, 0 182 br i1 %cond, label %gen_error, label %bb_cont 183 184gen_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 192bb_cont: 193 %cmp = fcmp ogt float %cc2, 1.000000e+00 194 br i1 %cmp, label %bb_end, label %bb_loop 195bb_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. 203define 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 229entry: 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. 241define 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 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-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 326entry: 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 334cont: 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 339handler: 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 349cont2: 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 354handler2: 355 call void @free(i8* %bitcast2) 356 357 ret float 1.0 358} 359