// File: /workspace/github_c_makefile_star2_O3/sharmaeklavya2[P]cerplag/compile_x86.c
// Function: compile_instr_to_x86
void compile_instr_to_x86(const IRInstr* inode, X86Code* ocode) {
    if(!check_arg(inode->arg1)) return;
    if(!check_arg(inode->arg2)) return;
    if(!check_arg(inode->res)) return;
    switch(inode->op) {
        case OP_MOV:
            op_addr_to_addr(ocode, X86_OP_mov, inode->res, inode->arg1);
            break;
        case OP_PLUS:
        case OP_MINUS:
        case OP_AND:
        case OP_OR:
            op_addr_to_reg(ocode, X86_OP_mov, 0, inode->arg1);
            op_addr_to_reg(ocode, get_opcode(inode->op), 0, inode->arg2);
            op_reg_to_addr(ocode, X86_OP_mov, inode->res, 0);
            break;
        case OP_UMINUS: {
            x86_code_append(ocode, x86_instr_new2(X86_OP_xor, "rax", "rax"));
            op_addr_to_reg(ocode, X86_OP_sub, 0, inode->arg1);
            op_reg_to_addr(ocode, X86_OP_mov, inode->res, 0);
            break;
        }
        case OP_INC:
            op_apply(ocode, X86_OP_inc, inode->res);
            break;
        case OP_MUL:
            op_addr_to_reg(ocode, X86_OP_mov, 0, inode->arg1);
            op_addr_to_reg(ocode, X86_OP_mov, 2, inode->arg2);
            x86_code_append(ocode, x86_instr_new2(X86_OP_imul, std_regs[2][TYPE_INTEGER], NULL));
            op_reg_to_addr(ocode, X86_OP_mov, inode->res, 0);
            break;
        case OP_DIV:
            op_addr_to_reg(ocode, X86_OP_mov, 0, inode->arg1);
            x86_code_append(ocode, x86_instr_new(X86_OP_cwd));
            op_addr_to_reg(ocode, X86_OP_mov, 2, inode->arg2);
            x86_code_append(ocode, x86_instr_new2(X86_OP_idiv, std_regs[2][TYPE_INTEGER], NULL));
            op_reg_to_addr(ocode, X86_OP_mov, inode->res, 0);
            break;

        case OP_EQ:
        case OP_NE:
        case OP_LT:
        case OP_LE:
        case OP_GT:
        case OP_GE:
            op_addr_to_addr(ocode, X86_OP_cmp, inode->arg1, inode->arg2);
            op_apply(ocode, get_setcode(inode->op), inode->res);
            break;
        case OP_OUTPUT: {
            int size = inode->arg1->size;
            enable_output(inode->arg1->type, size);
            if(size == 0) {
                op_addr_to_reg(ocode, X86_OP_mov, 2, inode->arg1);
                snprintf(temp_str, TEMP_STR_SIZE, "print_%s", TYPE_STRS[inode->arg1->type]);
                x86_code_append(ocode, x86_instr_new2(X86_OP_call, temp_str, NULL));
            }
            else {
                op_addr_to_reg(ocode, X86_OP_lea, 3, inode->arg1);
                snprintf(temp_str, TEMP_STR_SIZE, "%d", size);
                x86_code_append(ocode, x86_instr_new2(X86_OP_mov, "rdx", temp_str));
                snprintf(temp_str, TEMP_STR_SIZE, "print_%s_array", TYPE_STRS[inode->arg1->type]);
                x86_code_append(ocode, x86_instr_new2(X86_OP_call, temp_str, NULL));
            }
            break;
        }
        case OP_INPUT: {
            int size = inode->res->size;
            if(size == 0) size = 1;
            enable_input(inode->res->type);
            op_addr_to_reg(ocode, X86_OP_lea, 3, inode->res);
            snprintf(temp_str, TEMP_STR_SIZE, "%d", size);
            x86_code_append(ocode, x86_instr_new2(X86_OP_mov, "rdx", temp_str));
            snprintf(temp_str, TEMP_STR_SIZE, "read_%s_array", TYPE_STRS[inode->res->type]);
            x86_code_append(ocode, x86_instr_new2(X86_OP_call, temp_str, NULL));
            break;
        }

        case OP_LABEL:
        case OP_JUMP:
        case OP_JUMP0:
        case OP_JUMP1:
        case OP_JNE:
        case OP_JG: {
            snprintf(temp_str, TEMP_STR_SIZE, "L%d", inode->label);
            x86_op_t opcode = get_branch_opcode(inode->op);
            if(inode->arg1 != NULL) {
                load_index_if_needed(ocode, inode->arg1, "si");
                X86Instr* onode = x86_instr_new(X86_OP_cmp);
                addr_to_x86_arg(inode->arg1, onode->arg1, true, "rsi");
                if(inode->arg2 != NULL) {
                    snprintf(onode->arg2, X86_ARG_SIZE, "%d", inode->arg2->imm.i);
                }
                else {
                    strcpy(onode->arg2, "0");
                }
                x86_code_append(ocode, onode);
            }
            x86_code_append(ocode, x86_instr_new2(opcode, temp_str, NULL));
            break;
        }
        default:
            break;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
movq %rsi, %rbx
movq %rdi, %r14
movq 0x8(%rdi), %rdi
callq 0xceab
testb %al, %al
je 0xcffa
movq 0x10(%r14), %rdi
callq 0xceab
testb %al, %al
je 0xcffa
movq 0x18(%r14), %rdi
callq 0xceab
testb %al, %al
je 0xcffa
movl (%r14), %eax
cmpq $0x16, %rax
ja 0xcffa
leaq 0x2cc4(%rip), %rcx      # 0xfc70
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x8(%r14), %rdx
movq 0x10(%r14), %rcx
movq %rbx, %rdi
movl $0x7, %esi
callq 0xcd8a
movl (%r14), %eax
addl $-0x2, %eax
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
cmpl $0x5, %eax
ja 0xcfe6
movl %eax, %eax
leaq 0x2d5d(%rip), %rcx      # 0xfd40
movl (%rcx,%rax,4), %esi
movq 0x18(%r14), %rdx
movq %rbx, %rdi
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0xce52
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
movl 0x30(%r14), %ecx
leaq 0xdf92(%rip), %rdi      # 0x1afa0
leaq 0x2e9a(%rip), %rdx      # 0xfeaf
movl $0x32, %esi
xorl %eax, %eax
callq 0x30c0
movl (%r14), %eax
addl $-0x10, %eax
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
cmpl $0x5, %eax
ja 0xd03f
movl %eax, %eax
leaq 0x2d1d(%rip), %rcx      # 0xfd58
movl (%rcx,%rax,4), %r15d
movq 0x8(%r14), %rsi
testq %rsi, %rsi
je 0xd0e6
leaq 0x2e06(%rip), %rdx      # 0xfe59
movq %rbx, %rdi
callq 0xcc1d
movl $0x7, %edi
callq 0xc5c9
movq %rax, %r12
movq 0x8(%r14), %rdi
leaq 0x4(%rax), %rsi
leaq 0x2de1(%rip), %rcx      # 0xfe58
movl $0x1, %edx
callq 0xca58
movq 0x10(%r14), %rax
movq %r12, %rdi
addq $0x22, %rdi
testq %rax, %rax
je 0xd0d6
movl 0x30(%rax), %ecx
leaq 0x19ad(%rip), %rdx      # 0xea48
movl $0x1e, %esi
xorl %eax, %eax
callq 0x30c0
jmp 0xd0db
movq 0x8(%r14), %rcx
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0xcc9d
movl (%r14), %edi
callq 0xcf29
movq 0x10(%r14), %rcx
movq %rbx, %rdi
movl %eax, %esi
xorl %edx, %edx
callq 0xcc9d
jmp 0xd25b
movw $0x30, (%rdi)
movq %rbx, %rdi
movq %r12, %rsi
callq 0xc8b4
leaq 0xdeb3(%rip), %rsi      # 0x1afa0
movl %r15d, %edi
jmp 0xd32a
movq 0x8(%r14), %rcx
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0xcc9d
movq 0x10(%r14), %rcx
movq %rbx, %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0xcc9d
leaq 0xde3b(%rip), %rsi      # 0x1af5a
movl $0x4, %edi
jmp 0xd249
movq 0x18(%r14), %rcx
movl 0x1c(%rcx), %r12d
cmpl $0x1, %r12d
adcl $0x0, %r12d
movl 0x18(%rcx), %eax
movb $0x1, %dl
movb %dl, 0x8bd4(%rip)       # 0x15d18
leaq 0x8bcd(%rip), %rsi      # 0x15d18
xorl %edi, %edi
cmpl $0x3, %eax
sete %dil
movb %dl, 0x5(%rdi,%rsi)
movq %rbx, %rdi
movl $0x1, %esi
movl $0x3, %edx
callq 0xcc9d
leaq 0xde2f(%rip), %r15      # 0x1afa0
leaq 0x18d0(%rip), %rdx      # 0xea48
movl $0x32, %esi
movq %r15, %rdi
movl %r12d, %ecx
xorl %eax, %eax
callq 0x30c0
leaq 0x2cfd(%rip), %rsi      # 0xfe8e
xorl %edi, %edi
movq %r15, %rdx
callq 0xc5f6
movq %rbx, %rdi
movq %rax, %rsi
callq 0xc8b4
movq 0x18(%r14), %rax
movl 0x18(%rax), %eax
leaq 0x8a0c(%rip), %rcx      # 0x15bc0
movq (%rcx,%rax,8), %rcx
leaq 0x2ce2(%rip), %rdx      # 0xfea1
jmp 0xd313
leaq 0x2cb6(%rip), %rdx      # 0xfe81
movl $0x6, %edi
movq %rdx, %rsi
callq 0xc5f6
movq %rbx, %rdi
movq %rax, %rsi
callq 0xc8b4
movq 0x8(%r14), %rcx
movq %rbx, %rdi
movl $0x3, %esi
jmp 0xd0ca
movq 0x18(%r14), %rdx
movq %rbx, %rdi
movl $0xb, %esi
jmp 0xcfed
movq 0x8(%r14), %rcx
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0xcc9d
movl $0xa, %edi
callq 0xc5c9
movq %rbx, %rdi
movq %rax, %rsi
callq 0xc8b4
movq 0x10(%r14), %rcx
movq %rbx, %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0xcc9d
leaq 0xdd16(%rip), %rsi      # 0x1af5a
movl $0x5, %edi
xorl %edx, %edx
callq 0xc5f6
movq %rbx, %rdi
movq %rax, %rsi
callq 0xc8b4
movq 0x18(%r14), %rdx
movq %rbx, %rdi
xorl %esi, %esi
xorl %ecx, %ecx
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0xcd15
movq 0x8(%r14), %rcx
movl 0x18(%rcx), %eax
movl 0x1c(%rcx), %r12d
movb $0x1, %dl
movb %dl, 0x8a92(%rip)       # 0x15d18
leaq 0x8a8b(%rip), %rsi      # 0x15d18
xorl %edi, %edi
cmpl $0x3, %eax
sete %dil
xorl %eax, %eax
testl %r12d, %r12d
setg %al
leaq (%rdi,%rax,2), %rax
movb %dl, 0x1(%rax,%rsi)
movq %rbx, %rdi
je 0xd35e
movl $0x1, %esi
movl $0x3, %edx
callq 0xcc9d
leaq 0xdcdb(%rip), %r15      # 0x1afa0
leaq 0x177c(%rip), %rdx      # 0xea48
movl $0x32, %esi
movq %r15, %rdi
movl %r12d, %ecx
xorl %eax, %eax
callq 0x30c0
leaq 0x2ba9(%rip), %rsi      # 0xfe8e
xorl %edi, %edi
movq %r15, %rdx
callq 0xc5f6
movq %rbx, %rdi
movq %rax, %rsi
callq 0xc8b4
movq 0x8(%r14), %rax
movl 0x18(%rax), %eax
leaq 0x88b8(%rip), %rcx      # 0x15bc0
movq (%rcx,%rax,8), %rcx
leaq 0x2b7f(%rip), %rdx      # 0xfe92
movl $0x32, %esi
movq %r15, %rdi
xorl %eax, %eax
callq 0x30c0
movl $0x1a, %edi
movq %r15, %rsi
xorl %edx, %edx
callq 0xc5f6
movq %rbx, %rdi
movq %rax, %rsi
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0xc8b4
movq 0x8(%r14), %rcx
movq 0x18(%r14), %rdx
movq %rbx, %rdi
xorl %esi, %esi
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0xcd8a
xorl %esi, %esi
movl $0x2, %edx
callq 0xcc9d
movq 0x8(%r14), %rax
movl 0x18(%rax), %eax
leaq 0x8848(%rip), %rcx      # 0x15bc0
movq (%rcx,%rax,8), %rcx
leaq 0xdc1d(%rip), %r14      # 0x1afa0
leaq 0x2afb(%rip), %rdx      # 0xfe85
movl $0x32, %esi
movq %r14, %rdi
xorl %eax, %eax
callq 0x30c0
movl $0x1a, %edi
movq %r14, %rsi
jmp 0xd32a