// File: /workspace/github_c_makefile_star2_O0/sharmaeklavya2[P]cerplag/compiler.c
// Function: compile_program
void compile_program(ProgramNode* root, pSD psd, bool code_gen, bool destroy_module_bodies) {
    if(code_gen) {
        allow_codegen = true;
    }

    vptr_int_hmap_init(&module_status, 10, false);
    vptr_pMN_hmap_init(&module_node_map, 10, false);

    IDListNode* decl_node = NULL;
    ModuleNode* module_node = NULL;

    decl_node = root->decls;
    while(decl_node != NULL) {
        int old_size = module_status.size;
        vptr_int_hmap_insert(&module_status, decl_node->varname, MODULE_DECLARED);
        if(module_status.size == old_size) {
            sprintf(msg, "Module '%s' has already been declared.", decl_node->varname);
            print_error("semantic", ERROR, -1, decl_node->base.line, decl_node->base.col, NULL, "MODULE_REDECL", msg);
        }
        decl_node = decl_node->next;
    }

    module_node = root->modules;
    while(module_node != NULL) {
        if(module_node->name != NULL) {
            vptr_int_hmap_insert(&module_status, module_node->name, 0);
            int old_size = module_node_map.size;
            ModuleNode* n2 = vptr_pMN_hmap_insert(&module_node_map, module_node->name, module_node)->value;
            if(module_node_map.size == old_size) {
                sprintf(msg, "Module '%s' has already been defined on line %d col %d.",
                    module_node->name, n2->base.line, n2->base.col);
                print_error("semantic", ERROR, -1, module_node->base.line, module_node->base.col, NULL, "MODULE_REDEF", msg);
            }
        }
        module_node = module_node->next;
    }

    module_node = root->modules;
    while(module_node != NULL) {
        SD_add_scope(psd, (pAstNode)module_node);
        compile_node((pAstNode)module_node, psd, module_node->name);
        SD_remove_scope(psd);
        if(destroy_module_bodies) {
            destroy_ast(module_node->body);
        }
        optimize_ircode(&(module_node->base.ircode));
        module_node->body = NULL;
        module_node = module_node->next;
    }

    //vptr_pMN_hmap_print(&module_node_map, stderr);
    //vptr_int_hmap_print(&module_status, stderr);

    decl_node = root->decls;
    while(decl_node != NULL) {
        int status = vptr_int_hmap_get(&module_status, decl_node->varname);
        if((status & MODULE_DECLARED) && (~status & MODULE_DEFINED)) {
            // module is declared but not defined
            sprintf(msg, "Module '%s' has been declared but not defined.", decl_node->varname);
            print_error("semantic", ERROR, -1, decl_node->base.line, decl_node->base.col, NULL, "MODULE_NOTDECL", msg);
        }
        decl_node = decl_node->next;
    }

    module_node = root->modules;
    while(module_node != NULL) {
        if(module_node->name != NULL) {
            int status = vptr_int_hmap_get(&module_status, module_node->name);
            if(~status & MODULE_USED) {
                sprintf(msg, "Module '%s' has not been used.", module_node->name);
                print_error("semantic", WARNING, 4, module_node->base.line, module_node->base.col, NULL, "MODULE_NOTUSED", msg);
            }
        }
        module_node = module_node->next;
    }

    vptr_int_hmap_clear(&module_status);
    vptr_pMN_hmap_clear(&module_node_map);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movb %cl, %al
movb %dl, %cl
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
andb $0x1, %cl
movb %cl, -0x11(%rbp)
andb $0x1, %al
movb %al, -0x12(%rbp)
testb $0x1, -0x11(%rbp)
je 0xf6ef
leaq 0xb654(%rip), %rax      # 0x1ad40
movb $0x1, (%rax)
leaq 0x107c2(%rip), %rdi     # 0x1feb8
movl $0xa, %esi
xorl %edx, %edx
callq 0x3a20
leaq 0x107c7(%rip), %rdi     # 0x1fed0
movl $0xa, %esi
xorl %edx, %edx
callq 0xd020
movq $0x0, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0xf7d5
movl 0x10782(%rip), %eax     # 0x1fec4
movl %eax, -0x2c(%rbp)
movq -0x20(%rbp), %rax
movq 0x40(%rax), %rsi
leaq 0x10764(%rip), %rdi     # 0x1feb8
movl $0x1, %edx
callq 0x3c50
movl 0x10760(%rip), %eax     # 0x1fec4
cmpl -0x2c(%rbp), %eax
jne 0xf7c4
movq -0x20(%rbp), %rax
movq 0x40(%rax), %rdx
leaq 0x10678(%rip), %rdi     # 0x1fdf0
leaq 0x6241(%rip), %rsi      # 0x159c0
movb $0x0, %al
callq 0x3190
movq -0x20(%rbp), %rax
movl 0xc(%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x10(%rax), %r8d
leaq 0x5a76(%rip), %rdi      # 0x15212
xorl %esi, %esi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
xorl %eax, %eax
movl %eax, %r9d
leaq 0x6238(%rip), %r10      # 0x159e7
leaq 0x1063a(%rip), %rax     # 0x1fdf0
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
callq 0xba50
movq -0x20(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x20(%rbp)
jmp 0xf731
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
je 0xf8c2
movq -0x28(%rbp), %rax
cmpq $0x0, 0x50(%rax)
je 0xf8b1
movq -0x28(%rbp), %rax
movq 0x50(%rax), %rsi
leaq 0x106ae(%rip), %rdi     # 0x1feb8
xorl %edx, %edx
callq 0x3c50
movl 0x106c5(%rip), %eax     # 0x1fedc
movl %eax, -0x30(%rbp)
movq -0x28(%rbp), %rax
movq 0x50(%rax), %rsi
movq -0x28(%rbp), %rdx
leaq 0x106a3(%rip), %rdi     # 0x1fed0
callq 0xd250
movq 0x10(%rax), %rax
movq %rax, -0x38(%rbp)
movl 0x1069c(%rip), %eax     # 0x1fedc
cmpl -0x30(%rbp), %eax
jne 0xf8af
movq -0x28(%rbp), %rax
movq 0x50(%rax), %rdx
movq -0x38(%rbp), %rax
movl 0xc(%rax), %ecx
movq -0x38(%rbp), %rax
movl 0x10(%rax), %r8d
leaq 0x1058d(%rip), %rdi     # 0x1fdf0
leaq 0x618b(%rip), %rsi      # 0x159f5
movb $0x0, %al
callq 0x3190
movq -0x28(%rbp), %rax
movl 0xc(%rax), %ecx
movq -0x28(%rbp), %rax
movl 0x10(%rax), %r8d
leaq 0x598b(%rip), %rdi      # 0x15212
xorl %esi, %esi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
xorl %eax, %eax
movl %eax, %r9d
leaq 0x6193(%rip), %r10      # 0x15a2d
leaq 0x1054f(%rip), %rax     # 0x1fdf0
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
callq 0xba50
jmp 0xf8b1
movq -0x28(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0xf7e1
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
je 0xf93a
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0xccf0
movq -0x28(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x28(%rbp), %rax
movq 0x50(%rax), %rdx
callq 0xd8a0
movq -0x10(%rbp), %rdi
callq 0xcd60
testb $0x1, -0x12(%rbp)
je 0xf913
movq -0x28(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0xa0b0
movq -0x28(%rbp), %rdi
addq $0x20, %rdi
callq 0x12df0
movq -0x28(%rbp), %rax
movq $0x0, 0x58(%rax)
movq -0x28(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0xf8ce
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0xf9ed
movq -0x20(%rbp), %rax
movq 0x40(%rax), %rsi
leaq 0x10558(%rip), %rdi     # 0x1feb8
callq 0x3bd0
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0xf9dc
movl -0x3c(%rbp), %eax
xorl $-0x1, %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0xf9dc
movq -0x20(%rbp), %rax
movq 0x40(%rax), %rdx
leaq 0x10460(%rip), %rdi     # 0x1fdf0
leaq 0x60a3(%rip), %rsi      # 0x15a3a
movb $0x0, %al
callq 0x3190
movq -0x20(%rbp), %rax
movl 0xc(%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x10(%rax), %r8d
leaq 0x585e(%rip), %rdi      # 0x15212
xorl %esi, %esi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
xorl %eax, %eax
movl %eax, %r9d
leaq 0x60a2(%rip), %r10      # 0x15a69
leaq 0x10422(%rip), %rax     # 0x1fdf0
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
callq 0xba50
movq -0x20(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x20(%rbp)
jmp 0xf946
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
je 0xfaa9
movq -0x28(%rbp), %rax
cmpq $0x0, 0x50(%rax)
je 0xfa98
movq -0x28(%rbp), %rax
movq 0x50(%rax), %rsi
leaq 0x10496(%rip), %rdi     # 0x1feb8
callq 0x3bd0
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
xorl $-0x1, %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0xfa96
movq -0x28(%rbp), %rax
movq 0x50(%rax), %rdx
leaq 0x103a9(%rip), %rdi     # 0x1fdf0
leaq 0x602a(%rip), %rsi      # 0x15a78
movb $0x0, %al
callq 0x3190
movq -0x28(%rbp), %rax
movl 0xc(%rax), %ecx
movq -0x28(%rbp), %rax
movl 0x10(%rax), %r8d
leaq 0x57a7(%rip), %rdi      # 0x15212
movl $0x1, %esi
movl $0x4, %edx
xorl %eax, %eax
movl %eax, %r9d
leaq 0x6016(%rip), %r10      # 0x15a97
leaq 0x10368(%rip), %rax     # 0x1fdf0
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
callq 0xba50
jmp 0xfa98
movq -0x28(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0xf9f9
leaq 0x10408(%rip), %rdi     # 0x1feb8
callq 0x3a80
leaq 0x10414(%rip), %rdi     # 0x1fed0
callq 0xd080
addq $0x50, %rsp
popq %rbp
retq
nopw (%rax,%rax)