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 %r9, %r2 20; CHECK-O0: mvi 8(%r2), 1 21entry: 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. 31define 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: cgijlh %r9, 0, 38; Access part of the error object and save it to error_ref 39; CHECK: lb %r[[REG2:[0-9]+]], 8(%r9) 40; CHECK: stc %r[[REG2]], 0(%r[[REG1]]) 41; CHECK: lgr %r2, %r9 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 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-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 86entry: 87 %error_ptr_ref = alloca swifterror %swift_error* 88 br label %bb_loop 89bb_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 96cont: 97 %cmp = fcmp ogt float %call, 1.000000e+00 98 br i1 %cmp, label %bb_end, label %bb_loop 99bb_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 104handler: 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. 111define 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 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 %r[[REG2:[0-9]+]], [[OFFS:[0-9]+]](%r15) 176; CHECK-O0: lgr %r9, %r[[REG2]] 177; CHECK-O0: br %r14 178entry: 179 br label %bb_loop 180 181bb_loop: 182 %cond = icmp ne i32 %cc, 0 183 br i1 %cond, label %gen_error, label %bb_cont 184 185gen_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 193bb_cont: 194 %cmp = fcmp ogt float %cc2, 1.000000e+00 195 br i1 %cmp, label %bb_end, label %bb_loop 196bb_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. 204define 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 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-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: cgijlh %r9, 0, 250; Access part of the error object and save it to error_ref 251; CHECK: lb %r0, 8(%r9) 252; CHECK: stc %r0, 0(%r[[REG1]]) 253; CHECK: lgr %r2, %r9 254; CHECK: brasl %r14, free 255 256; CHECK-O0-LABEL: caller3: 257; CHECK-O0: lghi %r9, 0 258; CHECK-O0: lhi %r3, 1 259; CHECK-O0: stg %r2, {{.*}}(%r15) 260; CHECK-O0: lgr %r2, {{.*}} 261; CHECK-O0: brasl %r14, foo_sret 262; CHECK-O0: lgr {{.*}}, %r9 263; CHECK-O0: cghi %r9, 0 264; CHECK-O0: jlh 265; Access part of the error object and save it to error_ref 266; CHECK-O0: lb %r0, 8(%r{{.*}}) 267; CHECK-O0: stc %r0, 0(%r{{.*}}) 268; reload from stack 269; CHECK-O0: lg %r2, {{.*}}(%r15) 270; CHECK-O0: brasl %r14, free 271entry: 272 %s = alloca %struct.S, align 8 273 %error_ptr_ref = alloca swifterror %swift_error* 274 store %swift_error* null, %swift_error** %error_ptr_ref 275 call void @foo_sret(%struct.S* sret %s, i32 1, %swift_error** swifterror %error_ptr_ref) 276 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref 277 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null 278 %tmp = bitcast %swift_error* %error_from_foo to i8* 279 br i1 %had_error_from_foo, label %handler, label %cont 280cont: 281 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 282 %t = load i8, i8* %v1 283 store i8 %t, i8* %error_ref 284 br label %handler 285handler: 286 call void @free(i8* %tmp) 287 ret float 1.0 288} 289 290; This is a caller with multiple swifterror values, it calls "foo" twice, each 291; time with a different swifterror value, from "alloca swifterror". 292define float @caller_with_multiple_swifterror_values(i8* %error_ref, i8* %error_ref2) { 293; CHECK-LABEL: caller_with_multiple_swifterror_values: 294; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2 295; CHECK-DAG: lgr %r[[REG2:[0-9]+]], %r3 296; The first swifterror value: 297; CHECK: lghi %r9, 0 298; CHECK: brasl %r14, foo 299; CHECK: cgijlh %r9, 0, 300; Access part of the error object and save it to error_ref 301; CHECK: lb %r0, 8(%r9) 302; CHECK: stc %r0, 0(%r[[REG1]]) 303; CHECK: lgr %r2, %r9 304; CHECK: brasl %r14, free 305 306; The second swifterror value: 307; CHECK: lghi %r9, 0 308; CHECK: brasl %r14, foo 309; CHECK: cgijlh %r9, 0, 310; Access part of the error object and save it to error_ref 311; CHECK: lb %r0, 8(%r9) 312; CHECK: stc %r0, 0(%r[[REG2]]) 313; CHECK: lgr %r2, %r9 314; CHECK: brasl %r14, free 315 316; CHECK-O0-LABEL: caller_with_multiple_swifterror_values: 317 318; The first swifterror value: 319; CHECK-O0: lghi %r9, 0 320; CHECK-O0: brasl %r14, foo 321; CHECK-O0: jlh 322 323; The second swifterror value: 324; CHECK-O0: lghi %r9, 0 325; CHECK-O0: brasl %r14, foo 326; CHECK-O0: jlh 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