// #target: macos-x64

module demo1;
import std::io;

faultdef ABC, DEF;

fn int? hello(int a)
{
	io::printn("hello");
	return a < 0 ? ABC~ : a;
}

fn void? bye()
{
	io::printn("bye");
	return DEF~;
}
fn void main()
{
	if (catch err = hello(-1), bye())
	{
		io::printfn("1 Got %s", err);
	}
	if (catch err = hello(0), bye())
	{
		io::printfn("2 Got %s", err);
	}
	if (catch hello(0), bye())
    {
    	io::printn("3 Ok");
    }
	if (catch fault err = hello(0), bye())
    {
		io::printfn("4 Got %s", err);
    }
}

/* #expect: demo1.ll

define void @demo1.main() #0 {
entry:
  %err = alloca i64, align 8
  %retparam = alloca i32, align 4
  %varargslots = alloca [1 x %any], align 16
  %retparam5 = alloca i64, align 8
  %err8 = alloca i64, align 8
  %retparam10 = alloca i32, align 4
  %varargslots21 = alloca [1 x %any], align 16
  %retparam22 = alloca i64, align 8
  %temp_err = alloca i64, align 8
  %retparam27 = alloca i32, align 4
  %len = alloca i64, align 8
  %error_var = alloca i64, align 8
  %retparam39 = alloca i64, align 8
  %error_var43 = alloca i64, align 8
  %error_var49 = alloca i64, align 8
  %err56 = alloca i64, align 8
  %retparam58 = alloca i32, align 4
  %varargslots69 = alloca [1 x %any], align 16
  %retparam70 = alloca i64, align 8
  br label %testblock

testblock:                                        ; preds = %entry
  %0 = call i64 @demo1.hello(ptr %retparam, i32 -1)
  %not_err = icmp eq i64 %0, 0
  %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
  br i1 %1, label %after_check, label %assign_optional

assign_optional:                                  ; preds = %testblock
  store i64 %0, ptr %err, align 8
  br label %end_block

after_check:                                      ; preds = %testblock
  br label %testblock1

testblock1:                                       ; preds = %after_check
  %2 = call i64 @demo1.bye()
  %not_err2 = icmp eq i64 %2, 0
  %3 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true)
  br i1 %3, label %after_check4, label %assign_optional3

assign_optional3:                                 ; preds = %testblock1
  store i64 %2, ptr %err, align 8
  br label %end_block

after_check4:                                     ; preds = %testblock1
  store i64 0, ptr %err, align 8
  br label %end_block

end_block:                                        ; preds = %after_check4, %assign_optional3, %assign_optional
  %4 = load i64, ptr %err, align 8
  %i2b = icmp ne i64 %4, 0
  br i1 %i2b, label %if.then, label %if.exit

if.then:                                          ; preds = %end_block
  %5 = insertvalue %any undef, ptr %err, 0
  %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.fault" to i64), 1
  store %any %6, ptr %varargslots, align 16
  %7 = call i64 @std.io.printfn(ptr %retparam5, ptr @.str.2, i64 8, ptr %varargslots, i64 1)
  br label %if.exit

if.exit:                                          ; preds = %if.then, %end_block
  br label %testblock9

testblock9:                                       ; preds = %if.exit
  %8 = call i64 @demo1.hello(ptr %retparam10, i32 0)
  %not_err11 = icmp eq i64 %8, 0
  %9 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true)
  br i1 %9, label %after_check13, label %assign_optional12

assign_optional12:                                ; preds = %testblock9
  store i64 %8, ptr %err8, align 8
  br label %end_block18

after_check13:                                    ; preds = %testblock9
  br label %testblock14

testblock14:                                      ; preds = %after_check13
  %10 = call i64 @demo1.bye()
  %not_err15 = icmp eq i64 %10, 0
  %11 = call i1 @llvm.expect.i1(i1 %not_err15, i1 true)
  br i1 %11, label %after_check17, label %assign_optional16

assign_optional16:                                ; preds = %testblock14
  store i64 %10, ptr %err8, align 8
  br label %end_block18

after_check17:                                    ; preds = %testblock14
  store i64 0, ptr %err8, align 8
  br label %end_block18

end_block18:                                      ; preds = %after_check17, %assign_optional16, %assign_optional12
  %12 = load i64, ptr %err8, align 8
  %i2b19 = icmp ne i64 %12, 0
  br i1 %i2b19, label %if.then20, label %if.exit25

if.then20:                                        ; preds = %end_block18
  %13 = insertvalue %any undef, ptr %err8, 0
  %14 = insertvalue %any %13, i64 ptrtoint (ptr @"$ct.fault" to i64), 1
  store %any %14, ptr %varargslots21, align 16
  %15 = call i64 @std.io.printfn(ptr %retparam22, ptr @.str.3, i64 8, ptr %varargslots21, i64 1)
  br label %if.exit25

if.exit25:                                        ; preds = %if.then20, %end_block18
  br label %testblock26

testblock26:                                      ; preds = %if.exit25
  %16 = call i64 @demo1.hello(ptr %retparam27, i32 0)
  %not_err28 = icmp eq i64 %16, 0
  %17 = call i1 @llvm.expect.i1(i1 %not_err28, i1 true)
  br i1 %17, label %after_check30, label %assign_optional29

assign_optional29:                                ; preds = %testblock26
  store i64 %16, ptr %temp_err, align 8
  br label %end_block35

after_check30:                                    ; preds = %testblock26
  br label %testblock31

testblock31:                                      ; preds = %after_check30
  %18 = call i64 @demo1.bye()
  %not_err32 = icmp eq i64 %18, 0
  %19 = call i1 @llvm.expect.i1(i1 %not_err32, i1 true)
  br i1 %19, label %after_check34, label %assign_optional33

assign_optional33:                                ; preds = %testblock31
  store i64 %18, ptr %temp_err, align 8
  br label %end_block35

after_check34:                                    ; preds = %testblock31
  store i64 0, ptr %temp_err, align 8
  br label %end_block35

end_block35:                                      ; preds = %after_check34, %assign_optional33, %assign_optional29
  %20 = load i64, ptr %temp_err, align 8
  %i2b36 = icmp ne i64 %20, 0
  br i1 %i2b36, label %if.then37, label %if.exit55

if.then37:                                        ; preds = %end_block35
  %21 = call ptr @std.io.stdout()
  %22 = call i64 @std.io.File.write(ptr %retparam39, ptr %21, ptr @.str.4, i64 4)
  %not_err40 = icmp eq i64 %22, 0
  %23 = call i1 @llvm.expect.i1(i1 %not_err40, i1 true)
  br i1 %23, label %after_check42, label %assign_optional41

assign_optional41:                                ; preds = %if.then37
  store i64 %22, ptr %error_var, align 8
  br label %guard_block

after_check42:                                    ; preds = %if.then37
  br label %noerr_block

guard_block:                                      ; preds = %assign_optional41
  br label %voiderr

noerr_block:                                      ; preds = %after_check42
  %24 = load i64, ptr %retparam39, align 8
  store i64 %24, ptr %len, align 8
  %25 = call i64 @std.io.File.write_byte(ptr %21, i8 zeroext 10)
  %not_err44 = icmp eq i64 %25, 0
  %26 = call i1 @llvm.expect.i1(i1 %not_err44, i1 true)
  br i1 %26, label %after_check46, label %assign_optional45

assign_optional45:                                ; preds = %noerr_block
  store i64 %25, ptr %error_var43, align 8
  br label %guard_block47

after_check46:                                    ; preds = %noerr_block
  br label %noerr_block48

guard_block47:                                    ; preds = %assign_optional45
  br label %voiderr

noerr_block48:                                    ; preds = %after_check46
  %27 = call i64 @std.io.File.flush(ptr %21)
  %not_err50 = icmp eq i64 %27, 0
  %28 = call i1 @llvm.expect.i1(i1 %not_err50, i1 true)
  br i1 %28, label %after_check52, label %assign_optional51

assign_optional51:                                ; preds = %noerr_block48
  store i64 %27, ptr %error_var49, align 8
  br label %guard_block53

after_check52:                                    ; preds = %noerr_block48
  br label %noerr_block54

guard_block53:                                    ; preds = %assign_optional51
  br label %voiderr

noerr_block54:                                    ; preds = %after_check52
  %29 = load i64, ptr %len, align 8
  %add = add i64 %29, 1
  br label %voiderr

voiderr:                                          ; preds = %noerr_block54, %guard_block53, %guard_block47, %guard_block
  br label %if.exit55

if.exit55:                                        ; preds = %voiderr, %end_block35
  br label %testblock57

testblock57:                                      ; preds = %if.exit55
  %30 = call i64 @demo1.hello(ptr %retparam58, i32 0)
  %not_err59 = icmp eq i64 %30, 0
  %31 = call i1 @llvm.expect.i1(i1 %not_err59, i1 true)
  br i1 %31, label %after_check61, label %assign_optional60

assign_optional60:                                ; preds = %testblock57
  store i64 %30, ptr %err56, align 8
  br label %end_block66

after_check61:                                    ; preds = %testblock57
  br label %testblock62

testblock62:                                      ; preds = %after_check61
  %32 = call i64 @demo1.bye()
  %not_err63 = icmp eq i64 %32, 0
  %33 = call i1 @llvm.expect.i1(i1 %not_err63, i1 true)
  br i1 %33, label %after_check65, label %assign_optional64

assign_optional64:                                ; preds = %testblock62
  store i64 %32, ptr %err56, align 8
  br label %end_block66

after_check65:                                    ; preds = %testblock62
  store i64 0, ptr %err56, align 8
  br label %end_block66

end_block66:                                      ; preds = %after_check65, %assign_optional64, %assign_optional60
  %34 = load i64, ptr %err56, align 8
  %i2b67 = icmp ne i64 %34, 0
  br i1 %i2b67, label %if.then68, label %if.exit73

if.then68:                                        ; preds = %end_block66
  %35 = insertvalue %any undef, ptr %err56, 0
  %36 = insertvalue %any %35, i64 ptrtoint (ptr @"$ct.fault" to i64), 1
  store %any %36, ptr %varargslots69, align 16
  %37 = call i64 @std.io.printfn(ptr %retparam70, ptr @.str.5, i64 8, ptr %varargslots69, i64 1)
  br label %if.exit73

if.exit73:                                        ; preds = %if.then68, %end_block66
  ret void
}