// File: /workspace/github_cpp_makefile_star2_O3/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 0x4f8e
movq %rax, %r14
movl 0x4(%r12), %eax
cmpq $0x5, %rax
ja 0x5c2c
leaq 0x3825(%rip), %rcx      # 0x92dc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
cmpl $0x5, %r15d
ja 0x5c2c
movl %r15d, %eax
leaq 0x3850(%rip), %rcx      # 0x9324
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x4308(%rip), %rdi      # 0x9dec
leaq 0x40ef(%rip), %rsi      # 0x9bda
leaq 0x4ddc(%rip), %rcx      # 0xa8ce
movl $0x167, %edx            # imm = 0x167
callq 0x1090
cmpl $0x5, %r15d
ja 0x5c2c
movl %r15d, %eax
leaq 0x37e4(%rip), %rcx      # 0x92f4
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
addq $0x8, %rbx
movq 0x8(%r12), %rsi
leaq 0x3b78(%rip), %rax      # 0x96a1
movq %rax, (%rsp)
leaq 0x4d7b(%rip), %rdx      # 0xa8af
leaq 0x4d8c(%rip), %r8       # 0xa8c7
movq %rbx, %rdi
movl $0x4, %ecx
jmp 0x5c94
cmpl $0x5, %r15d
je 0x5ba7
leal -0x1(%r15), %eax
cmpl $0x4, %eax
jae 0x5c08
addq $0x8, %rbx
movq 0x8(%r12), %rsi
leaq 0x3b36(%rip), %rax      # 0x96a1
movq %rax, (%rsp)
leaq 0x4d39(%rip), %rdx      # 0xa8af
leaq 0x4d4a(%rip), %r8       # 0xa8c7
movq %rbx, %rdi
movl $0x5, %ecx
jmp 0x5c94
cmpl $0x5, %r15d
ja 0x5c2c
movl %r15d, %eax
leaq 0x376e(%rip), %rcx      # 0x930c
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 0x4d43(%rip), %r15      # 0xa901
movl $0x4, %r12d
jmp 0x5bd3
leaq 0x4d39(%rip), %r15      # 0xa906
movl $0x10, %r12d
movq (%rbx), %rdi
movl $0x1, %esi
callq 0x8296
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 0x7bbe
testl %r15d, %r15d
jne 0x5c2c
leaq 0x41d8(%rip), %rdi      # 0x9dec
leaq 0x3fbf(%rip), %rsi      # 0x9bda
leaq 0x4cac(%rip), %rcx      # 0xa8ce
movl $0x157, %edx            # imm = 0x157
callq 0x1090
leaq 0x41e4(%rip), %rdi      # 0x9e17
leaq 0x3fa0(%rip), %rsi      # 0x9bda
leaq 0x4c8d(%rip), %rcx      # 0xa8ce
movl $0x192, %edx            # imm = 0x192
callq 0x1090
leaq 0x419a(%rip), %rdi      # 0x9dec
leaq 0x3f81(%rip), %rsi      # 0x9bda
leaq 0x4c6e(%rip), %rcx      # 0xa8ce
movl $0x18e, %edx            # imm = 0x18E
callq 0x1090
addq $0x8, %rbx
movq 0x8(%r12), %rsi
leaq 0x3a27(%rip), %rax      # 0x96a1
movq %rax, (%rsp)
leaq 0x4c2a(%rip), %rdx      # 0xa8af
leaq 0x4c3b(%rip), %r8       # 0xa8c7
movq %rbx, %rdi
movl $0x1, %ecx
movl %r15d, %r9d
callq 0x6fce
leaq 0x4149(%rip), %rdi      # 0x9dec
leaq 0x3f30(%rip), %rsi      # 0x9bda
leaq 0x4c1d(%rip), %rcx      # 0xa8ce
movl $0x188, %edx            # imm = 0x188
callq 0x1090
addq $0x8, %rbx
movq 0x8(%r12), %rsi
leaq 0x39d6(%rip), %rax      # 0x96a1
movq %rax, (%rsp)
leaq 0x4bd9(%rip), %rdx      # 0xa8af
leaq 0x4bea(%rip), %r8       # 0xa8c7
movq %rbx, %rdi
movl $0x3, %ecx
movl $0x2, %r9d
callq 0x6fce
leaq 0x40f5(%rip), %rdi      # 0x9dec
leaq 0x3edc(%rip), %rsi      # 0x9bda
leaq 0x4bc9(%rip), %rcx      # 0xa8ce
movl $0x178, %edx            # imm = 0x178
callq 0x1090
nop