// File: cphinton42[P]hinton-language/src/check.cpp
// Function: typecheck_binop_ast(Context*, unsigned int, Expr_AST*, Binary_Operator_AST*)
internal
bool typecheck_binop_ast(Context *ctx, u32 stage, Expr_AST *type, Binary_Operator_AST *binop_ast)
{
    u32 new_stage = 0;
    u32 done_stage = 0;
    bool add_job = false;
    
    switch(binop_ast->op)
    {
        case Binary_Operator::cmp_eq:
        case Binary_Operator::cmp_neq:
        case Binary_Operator::cmp_lt:
        case Binary_Operator::cmp_le:
        case Binary_Operator::cmp_gt:
        case Binary_Operator::cmp_ge: {
            done_stage = 4;
            switch(stage)
            {
                case 0: {
                    binop_ast->flags |= EXPR_FLAG_NOT_LVALUE;
                    if(type)
                    {
                        Status status = types_match(ctx, &boollike_t_ast, type);
                        if(status != Status::good)
                        {
                            goto finish;
                        }
                    }
                    add_job = true;
                } // fall through
                case 1: {
                    new_stage = 1;
                    Expr_AST *binop_type;
                    if(type)
                    {
                        binop_type = type;
                    }
                    else
                    {
                        binop_type = &bool8_t_ast;
                    }
                    set_resolved_type(binop_ast, binop_type);
                    add_job = true;
                } // fall through
                case 2: {
                    new_stage = 2;
                    // TODO: change with operator overloading
                    auto job = make_typecheck_job(&numberlike_t_ast, binop_ast->lhs);
                    do_typecheck_job(ctx, job);
                    job = make_typecheck_job(&numberlike_t_ast, binop_ast->rhs);
                    do_typecheck_job(ctx, job);
                    add_job = true;
                } // fall through
                case 3: {
                    new_stage = 3;
                    if(!type_resolved(binop_ast->lhs))
                    {
                        goto finish;
                    }
                    if(!type_resolved(binop_ast->rhs))
                    {
                        goto finish;
                    }
                    Status status = types_match(ctx, binop_ast->lhs->resolved_type, binop_ast->rhs->resolved_type);
                    if(status != Status::good)
                    {
                        goto finish;
                    }
                    new_stage = 4;
                } // fall through
                
            }
        } break;
        case Binary_Operator::add:
        case Binary_Operator::sub:
        case Binary_Operator::mul:
        case Binary_Operator::div: {
            done_stage = 3;
            switch(stage)
            {
                case 0: {
                    binop_ast->flags |= EXPR_FLAG_NOT_LVALUE;
                    if(type)
                    {
                        Status status = types_match(ctx, &numberlike_t_ast, type);
                        if(status != Status::good)
                        {
                            goto finish;
                        }
                    }
                    add_job = true;
                } // fall through
                case 1: {
                    new_stage = 1;
                    Expr_AST *number_type;
                    if(type)
                    {
                        number_type = type;
                    }
                    else
                    {
                        number_type = &numberlike_t_ast;
                    }
                    auto job = make_typecheck_job(number_type, binop_ast->lhs);
                    do_typecheck_job(ctx, job);
                    job = make_typecheck_job(number_type, binop_ast->rhs);
                    do_typecheck_job(ctx, job);
                    add_job = true;
                } // fall through
                case 2: {
                    new_stage = 2;
                    if(!type_resolved(binop_ast->lhs))
                    {
                        goto finish;
                    }
                    if(!type_resolved(binop_ast->rhs))
                    {
                        goto finish;
                    }
                    Primitive_AST *combined;
                    Status status = combine_number_types(ctx, binop_ast->lhs->resolved_type, binop_ast->rhs->resolved_type, &combined);
                    if(status != Status::good)
                    {
                        goto finish;
                    }
                    if(type)
                    {
                        status = types_match(ctx, type, combined);
                        if(status != Status::good)
                        {
                            goto finish;
                        }
                    }
                    set_resolved_type(binop_ast, combined);
                    new_stage = 3;
                } // fall through
            }
        } break;
        case Binary_Operator::subscript: {
            // TODO: change once operator overloading is a thing
            // Polymorphism may also change it (e.g. operator[](ptr : &$T) -> &T
            done_stage = 2;
            switch(stage)
            {
                case 0: {
                    // TODO: once fixed size arrays are a thing, this may not be an lvalue
                    binop_ast->flags |= EXPR_FLAG_LVALUE;
                    Expr_AST *type_to_check = nullptr;
                    if(type)
                    {
                        // TODO: maybe make a canonical type table, so not every & makes a new type in memory
                        Unary_Operator_AST *type_to_deref = construct_ast(ctx->ast_pool, Unary_Operator_AST, 0, 0);
                        type_to_deref->flags |= AST_FLAG_SYNTHETIC;
                        set_resolved_type(type_to_deref, &type_t_ast);
                        type_to_deref->op = Unary_Operator::ref;
                        type_to_deref->operand = type;
                        type_to_check = type_to_deref;
                    }
                    auto job = make_typecheck_job(type_to_check, binop_ast->lhs);
                    do_typecheck_job(ctx, job);
                    job = make_typecheck_job(&numberlike_t_ast, binop_ast->rhs);
                    do_typecheck_job(ctx, job);
                } // fall through
                case 1: {
                    new_stage = 1;
                    if(!type_resolved(binop_ast->lhs))
                    {
                        goto finish;
                    }
                    Expr_AST *reduced;
                    Status status = reduce_type(ctx, binop_ast->lhs->resolved_type, &reduced);
                    if(status != Status::good)
                    {
                        goto finish;
                    }
                    if(reduced->type != AST_Type::unary_ast)
                    {
                        report_error("Expected expr of pointer type", binop_ast->lhs);
                        ctx->success = false;
                        goto finish;
                    }
                    Unary_Operator_AST *lhs_type = static_cast<Unary_Operator_AST*>(reduced);
                    assert(lhs_type->resolved_type == &type_t_ast);
                    assert(lhs_type->op == Unary_Operator::ref);
                    status = types_match(ctx, type, lhs_type->operand);
                    if(status != Status::good)
                    {
                        goto finish;
                    }
                    set_resolved_type(binop_ast, lhs_type->operand);
                    new_stage = 2;
                } // fall through
            }
        } break;
        case Binary_Operator::lor:
        case Binary_Operator::land: {
            done_stage = 1;
            Expr_AST *bool_type;
            if(type)
            {
                Status status = types_match(ctx, &boollike_t_ast, type);
                if(status != Status::good)
                {
                    goto finish;
                }
                bool_type = type;
            }
            else
            {
                bool_type = &bool8_t_ast;
            }
            binop_ast->flags |= EXPR_FLAG_NOT_LVALUE;
            auto job = make_typecheck_job(bool_type, binop_ast->lhs);
            do_typecheck_job(ctx, job);
            job = make_typecheck_job(bool_type, binop_ast->rhs);
            do_typecheck_job(ctx, job);
            
            // TODO: make sure this is a concrete bool type, not boollike
            set_resolved_type(binop_ast, bool_type);
            new_stage = 1;
        } break;
    }
    finish:
    
    if(new_stage < done_stage)
    {
        auto job = make_typecheck_job(type, binop_ast, new_stage);
        array_add(ctx->waiting_jobs, job);
    }
    return new_stage != stage;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x280, %rsp            # imm = 0x280
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
movl $0x0, -0x28(%rbp)
movb $0x0, -0x29(%rbp)
movq -0x20(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x258(%rbp)
subq $0xc, %rax
ja 0x7b8b
movq -0x258(%rbp), %rax
leaq 0x11e6d(%rip), %rcx     # 0x190e0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x4, -0x28(%rbp)
movl -0xc(%rbp), %eax
movq %rax, -0x260(%rbp)
subq $0x3, %rax
ja 0x7478
movq -0x260(%rbp), %rax
leaq 0x11e6f(%rip), %rcx     # 0x19114
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x20(%rbp), %rax
movzwl 0x2(%rax), %ecx
orl $0x20, %ecx
movw %cx, 0x2(%rax)
cmpq $0x0, -0x18(%rbp)
je 0x72ed
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rdx
leaq 0x18cbd(%rip), %rsi     # 0x1ff90
movl $0x1, %ecx
callq 0x9240
movl %eax, -0x30(%rbp)
cmpl $0x0, -0x30(%rbp)
je 0x72eb
jmp 0x7b8d
jmp 0x72ed
movb $0x1, -0x29(%rbp)
movl $0x1, -0x24(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0x7309
movq -0x18(%rbp), %rax
movq %rax, -0x38(%rbp)
jmp 0x7314
leaq 0x18ac8(%rip), %rax     # 0x1fdd8
movq %rax, -0x38(%rbp)
movq -0x20(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x3be0
movb $0x1, -0x29(%rbp)
movl $0x2, -0x24(%rbp)
movq -0x20(%rbp), %rax
movq 0x28(%rax), %rdx
leaq -0x50(%rbp), %rdi
leaq 0x18c29(%rip), %rsi     # 0x1ff68
xorl %ecx, %ecx
callq 0x4a80
movq -0x8(%rbp), %rdi
movq -0x50(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0x58(%rbp)
leaq -0x68(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0x4b40
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rdx
leaq -0x80(%rbp), %rdi
leaq 0x18bd1(%rip), %rsi     # 0x1ff68
xorl %ecx, %ecx
callq 0x4a80
movq -0x80(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x78(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x70(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x8(%rbp), %rdi
movq -0x50(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0x88(%rbp)
leaq -0x98(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0x4b40
movb $0x1, -0x29(%rbp)
movl $0x3, -0x24(%rbp)
movq -0x20(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x5600
testb $0x1, %al
jne 0x7421
jmp 0x7b8d
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0x5600
testb $0x1, %al
jne 0x7437
jmp 0x7b8d
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x18(%rax), %rsi
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rax
movq 0x18(%rax), %rdx
movl $0x1, %ecx
callq 0x9240
movl %eax, -0x9c(%rbp)
cmpl $0x0, -0x9c(%rbp)
je 0x7471
jmp 0x7b8d
movl $0x4, -0x24(%rbp)
jmp 0x7b8b
movl $0x3, -0x28(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0x264(%rbp)
testl %eax, %eax
je 0x74b4
jmp 0x7493
movl -0x264(%rbp), %eax
subl $0x1, %eax
je 0x74fd
jmp 0x74a0
movl -0x264(%rbp), %eax
subl $0x2, %eax
je 0x7634
jmp 0x76f0
movq -0x20(%rbp), %rax
movzwl 0x2(%rax), %ecx
orl $0x20, %ecx
movw %cx, 0x2(%rax)
cmpq $0x0, -0x18(%rbp)
je 0x74f9
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rdx
leaq 0x18a8f(%rip), %rsi     # 0x1ff68
movl $0x1, %ecx
callq 0x9240
movl %eax, -0xa0(%rbp)
cmpl $0x0, -0xa0(%rbp)
je 0x74f7
jmp 0x7b8d
jmp 0x74f9
movb $0x1, -0x29(%rbp)
movl $0x1, -0x24(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0x7518
movq -0x18(%rbp), %rax
movq %rax, -0xa8(%rbp)
jmp 0x7526
leaq 0x18a49(%rip), %rax     # 0x1ff68
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rsi
movq -0x20(%rbp), %rax
movq 0x28(%rax), %rdx
leaq -0xc0(%rbp), %rdi
xorl %ecx, %ecx
callq 0x4a80
movq -0x8(%rbp), %rdi
movq -0xc0(%rbp), %rax
movq %rax, -0xd8(%rbp)
movq -0xb8(%rbp), %rax
movq %rax, -0xd0(%rbp)
movq -0xb0(%rbp), %rax
movq %rax, -0xc8(%rbp)
leaq -0xd8(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0x4b40
movq -0xa8(%rbp), %rsi
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rdx
leaq -0xf0(%rbp), %rdi
xorl %ecx, %ecx
callq 0x4a80
movq -0xf0(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0xe8(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0xe0(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0x8(%rbp), %rdi
movq -0xc0(%rbp), %rax
movq %rax, -0x108(%rbp)
movq -0xb8(%rbp), %rax
movq %rax, -0x100(%rbp)
movq -0xb0(%rbp), %rax
movq %rax, -0xf8(%rbp)
leaq -0x108(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0x4b40
movb $0x1, -0x29(%rbp)
movl $0x2, -0x24(%rbp)
movq -0x20(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x5600
testb $0x1, %al
jne 0x7651
jmp 0x7b8d
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0x5600
testb $0x1, %al
jne 0x7667
jmp 0x7b8d
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x18(%rax), %rsi
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rax
movq 0x18(%rax), %rdx
leaq -0x110(%rbp), %rcx
callq 0x12010
movl %eax, -0x114(%rbp)
cmpl $0x0, -0x114(%rbp)
je 0x76a3
jmp 0x7b8d
cmpq $0x0, -0x18(%rbp)
je 0x76d9
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x110(%rbp), %rdx
movl $0x1, %ecx
callq 0x9240
movl %eax, -0x114(%rbp)
cmpl $0x0, -0x114(%rbp)
je 0x76d7
jmp 0x7b8d
jmp 0x76d9
movq -0x20(%rbp), %rdi
movq -0x110(%rbp), %rsi
callq 0x3be0
movl $0x3, -0x24(%rbp)
jmp 0x7b8b
movl $0x2, -0x28(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0x268(%rbp)
testl %eax, %eax
je 0x771f
jmp 0x770b
movl -0x268(%rbp), %eax
subl $0x1, %eax
je 0x78c7
jmp 0x7a00
movq -0x20(%rbp), %rax
movzwl 0x2(%rax), %ecx
orl $0x10, %ecx
movw %cx, 0x2(%rax)
movq $0x0, -0x120(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0x77bd
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0x30, %esi
callq 0xcd80
movq %rax, %rdi
movl $0x10, %esi
xorl %eax, %eax
movl %eax, %ecx
movq %rcx, %rdx
callq 0x3c10
movq %rax, -0x128(%rbp)
movq -0x128(%rbp), %rax
movzwl 0x2(%rax), %ecx
orl $0x1, %ecx
movw %cx, 0x2(%rax)
movq -0x128(%rbp), %rdi
leaq 0x18764(%rip), %rsi     # 0x1fef0
callq 0x3be0
movq -0x128(%rbp), %rax
movq $0x3, 0x20(%rax)
movq -0x18(%rbp), %rcx
movq -0x128(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x128(%rbp), %rax
movq %rax, -0x120(%rbp)
movq -0x120(%rbp), %rsi
movq -0x20(%rbp), %rax
movq 0x28(%rax), %rdx
leaq -0x140(%rbp), %rdi
xorl %ecx, %ecx
callq 0x4a80
movq -0x8(%rbp), %rdi
movq -0x140(%rbp), %rax
movq %rax, -0x158(%rbp)
movq -0x138(%rbp), %rax
movq %rax, -0x150(%rbp)
movq -0x130(%rbp), %rax
movq %rax, -0x148(%rbp)
leaq -0x158(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0x4b40
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rdx
leaq -0x170(%rbp), %rdi
leaq 0x18725(%rip), %rsi     # 0x1ff68
xorl %ecx, %ecx
callq 0x4a80
movq -0x170(%rbp), %rax
movq %rax, -0x140(%rbp)
movq -0x168(%rbp), %rax
movq %rax, -0x138(%rbp)
movq -0x160(%rbp), %rax
movq %rax, -0x130(%rbp)
movq -0x8(%rbp), %rdi
movq -0x140(%rbp), %rax
movq %rax, -0x188(%rbp)
movq -0x138(%rbp), %rax
movq %rax, -0x180(%rbp)
movq -0x130(%rbp), %rax
movq %rax, -0x178(%rbp)
leaq -0x188(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0x4b40
movl $0x1, -0x24(%rbp)
movq -0x20(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x5600
testb $0x1, %al
jne 0x78e4
jmp 0x7b8d
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x18(%rax), %rsi
leaq -0x190(%rbp), %rdx
callq 0x9040
movl %eax, -0x194(%rbp)
cmpl $0x0, -0x194(%rbp)
je 0x7914
jmp 0x7b8d
movq -0x190(%rbp), %rax
cmpw $0x10, (%rax)
je 0x7942
movq -0x20(%rbp), %rax
movq 0x28(%rax), %rsi
leaq 0x13107(%rip), %rdi     # 0x1aa37
callq 0x4950
movq -0x8(%rbp), %rax
movb $0x0, 0x10(%rax)
jmp 0x7b8d
movq -0x190(%rbp), %rax
movq %rax, -0x1a0(%rbp)
movq -0x1a0(%rbp), %rax
leaq 0x18592(%rip), %rcx     # 0x1fef0
cmpq %rcx, 0x18(%rax)
jne 0x7966
jmp 0x7985
leaq 0x130e8(%rip), %rdi     # 0x1aa55
leaq 0x12578(%rip), %rsi     # 0x19eec
movl $0x3be, %edx            # imm = 0x3BE
leaq 0x130fc(%rip), %rcx     # 0x1aa7c
callq 0x3080
movq -0x1a0(%rbp), %rax
cmpq $0x3, 0x20(%rax)
jne 0x7995
jmp 0x79b4
leaq 0x1312c(%rip), %rdi     # 0x1aac8
leaq 0x12549(%rip), %rsi     # 0x19eec
movl $0x3bf, %edx            # imm = 0x3BF
leaq 0x130cd(%rip), %rcx     # 0x1aa7c
callq 0x3080
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x1a0(%rbp), %rax
movq 0x28(%rax), %rdx
movl $0x1, %ecx
callq 0x9240
movl %eax, -0x194(%rbp)
cmpl $0x0, -0x194(%rbp)
je 0x79e5
jmp 0x7b8d
movq -0x20(%rbp), %rdi
movq -0x1a0(%rbp), %rax
movq 0x28(%rax), %rsi
callq 0x3be0
movl $0x2, -0x24(%rbp)
jmp 0x7b8b
movl $0x1, -0x28(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0x7a4d
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rdx
leaq 0x1856e(%rip), %rsi     # 0x1ff90
movl $0x1, %ecx
callq 0x9240
movl %eax, -0x1ac(%rbp)
cmpl $0x0, -0x1ac(%rbp)
je 0x7a40
jmp 0x7b8d
movq -0x18(%rbp), %rax
movq %rax, -0x1a8(%rbp)
jmp 0x7a5b
leaq 0x18384(%rip), %rax     # 0x1fdd8
movq %rax, -0x1a8(%rbp)
movq -0x20(%rbp), %rax
movzwl 0x2(%rax), %ecx
orl $0x20, %ecx
movw %cx, 0x2(%rax)
movq -0x1a8(%rbp), %rsi
movq -0x20(%rbp), %rax
movq 0x28(%rax), %rdx
leaq -0x1c8(%rbp), %rdi
xorl %ecx, %ecx
callq 0x4a80
movq -0x8(%rbp), %rdi
movq -0x1c8(%rbp), %rax
movq %rax, -0x1e0(%rbp)
movq -0x1c0(%rbp), %rax
movq %rax, -0x1d8(%rbp)
movq -0x1b8(%rbp), %rax
movq %rax, -0x1d0(%rbp)
leaq -0x1e0(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0x4b40
movq -0x1a8(%rbp), %rsi
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rdx
leaq -0x1f8(%rbp), %rdi
xorl %ecx, %ecx
callq 0x4a80
movq -0x1f8(%rbp), %rax
movq %rax, -0x1c8(%rbp)
movq -0x1f0(%rbp), %rax
movq %rax, -0x1c0(%rbp)
movq -0x1e8(%rbp), %rax
movq %rax, -0x1b8(%rbp)
movq -0x8(%rbp), %rdi
movq -0x1c8(%rbp), %rax
movq %rax, -0x210(%rbp)
movq -0x1c0(%rbp), %rax
movq %rax, -0x208(%rbp)
movq -0x1b8(%rbp), %rax
movq %rax, -0x200(%rbp)
leaq -0x210(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0x4b40
movq -0x20(%rbp), %rdi
movq -0x1a8(%rbp), %rsi
callq 0x3be0
movl $0x1, -0x24(%rbp)
jmp 0x7b8d
movl -0x24(%rbp), %eax
cmpl -0x28(%rbp), %eax
jae 0x7c31
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
movl -0x24(%rbp), %ecx
leaq -0x228(%rbp), %rdi
callq 0x4a80
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x228(%rbp), %rax
movq %rax, -0x240(%rbp)
movq -0x220(%rbp), %rax
movq %rax, -0x238(%rbp)
movq -0x218(%rbp), %rax
movq %rax, -0x230(%rbp)
movq 0x18097(%rip), %rax     # 0x1fc80
movq %rax, -0x250(%rbp)
movq 0x18091(%rip), %rax     # 0x1fc88
movq %rax, -0x248(%rbp)
movq -0x250(%rbp), %rsi
movq -0x248(%rbp), %rdx
leaq -0x240(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0x17c30
movl -0x24(%rbp), %eax
cmpl -0xc(%rbp), %eax
setne %al
andb $0x1, %al
addq $0x280, %rsp            # imm = 0x280
popq %rbp
retq
nopw %cs:(%rax,%rax)