// File: /workspace/github_c_makefile_star2_O2/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 %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %rbx
movq %rdi, %r14
movq 0x8(%rdi), %rdi
callq 0xbf1c
testb %al, %al
je 0xc062
movq 0x10(%r14), %rdi
callq 0xbf1c
testb %al, %al
je 0xc062
movq 0x18(%r14), %rdi
callq 0xbf1c
testb %al, %al
je 0xc062
movl (%r14), %eax
cmpq $0x16, %rax
ja 0xc062
leaq 0x2c4e(%rip), %rcx      # 0xec70
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x8(%r14), %rdx
movq 0x10(%r14), %rcx
pushq $0x7
popq %rsi
movq %rbx, %rdi
callq 0xbdee
movl (%r14), %edi
callq 0xbf77
movq 0x18(%r14), %rdx
movq %rbx, %rdi
movl %eax, %esi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xbec5
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl 0x30(%r14), %ecx
leaq 0xdf24(%rip), %rdi      # 0x19fa0
leaq 0x2e2c(%rip), %rdx      # 0xeeaf
pushq $0x32
popq %rsi
xorl %eax, %eax
callq 0x30c0
movl (%r14), %edi
callq 0xbfb6
movl %eax, %r15d
movq 0x8(%r14), %rsi
testq %rsi, %rsi
je 0xc139
leaq 0x2dad(%rip), %rdx      # 0xee59
movq %rbx, %rdi
callq 0xbc87
pushq $0x7
popq %rdi
callq 0xb65f
movq %rax, %r12
movq 0x8(%r14), %rdi
leaq 0x4(%rax), %rsi
leaq 0x2d8a(%rip), %rcx      # 0xee58
pushq $0x1
popq %rdx
callq 0xbac4
movq 0x10(%r14), %rax
movq %r12, %rdi
addq $0x22, %rdi
testq %rax, %rax
je 0xc129
movl 0x30(%rax), %ecx
leaq 0x1958(%rip), %rdx      # 0xda48
pushq $0x1e
popq %rsi
xorl %eax, %eax
callq 0x30c0
jmp 0xc12e
movq 0x8(%r14), %rcx
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0xbd05
movl (%r14), %edi
callq 0xbf98
movq 0x10(%r14), %rcx
movq %rbx, %rdi
movl %eax, %esi
xorl %edx, %edx
callq 0xbd05
jmp 0xc29b
movw $0x30, (%rdi)
movq %rbx, %rdi
movq %r12, %rsi
callq 0xb8ff
leaq 0xde60(%rip), %rsi      # 0x19fa0
movl %r15d, %edi
jmp 0xc36a
movq 0x8(%r14), %rcx
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0xbd05
movq 0x10(%r14), %rcx
pushq $0x2
popq %rdx
movq %rbx, %rdi
xorl %esi, %esi
callq 0xbd05
leaq 0xddea(%rip), %rsi      # 0x19f5a
pushq $0x4
jmp 0xc288
movq 0x18(%r14), %rcx
movl 0x1c(%rcx), %r12d
cmpl $0x1, %r12d
adcl $0x0, %r12d
movl 0x18(%rcx), %eax
movb $0x1, %dl
movb %dl, 0x8b86(%rip)       # 0x14d18
leaq 0x8b7f(%rip), %rsi      # 0x14d18
xorl %edi, %edi
cmpl $0x3, %eax
sete %dil
movb %dl, 0x5(%rdi,%rsi)
pushq $0x1
popq %rsi
pushq $0x3
popq %rdx
movq %rbx, %rdi
callq 0xbd05
leaq 0xdde5(%rip), %r15      # 0x19fa0
leaq 0x1886(%rip), %rdx      # 0xda48
pushq $0x32
popq %r13
movq %r15, %rdi
movq %r13, %rsi
movl %r12d, %ecx
xorl %eax, %eax
callq 0x30c0
leaq 0x2cb1(%rip), %rsi      # 0xee8e
xorl %edi, %edi
movq %r15, %rdx
callq 0xb687
movq %rbx, %rdi
movq %rax, %rsi
callq 0xb8ff
movq 0x18(%r14), %rax
movl 0x18(%rax), %eax
leaq 0x89c0(%rip), %rcx      # 0x14bc0
movq (%rcx,%rax,8), %rcx
leaq 0x2c96(%rip), %rdx      # 0xeea1
jmp 0xc357
leaq 0x2c6a(%rip), %rdx      # 0xee81
pushq $0x6
popq %rdi
movq %rdx, %rsi
callq 0xb687
movq %rbx, %rdi
movq %rax, %rsi
callq 0xb8ff
movq 0x8(%r14), %rcx
pushq $0x3
popq %rsi
movq %rbx, %rdi
jmp 0xc11d
movq 0x18(%r14), %rdx
pushq $0xb
popq %rsi
movq %rbx, %rdi
jmp 0xc04f
movq 0x8(%r14), %rcx
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0xbd05
pushq $0xa
popq %rdi
callq 0xb65f
movq %rbx, %rdi
movq %rax, %rsi
callq 0xb8ff
movq 0x10(%r14), %rcx
pushq $0x2
popq %rdx
movq %rbx, %rdi
xorl %esi, %esi
callq 0xbd05
leaq 0xdcd4(%rip), %rsi      # 0x19f5a
pushq $0x5
popq %rdi
xorl %edx, %edx
callq 0xb687
movq %rbx, %rdi
movq %rax, %rsi
callq 0xb8ff
movq 0x18(%r14), %rdx
movq %rbx, %rdi
xorl %esi, %esi
xorl %ecx, %ecx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xbd7b
movq 0x8(%r14), %rcx
movl 0x18(%rcx), %eax
movl 0x1c(%rcx), %r12d
movb $0x1, %dl
movb %dl, 0x8a4c(%rip)       # 0x14d18
leaq 0x8a45(%rip), %rsi      # 0x14d18
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)
je 0xc3aa
pushq $0x1
popq %rsi
pushq $0x3
popq %rdx
movq %rbx, %rdi
callq 0xbd05
leaq 0xdc99(%rip), %r15      # 0x19fa0
leaq 0x173a(%rip), %rdx      # 0xda48
pushq $0x32
popq %r13
movq %r15, %rdi
movq %r13, %rsi
movl %r12d, %ecx
xorl %eax, %eax
callq 0x30c0
leaq 0x2b65(%rip), %rsi      # 0xee8e
xorl %edi, %edi
movq %r15, %rdx
callq 0xb687
movq %rbx, %rdi
movq %rax, %rsi
callq 0xb8ff
movq 0x8(%r14), %rax
movl 0x18(%rax), %eax
leaq 0x8874(%rip), %rcx      # 0x14bc0
movq (%rcx,%rax,8), %rcx
leaq 0x2b3b(%rip), %rdx      # 0xee92
movq %r15, %rdi
movq %r13, %rsi
xorl %eax, %eax
callq 0x30c0
pushq $0x1a
popq %rdi
movq %r15, %rsi
xorl %edx, %edx
callq 0xb687
movq %rbx, %rdi
movq %rax, %rsi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xb8ff
movq 0x8(%r14), %rcx
movq 0x18(%r14), %rdx
movq %rbx, %rdi
xorl %esi, %esi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xbdee
pushq $0x2
popq %rdx
movq %rbx, %rdi
xorl %esi, %esi
callq 0xbd05
movq 0x8(%r14), %rax
movl 0x18(%rax), %eax
leaq 0x87fb(%rip), %rcx      # 0x14bc0
movq (%rcx,%rax,8), %rcx
leaq 0xdbd0(%rip), %r14      # 0x19fa0
leaq 0x2aae(%rip), %rdx      # 0xee85
pushq $0x32
popq %rsi
movq %r14, %rdi
xorl %eax, %eax
callq 0x30c0
pushq $0x1a
popq %rdi
movq %r14, %rsi
jmp 0xc36a