// File: /workspace/github_cpp_makefile_star2_O1/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 0x51b2
movl 0x4(%r12), %ecx
cmpq $0x5, %rcx
ja 0x5e3e
movq %rax, %r14
leaq 0x45ed(%rip), %rax      # 0xa2c8
movslq (%rax,%rcx,4), %rdx
addq %rax, %rdx
jmpq *%rdx
cmpl $0x5, %r15d
ja 0x5e3e
movl %r15d, %eax
leaq 0x4618(%rip), %rcx      # 0xa310
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x50c4(%rip), %rdi      # 0xadcc
leaq 0x4eab(%rip), %rsi      # 0xabba
leaq 0x5b98(%rip), %rcx      # 0xb8ae
movl $0x167, %edx            # imm = 0x167
callq 0x1090
cmpl $0x5, %r15d
ja 0x5e3e
movl %r15d, %eax
leaq 0x45ac(%rip), %rdx      # 0xa2e0
movslq (%rdx,%rax,4), %rax
addq %rdx, %rax
jmpq *%rax
leaq 0x5088(%rip), %rdi      # 0xadcc
leaq 0x4e6f(%rip), %rsi      # 0xabba
leaq 0x5b5c(%rip), %rcx      # 0xb8ae
movl $0x188, %edx            # imm = 0x188
callq 0x1090
cmpl $0x5, %r15d
je 0x5db9
leal -0x1(%r15), %eax
cmpl $0x4, %eax
jae 0x5e1a
addq $0x8, %rbx
movq 0x8(%r12), %rsi
leaq 0x4902(%rip), %rax      # 0xa681
movq %rax, (%rsp)
leaq 0x5b05(%rip), %rdx      # 0xb88f
leaq 0x5b16(%rip), %r8       # 0xb8a7
movq %rbx, %rdi
movl %r15d, %r9d
callq 0x726a
cmpl $0x5, %r15d
ja 0x5e3e
movl %r15d, %eax
leaq 0x4548(%rip), %rcx      # 0xa2f8
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 0x5b11(%rip), %r15      # 0xb8e1
movl $0x4, %r12d
jmp 0x5de5
leaq 0x5b07(%rip), %r15      # 0xb8e6
movl $0x10, %r12d
movq (%rbx), %rdi
movl $0x1, %esi
callq 0x85c6
movl $0x1, (%rax)
movq %r12, 0x8(%rax)
movq %r15, 0x10(%rax)
movq %rbx, %rdi
movq %rax, %rsi
movq %r14, %rdx
addq $0x10, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x7e62
testl %r15d, %r15d
jne 0x5e3e
leaq 0x4fa6(%rip), %rdi      # 0xadcc
leaq 0x4d8d(%rip), %rsi      # 0xabba
leaq 0x5a7a(%rip), %rcx      # 0xb8ae
movl $0x157, %edx            # imm = 0x157
callq 0x1090
leaq 0x4fb2(%rip), %rdi      # 0xadf7
leaq 0x4d6e(%rip), %rsi      # 0xabba
leaq 0x5a5b(%rip), %rcx      # 0xb8ae
movl $0x192, %edx            # imm = 0x192
callq 0x1090
leaq 0x4f68(%rip), %rdi      # 0xadcc
leaq 0x4d4f(%rip), %rsi      # 0xabba
leaq 0x5a3c(%rip), %rcx      # 0xb8ae
movl $0x18e, %edx            # imm = 0x18E
callq 0x1090
addq $0x8, %rbx
movq 0x8(%r12), %rsi
leaq 0x47f5(%rip), %rax      # 0xa681
movq %rax, (%rsp)
leaq 0x59f8(%rip), %rdx      # 0xb88f
leaq 0x5a09(%rip), %r8       # 0xb8a7
movq %rbx, %rdi
movl $0x1, %ecx
jmp 0x5d94
addq $0x8, %rbx
movq 0x8(%r12), %rsi
leaq 0x47c6(%rip), %rax      # 0xa681
movq %rax, (%rsp)
leaq 0x59c9(%rip), %rdx      # 0xb88f
leaq 0x59da(%rip), %r8       # 0xb8a7
movq %rbx, %rdi
movl $0x3, %ecx
movl $0x2, %r9d
callq 0x726a
leaq 0x4ee5(%rip), %rdi      # 0xadcc
leaq 0x4ccc(%rip), %rsi      # 0xabba
leaq 0x59b9(%rip), %rcx      # 0xb8ae
movl $0x178, %edx            # imm = 0x178
callq 0x1090
nop