// File: /workspace/github_cpp_makefile_star2_O3/cphinton42[P]hinton-language/src/check.cpp
// Function: combine_number_types(Context*, Expr_AST*, Expr_AST*, Primitive_AST**)
internal
Status combine_number_types(Context *ctx, Expr_AST *t1, Expr_AST *t2, Primitive_AST **out)
{
    Expr_AST *reduced_t1, *reduced_t2;
    Status status = reduce_type(ctx, t1, &reduced_t1);
    if(status != Status::good)
    {
        return status;
    }
    status = reduce_type(ctx, t2, &reduced_t2);
    if(status != Status::good)
    {
        return status;
    }
    if(reduced_t1->type != AST_Type::primitive_ast)
    {
        report_error("Expected number type", t1);
        ctx->success = false;
        return Status::bad;
    }
    if(reduced_t2->type != AST_Type::primitive_ast)
    {
        report_error("Expected number type", t2);
        ctx->success = false;
        return Status::bad;
    }
    Primitive_AST *prim_ast1 = static_cast<Primitive_AST*>(reduced_t1);
    Primitive_AST *prim_ast2 = static_cast<Primitive_AST*>(reduced_t2);
    
    u64 prim1 = prim_ast1->primitive;
    u64 prim2 = prim_ast2->primitive;
    u64 size1 = prim1 & PRIM_SIZE_MASK;
    u64 size2 = prim2 & PRIM_SIZE_MASK;
    u64 max_size = max(size1, size2);
    
    if((prim1 & PRIM_FLOATLIKE) && (prim2 & PRIM_FLOATLIKE))
    {
        if(max_size == PRIM_NO_SIZE)
        {
            // TODO: should this be a concrete type, rather than floatlike?
            *out = &floatlike_t_ast;
        }
        else if(max_size == PRIM_SIZE4)
        {
            *out = &f32_t_ast;
        }
        else
        {
            assert(max_size == PRIM_SIZE8);
            *out = &f64_t_ast;
        }
    }
    else if((prim1 & PRIM_INTLIKE) && (prim2 & PRIM_INTLIKE))
    {
        // TODO: maybe a warning or error if mixing signed and unsigned?
        // Maybe only if u64 and s64, since u64 doesn't necessarily fit in s64
        if((prim1 & PRIM_SIGN_MASK) == PRIM_UNSIGNED_INT && (prim2 & PRIM_SIGN_MASK) == PRIM_UNSIGNED_INT)
        {
            switch(max_size)
            {
                case PRIM_NO_SIZE: {
                    // TODO: maybe make uintlike_t_ast ?
                    *out = &intlike_t_ast;
                } break;
                case PRIM_SIZE1: {
                    *out = &u8_t_ast;
                } break;
                case PRIM_SIZE2: {
                    *out = &u16_t_ast;
                } break;
                case PRIM_SIZE4: {
                    *out = &u32_t_ast;
                } break;
                case PRIM_SIZE8: {
                    *out = &u64_t_ast;
                } break;
                default: {
                    assert(false);
                } break;
            }
        }
        else
        {
            switch(max_size)
            {
                case PRIM_NO_SIZE: {
                    *out = &intlike_t_ast;
                } break;
                case PRIM_SIZE1: {
                    *out = &s8_t_ast;
                } break;
                case PRIM_SIZE2: {
                    *out = &s16_t_ast;
                } break;
                case PRIM_SIZE4: {
                    *out = &s32_t_ast;
                } break;
                case PRIM_SIZE8: {
                    *out = &s64_t_ast;
                } break;
                default: {
                    assert(false);
                } break;
            }
        }
    }
    else
    {
        // TODO: better error reporting
        report_error("Number types don't match", t1, t2);
        ctx->success = false;
        return Status::bad;
    }
    
    return Status::good;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rcx, %rbx
movq %rdx, %r15
movq %rsi, %r12
movq %rdi, %r14
leaq 0x10(%rsp), %rdx
callq 0x684d
testl %eax, %eax
jne 0xcaa5
leaq 0x8(%rsp), %rdx
movq %r14, %rdi
movq %r15, %rsi
callq 0x684d
testl %eax, %eax
jne 0xcaa5
movq 0x10(%rsp), %rax
cmpw $0x11, (%rax)
jne 0xca72
movq 0x8(%rsp), %rcx
cmpw $0x11, (%rcx)
jne 0xca7e
movq 0x20(%rax), %rdx
movq 0x20(%rcx), %rcx
movl %edx, %esi
andl $0x7, %esi
movl %ecx, %eax
andl $0x7, %eax
cmpq %rax, %rsi
cmovaq %rsi, %rax
movq %rcx, %rsi
andq %rdx, %rsi
testb $0x40, %sil
jne 0xcab1
testb $0x20, %sil
jne 0xcad0
movl 0x8(%r12), %esi
movl 0xc(%r12), %edx
movl 0x8(%r15), %ecx
movl 0xc(%r15), %r8d
leaq 0x4318(%rip), %rdi      # 0x10d7a
leaq 0x4f29(%rip), %r9       # 0x11992
xorl %eax, %eax
callq 0x416b
jmp 0xca9b
movl 0x8(%r12), %esi
movl 0xc(%r12), %edx
jmp 0xca86
movl 0x8(%r15), %esi
movl 0xc(%r15), %edx
leaq 0x42db(%rip), %rdi      # 0x10d68
leaq 0x4e81(%rip), %rcx      # 0x11915
xorl %eax, %eax
callq 0x416b
movb $0x0, 0x10(%r14)
movl $0x2, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
cmpl $0x4, %eax
je 0xcb0c
cmpl $0x3, %eax
je 0xcb03
testq %rax, %rax
jne 0xcb7b
leaq 0x935d(%rip), %rax      # 0x15e28
jmp 0xcb71
andl $0x18, %edx
cmpl $0x10, %edx
jne 0xcb15
andl $0x18, %ecx
cmpl $0x10, %ecx
jne 0xcb15
cmpq $0x4, %rax
ja 0xcbb9
leaq 0x3aa3(%rip), %rcx      # 0x10594
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x907f(%rip), %rax      # 0x15b80
jmp 0xcb71
leaq 0x9256(%rip), %rax      # 0x15d60
jmp 0xcb71
leaq 0x9275(%rip), %rax      # 0x15d88
jmp 0xcb71
cmpq $0x4, %rax
ja 0xcb9a
leaq 0x3a5e(%rip), %rcx      # 0x10580
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x92ce(%rip), %rax      # 0x15e00
jmp 0xcb71
leaq 0x915d(%rip), %rax      # 0x15c98
jmp 0xcb71
leaq 0x90b4(%rip), %rax      # 0x15bf8
jmp 0xcb71
leaq 0x90fb(%rip), %rax      # 0x15c48
jmp 0xcb71
leaq 0x9052(%rip), %rax      # 0x15ba8
jmp 0xcb71
leaq 0x9111(%rip), %rax      # 0x15c70
jmp 0xcb71
leaq 0x90b8(%rip), %rax      # 0x15c20
jmp 0xcb71
leaq 0x905f(%rip), %rax      # 0x15bd0
movq %rax, (%rbx)
xorl %eax, %eax
jmp 0xcaa5
leaq 0x4da8(%rip), %rdi      # 0x1192a
leaq 0x4211(%rip), %rsi      # 0x10d9a
leaq 0x4db1(%rip), %rcx      # 0x11941
movl $0x6ca, %edx            # imm = 0x6CA
callq 0x3080
leaq 0x412f(%rip), %rdi      # 0x10cd0
leaq 0x41f2(%rip), %rsi      # 0x10d9a
leaq 0x4d92(%rip), %rcx      # 0x11941
movl $0x6ff, %edx            # imm = 0x6FF
callq 0x3080
leaq 0x4110(%rip), %rdi      # 0x10cd0
leaq 0x41d3(%rip), %rsi      # 0x10d9a
leaq 0x4d73(%rip), %rcx      # 0x11941
movl $0x6e7, %edx            # imm = 0x6E7
callq 0x3080