// File: /workspace/github_c_makefile_star2_O2/jtuu[P]quesler/src/compiler.c
// Function: binary
static void binary(bool can_assign) {
    UNUSED(can_assign);

    int ret;
    uint8_t reg1, reg2;

    if ((ret = alloc_register()) < 0) {
        error_alloc_register();
        return;
    }

    reg1 = (uint8_t) ret;

    if ((ret = alloc_register()) < 0) {
        free_register(reg1);
        error_alloc_register();
        return;
    }

    reg2 = (uint8_t) ret;

#define BINARY_OP_I(opcode) \
    do { \
        emit_stack_pop(reg2); \
        emit_stack_pop(reg1); \
 \
        emit_opcode(opcode); \
        emit_register(reg1); \
        emit_register(reg2); \
 \
        emit_stack_push(reg1); \
 \
        free_register(reg1); \
        free_register(reg2); \
    } while (false)

#define COMPARISON_OP(opcode) \
    do { \
        size_t label_true = take_label(); \
        size_t label_continue = take_label(); \
 \
        emit_stack_pop(reg2); \
        emit_stack_pop(reg1); \
 \
        emit_conditional_jump_rr(opcode, reg1, reg2, label_true); \
 \
        emit_stack_push_value(CONSTANT_FALSE); \
        emit_jump(label_continue); \
 \
        set_label_here(label_true); \
        emit_stack_push_value(CONSTANT_TRUE); \
 \
        set_label_here(label_continue); \
    } while (false)

    TokenType operator_type = parser.previous.type;

    ParseRule* rule = get_rule(operator_type);
    parse_precedence((Precedence) (rule->precedence + 1));

    switch (operator_type) {
        case TOKEN_PLUS: 
            BINARY_OP_I(OP_ADD);
            break;
        case TOKEN_MINUS:
            BINARY_OP_I(OP_SUB);
            break;
        case TOKEN_STAR:
            BINARY_OP_I(OP_MUL);
            break;
        case TOKEN_SLASH:
            BINARY_OP_I(OP_DIV);
            break;
        case TOKEN_EQUAL_EQUAL:
            COMPARISON_OP(OP_JMP_EQ);
            break;
        case TOKEN_BANG_EQUAL:
            COMPARISON_OP(OP_JMP_NEQ);
            break;
        case TOKEN_GREATER:
            COMPARISON_OP(OP_JMP_GT);
            break;
        case TOKEN_LESS:
            COMPARISON_OP(OP_JMP_LT);
            break;
        case TOKEN_GREATER_EQUAL:
            COMPARISON_OP(OP_JMP_GTE);
            break;
        case TOKEN_LESS_EQUAL:
            COMPARISON_OP(OP_JMP_LTE);
            break;
        default:
            error("Unknown token");
            break;
    }

    free_register(reg1);
    free_register(reg2);

#undef BINARY_OP_I
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
callq 0x54e1
testl %eax, %eax
js 0x49b9
movl %eax, %ebx
callq 0x54e1
testl %eax, %eax
js 0x49b1
movl %eax, %r14d
movl 0x10c6e(%rip), %r15d    # 0x155d0
imulq $0x18, %r15, %rax
leaq 0x10773(%rip), %rcx     # 0x150e0
movl 0x10(%rax,%rcx), %edi
incl %edi
callq 0x530a
leal -0x5(%r15), %eax
movzbl %bl, %ebp
movzbl %r14b, %ebx
cmpl $0xf, %eax
ja 0x4a5e
leaq 0x36b9(%rip), %rcx      # 0x804c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl %ebx, %edi
callq 0x5551
movl %ebp, %edi
callq 0x5551
pushq $0x1a
jmp 0x4a7f
movzbl %bl, %edi
callq 0x551c
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x5510
movl %ebx, %edi
callq 0x5551
movl %ebp, %edi
callq 0x5551
pushq $0x1e
jmp 0x4a7f
callq 0x5654
movq %rax, %r15
callq 0x5654
movq %rax, %r14
movl %ebx, %edi
callq 0x5551
movl %ebp, %edi
callq 0x5551
pushq $0x2c
jmp 0x4b11
movl %ebx, %edi
callq 0x5551
movl %ebp, %edi
callq 0x5551
pushq $0x18
jmp 0x4a7f
callq 0x5654
movq %rax, %r15
callq 0x5654
movq %rax, %r14
movl %ebx, %edi
callq 0x5551
movl %ebp, %edi
callq 0x5551
pushq $0x32
jmp 0x4b11
callq 0x5654
movq %rax, %r15
callq 0x5654
movq %rax, %r14
movl %ebx, %edi
callq 0x5551
movl %ebp, %edi
callq 0x5551
pushq $0x3a
jmp 0x4b11
leaq 0x38a4(%rip), %rdi      # 0x8309
callq 0x52e1
jmp 0x4b45
movl %ebx, %edi
callq 0x5551
movl %ebp, %edi
callq 0x5551
pushq $0x1c
popq %rdi
callq 0x5561
movl %ebp, %edi
callq 0x55a9
movl %ebx, %edi
callq 0x55a9
movl %ebp, %edi
callq 0x54ce
movl %ebp, %edi
callq 0x551c
movl %ebx, %edi
callq 0x551c
jmp 0x4b45
callq 0x5654
movq %rax, %r15
callq 0x5654
movq %rax, %r14
movl %ebx, %edi
callq 0x5551
movl %ebp, %edi
callq 0x5551
pushq $0x2e
jmp 0x4b11
callq 0x5654
movq %rax, %r15
callq 0x5654
movq %rax, %r14
movl %ebx, %edi
callq 0x5551
movl %ebp, %edi
callq 0x5551
pushq $0x3e
jmp 0x4b11
callq 0x5654
movq %rax, %r15
callq 0x5654
movq %rax, %r14
movl %ebx, %edi
callq 0x5551
movl %ebp, %edi
callq 0x5551
pushq $0x36
popq %rdi
movl %ebp, %esi
movl %ebx, %edx
movq %r15, %rcx
callq 0x5680
xorl %edi, %edi
callq 0x55ca
movq %r14, %rdi
callq 0x56a9
movq %r15, %rdi
callq 0x56be
pushq $0x1
popq %rdi
callq 0x55ca
movq %r14, %rdi
callq 0x56be
movl %ebp, %edi
callq 0x551c
movl %ebx, %edi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x551c