1; RUN: llc -verify-machineinstrs -frame-pointer=all -global-isel < %s -mtriple=aarch64-apple-ios | FileCheck %s 2 3declare ptr @malloc(i64) 4declare void @free(ptr) 5%swift_error = type {i64, i8} 6 7; This tests the basic usage of a swifterror parameter. "foo" is the function 8; that takes a swifterror parameter and "caller" is the caller of "foo". 9define float @foo(ptr swifterror %error_ptr_ref) { 10; CHECK-LABEL: foo: 11; CHECK: mov w0, #16 12; CHECK: malloc 13; CHECK: mov [[ID:w[0-9]+]], #1 14; CHECK: mov x21, x0 15; CHECK: strb [[ID]], [x0, #8] 16; CHECK-NOT: x21 17 18entry: 19 %call = call ptr @malloc(i64 16) 20 store ptr %call, ptr %error_ptr_ref 21 %tmp = getelementptr inbounds i8, ptr %call, i64 8 22 store i8 1, ptr %tmp 23 ret float 1.0 24} 25 26; "caller" calls "foo" that takes a swifterror parameter. 27define float @caller(ptr %error_ref) { 28; CHECK-LABEL: caller: 29; CHECK: mov [[ID:x[0-9]+]], x0 30; CHECK: bl {{.*}}foo 31; CHECK: mov x0, x21 32; CHECK: cbnz x21 33; Access part of the error object and save it to error_ref 34; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8] 35; CHECK: strb [[CODE]], [{{.*}}[[ID]]] 36; CHECK: bl {{.*}}free 37 38entry: 39 %error_ptr_ref = alloca swifterror ptr 40 store ptr null, ptr %error_ptr_ref 41 %call = call float @foo(ptr swifterror %error_ptr_ref) 42 %error_from_foo = load ptr, ptr %error_ptr_ref 43 %had_error_from_foo = icmp ne ptr %error_from_foo, null 44 br i1 %had_error_from_foo, label %handler, label %cont 45cont: 46 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1 47 %t = load i8, ptr %v1 48 store i8 %t, ptr %error_ref 49 br label %handler 50handler: 51 call void @free(ptr %error_from_foo) 52 ret float 1.0 53} 54 55; "caller2" is the caller of "foo", it calls "foo" inside a loop. 56define float @caller2(ptr %error_ref) { 57; CHECK-LABEL: caller2: 58; CHECK: fmov [[CMP:s[0-9]+]], #1.0 59; CHECK: mov [[ID:x[0-9]+]], x0 60; CHECK: mov x21, xzr 61; CHECK: bl {{.*}}foo 62; CHECK: cbnz x21 63; CHECK: fcmp s0, [[CMP]] 64; CHECK: b.le 65; Access part of the error object and save it to error_ref 66; CHECK: ldrb [[CODE:w[0-9]+]], [x21, #8] 67; CHECK: strb [[CODE]], [{{.*}}[[ID]]] 68; CHECK: mov x0, x21 69; CHECK: bl {{.*}}free 70 71entry: 72 %error_ptr_ref = alloca swifterror ptr 73 br label %bb_loop 74bb_loop: 75 store ptr null, ptr %error_ptr_ref 76 %call = call float @foo(ptr swifterror %error_ptr_ref) 77 %error_from_foo = load ptr, ptr %error_ptr_ref 78 %had_error_from_foo = icmp ne ptr %error_from_foo, null 79 br i1 %had_error_from_foo, label %handler, label %cont 80cont: 81 %cmp = fcmp ogt float %call, 1.000000e+00 82 br i1 %cmp, label %bb_end, label %bb_loop 83bb_end: 84 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1 85 %t = load i8, ptr %v1 86 store i8 %t, ptr %error_ref 87 br label %handler 88handler: 89 call void @free(ptr %error_from_foo) 90 ret float 1.0 91} 92 93; "foo_if" is a function that takes a swifterror parameter, it sets swifterror 94; under a certain condition. 95define float @foo_if(ptr swifterror %error_ptr_ref, i32 %cc) { 96; CHECK-LABEL: foo_if: 97; CHECK: cbz w0 98; CHECK: mov w0, #16 99; CHECK: malloc 100; CHECK-DAG: mov x21, x0 101; CHECK-DAG: mov [[ID:w[0-9]+]], #1 102; CHECK: strb [[ID]], [x0, #8] 103; CHECK-NOT: x21 104; CHECK: ret 105 106entry: 107 %cond = icmp ne i32 %cc, 0 108 br i1 %cond, label %gen_error, label %normal 109 110gen_error: 111 %call = call ptr @malloc(i64 16) 112 store ptr %call, ptr %error_ptr_ref 113 %tmp = getelementptr inbounds i8, ptr %call, i64 8 114 store i8 1, ptr %tmp 115 ret float 1.0 116 117normal: 118 ret float 0.0 119} 120 121; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror 122; under a certain condition inside a loop. 123define float @foo_loop(ptr swifterror %error_ptr_ref, i32 %cc, float %cc2) { 124; CHECK-LABEL: foo_loop: 125; CHECK: cbz 126; CHECK: mov w0, #16 127; CHECK: malloc 128; CHECK: mov x21, x0 129; CHECK: strb w{{.*}}, [x0, #8] 130; CHECK: ret 131 132entry: 133 br label %bb_loop 134 135bb_loop: 136 %cond = icmp ne i32 %cc, 0 137 br i1 %cond, label %gen_error, label %bb_cont 138 139gen_error: 140 %call = call ptr @malloc(i64 16) 141 store ptr %call, ptr %error_ptr_ref 142 %tmp = getelementptr inbounds i8, ptr %call, i64 8 143 store i8 1, ptr %tmp 144 br label %bb_cont 145 146bb_cont: 147 %cmp = fcmp ogt float %cc2, 1.000000e+00 148 br i1 %cmp, label %bb_end, label %bb_loop 149bb_end: 150 ret float 0.0 151} 152 153%struct.S = type { i32, i32, i32, i32, i32, i32 } 154 155; "foo_sret" is a function that takes a swifterror parameter, it also has a sret 156; parameter. 157define void @foo_sret(ptr sret(%struct.S) %agg.result, i32 %val1, ptr swifterror %error_ptr_ref) { 158; CHECK-LABEL: foo_sret: 159; CHECK-DAG: mov [[SRET:x[0-9]+]], x8 160; CHECK-DAG: mov w0, #16 161; CHECK: malloc 162; CHECK: mov [[ID:w[0-9]+]], #1 163; CHECK: strb [[ID]], [x0, #8] 164; CHECK: mov x21, x0 165; CHECK: str w{{.*}}, [{{.*}}[[SRET]], #4] 166; CHECK-NOT: x21 167 168entry: 169 %call = call ptr @malloc(i64 16) 170 store ptr %call, ptr %error_ptr_ref 171 %tmp = getelementptr inbounds i8, ptr %call, i64 8 172 store i8 1, ptr %tmp 173 %v2 = getelementptr inbounds %struct.S, ptr %agg.result, i32 0, i32 1 174 store i32 %val1, ptr %v2 175 ret void 176} 177 178; "caller3" calls "foo_sret" that takes a swifterror parameter. 179define float @caller3(ptr %error_ref) { 180; CHECK-LABEL: caller3: 181; CHECK: mov [[ID:x[0-9]+]], x0 182; CHECK: mov [[ZERO:x[0-9]+]], xzr 183; CHECK: bl {{.*}}foo_sret 184; CHECK: mov x0, x21 185; CHECK: cbnz x21 186; Access part of the error object and save it to error_ref 187; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8] 188; CHECK: strb [[CODE]], [{{.*}}[[ID]]] 189; CHECK: bl {{.*}}free 190 191entry: 192 %s = alloca %struct.S, align 8 193 %error_ptr_ref = alloca swifterror ptr 194 store ptr null, ptr %error_ptr_ref 195 call void @foo_sret(ptr sret(%struct.S) %s, i32 1, ptr swifterror %error_ptr_ref) 196 %error_from_foo = load ptr, ptr %error_ptr_ref 197 %had_error_from_foo = icmp ne ptr %error_from_foo, null 198 br i1 %had_error_from_foo, label %handler, label %cont 199cont: 200 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1 201 %t = load i8, ptr %v1 202 store i8 %t, ptr %error_ref 203 br label %handler 204handler: 205 call void @free(ptr %error_from_foo) 206 ret float 1.0 207} 208 209; "foo_vararg" is a function that takes a swifterror parameter, it also has 210; variable number of arguments. 211declare void @llvm.va_start(ptr) nounwind 212define float @foo_vararg(ptr swifterror %error_ptr_ref, ...) { 213; CHECK-LABEL: foo_vararg: 214; CHECK: mov w0, #16 215; CHECK: malloc 216; CHECK: mov [[ID:w[0-9]+]], #1 217; CHECK: strb [[ID]], [x0, #8] 218; CHECK: mov x21, x0 219; CHECK-NOT: x21 220 221; First vararg 222; CHECK: ldr {{w[0-9]+}}, [x[[ARG1:[0-9]+]]] 223; CHECK-NOT: x21 224; Second vararg 225; CHECK: ldr {{w[0-9]+}}, [x[[ARG1]]] 226; CHECK-NOT: x21 227; Third vararg 228; CHECK: ldr {{w[0-9]+}}, [x[[ARG1]]] 229; CHECK-NOT: x21 230entry: 231 %call = call ptr @malloc(i64 16) 232 store ptr %call, ptr %error_ptr_ref 233 %tmp = getelementptr inbounds i8, ptr %call, i64 8 234 store i8 1, ptr %tmp 235 236 %args = alloca ptr, align 8 237 %a10 = alloca i32, align 4 238 %a11 = alloca i32, align 4 239 %a12 = alloca i32, align 4 240 call void @llvm.va_start(ptr %args) 241 %v11 = va_arg ptr %args, i32 242 store i32 %v11, ptr %a10, align 4 243 %v12 = va_arg ptr %args, i32 244 store i32 %v12, ptr %a11, align 4 245 %v13 = va_arg ptr %args, i32 246 store i32 %v13, ptr %a12, align 4 247 248 ret float 1.0 249} 250 251; "caller4" calls "foo_vararg" that takes a swifterror parameter. 252define float @caller4(ptr %error_ref) { 253; CHECK-LABEL: caller4: 254 255; CHECK: mov x21, xzr 256; CHECK: mov [[ID:x[0-9]+]], x0 257; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp] 258; CHECK: str {{x[0-9]+}}, [sp, #16] 259 260; CHECK: bl {{.*}}foo_vararg 261; CHECK: mov x0, x21 262; CHECK: cbnz x21 263; Access part of the error object and save it to error_ref 264; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8] 265; CHECK: strb [[CODE]], [{{.*}}[[ID]]] 266; CHECK: bl {{.*}}free 267entry: 268 %error_ptr_ref = alloca swifterror ptr 269 store ptr null, ptr %error_ptr_ref 270 271 %a10 = alloca i32, align 4 272 %a11 = alloca i32, align 4 273 %a12 = alloca i32, align 4 274 store i32 10, ptr %a10, align 4 275 store i32 11, ptr %a11, align 4 276 store i32 12, ptr %a12, align 4 277 %v10 = load i32, ptr %a10, align 4 278 %v11 = load i32, ptr %a11, align 4 279 %v12 = load i32, ptr %a12, align 4 280 281 %call = call float (ptr, ...) @foo_vararg(ptr swifterror %error_ptr_ref, i32 %v10, i32 %v11, i32 %v12) 282 %error_from_foo = load ptr, ptr %error_ptr_ref 283 %had_error_from_foo = icmp ne ptr %error_from_foo, null 284 br i1 %had_error_from_foo, label %handler, label %cont 285 286cont: 287 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1 288 %t = load i8, ptr %v1 289 store i8 %t, ptr %error_ref 290 br label %handler 291handler: 292 call void @free(ptr %error_from_foo) 293 ret float 1.0 294} 295 296; Check that we don't blow up on tail calling swifterror argument functions. 297define float @tailcallswifterror(ptr swifterror %error_ptr_ref) { 298entry: 299 %0 = tail call float @tailcallswifterror(ptr swifterror %error_ptr_ref) 300 ret float %0 301} 302define swiftcc float @tailcallswifterror_swiftcc(ptr swifterror %error_ptr_ref) { 303entry: 304 %0 = tail call swiftcc float @tailcallswifterror_swiftcc(ptr swifterror %error_ptr_ref) 305 ret float %0 306} 307 308; CHECK-LABEL: params_in_reg 309; Save callee saved registers and swifterror since it will be clobbered by the first call to params_in_reg2. 310; CHECK: str x28, [sp 311; CHECK: stp x27, x26, [sp 312; CHECK: stp x25, x24, [sp 313; CHECK: stp x23, x22, [sp 314; CHECK: stp x20, x19, [sp 315; CHECK: stp x29, x30, [sp 316; Store argument registers. 317; CHECK: mov x20, x1 318; CHECK: mov x22, x2 319; CHECK: mov x23, x3 320; CHECK: mov x24, x4 321; CHECK: mov x25, x5 322; CHECK: mov x26, x6 323; CHECK: mov x27, x7 324; CHECK: mov x28, x21 325; Setup call. 326; CHECK: mov w0, #1 327; CHECK: mov w1, #2 328; CHECK: mov w2, #3 329; CHECK: mov w3, #4 330; CHECK: mov w4, #5 331; CHECK: mov w5, #6 332; CHECK: mov w6, #7 333; CHECK: mov w7, #8 334; CHECK: mov x21, xzr 335; CHECK: str xzr, [sp] 336; CHECK: bl _params_in_reg2 337; Restore original arguments for next call. 338; CHECK: ldr x8, [sp, #24] 339; CHECK: mov x1, x20 340; CHECK: mov x2, x22 341; CHECK: mov x3, x23 342; CHECK: mov x4, x24 343; CHECK: mov x5, x25 344; CHECK: mov x6, x26 345; CHECK: mov x7, x27 346; Restore original swiftself argument and swifterror %err. 347; CHECK: mov x21, x28 348; CHECK: bl _params_in_reg2 349; Restore calle save registers but don't clober swifterror x21. 350; CHECK-NOT: x21 351; CHECK: ldp x29, x30, [sp 352; CHECK-NOT: x21 353; CHECK: ldr x28, [sp 354; CHECK-NOT: x21 355; CHECK: ldp x20, x19, [sp 356; CHECK-NOT: x21 357; CHECK: ldp x23, x22, [sp 358; CHECK-NOT: x21 359; CHECK: ldp x25, x24, [sp 360; CHECK-NOT: x21 361; CHECK: ldp x27, x26, [sp 362; CHECK-NOT: x21 363; CHECK: ret 364define swiftcc void @params_in_reg(i64, i64, i64, i64, i64, i64, i64, i64, ptr, ptr nocapture swifterror %err) { 365 %error_ptr_ref = alloca swifterror ptr, align 8 366 store ptr null, ptr %error_ptr_ref 367 call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, ptr null, ptr nocapture swifterror %error_ptr_ref) 368 call swiftcc void @params_in_reg2(i64 %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i64 %6, i64 %7, ptr %8, ptr nocapture swifterror %err) 369 ret void 370} 371declare swiftcc void @params_in_reg2(i64, i64, i64, i64, i64, i64, i64, i64, ptr , ptr nocapture swifterror %err) 372 373; CHECK-LABEL: params_and_return_in_reg 374; Store callee saved registers. 375; CHECK: stp x28, x0, [sp, #16 376; CHECK: stp x27, x26, [sp 377; CHECK: stp x25, x24, [sp 378; CHECK: stp x23, x22, [sp 379; CHECK: stp x20, x19, [sp 380; CHECK: stp x29, x30, [sp 381; Save original arguments. 382; CHECK: mov x20, x1 383; CHECK: mov x22, x2 384; CHECK: mov x23, x3 385; CHECK: mov x24, x4 386; CHECK: mov x25, x5 387; CHECK: mov x26, x6 388; CHECK: mov x27, x7 389; Setup call arguments. 390; CHECK: mov w0, #1 391; CHECK: mov w1, #2 392; CHECK: mov w2, #3 393; CHECK: mov w3, #4 394; CHECK: mov w4, #5 395; CHECK: mov w5, #6 396; CHECK: mov w6, #7 397; CHECK: mov w7, #8 398; CHECK: mov x21, xzr 399; CHECK: bl _params_in_reg2 400; Store swifterror %error_ptr_ref. 401; CHECK: ldr x0, [sp, #24] 402; CHECK: stp {{x[0-9]+}}, x21, [sp] 403; Setup call arguments from original arguments. 404; CHECK: mov x1, x20 405; CHECK: mov x2, x22 406; CHECK: mov x3, x23 407; CHECK: mov x4, x24 408; CHECK: mov x5, x25 409; CHECK: mov x6, x26 410; CHECK: mov x7, x27 411; CHECK: mov x21, x28 412; CHECK: bl _params_and_return_in_reg2 413; CHECK: mov x19, x21 414; CHECK: ldr x21, [sp, #8 415; Store return values. 416; CHECK: mov x20, x0 417; CHECK: mov x22, x1 418; CHECK: mov x23, x2 419; CHECK: mov x24, x3 420; CHECK: mov x25, x4 421; CHECK: mov x26, x5 422; CHECK: mov x27, x6 423; CHECK: mov x28, x7 424; Setup call. 425; CHECK: mov w0, #1 426; CHECK: mov w1, #2 427; CHECK: mov w2, #3 428; CHECK: mov w3, #4 429; CHECK: mov w4, #5 430; CHECK: mov w5, #6 431; CHECK: mov w6, #7 432; CHECK: mov w7, #8 433; CHECK: str xzr, [sp] 434; CHECK: bl _params_in_reg2 435; Restore return values for return from this function. 436; CHECK: mov x0, x20 437; CHECK: mov x1, x22 438; CHECK: mov x2, x23 439; CHECK: mov x3, x24 440; CHECK: mov x4, x25 441; CHECK: mov x5, x26 442; CHECK: mov x6, x27 443; CHECK: mov x21, x19 444; CHECK: mov x7, x28 445; CHECK: ldp x29, x30, [sp, #96] ; 16-byte Folded Reload 446; CHECK: ldr x28, [sp, #16] ; 8-byte Folded Reload 447; CHECK: ldp x20, x19, [sp, #80] ; 16-byte Folded Reload 448; CHECK: ldp x23, x22, [sp, #64] ; 16-byte Folded Reload 449; CHECK: ldp x25, x24, [sp, #48] ; 16-byte Folded Reload 450; CHECK: ldp x27, x26, [sp, #32] ; 16-byte Folded Reload 451; CHECK: add sp, sp, #112 452; CHECK: ret 453define swiftcc { i64, i64, i64, i64, i64, i64, i64, i64 } @params_and_return_in_reg(i64, i64, i64, i64, i64, i64, i64, i64, ptr , ptr nocapture swifterror %err) { 454 %error_ptr_ref = alloca swifterror ptr, align 8 455 store ptr null, ptr %error_ptr_ref 456 call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, ptr null, ptr nocapture swifterror %error_ptr_ref) 457 %val = call swiftcc { i64, i64, i64, i64, i64, i64, i64, i64 } @params_and_return_in_reg2(i64 %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i64 %6, i64 %7, ptr %8, ptr nocapture swifterror %err) 458 call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, ptr null, ptr nocapture swifterror %error_ptr_ref) 459 ret { i64, i64, i64, i64, i64, i64, i64, i64 } %val 460} 461 462declare swiftcc { i64, i64, i64, i64, i64, i64, i64, i64 } @params_and_return_in_reg2(i64, i64, i64, i64, i64, i64, i64, i64, ptr , ptr nocapture swifterror %err) 463 464declare void @acallee(ptr) 465 466; Make sure we don't tail call if the caller returns a swifterror value. We 467; would have to move into the swifterror register before the tail call. 468; CHECK-LABEL: tailcall_from_swifterror: 469; CHECK-NOT: b _acallee 470; CHECK: bl _acallee 471 472define swiftcc void @tailcall_from_swifterror(ptr swifterror %error_ptr_ref) { 473entry: 474 tail call void @acallee(ptr null) 475 ret void 476} 477 478; CHECK: tailcall_from_swifterror2 479; CHECK-NOT: b _simple_fn 480; CHECK: bl _simple_fn 481declare void @simple_fn() 482define swiftcc void @tailcall_from_swifterror2(ptr swifterror %error_ptr_ref) { 483 tail call void @simple_fn() 484 ret void 485} 486 487declare swiftcc void @foo2(ptr swifterror) 488; CHECK-LABEL: testAssign 489; CHECK: mov x21, xzr 490; CHECK: bl _foo2 491; CHECK: mov x0, x21 492 493define swiftcc ptr @testAssign(ptr %error_ref) { 494entry: 495 %error_ptr = alloca swifterror ptr 496 store ptr null, ptr %error_ptr 497 call swiftcc void @foo2(ptr swifterror %error_ptr) 498 br label %a 499 500a: 501 %error = load ptr, ptr %error_ptr 502 ret ptr %error 503} 504 505; foo takes a swifterror parameter. We should be able to see that even when 506; it isn't explicitly on the call. 507define float @swifterror_param_not_on_call(ptr %error_ref) { 508; CHECK-LABEL: swifterror_param_not_on_call: 509; CHECK: mov [[ID:x[0-9]+]], x0 510; CHECK: bl {{.*}}foo 511; CHECK: mov x0, x21 512; CHECK: cbnz x21 513; Access part of the error object and save it to error_ref 514; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8] 515; CHECK: strb [[CODE]], [{{.*}}[[ID]]] 516; CHECK: bl {{.*}}free 517 518entry: 519 %error_ptr_ref = alloca swifterror ptr 520 store ptr null, ptr %error_ptr_ref 521 %call = call float @foo(ptr %error_ptr_ref) 522 %error_from_foo = load ptr, ptr %error_ptr_ref 523 %had_error_from_foo = icmp ne ptr %error_from_foo, null 524 br i1 %had_error_from_foo, label %handler, label %cont 525cont: 526 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1 527 %t = load i8, ptr %v1 528 store i8 %t, ptr %error_ref 529 br label %handler 530handler: 531 call void @free(ptr %error_from_foo) 532 ret float 1.0 533} 534 535; foo_sret takes an sret parameter and a swifterror parameter. We should be 536; able to see that, even if it's not explicitly on the call. 537define float @swifterror_param_not_on_call2(ptr %error_ref) { 538; CHECK-LABEL: swifterror_param_not_on_call2: 539; CHECK: mov [[ID:x[0-9]+]], x0 540; CHECK: mov [[ZERO:x[0-9]+]], xzr 541; CHECK: bl {{.*}}foo_sret 542; CHECK: mov x0, x21 543; CHECK: cbnz x21 544; Access part of the error object and save it to error_ref 545; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8] 546; CHECK: strb [[CODE]], [{{.*}}[[ID]]] 547; CHECK: bl {{.*}}free 548 549entry: 550 %s = alloca %struct.S, align 8 551 %error_ptr_ref = alloca swifterror ptr 552 store ptr null, ptr %error_ptr_ref 553 call void @foo_sret(ptr %s, i32 1, ptr %error_ptr_ref) 554 %error_from_foo = load ptr, ptr %error_ptr_ref 555 %had_error_from_foo = icmp ne ptr %error_from_foo, null 556 br i1 %had_error_from_foo, label %handler, label %cont 557cont: 558 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1 559 %t = load i8, ptr %v1 560 store i8 %t, ptr %error_ref 561 br label %handler 562handler: 563 call void @free(ptr %error_from_foo) 564 ret float 1.0 565} 566