// #target: macos-x64
module oups;
import std::io;

fn void main()
{
	ByteReader r;
	InStream s = &r;
	s.foo()!!;
}

macro InStream.foo(&self)
{
	char? c = self.read_byte();
	if (catch err = c)
	{
		return err~;
	}
	return;
}


/* #expect: oups.ll

define void @oups.main() #0 {
entry:
  %r = alloca %ByteReader, align 8
  %s = alloca %any, align 8
  %error_var = alloca i64, align 8
  %c = alloca i8, align 1
  %c.f = alloca i64, align 8
  %.inlinecache = alloca ptr, align 8
  %.cachedtype = alloca ptr, align 8
  %retparam = alloca i8, align 1
  %err = alloca i64, align 8
  %varargslots = alloca [1 x %any], align 16
  %indirectarg = alloca %"any[]", align 8
  store ptr null, ptr %.cachedtype, align 8
  call void @llvm.memset.p0.i64(ptr align 8 %r, i8 0, i64 24, i1 false)
  %0 = insertvalue %any undef, ptr %r, 0
  %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.std.io.ByteReader" to i64), 1
  store %any %1, ptr %s, align 8
  %neq = icmp ne ptr %s, null
  call void @llvm.assume(i1 %neq)
  %ptradd = getelementptr inbounds i8, ptr %s, i64 8
  %2 = load i64, ptr %ptradd, align 8
  %3 = inttoptr i64 %2 to ptr
  %4 = load ptr, ptr %.cachedtype, align 8
  %5 = icmp eq ptr %3, %4
  br i1 %5, label %cache_hit, label %cache_miss

cache_miss:                                       ; preds = %entry
  %6 = call ptr @.dyn_search(ptr %3, ptr @"$sel.read_byte")
  store ptr %6, ptr %.inlinecache, align 8
  store ptr %3, ptr %.cachedtype, align 8
  br label %8

cache_hit:                                        ; preds = %entry
  %7 = load ptr, ptr %.inlinecache, align 8
  br label %8

8:                                                ; preds = %cache_hit, %cache_miss
  %fn_phi = phi ptr [ %7, %cache_hit ], [ %6, %cache_miss ]
  %9 = icmp eq ptr %fn_phi, null
  br i1 %9, label %missing_function, label %match

missing_function:                                 ; preds = %8
  %10 = load ptr, ptr @std.core.builtin.panic, align 8
  call void %10(ptr @.panic_msg, i64 46, ptr @.file, i64 25, ptr @.func, i64 4, i32 13) #4
  unreachable

match:                                            ; preds = %8
  %11 = load ptr, ptr %s, align 8
  %12 = call i64 %fn_phi(ptr %retparam, ptr %11)
  %not_err = icmp eq i64 %12, 0
  %13 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
  br i1 %13, label %after_check, label %assign_optional

assign_optional:                                  ; preds = %match
  store i64 %12, ptr %c.f, align 8
  br label %after_assign

after_check:                                      ; preds = %match
  %14 = load i8, ptr %retparam, align 1
  store i8 %14, ptr %c, align 1
  store i64 0, ptr %c.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 %c.f, align 8
  %not_err1 = icmp eq i64 %optval, 0
  %15 = call i1 @llvm.expect.i1(i1 %not_err1, i1 true)
  br i1 %15, 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
  %16 = load i64, ptr %err, align 8
  %i2b = icmp ne i64 %16, 0
  br i1 %i2b, label %if.then, label %if.exit

if.then:                                          ; preds = %end_block
  %17 = load i64, ptr %err, align 8
  store i64 %17, ptr %error_var, align 8
  br label %panic_block

if.exit:                                          ; preds = %end_block
  br label %noerr_block

panic_block:                                      ; preds = %if.then
  %18 = insertvalue %any undef, ptr %error_var, 0
  %19 = insertvalue %any %18, i64 ptrtoint (ptr @"$ct.fault" to i64), 1
  store %any %19, ptr %varargslots, align 16
  %20 = insertvalue %"any[]" undef, ptr %varargslots, 0
  %"$$temp" = insertvalue %"any[]" %20, i64 1, 1
  store %"any[]" %"$$temp", ptr %indirectarg, align 8
  call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 36,
  unreachable

noerr_block:                                      ; preds = %if.exit
  ret void
}