// File: 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
subq $0xb0, %rsp
movl %esi, -0x18(%rbp)
movq %rdx, -0x10(%rbp)
movq %rdi, -0x20(%rbp)
movq -0x20(%rbp), %rdi
movq %rdi, -0x88(%rbp)
movq -0x10(%rbp), %rsi
callq 0x70d0
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movl 0x4(%rax), %eax
movq %rax, -0x80(%rbp)
subq $0x5, %rax
ja 0x86bd
movq -0x80(%rbp), %rax
leaq 0x61e2(%rip), %rcx      # 0xe4b0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x88(%rbp), %rdi
addq $0x8, %rdi
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
movq -0x10(%rbp), %rax
movl 0x4(%rax), %ecx
movl -0x18(%rbp), %r9d
leaq 0x78bb(%rip), %rdx      # 0xfbb7
leaq 0x78cc(%rip), %r8       # 0xfbcf
leaq 0x65d3(%rip), %rax      # 0xe8dd
movq %rax, (%rsp)
callq 0xa3c0
movl -0x18(%rbp), %eax
movl %eax, -0x8c(%rbp)
testl %eax, %eax
je 0x8387
jmp 0x8322
movl -0x8c(%rbp), %eax
decl %eax
subl $0x4, %eax
jb 0x834b
jmp 0x8331
movl -0x8c(%rbp), %eax
subl $0x5, %eax
jne 0x83a6
jmp 0x833e
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x86dc
movq -0x88(%rbp), %rdi
addq $0x8, %rdi
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
movq -0x10(%rbp), %rax
movl 0x4(%rax), %ecx
movl -0x18(%rbp), %r9d
leaq 0x7847(%rip), %rdx      # 0xfbb7
leaq 0x7858(%rip), %r8       # 0xfbcf
leaq 0x655f(%rip), %rax      # 0xe8dd
movq %rax, (%rsp)
callq 0xa3c0
leaq 0x6d66(%rip), %rdi      # 0xf0f4
leaq 0x6b23(%rip), %rsi      # 0xeeb8
movl $0x157, %edx            # imm = 0x157
leaq 0x7835(%rip), %rcx      # 0xfbd6
callq 0x10c0
jmp 0x86bd
movl -0x18(%rbp), %eax
movq %rax, -0x98(%rbp)
subq $0x5, %rax
ja 0x8494
movq -0x98(%rbp), %rax
leaq 0x612b(%rip), %rcx      # 0xe4f8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x782c(%rip), %rdi      # 0xfc09
movl $0x4, %esi
callq 0x12e0
movq -0x88(%rbp), %rdi
movq %rax, -0x38(%rbp)
movq %rdx, -0x30(%rbp)
movq -0x38(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0xb5c0
movq -0x88(%rbp), %rdi
movq %rax, %rsi
movq -0x28(%rbp), %rdx
callq 0xb780
movq %rax, -0x8(%rbp)
jmp 0x86dc
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x86dc
leaq 0x77db(%rip), %rdi      # 0xfc0e
movl $0x10, %esi
callq 0x12e0
movq -0x88(%rbp), %rdi
movq %rax, -0x48(%rbp)
movq %rdx, -0x40(%rbp)
movq -0x48(%rbp), %rsi
movq -0x40(%rbp), %rdx
callq 0xb5c0
movq -0x88(%rbp), %rdi
movq %rax, %rsi
movq -0x28(%rbp), %rdx
callq 0xb780
movq %rax, -0x8(%rbp)
jmp 0x86dc
leaq 0x6c78(%rip), %rdi      # 0xf0f4
leaq 0x6a35(%rip), %rsi      # 0xeeb8
movl $0x167, %edx            # imm = 0x167
leaq 0x7747(%rip), %rcx      # 0xfbd6
callq 0x10c0
jmp 0x86bd
movl -0x18(%rbp), %eax
movq %rax, -0xa0(%rbp)
subq $0x5, %rax
ja 0x85be
movq -0xa0(%rbp), %rax
leaq 0x6025(%rip), %rcx      # 0xe4e0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x773e(%rip), %rdi      # 0xfc09
movl $0x4, %esi
callq 0x12e0
movq -0x88(%rbp), %rdi
movq %rax, -0x58(%rbp)
movq %rdx, -0x50(%rbp)
movq -0x58(%rbp), %rsi
movq -0x50(%rbp), %rdx
callq 0xb5c0
movq -0x88(%rbp), %rdi
movq %rax, %rsi
movq -0x28(%rbp), %rdx
callq 0xb780
movq %rax, -0x8(%rbp)
jmp 0x86dc
movq -0x88(%rbp), %rdi
addq $0x8, %rdi
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
movq -0x10(%rbp), %rax
movl 0x4(%rax), %ecx
movl -0x18(%rbp), %r9d
leaq 0x7685(%rip), %rdx      # 0xfbb7
leaq 0x7696(%rip), %r8       # 0xfbcf
leaq 0x639d(%rip), %rax      # 0xe8dd
movq %rax, (%rsp)
callq 0xa3c0
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x86dc
leaq 0x76b1(%rip), %rdi      # 0xfc0e
movl $0x10, %esi
callq 0x12e0
movq -0x88(%rbp), %rdi
movq %rax, -0x68(%rbp)
movq %rdx, -0x60(%rbp)
movq -0x68(%rbp), %rsi
movq -0x60(%rbp), %rdx
callq 0xb5c0
movq -0x88(%rbp), %rdi
movq %rax, %rsi
movq -0x28(%rbp), %rdx
callq 0xb780
movq %rax, -0x8(%rbp)
jmp 0x86dc
leaq 0x6b4e(%rip), %rdi      # 0xf0f4
leaq 0x690b(%rip), %rsi      # 0xeeb8
movl $0x178, %edx            # imm = 0x178
leaq 0x761d(%rip), %rcx      # 0xfbd6
callq 0x10c0
jmp 0x86bd
movl -0x18(%rbp), %eax
movq %rax, -0xa8(%rbp)
subq $0x5, %rax
ja 0x869c
movq -0xa8(%rbp), %rax
leaq 0x5ee3(%rip), %rcx      # 0xe4c8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x7614(%rip), %rdi      # 0xfc09
movl $0x4, %esi
callq 0x12e0
movq -0x88(%rbp), %rdi
movq %rax, -0x78(%rbp)
movq %rdx, -0x70(%rbp)
movq -0x78(%rbp), %rsi
movq -0x70(%rbp), %rdx
callq 0xb5c0
movq -0x88(%rbp), %rdi
movq %rax, %rsi
movq -0x28(%rbp), %rdx
callq 0xb780
movq %rax, -0x8(%rbp)
jmp 0x86dc
movq -0x88(%rbp), %rdi
addq $0x8, %rdi
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
movq -0x10(%rbp), %rax
movl 0x4(%rax), %ecx
movl -0x18(%rbp), %r9d
leaq 0x755b(%rip), %rdx      # 0xfbb7
leaq 0x756c(%rip), %r8       # 0xfbcf
leaq 0x6273(%rip), %rax      # 0xe8dd
movq %rax, (%rsp)
callq 0xa3c0
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x86dc
leaq 0x6a70(%rip), %rdi      # 0xf0f4
leaq 0x682d(%rip), %rsi      # 0xeeb8
movl $0x188, %edx            # imm = 0x188
leaq 0x753f(%rip), %rcx      # 0xfbd6
callq 0x10c0
jmp 0x86bd
leaq 0x6a4f(%rip), %rdi      # 0xf0f4
leaq 0x680c(%rip), %rsi      # 0xeeb8
movl $0x18e, %edx            # imm = 0x18E
leaq 0x751e(%rip), %rcx      # 0xfbd6
callq 0x10c0
leaq 0x6a5b(%rip), %rdi      # 0xf11f
leaq 0x67ed(%rip), %rsi      # 0xeeb8
movl $0x192, %edx            # imm = 0x192
leaq 0x74ff(%rip), %rcx      # 0xfbd6
callq 0x10c0
movq -0x8(%rbp), %rax
addq $0xb0, %rsp
popq %rbp
retq
nopl (%rax)