// File: /workspace/github_cpp_makefile_star2_O1/kelwinfc[P]ci4721-Fernandez-Gyomrey/src/block.cpp
// Function: Block::gen_graph()
void Block::gen_graph(){
    
    // Marcar los lideres de grupo
    int* leaders;
    leaders = (int*)malloc( (max_label()/32 + 1)*sizeof(int));
    memset(leaders, 0, (max_label()/32 + 1)*sizeof(int) );
    
    vector<inst*>::iterator it = instructions.vinst->begin();
    
    bool was_jump = true; // indica si la instruccion anterior fue un salto
    unsigned int index;
    for (index = 0; index != instructions.vinst->size(); index++){
        
        inst* current_inst = (*(instructions.vinst))[index];
        
        if ( was_jump ){
            SET_LEADER(leaders,current_inst->label);
            was_jump = false;
        }
        
        if ( current_inst->is_jump() ){
            
            if ( ((inst*)current_inst)->op == inst::CALL )
            {
                int destino = 
                  func_to_prologue[((inst*)current_inst)->arg1->data.sym->getName()];
                SET_LEADER(leaders,destino);
                was_jump = true;
            } else if ( ((inst*)current_inst)->op == inst::EPILOGUE )
            {
                int destino = 
                  func_to_epilogue[((inst*)current_inst)->arg2->data.sym->getName()];
                  SET_LEADER(leaders,destino);
                was_jump = true;
            } else if (((inst*)current_inst)->arg2 != 0) {
                unsigned int destino = ((inst*)current_inst)->arg2->data.pint;
                SET_LEADER(leaders,destino);
                was_jump = true;
            }
        }
    }

    /* este es el único lugar en el que se usa cout fuera de main.
       si es importante conocer los líderes, entonces deberían ser
       conservados hasta el final para poder ser impresos. de otra
       forma no se tiene control sobre la impresión de este segmento
    cout << "lideres:";
    for (uint i=0; i<instructions.vinst->size(); i++){
        if ( IS_LEADER(leaders, i) ){
            cout << " " << i;
        }
    }
    cout << endl;
    */
    
    map<unsigned int, Block*> label_to_block;
    
    // Creacion de los bloques basicos
    index = 0;
    
    while( index < instructions.vinst->size() ){
        
        // Agregar el siguiente bloque basico a la lista global de bloques
        Block* next_block = new Block(false);
        next_block->index = list_of_blocks.size();
        
        list_of_blocks.push_back(next_block);
        
        // Añadir todas las instrucciones del bloque basico
        inst* current_inst = (*(instructions.vinst))[index];
        label_to_block[ current_inst->label ] = list_of_blocks.back();
        
        do {
            list_of_blocks.back()->append_inst(current_inst, false);
            
            index++;
            current_inst = (*(instructions.vinst))[index];
            
        } while( index < instructions.vinst->size() 
                    && !IS_LEADER(leaders,current_inst->label)
               );
    }
    
    // En este punto ya se puede eliminar el arreglo de lideres. Los lideres son
    // la primera instruccion de cada bloque basico.
    free(leaders);
    
    // Conectar los bloques
    for (uint block_index = 0 ; block_index != list_of_blocks.size();
         block_index++)
    {        
        Block* current_block = list_of_blocks[block_index];
        
        /* Definicion de salida obligatoria
         * Se coloca que la salida obligatoria de una funcion call es la
         * siguiente para mantener informacion de la secuencialidad.
         * En caso de no desear este comportamiento colocar en inst el operador
         * call como obligatorio
         */
        current_block->mandatory_exit = 0;
        if ( block_index + 1 < list_of_blocks.size()
             && (    !list_of_blocks[block_index]->last_instruction()->is_jump()
                  || !list_of_blocks[block_index]->last_instruction()
                          ->mandatory_jump() )
           )
        {
                current_block->mandatory_exit = list_of_blocks[block_index+1];
        }
        
        inst* last_inst = current_block->last_instruction();
        
        if ( last_inst->is_jump() && ((inst*)last_inst)->op == inst::GOTO ){
            current_block->mandatory_exit = 
                label_to_block[ ((inst*)last_inst)->arg2->data.pint ];
        }
        
        if ( ((inst*)last_inst)->op == inst::RETURN ){
            current_block->mandatory_exit = 
                label_to_block[((inst*)last_inst)->arg2->data.pint];
        }
        
        // Marcar las salidas opcionales
        if ( last_inst->is_jump() && !last_inst->mandatory_jump() )
        {
            if ( ((inst*)last_inst)->op == inst::CALL ){
                string func = ((inst*)last_inst)->arg1->data.sym->getName();
                
                // Agregar salto desde el llamador al prologo del llamado
                current_block->sucessors.push_back(
                    label_to_block[ func_to_prologue[func]]);
                
                // Agregar salto desde el epilogo del llamado a la salida
                // obligatoria de este bloque (siguiente instruccion despues
                // de la llamada)
                label_to_block[func_to_epilogue[func]]->sucessors.push_back(
                    current_block->mandatory_exit);
            } else if ( ((inst*)last_inst)->arg2 != 0 ){
                current_block->sucessors.push_back(
                            label_to_block[((inst*)last_inst)->arg2->data.pint] );
            }
        }
    }
    
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdi, %rbx
callq 0x1b7be
shrl $0x5, %eax
leal 0x4(,%rax,4), %edi
callq 0x63f0
movq %rax, %r14
movq %rbx, %rdi
callq 0x1b7be
shrl $0x5, %eax
leal 0x4(,%rax,4), %edx
movq %r14, %rdi
xorl %esi, %esi
callq 0x6190
movq 0x8(%rbx), %rcx
movq (%rcx), %rax
cmpq %rax, 0x8(%rcx)
je 0x1b971
movb $0x1, %r12b
movl $0x1, %r13d
xorl %ecx, %ecx
leaq 0x28(%rsp), %r15
movq (%rax,%rcx,8), %rbp
testb $0x1, %r12b
je 0x1b8a1
movl 0x8(%rbp), %ecx
movl %ecx, %eax
shrl $0x5, %eax
movl $0x1, %edx
shll %cl, %edx
orl %edx, (%r14,%rax,4)
xorl %r12d, %r12d
movq (%rbp), %rax
movq %rbp, %rdi
callq *0x8(%rax)
testb %al, %al
je 0x1b950
movl 0xc(%rbp), %eax
cmpl $0xf, %eax
je 0x1b8e0
cmpl $0x1, %eax
jne 0x1b932
movq 0x18(%rbp), %rax
movq (%rax), %rsi
movq %r15, %rdi
callq 0x17fb8
leaq 0x22a3a(%rip), %rdi     # 0x3e310
movq %r15, %rsi
callq 0x168a6
jmp 0x1b8fe
movq 0x20(%rbp), %rax
movq (%rax), %rsi
movq %r15, %rdi
callq 0x17fb8
leaq 0x22a4a(%rip), %rdi     # 0x3e340
movq %r15, %rsi
callq 0x168a6
movl (%rax), %ebp
movq 0x28(%rsp), %rdi
leaq 0x38(%rsp), %rax
cmpq %rax, %rdi
je 0x1b91c
movq 0x38(%rsp), %rsi
incq %rsi
callq 0x62f0
leal 0x1f(%rbp), %eax
testl %ebp, %ebp
cmovnsl %ebp, %eax
sarl $0x5, %eax
cltq
movl $0x1, %edx
movl %ebp, %ecx
jmp 0x1b947
movq 0x20(%rbp), %rax
testq %rax, %rax
je 0x1b950
movl (%rax), %ecx
movl %ecx, %eax
shrl $0x5, %eax
movl $0x1, %edx
shll %cl, %edx
orl %edx, (%r14,%rax,4)
movb $0x1, %r12b
movl %r13d, %ecx
movq 0x8(%rbx), %rdx
movq (%rdx), %rax
movq 0x8(%rdx), %rdx
subq %rax, %rdx
sarq $0x3, %rdx
incl %r13d
cmpq %rcx, %rdx
jne 0x1b881
leaq 0x30(%rsp), %rax
movl $0x0, (%rax)
xorl %r12d, %r12d
movq %r12, 0x8(%rax)
movq %rax, 0x10(%rax)
movq %rax, 0x18(%rax)
movq %r12, 0x20(%rax)
movq 0x8(%rbx), %rax
movq 0x8(%rax), %rcx
cmpq (%rax), %rcx
je 0x1ba7f
leaq 0x22a09(%rip), %r15     # 0x3e3b0
xorl %r13d, %r13d
movl $0x30, %edi
callq 0x62e0
movq %rax, %rbp
movq %rax, %rdi
xorl %esi, %esi
callq 0x1b514
movq %rbp, 0x8(%rsp)
movq 0x8(%r15), %rsi
movq %rsi, %rax
subq (%r15), %rax
shrq $0x3, %rax
movl %eax, (%rbp)
cmpq 0x10(%r15), %rsi
je 0x1b9e7
movq %rbp, (%rsi)
addq $0x8, 0x8(%r15)
jmp 0x1b9f4
movq %r15, %rdi
leaq 0x8(%rsp), %rdx
callq 0x1cbc2
movq 0x8(%rbx), %rax
movq (%rax), %rax
movq (%rax,%r13,8), %rbp
movq 0x8(%r15), %rax
movq -0x8(%rax), %r13
leaq 0x8(%rbp), %rsi
leaq 0x28(%rsp), %rdi
callq 0x1c8e6
movq %r13, (%rax)
incl %r12d
movl %r12d, %eax
movl %eax, %r12d
movq 0x8(%r15), %rax
movq -0x8(%rax), %rdi
movq %rbp, %rsi
xorl %edx, %edx
callq 0x1b59a
movq 0x8(%rbx), %rcx
movl %r12d, %r13d
movq (%rcx), %rax
movq 0x8(%rcx), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %r13, %rcx
jbe 0x1ba67
movq (%rax,%r13,8), %rbp
movl 0x8(%rbp), %ecx
movl %ecx, %eax
shrl $0x5, %eax
movl (%r14,%rax,4), %edx
leal 0x1(%r12), %eax
btl %ecx, %edx
jae 0x1ba1e
movq 0x8(%rbx), %rax
movq 0x8(%rax), %rcx
subq (%rax), %rcx
sarq $0x3, %rcx
cmpq %r13, %rcx
ja 0x1b9aa
movq %r14, %rdi
callq 0x63a0
leaq 0x22922(%rip), %r12     # 0x3e3b0
movq (%r12), %rax
movq 0x8(%r12), %rcx
subq %rax, %rcx
je 0x1bd00
sarq $0x3, %rcx
movl $0x1, %edx
xorl %r13d, %r13d
movq $-0x8, %rbx
movq (%rax,%r13,8), %r15
leaq 0x10(%r15), %rbp
movq $0x0, 0x10(%r15)
movl %edx, %r14d
cmpq %r14, %rcx
jbe 0x1bb29
movq (%rax,%r13,8), %rax
movq 0x8(%rax), %rcx
movq 0x8(%rcx), %rcx
cmpb $0x0, 0x4(%rax)
movl $0x10, %eax
cmovneq %rbx, %rax
movq (%rcx,%rax), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
testb %al, %al
je 0x1bb1d
movq (%r12), %rax
movq (%rax,%r13,8), %rax
movq 0x8(%rax), %rcx
movq 0x8(%rcx), %rcx
cmpb $0x0, 0x4(%rax)
movl $0x10, %eax
cmovneq %rbx, %rax
movq (%rcx,%rax), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
testb %al, %al
jne 0x1bb29
movq (%r12), %rax
movq (%rax,%r14,8), %rax
movq %rax, (%rbp)
movq 0x8(%r15), %rax
movq 0x8(%rax), %rax
cmpb $0x0, 0x4(%r15)
movl $0x10, %ecx
cmovneq %rbx, %rcx
movq (%rax,%rcx), %r13
movq (%r13), %rax
movq %r13, %rdi
callq *0x8(%rax)
testb %al, %al
je 0x1bb78
cmpl $0x16, 0xc(%r13)
jne 0x1bb78
movq 0x20(%r13), %rax
movl (%rax), %eax
movl %eax, 0x8(%rsp)
leaq 0x28(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x1c94a
movq (%rax), %rax
movq %rax, (%rbp)
cmpl $0x10, 0xc(%r13)
jne 0x1bb9f
movq 0x20(%r13), %rax
movl (%rax), %eax
movl %eax, 0x8(%rsp)
leaq 0x28(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x1c94a
movq (%rax), %rax
movq %rax, (%rbp)
movq (%r13), %rax
movq %r13, %rdi
callq *0x8(%rax)
testb %al, %al
je 0x1bce0
movq (%r13), %rax
movq %r13, %rdi
callq *0x10(%rax)
testb %al, %al
jne 0x1bce0
cmpl $0x1, 0xc(%r13)
jne 0x1bc19
movq 0x18(%r13), %rax
movq (%rax), %rsi
leaq 0x8(%rsp), %r13
movq %r13, %rdi
callq 0x17fb8
leaq 0x2272b(%rip), %rdi     # 0x3e310
movq %r13, %rsi
callq 0x1a308
movl (%rax), %eax
movl %eax, 0x4(%rsp)
leaq 0x28(%rsp), %rdi
leaq 0x4(%rsp), %rsi
callq 0x1c94a
movq 0x20(%r15), %rsi
cmpq 0x28(%r15), %rsi
je 0x1bc59
movq (%rax), %rax
movq %rax, (%rsi)
addq $0x8, 0x20(%r15)
jmp 0x1bc68
movq 0x20(%r13), %rax
testq %rax, %rax
je 0x1bce0
movl (%rax), %eax
movl %eax, 0x8(%rsp)
leaq 0x28(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x1c94a
movq 0x20(%r15), %rsi
cmpq 0x28(%r15), %rsi
je 0x1bcd1
movq (%rax), %rax
movq %rax, (%rsi)
addq $0x8, 0x20(%r15)
jmp 0x1bce0
addq $0x18, %r15
movq %r15, %rdi
movq %rax, %rdx
callq 0x1cbc2
leaq 0x226d1(%rip), %rdi     # 0x3e340
movq %r13, %rsi
callq 0x1a308
movl (%rax), %eax
movl %eax, 0x4(%rsp)
leaq 0x28(%rsp), %rdi
leaq 0x4(%rsp), %rsi
callq 0x1c94a
movq (%rax), %rdi
movq 0x20(%rdi), %rsi
cmpq 0x28(%rdi), %rsi
je 0x1bca7
movq (%rbp), %rax
movq %rax, (%rsi)
addq $0x8, 0x20(%rdi)
jmp 0x1bcb3
addq $0x18, %rdi
movq %rbp, %rdx
callq 0x1cbc2
movq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rdi
je 0x1bce0
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x62f0
jmp 0x1bce0
addq $0x18, %r15
movq %r15, %rdi
movq %rax, %rdx
callq 0x1cbc2
movq (%r12), %rax
movq 0x8(%r12), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
leal 0x1(%r14), %edx
movq %r14, %r13
cmpq %r14, %rcx
jne 0x1bab3
leaq 0x28(%rsp), %rdi
callq 0x1ca36
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x1bd7c
jmp 0x1bd7c
jmp 0x1bd1f
movq %rax, %rbx
movq 0x28(%rsp), %rdi
leaq 0x38(%rsp), %rax
cmpq %rax, %rdi
je 0x1bd89
movq 0x38(%rsp), %rsi
incq %rsi
callq 0x62f0
jmp 0x1bd89
jmp 0x1bd7c
jmp 0x1bd44
movq %rax, %rbx
movq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rdi
je 0x1bd7f
movq 0x18(%rsp), %rsi
incq %rsi
jmp 0x1bd6f
jmp 0x1bd7c
jmp 0x1bd7c
movq %rax, %rbx
movl $0x30, %esi
movq %rbp, %rdi
callq 0x62f0
jmp 0x1bd7f
jmp 0x1bd7c
jmp 0x1bd7c
jmp 0x1bd7c
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x1ca36
movq %rbx, %rdi
callq 0x6550