// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x80, %rsp
movb %dil, %al
andb $0x1, %al
movb %al, -0x1(%rbp)
callq 0x5bc0
movl %eax, -0x8(%rbp)
cmpl $0x0, %eax
jge 0x4dca
callq 0x5c30
jmp 0x5240
movl -0x8(%rbp), %eax
movb %al, -0x9(%rbp)
callq 0x5bc0
movl %eax, -0x8(%rbp)
cmpl $0x0, %eax
jge 0x4df0
movzbl -0x9(%rbp), %edi
callq 0x5c50
callq 0x5c30
jmp 0x5240
movb -0x8(%rbp), %al
movb %al, -0xa(%rbp)
movl 0x147d4(%rip), %eax     # 0x195d0
movl %eax, -0x10(%rbp)
movl -0x10(%rbp), %edi
callq 0x58f0
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movl 0x10(%rax), %edi
incl %edi
callq 0x5820
movl -0x10(%rbp), %eax
addl $-0x5, %eax
movl %eax, %ecx
movq %rcx, -0x80(%rbp)
subl $0xf, %eax
ja 0x5222
movq -0x80(%rbp), %rax
leaq 0x71f7(%rip), %rcx      # 0xc030
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
jmp 0x4e44
movzbl -0xa(%rbp), %edi
callq 0x5cb0
movzbl -0x9(%rbp), %edi
callq 0x5cb0
movl $0x18, %edi
callq 0x5ce0
movzbl -0x9(%rbp), %edi
callq 0x5d80
movzbl -0xa(%rbp), %edi
callq 0x5d80
movzbl -0x9(%rbp), %edi
callq 0x5b30
movzbl -0x9(%rbp), %edi
callq 0x5c50
movzbl -0xa(%rbp), %edi
callq 0x5c50
jmp 0x522e
jmp 0x4e94
movzbl -0xa(%rbp), %edi
callq 0x5cb0
movzbl -0x9(%rbp), %edi
callq 0x5cb0
movl $0x1a, %edi
callq 0x5ce0
movzbl -0x9(%rbp), %edi
callq 0x5d80
movzbl -0xa(%rbp), %edi
callq 0x5d80
movzbl -0x9(%rbp), %edi
callq 0x5b30
movzbl -0x9(%rbp), %edi
callq 0x5c50
movzbl -0xa(%rbp), %edi
callq 0x5c50
jmp 0x522e
jmp 0x4ee4
movzbl -0xa(%rbp), %edi
callq 0x5cb0
movzbl -0x9(%rbp), %edi
callq 0x5cb0
movl $0x1c, %edi
callq 0x5ce0
movzbl -0x9(%rbp), %edi
callq 0x5d80
movzbl -0xa(%rbp), %edi
callq 0x5d80
movzbl -0x9(%rbp), %edi
callq 0x5b30
movzbl -0x9(%rbp), %edi
callq 0x5c50
movzbl -0xa(%rbp), %edi
callq 0x5c50
jmp 0x522e
jmp 0x4f34
movzbl -0xa(%rbp), %edi
callq 0x5cb0
movzbl -0x9(%rbp), %edi
callq 0x5cb0
movl $0x1e, %edi
callq 0x5ce0
movzbl -0x9(%rbp), %edi
callq 0x5d80
movzbl -0xa(%rbp), %edi
callq 0x5d80
movzbl -0x9(%rbp), %edi
callq 0x5b30
movzbl -0x9(%rbp), %edi
callq 0x5c50
movzbl -0xa(%rbp), %edi
callq 0x5c50
jmp 0x522e
jmp 0x4f84
callq 0x5f80
movq %rax, -0x20(%rbp)
callq 0x5f80
movq %rax, -0x28(%rbp)
movzbl -0xa(%rbp), %edi
callq 0x5cb0
movzbl -0x9(%rbp), %edi
callq 0x5cb0
movb -0x9(%rbp), %dl
movb -0xa(%rbp), %al
movq -0x20(%rbp), %rcx
movl $0x2c, %edi
movzbl %dl, %esi
movzbl %al, %edx
callq 0x5fc0
xorl %edi, %edi
callq 0x5e00
movq -0x28(%rbp), %rdi
callq 0x6010
movq -0x20(%rbp), %rdi
callq 0x6040
movl $0x1, %edi
callq 0x5e00
movq -0x28(%rbp), %rdi
callq 0x6040
jmp 0x522e
jmp 0x4ff5
callq 0x5f80
movq %rax, -0x30(%rbp)
callq 0x5f80
movq %rax, -0x38(%rbp)
movzbl -0xa(%rbp), %edi
callq 0x5cb0
movzbl -0x9(%rbp), %edi
callq 0x5cb0
movb -0x9(%rbp), %dl
movb -0xa(%rbp), %al
movq -0x30(%rbp), %rcx
movl $0x2e, %edi
movzbl %dl, %esi
movzbl %al, %edx
callq 0x5fc0
xorl %edi, %edi
callq 0x5e00
movq -0x38(%rbp), %rdi
callq 0x6010
movq -0x30(%rbp), %rdi
callq 0x6040
movl $0x1, %edi
callq 0x5e00
movq -0x38(%rbp), %rdi
callq 0x6040
jmp 0x522e
jmp 0x5066
callq 0x5f80
movq %rax, -0x40(%rbp)
callq 0x5f80
movq %rax, -0x48(%rbp)
movzbl -0xa(%rbp), %edi
callq 0x5cb0
movzbl -0x9(%rbp), %edi
callq 0x5cb0
movb -0x9(%rbp), %dl
movb -0xa(%rbp), %al
movq -0x40(%rbp), %rcx
movl $0x32, %edi
movzbl %dl, %esi
movzbl %al, %edx
callq 0x5fc0
xorl %edi, %edi
callq 0x5e00
movq -0x48(%rbp), %rdi
callq 0x6010
movq -0x40(%rbp), %rdi
callq 0x6040
movl $0x1, %edi
callq 0x5e00
movq -0x48(%rbp), %rdi
callq 0x6040
jmp 0x522e
jmp 0x50d7
callq 0x5f80
movq %rax, -0x50(%rbp)
callq 0x5f80
movq %rax, -0x58(%rbp)
movzbl -0xa(%rbp), %edi
callq 0x5cb0
movzbl -0x9(%rbp), %edi
callq 0x5cb0
movb -0x9(%rbp), %dl
movb -0xa(%rbp), %al
movq -0x50(%rbp), %rcx
movl $0x36, %edi
movzbl %dl, %esi
movzbl %al, %edx
callq 0x5fc0
xorl %edi, %edi
callq 0x5e00
movq -0x58(%rbp), %rdi
callq 0x6010
movq -0x50(%rbp), %rdi
callq 0x6040
movl $0x1, %edi
callq 0x5e00
movq -0x58(%rbp), %rdi
callq 0x6040
jmp 0x522e
jmp 0x5148
callq 0x5f80
movq %rax, -0x60(%rbp)
callq 0x5f80
movq %rax, -0x68(%rbp)
movzbl -0xa(%rbp), %edi
callq 0x5cb0
movzbl -0x9(%rbp), %edi
callq 0x5cb0
movb -0x9(%rbp), %dl
movb -0xa(%rbp), %al
movq -0x60(%rbp), %rcx
movl $0x3a, %edi
movzbl %dl, %esi
movzbl %al, %edx
callq 0x5fc0
xorl %edi, %edi
callq 0x5e00
movq -0x68(%rbp), %rdi
callq 0x6010
movq -0x60(%rbp), %rdi
callq 0x6040
movl $0x1, %edi
callq 0x5e00
movq -0x68(%rbp), %rdi
callq 0x6040
jmp 0x522e
jmp 0x51b6
callq 0x5f80
movq %rax, -0x70(%rbp)
callq 0x5f80
movq %rax, -0x78(%rbp)
movzbl -0xa(%rbp), %edi
callq 0x5cb0
movzbl -0x9(%rbp), %edi
callq 0x5cb0
movb -0x9(%rbp), %dl
movb -0xa(%rbp), %al
movq -0x70(%rbp), %rcx
movl $0x3e, %edi
movzbl %dl, %esi
movzbl %al, %edx
callq 0x5fc0
xorl %edi, %edi
callq 0x5e00
movq -0x78(%rbp), %rdi
callq 0x6010
movq -0x70(%rbp), %rdi
callq 0x6040
movl $0x1, %edi
callq 0x5e00
movq -0x78(%rbp), %rdi
callq 0x6040
jmp 0x522e
leaq 0x70c4(%rip), %rdi      # 0xc2ed
callq 0x57b0
movzbl -0x9(%rbp), %edi
callq 0x5c50
movzbl -0xa(%rbp), %edi
callq 0x5c50
addq $0x80, %rsp
popq %rbp
retq
nopl (%rax)