// File: /workspace/github_cpp_makefile_star2_O2/tsoding[P]wcc/src/./wcc_wat_compiler.cpp
// Function: Wat_Compiler::compile_type_cast(Type_Cast)
S_Expr *Wat_Compiler::compile_type_cast(Type_Cast type_cast)
{
    auto expression = compile_expression(type_cast.expression);

    switch (type_cast.expression->type) {
    case Type::U0:
        reporter.fail(type_cast.expression->offset, "Impossible to convert `", type_cast.expression->type, "` to `", type_cast.type, "`");

    case Type::Bool:
        switch (type_cast.type) {
        case Type::Bool:
            return expression;
        case Type::U0:
        case Type::U8:
        case Type::U32:
        case Type::U64:
            reporter.fail(type_cast.expression->offset, "Impossible to convert `", type_cast.expression->type, "` to `", type_cast.type, "`");

        case Type::Unchecked:
            assert(0 && "Unchecked type in a checked context");
            break;
        }
        break;

    case Type::U8:
        switch (type_cast.type) {
        case Type::U0:
            return list(atom("drop"_sv), expression);
        case Type::U8:
        case Type::U32:
        case Type::Bool:
            return expression;
        case Type::U64:
            return list(atom("i64.extend_u/i32"_sv), expression);
        case Type::Unchecked:
            assert(0 && "Unchecked type in a checked context");
            break;
        }
        break;

    case Type::U32:
        switch (type_cast.type) {
        case Type::U0:
            return list(atom("drop"_sv), expression);
        case Type::U8:
            reporter.fail(type_cast.expression->offset, "Impossible to convert `", type_cast.expression->type, "` to `", type_cast.type, "`");
        case Type::Bool:
        case Type::U32:
            return expression;
        case Type::U64:
            return list(atom("i64.extend_u/i32"_sv), expression);
        case Type::Unchecked:
            assert(0 && "Unchecked type in a checked context");
            break;
        }
        break;

    case Type::U64:
        switch (type_cast.type) {
        case Type::U0:
            return list(atom("drop"_sv), expression);
        case Type::U8:
        case Type::U32:
        case Type::Bool:
            reporter.fail(type_cast.expression->offset, "Impossible to convert `", type_cast.expression->type, "` to `", type_cast.type, "`");
        case Type::U64:
            return expression;
        case Type::Unchecked:
            assert(0 && "Unchecked type in a checked context");
            break;
        }
        break;

    case Type::Unchecked:
        assert(0 && "Unchecked type in a checked context");
        break;
    }

    assert(0 && "Memory corruption?");
    return nullptr;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x10, %rsp
movq %rdx, %r12
movl %esi, %r15d
movq %rdi, %rbx
movq %rdx, %rsi
callq 0x4380
movq %rax, %r14
movl 0x4(%r12), %eax
cmpq $0x5, %rax
ja 0x4e0e
leaq 0x3551(%rip), %rcx      # 0x8214
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
cmpl $0x5, %r15d
ja 0x4e0e
movl %r15d, %eax
leaq 0x357c(%rip), %rcx      # 0x825c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x40f0(%rip), %rdi      # 0x8de0
leaq 0x3ed7(%rip), %rsi      # 0x8bce
leaq 0x4bc4(%rip), %rcx      # 0x98c2
movl $0x167, %edx            # imm = 0x167
callq 0x1090
cmpl $0x5, %r15d
ja 0x4e0e
movl %r15d, %eax
leaq 0x3510(%rip), %rcx      # 0x822c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
addq $0x8, %rbx
movq 0x8(%r12), %rsi
leaq 0x3960(%rip), %rax      # 0x8695
movq %rax, (%rsp)
leaq 0x4b63(%rip), %rdx      # 0x98a3
leaq 0x4b74(%rip), %r8       # 0x98bb
pushq $0x4
jmp 0x4e70
cmpl $0x5, %r15d
je 0x4da3
leal -0x1(%r15), %eax
cmpl $0x4, %eax
jae 0x4dea
addq $0x8, %rbx
movq 0x8(%r12), %rsi
leaq 0x3924(%rip), %rax      # 0x8695
movq %rax, (%rsp)
leaq 0x4b27(%rip), %rdx      # 0x98a3
leaq 0x4b38(%rip), %r8       # 0x98bb
pushq $0x5
jmp 0x4e70
cmpl $0x5, %r15d
ja 0x4e0e
movl %r15d, %eax
leaq 0x34aa(%rip), %rcx      # 0x8244
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %r14, %rax
addq $0x10, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x4b3b(%rip), %rdx      # 0x98f5
pushq $0x4
jmp 0x4dc7
leaq 0x4b35(%rip), %rdx      # 0x98fa
pushq $0x10
popq %rsi
movq %rbx, %rdi
callq 0x6716
movq %rbx, %rdi
movq %rax, %rsi
movq %r14, %rdx
addq $0x10, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x67fc
testl %r15d, %r15d
jne 0x4e0e
leaq 0x3fea(%rip), %rdi      # 0x8de0
leaq 0x3dd1(%rip), %rsi      # 0x8bce
leaq 0x4abe(%rip), %rcx      # 0x98c2
movl $0x157, %edx            # imm = 0x157
callq 0x1090
leaq 0x3ff6(%rip), %rdi      # 0x8e0b
leaq 0x3db2(%rip), %rsi      # 0x8bce
leaq 0x4a9f(%rip), %rcx      # 0x98c2
movl $0x192, %edx            # imm = 0x192
callq 0x1090
leaq 0x3fac(%rip), %rdi      # 0x8de0
leaq 0x3d93(%rip), %rsi      # 0x8bce
leaq 0x4a80(%rip), %rcx      # 0x98c2
movl $0x18e, %edx            # imm = 0x18E
callq 0x1090
addq $0x8, %rbx
movq 0x8(%r12), %rsi
leaq 0x3839(%rip), %rax      # 0x8695
movq %rax, (%rsp)
leaq 0x4a3c(%rip), %rdx      # 0x98a3
leaq 0x4a4d(%rip), %r8       # 0x98bb
pushq $0x1
popq %rcx
movq %rbx, %rdi
movl %r15d, %r9d
callq 0x5d62
leaq 0x3f5d(%rip), %rdi      # 0x8de0
leaq 0x3d44(%rip), %rsi      # 0x8bce
leaq 0x4a31(%rip), %rcx      # 0x98c2
movl $0x188, %edx            # imm = 0x188
callq 0x1090
addq $0x8, %rbx
movq 0x8(%r12), %rsi
leaq 0x37ea(%rip), %rax      # 0x8695
movq %rax, (%rsp)
leaq 0x49ed(%rip), %rdx      # 0x98a3
leaq 0x49fe(%rip), %r8       # 0x98bb
pushq $0x3
popq %rcx
pushq $0x2
popq %r9
movq %rbx, %rdi
callq 0x5d62
leaq 0x3f0d(%rip), %rdi      # 0x8de0
leaq 0x3cf4(%rip), %rsi      # 0x8bce
leaq 0x49e1(%rip), %rcx      # 0x98c2
movl $0x178, %edx            # imm = 0x178
callq 0x1090
nop