// File: /workspace/github_c_makefile_star2_O0/sharmaeklavya2[P]cerplag/compile_x86.c
// Function: compile_program_to_x86
void compile_program_to_x86(ProgramNode* program_node, pSD psd, FILE* ofp) {
    int data_size = psd->root->value->max_offset;

    fprintf(ofp, PROLOGUE_STR, data_size);

    strcpy(std_regs[0][TYPE_INTEGER], "ax");    // std_regs[0] must be "ax" for multiply to work
    strcpy(std_regs[0][TYPE_BOOLEAN], "al");
    strcpy(std_regs[0][TYPE_REAL], "xmm0");
    strcpy(std_regs[1][TYPE_INTEGER], "rax");
    strcpy(std_regs[1][TYPE_BOOLEAN], "rax");
    strcpy(std_regs[1][TYPE_REAL], "rax");
    strcpy(std_regs[2][TYPE_INTEGER], "cx");
    strcpy(std_regs[2][TYPE_BOOLEAN], "cl");
    strcpy(std_regs[2][TYPE_REAL], "xmm1");
    strcpy(std_regs[3][TYPE_INTEGER], "rcx");
    strcpy(std_regs[3][TYPE_BOOLEAN], "rcx");
    strcpy(std_regs[3][TYPE_REAL], "rcx");
    strcpy(std_size_name[TYPE_INTEGER], "word");
    strcpy(std_size_name[TYPE_BOOLEAN], "byte");
    strcpy(std_size_name[TYPE_REAL], "dword");

    X86Code x86_code;
    x86_code_init(&x86_code);
    ModuleNode* module_node = program_node->modules;
    for(; module_node != NULL; module_node = module_node->next) {
        if(module_node->name == NULL) {
            fprintf(ofp, "main:\n");
        }
        else {
            fprintf(ofp, "module_%s:\n", module_node->name);
        }

        x86_code_append(&x86_code, x86_instr_new2(X86_OP_mov, DATA_REG, "data"));
        x86_code_append(&x86_code, x86_instr_new2(X86_OP_xor, "rsi", "rsi"));
        x86_code_append(&x86_code, x86_instr_new2(X86_OP_xor, "rdi", "rdi"));
        compile_code_to_x86(&(module_node->base.ircode), &x86_code);
        if(module_node->name == NULL) {
            x86_code_append(&x86_code, x86_instr_new2(X86_OP_mov, "rax", "0"));
        }
        x86_code_append(&x86_code, x86_instr_new(X86_OP_ret));
        optimize_x86_code(&x86_code);
        x86_code_print(&x86_code, ofp);
        x86_code_clear(&x86_code);
    }

    // read libs and output them
    int num_libs = sizeof(include_lib_files) / sizeof(bool);
    int i;
    for(i=0; i<num_libs; ++i) {
        if(include_lib_files[i]) {
            fputc('\n', ofp);
            FILE* libfp = fopen(ASM_LIB_FILES[i], "r");
            setvbuf(libfp, NULL, _IOFBF, BUFSIZ);   // fully buffer file
            if (libfp) {
                int c;
                while ((c = fgetc(libfp)) != EOF)
                    fputc(c, ofp);
                fclose(libfp);
            }
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rax
movl 0x4c(%rax), %eax
movl %eax, -0x1c(%rbp)
movq -0x18(%rbp), %rdi
movl -0x1c(%rbp), %edx
leaq 0x3d7e(%rip), %rsi      # 0x15d70
movb $0x0, %al
callq 0x3120
leaq 0xdf2a(%rip), %rdi      # 0x1ff2a
leaq 0x3ebd(%rip), %rsi      # 0x15ec4
callq 0x3050
leaq 0xdf2b(%rip), %rdi      # 0x1ff3e
leaq 0x246c(%rip), %rsi      # 0x14486
callq 0x3050
leaq 0xdf0e(%rip), %rdi      # 0x1ff34
leaq 0x3ec8(%rip), %rsi      # 0x15ef5
callq 0x3050
leaq 0xdf19(%rip), %rdi      # 0x1ff52
leaq 0x3e83(%rip), %rsi      # 0x15ec3
callq 0x3050
leaq 0xdf1a(%rip), %rdi      # 0x1ff66
leaq 0x3e70(%rip), %rsi      # 0x15ec3
callq 0x3050
leaq 0xdefd(%rip), %rdi      # 0x1ff5c
leaq 0x3e5d(%rip), %rsi      # 0x15ec3
callq 0x3050
leaq 0xdf08(%rip), %rdi      # 0x1ff7a
leaq 0x3e8a(%rip), %rsi      # 0x15f03
callq 0x3050
leaq 0xdf09(%rip), %rdi      # 0x1ff8e
leaq 0x3e6e(%rip), %rsi      # 0x15efa
callq 0x3050
leaq 0xdeec(%rip), %rdi      # 0x1ff84
leaq 0x3e5e(%rip), %rsi      # 0x15efd
callq 0x3050
leaq 0xdef7(%rip), %rdi      # 0x1ffa2
leaq 0x3e50(%rip), %rsi      # 0x15f02
callq 0x3050
leaq 0xdef8(%rip), %rdi      # 0x1ffb6
leaq 0x3e3d(%rip), %rsi      # 0x15f02
callq 0x3050
leaq 0xdedb(%rip), %rdi      # 0x1ffac
leaq 0x3e2a(%rip), %rsi      # 0x15f02
callq 0x3050
leaq 0xde16(%rip), %rdi      # 0x1fefa
leaq 0x3e21(%rip), %rsi      # 0x15f0c
callq 0x3050
leaq 0xde17(%rip), %rdi      # 0x1ff0e
leaq 0x3e08(%rip), %rsi      # 0x15f06
callq 0x3050
leaq 0xddfa(%rip), %rdi      # 0x1ff04
leaq 0x3dfa(%rip), %rsi      # 0x15f0b
callq 0x3050
leaq -0x38(%rbp), %rdi
callq 0x10cd0
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rax
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
je 0x12253
movq -0x40(%rbp), %rax
cmpq $0x0, 0x50(%rax)
jne 0x12155
movq -0x18(%rbp), %rdi
leaq 0x3dc5(%rip), %rsi      # 0x15f11
movb $0x0, %al
callq 0x3120
jmp 0x1216f
movq -0x18(%rbp), %rdi
movq -0x40(%rbp), %rax
movq 0x50(%rax), %rdx
leaq 0x3db0(%rip), %rsi      # 0x15f18
movb $0x0, %al
callq 0x3120
xorl %edi, %edi
leaq 0x3bf4(%rip), %rsi      # 0x15d6c
leaq 0x3da5(%rip), %rdx      # 0x15f24
callq 0x10a20
movq %rax, %rsi
leaq -0x38(%rbp), %rdi
callq 0x10e70
movl $0x6, %edi
leaq 0x3cfe(%rip), %rdx      # 0x15e9a
movq %rdx, %rsi
callq 0x10a20
movq %rax, %rsi
leaq -0x38(%rbp), %rdi
callq 0x10e70
movl $0x6, %edi
leaq 0x3ce2(%rip), %rdx      # 0x15e9e
movq %rdx, %rsi
callq 0x10a20
movq %rax, %rsi
leaq -0x38(%rbp), %rdi
callq 0x10e70
movq -0x40(%rbp), %rdi
addq $0x20, %rdi
leaq -0x38(%rbp), %rsi
callq 0x11f70
movq -0x40(%rbp), %rax
cmpq $0x0, 0x50(%rax)
jne 0x1220d
xorl %edi, %edi
leaq 0x3cce(%rip), %rsi      # 0x15ec3
leaq 0x3cfc(%rip), %rdx      # 0x15ef8
callq 0x10a20
movq %rax, %rsi
leaq -0x38(%rbp), %rdi
callq 0x10e70
movl $0x14, %edi
callq 0x109f0
movq %rax, %rsi
leaq -0x38(%rbp), %rdi
callq 0x10e70
leaq -0x38(%rbp), %rdi
callq 0x11160
movq -0x18(%rbp), %rsi
leaq -0x38(%rbp), %rdi
callq 0x11060
leaq -0x38(%rbp), %rdi
callq 0x11020
movq -0x40(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x40(%rbp)
jmp 0x1212b
movl $0x7, -0x44(%rbp)
movl $0x0, -0x48(%rbp)
movl -0x48(%rbp), %eax
cmpl -0x44(%rbp), %eax
jge 0x12302
movslq -0x48(%rbp), %rcx
leaq 0x8ac0(%rip), %rax      # 0x1ad38
testb $0x1, (%rax,%rcx)
je 0x122f2
movq -0x18(%rbp), %rsi
movl $0xa, %edi
callq 0x30f0
movslq -0x48(%rbp), %rcx
leaq 0x8a69(%rip), %rax      # 0x1ad00
movq (%rax,%rcx,8), %rdi
leaq 0x25eb(%rip), %rsi      # 0x1488d
callq 0x3150
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
xorl %edx, %edx
movl $0x2000, %ecx           # imm = 0x2000
callq 0x3140
cmpq $0x0, -0x50(%rbp)
je 0x122f0
jmp 0x122c8
movq -0x50(%rbp), %rdi
callq 0x30e0
movl %eax, -0x54(%rbp)
cmpl $-0x1, %eax
je 0x122e7
movl -0x54(%rbp), %edi
movq -0x18(%rbp), %rsi
callq 0x30f0
jmp 0x122c8
movq -0x50(%rbp), %rdi
callq 0x3090
jmp 0x122f2
jmp 0x122f4
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x12261
addq $0x60, %rsp
popq %rbp
retq
nopl (%rax,%rax)