// #target: macos-x64
module mymodule;

extern fn void printf(char *, ...);

faultdef FOO;
faultdef BAR, BAZ;

fn void test()
{
    int? x = BAR?;

    typeid z = int.typeid;
    switch (z)
    {
        case int:
            printf("Was int!\n");
        case bool:
            nextcase double;
        case double:
            nextcase;
        default:
            printf("Wasn't int :(\n");
    }
    int a = 1;
    int b = 2;
    int zy = b + a;
    switch (zy)
    {
        case a:
            printf("Got a\n");
        case b:
            printf("Got b\n");
        default:
            printf("None of the above\n");
    }
    switch
    {
        case a < 0:
            printf("A negative\n");
        case a == 1:
            printf("A is 1\n");
        default:
            printf("Unexpected a\n");
    }
}
fn void main()
{
    test();
    printf("Hello!\n");
}

/* #expect: mymodule.ll

define void @mymodule.test() #0 {
entry:
  %x = alloca i32, align 4
  %x.f = alloca i64, align 8
  %z = alloca i64, align 8
  %switch = alloca i64, align 8
  %a = alloca i32, align 4
  %b = alloca i32, align 4
  %zy = alloca i32, align 4
  %switch17 = alloca i32, align 4
  %switch27 = alloca i8, align 1
  store i64 ptrtoint (ptr @mymodule.BAR to i64), ptr %x.f, align 8
  store i64 ptrtoint (ptr @"$ct.int" to i64), ptr %z, align 8
  %0 = load i64, ptr %z, align 8
  store i64 %0, ptr %switch, align 8
  br label %switch.entry

switch.entry:                                     ; preds = %entry
  %1 = load i64, ptr %switch, align 8
  br label %check_subtype

check_subtype:                                    ; preds = %parent_type_block, %switch.entry
  %2 = phi i64 [ %1, %switch.entry ], [ %typeid.parent, %parent_type_block ]
  %eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %2
  br i1 %eq, label %result_block, label %parent_type_block

parent_type_block:                                ; preds = %check_subtype
  %3 = inttoptr i64 %2 to ptr
  %ptradd = getelementptr inbounds i8, ptr %3, i64 8
  %typeid.parent = load i64, ptr %ptradd, align 8
  %4 = icmp eq i64 %typeid.parent, 0
  br i1 %4, label %result_block, label %check_subtype

result_block:                                     ; preds = %parent_type_block, %check_subtype
  %5 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
  br i1 %5, label %switch.case, label %next_if

switch.case:                                      ; preds = %result_block
  call void (ptr, ...) @printf(ptr @.str)
  br label %switch.exit

next_if:                                          ; preds = %result_block
  br label %check_subtype1

check_subtype1:                                   ; preds = %parent_type_block3, %next_if
  %6 = phi i64 [ %1, %next_if ], [ %typeid.parent5, %parent_type_block3 ]
  %eq2 = icmp eq i64 ptrtoint (ptr @"$ct.bool" to i64), %6
  br i1 %eq2, label %result_block6, label %parent_type_block3

parent_type_block3:                               ; preds = %check_subtype1
  %7 = inttoptr i64 %6 to ptr
  %ptradd4 = getelementptr inbounds i8, ptr %7, i64 8
  %typeid.parent5 = load i64, ptr %ptradd4, align 8
  %8 = icmp eq i64 %typeid.parent5, 0
  br i1 %8, label %result_block6, label %check_subtype1

result_block6:                                    ; preds = %parent_type_block3, %check_subtype1
  %9 = phi i1 [ false, %parent_type_block3 ], [ true, %check_subtype1 ]
  br i1 %9, label %switch.case7, label %next_if8

switch.case7:                                     ; preds = %result_block6
  br label %switch.case15

next_if8:                                         ; preds = %result_block6
  br label %check_subtype9

check_subtype9:                                   ; preds = %parent_type_block11, %next_if8
  %10 = phi i64 [ %1, %next_if8 ], [ %typeid.parent13, %parent_type_block11 ]
  %eq10 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %10
  br i1 %eq10, label %result_block14, label %parent_type_block11

parent_type_block11:                              ; preds = %check_subtype9
  %11 = inttoptr i64 %10 to ptr
  %ptradd12 = getelementptr inbounds i8, ptr %11, i64 8
  %typeid.parent13 = load i64, ptr %ptradd12, align 8
  %12 = icmp eq i64 %typeid.parent13, 0
  br i1 %12, label %result_block14, label %check_subtype9

result_block14:                                   ; preds = %parent_type_block11, %check_subtype9
  %13 = phi i1 [ false, %parent_type_block11 ], [ true, %check_subtype9 ]
  br i1 %13, label %switch.case15, label %next_if16

switch.case15:                                    ; preds = %result_block14, %switch.case7
  br label %switch.default

next_if16:                                        ; preds = %result_block14
  br label %switch.default

switch.default:                                   ; preds = %next_if16, %switch.case15
  call void (ptr, ...) @printf(ptr @.str.1)
  br label %switch.exit

switch.exit:                                      ; preds = %switch.default, %switch.case
  store i32 1, ptr %a, align 4
  store i32 2, ptr %b, align 4
  %14 = load i32, ptr %b, align 4
  %15 = load i32, ptr %a, align 4
  %add = add i32 %14, %15
  store i32 %add, ptr %zy, align 4
  %16 = load i32, ptr %zy, align 4
  store i32 %16, ptr %switch17, align 4
  br label %switch.entry18

switch.entry18:                                   ; preds = %switch.exit
  %17 = load i32, ptr %switch17, align 4
  %18 = load i32, ptr %a, align 4
  %eq19 = icmp eq i32 %18, %17
  br i1 %eq19, label %switch.case20, label %next_if21

switch.case20:                                    ; preds = %switch.entry18
  call void (ptr, ...) @printf(ptr @.str.2)
  br label %switch.exit26

next_if21:                                        ; preds = %switch.entry18
  %19 = load i32, ptr %b, align 4
  %eq22 = icmp eq i32 %19, %17
  br i1 %eq22, label %switch.case23, label %next_if24

switch.case23:                                    ; preds = %next_if21
  call void (ptr, ...) @printf(ptr @.str.3)
  br label %switch.exit26

next_if24:                                        ; preds = %next_if21
  br label %switch.default25

switch.default25:                                 ; preds = %next_if24
  call void (ptr, ...) @printf(ptr @.str.4)
  br label %switch.exit26

switch.exit26:                                    ; preds = %switch.default25, %switch.case23, %switch.case20
  store i8 1, ptr %switch27, align 1
  br label %switch.entry28

switch.entry28:                                   ; preds = %switch.exit26
  %20 = load i8, ptr %switch27, align 1
  %21 = trunc i8 %20 to i1
  %22 = load i32, ptr %a, align 4
  %lt = icmp slt i32 %22, 0
  %eq29 = icmp eq i1 %lt, %21
  br i1 %eq29, label %switch.case30, label %next_if31

switch.case30:                                    ; preds = %switch.entry28
  call void (ptr, ...) @printf(ptr @.str.5)
  br label %switch.exit37

next_if31:                                        ; preds = %switch.entry28
  %23 = load i32, ptr %a, align 4
  %eq32 = icmp eq i32 %23, 1
  %eq33 = icmp eq i1 %eq32, %21
  br i1 %eq33, label %switch.case34, label %next_if35

switch.case34:                                    ; preds = %next_if31
  call void (ptr, ...) @printf(ptr @.str.6)
  br label %switch.exit37

next_if35:                                        ; preds = %next_if31
  br label %switch.default36

switch.default36:                                 ; preds = %next_if35
  call void (ptr, ...) @printf(ptr @.str.7)
  br label %switch.exit37

switch.exit37:                                    ; preds = %switch.default36, %switch.case34, %switch.case30
  ret void
}

; Function Attrs: nounwind uwtable
define void @mymodule.main() #0 {
entry:
  call void @mymodule.test()
  call void (ptr, ...) @printf(ptr @.str.8)
  ret void
}
