// File: /workspace/github_cpp_makefile_star2_O1/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 0x6b4e
testl %eax, %eax
jne 0xcc43
leaq 0x8(%rsp), %rdx
movq %r14, %rdi
movq %r15, %rsi
callq 0x6b4e
testl %eax, %eax
jne 0xcc43
movq 0x10(%rsp), %rax
cmpw $0x11, (%rax)
jne 0xcc10
movq 0x8(%rsp), %rcx
cmpw $0x11, (%rcx)
jne 0xcc1c
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
movl %ecx, %esi
andl %edx, %esi
testb $0x40, %sil
jne 0xcc4f
movl %ecx, %esi
andl %edx, %esi
testb $0x20, %sil
jne 0xcc6e
movl 0x8(%r12), %esi
movl 0xc(%r12), %edx
movl 0x8(%r15), %ecx
movl 0xc(%r15), %r8d
leaq 0x417a(%rip), %rdi      # 0x10d7a
leaq 0x4e10(%rip), %r9       # 0x11a17
xorl %eax, %eax
callq 0x4261
jmp 0xcc39
movl 0x8(%r12), %esi
movl 0xc(%r12), %edx
jmp 0xcc24
movl 0x8(%r15), %esi
movl 0xc(%r15), %edx
leaq 0x413d(%rip), %rdi      # 0x10d68
leaq 0x4d68(%rip), %rcx      # 0x1199a
xorl %eax, %eax
callq 0x4261
movb $0x0, 0x10(%r14)
movl $0x2, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
cmpl $0x4, %eax
je 0xccaa
cmpl $0x3, %eax
je 0xcca1
testq %rax, %rax
jne 0xcd19
leaq 0x91bf(%rip), %rax      # 0x15e28
jmp 0xcd0f
andl $0x18, %edx
cmpl $0x10, %edx
jne 0xccb3
andl $0x18, %ecx
cmpl $0x10, %ecx
jne 0xccb3
cmpq $0x4, %rax
ja 0xcd57
leaq 0x3905(%rip), %rcx      # 0x10594
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x8ee1(%rip), %rax      # 0x15b80
jmp 0xcd0f
leaq 0x90b8(%rip), %rax      # 0x15d60
jmp 0xcd0f
leaq 0x90d7(%rip), %rax      # 0x15d88
jmp 0xcd0f
cmpq $0x4, %rax
ja 0xcd38
leaq 0x38c0(%rip), %rcx      # 0x10580
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x9130(%rip), %rax      # 0x15e00
jmp 0xcd0f
leaq 0x8fbf(%rip), %rax      # 0x15c98
jmp 0xcd0f
leaq 0x8f16(%rip), %rax      # 0x15bf8
jmp 0xcd0f
leaq 0x8f5d(%rip), %rax      # 0x15c48
jmp 0xcd0f
leaq 0x8eb4(%rip), %rax      # 0x15ba8
jmp 0xcd0f
leaq 0x8f73(%rip), %rax      # 0x15c70
jmp 0xcd0f
leaq 0x8f1a(%rip), %rax      # 0x15c20
jmp 0xcd0f
leaq 0x8ec1(%rip), %rax      # 0x15bd0
movq %rax, (%rbx)
xorl %eax, %eax
jmp 0xcc43
leaq 0x4c8f(%rip), %rdi      # 0x119af
leaq 0x4073(%rip), %rsi      # 0x10d9a
leaq 0x4c98(%rip), %rcx      # 0x119c6
movl $0x6ca, %edx            # imm = 0x6CA
callq 0x3080
leaq 0x3f91(%rip), %rdi      # 0x10cd0
leaq 0x4054(%rip), %rsi      # 0x10d9a
leaq 0x4c79(%rip), %rcx      # 0x119c6
movl $0x6ff, %edx            # imm = 0x6FF
callq 0x3080
leaq 0x3f72(%rip), %rdi      # 0x10cd0
leaq 0x4035(%rip), %rsi      # 0x10d9a
leaq 0x4c5a(%rip), %rcx      # 0x119c6
movl $0x6e7, %edx            # imm = 0x6E7
callq 0x3080