Files
c3c/test/test_suite/from_docs/examples_if_catch.c3t

163 lines
4.7 KiB
Plaintext

// #target: macos-x64
module demo;
import libc;
import std::io;
fault MathError
{
DIVISION_BY_ZERO
}
fn int foo() { return 123; }
fn int bar() { return 0; }
fn double! divide(int a, int b)
{
if (b == 0) return MathError.DIVISION_BY_ZERO?;
return (double)(a) / (double)(b);
}
// Rethrowing an error uses "?" suffix
fn void! testMayError()
{
divide(foo(), bar())!;
}
fn void main()
{
// ratio has an optional type.
double! ratio = divide(foo(), bar());
// Handle the error
if (catch err = ratio)
{
case MathError.DIVISION_BY_ZERO:
libc::printf("Division by zero\n");
return;
default:
libc::printf("Unexpected error!");
return;
}
// Flow typing makes "ratio"
// have the type double here.
libc::printf("Ratio was %f\n", ratio);
}
/* #expect: demo.ll
define i64 @demo.divide(ptr %0, i32 %1, i32 %2) #0 {
entry:
%reterr = alloca i64, align 8
%eq = icmp eq i32 %2, 0
br i1 %eq, label %if.then, label %if.exit
if.then: ; preds = %entry
ret i64 ptrtoint (ptr @"demo.MathError$DIVISION_BY_ZERO" to i64)
if.exit: ; preds = %entry
%sifp = sitofp i32 %1 to double
%sifp1 = sitofp i32 %2 to double
%fdiv = fdiv double %sifp, %sifp1
store double %fdiv, ptr %0, align 8
ret i64 0
}
define i64 @demo.testMayError() #0 {
entry:
%error_var = alloca i64, align 8
%retparam = alloca double, align 8
%0 = call i32 @demo.foo()
%1 = call i32 @demo.bar()
%2 = call i64 @demo.divide(ptr %retparam, i32 %0, i32 %1)
%not_err = icmp eq i64 %2, 0
%3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
br i1 %3, label %after_check, label %assign_optional
assign_optional: ; preds = %entry
store i64 %2, ptr %error_var, align 8
br label %guard_block
after_check: ; preds = %entry
br label %noerr_block
guard_block: ; preds = %assign_optional
%4 = load i64, ptr %error_var, align 8
ret i64 %4
noerr_block: ; preds = %after_check
ret i64 0
}
define void @demo.main() #0 {
entry:
%ratio = alloca double, align 8
%ratio.f = alloca i64, align 8
%retparam = alloca double, align 8
%err = alloca i64, align 8
%switch = alloca i64, align 8
%0 = call i32 @demo.foo()
%1 = call i32 @demo.bar()
%2 = call i64 @demo.divide(ptr %retparam, i32 %0, i32 %1)
%not_err = icmp eq i64 %2, 0
%3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
br i1 %3, label %after_check, label %assign_optional
assign_optional: ; preds = %entry
store i64 %2, ptr %ratio.f, align 8
br label %after_assign
after_check: ; preds = %entry
%4 = load double, ptr %retparam, align 8
store double %4, ptr %ratio, align 8
store i64 0, ptr %ratio.f, align 8
br label %after_assign
after_assign: ; preds = %after_check, %assign_optional
br label %testblock
testblock: ; preds = %after_assign
%optval = load i64, ptr %ratio.f, align 8
%not_err1 = icmp eq i64 %optval, 0
%5 = call i1 @llvm.expect.i1(i1 %not_err1, i1 true)
br i1 %5, label %after_check3, label %assign_optional2
assign_optional2: ; preds = %testblock
store i64 %optval, ptr %err, align 8
br label %end_block
after_check3: ; preds = %testblock
store i64 0, ptr %err, align 8
br label %end_block
end_block: ; preds = %after_check3, %assign_optional2
%6 = load i64, ptr %err, align 8
%neq = icmp ne i64 %6, 0
br i1 %neq, label %if.then, label %if.exit
if.then: ; preds = %end_block
store i64 %6, ptr %switch, align 8
br label %switch.entry
switch.entry: ; preds = %if.then
%7 = load i64, ptr %switch, align 8
%eq = icmp eq i64 ptrtoint (ptr @"demo.MathError$DIVISION_BY_ZERO" to i64), %7
br i1 %eq, label %switch.case, label %next_if
switch.case: ; preds = %switch.entry
%8 = call i32 (ptr, ...) @printf(ptr @.str)
ret void
next_if: ; preds = %switch.entry
br label %switch.default
switch.default: ; preds = %next_if
%9 = call i32 (ptr, ...) @printf(ptr @.str.1)
ret void
if.exit: ; preds = %end_block
%10 = load double, ptr %ratio, align 8
%11 = call i32 (ptr, ...) @printf(ptr @.str.2, double %10)
ret void
}