// File: /workspace/github_cpp_makefile_star2_O2/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, %r14
callq 0x16d50
shrl $0x5, %eax
leal 0x4(,%rax,4), %edi
callq 0x63d0
movq %rax, %r15
movq %r14, %rdi
callq 0x16d50
shrl $0x5, %eax
leal 0x4(,%rax,4), %edx
xorl %r12d, %r12d
movq %r15, %rdi
xorl %esi, %esi
callq 0x6180
movb $0x1, %cl
leaq 0x8(%rsp), %rbx
pushq $0x20
popq %r13
movl %r12d, %r12d
movq 0x8(%r14), %rax
movq (%rax), %rdx
movq 0x8(%rax), %rax
movq %rax, %rsi
subq %rdx, %rsi
sarq $0x3, %rsi
cmpq %r12, %rsi
je 0x16ecc
movq (%rdx,%r12,8), %rbp
testb $0x1, %cl
je 0x16e2d
movl 0x8(%rbp), %ecx
movl %ecx, %eax
pushq $0x1
popq %rdx
shll %cl, %edx
shrl $0x5, %eax
orl %edx, (%r15,%rax,4)
movq (%rbp), %rax
movq %rbp, %rdi
callq *0x8(%rax)
testb %al, %al
je 0x16ec2
movl 0xc(%rbp), %eax
cmpl $0xf, %eax
je 0x16e6c
cmpl $0x1, %eax
jne 0x16ea5
movq 0x18(%rbp), %rax
movq (%rax), %rsi
movq %rbx, %rdi
callq 0x13efa
leaq 0x214ae(%rip), %rdi     # 0x38310
movq %rbx, %rsi
callq 0x12504
jmp 0x16e8a
movq 0x20(%rbp), %rax
movq (%rax), %rsi
movq %rbx, %rdi
callq 0x13efa
leaq 0x214be(%rip), %rdi     # 0x38340
movq %rbx, %rsi
callq 0x12504
movl (%rax), %ebp
movq %rbx, %rdi
callq 0x65c8
movl %ebp, %eax
cltd
idivl %r13d
cltq
pushq $0x1
popq %rcx
movl %ecx, %edx
movl %ebp, %ecx
jmp 0x16eb8
movq 0x20(%rbp), %rax
testq %rax, %rax
je 0x16ec2
movl (%rax), %ecx
movl %ecx, %eax
shrl $0x5, %eax
pushq $0x1
popq %rdx
shll %cl, %edx
orl %edx, (%r15,%rax,4)
movb $0x1, %cl
jmp 0x16ec4
xorl %ecx, %ecx
incl %r12d
jmp 0x16df2
leaq 0x10(%rsp), %rcx
andl $0x0, (%rcx)
andq $0x0, 0x8(%rcx)
movq %rcx, 0x10(%rcx)
movq %rcx, 0x18(%rcx)
andq $0x0, 0x20(%rcx)
xorl %r13d, %r13d
leaq 0x214c0(%rip), %rbx     # 0x383b0
subq %rdx, %rax
movl %r13d, %ebp
sarq $0x3, %rax
cmpq %rbp, %rax
jbe 0x16fb5
pushq $0x30
popq %rdi
callq 0x62d0
movq %rax, %r12
movq %rax, %rdi
xorl %esi, %esi
callq 0x16ba0
movq %r12, 0x38(%rsp)
movq 0x8(%rbx), %rax
subq (%rbx), %rax
shrq $0x3, %rax
movl %eax, (%r12)
movq %rbx, %rdi
leaq 0x38(%rsp), %rsi
callq 0x178fa
movq 0x8(%r14), %rax
movq (%rax), %rax
movq (%rax,%rbp,8), %r12
movq 0x8(%rbx), %rax
movq -0x8(%rax), %r13
leaq 0x8(%r12), %rsi
leaq 0x8(%rsp), %rdi
callq 0x17918
movq %r13, (%rax)
incl %ebp
movl %ebp, %r13d
movq 0x8(%rbx), %rax
movq -0x8(%rax), %rdi
movq %r12, %rsi
xorl %edx, %edx
callq 0x16c02
movq 0x8(%r14), %rcx
movl %r13d, %edx
movq (%rcx), %rsi
movq 0x8(%rcx), %rax
movq %rax, %rdi
subq %rsi, %rdi
sarq $0x3, %rdi
cmpq %rdx, %rdi
jbe 0x16fad
movq (%rsi,%rdx,8), %r12
movl 0x8(%r12), %edx
movl %edx, %esi
shrl $0x5, %esi
movl (%r15,%rsi,4), %esi
leal 0x1(%r13), %ebp
btl %edx, %esi
jae 0x16f60
movq (%rcx), %rdx
jmp 0x16ef0
movq %r15, %rdi
callq 0x6370
pushq $0x1
popq %rdx
leal -0x1(%rdx), %r14d
movq (%rbx), %rax
movq 0x8(%rbx), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %r14, %rcx
je 0x171a7
movq (%rax,%r14,8), %rbp
andq $0x0, 0x10(%rbp)
leaq 0x10(%rbp), %r12
movq %rdx, %r15
movl %edx, %r13d
cmpq %r13, %rcx
jbe 0x17051
movq (%rax,%r14,8), %rax
movq 0x8(%rax), %rcx
movq 0x8(%rcx), %rcx
cmpb $0x0, 0x4(%rax)
pushq $0x10
popq %rax
pushq $-0x8
popq %rdx
cmovneq %rdx, %rax
movq (%rcx,%rax), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
testb %al, %al
je 0x17046
movq (%rbx), %rax
movq (%rax,%r14,8), %rax
movq 0x8(%rax), %rcx
movq 0x8(%rcx), %rcx
cmpb $0x0, 0x4(%rax)
pushq $0x10
popq %rax
pushq $-0x8
popq %rdx
cmovneq %rdx, %rax
movq (%rcx,%rax), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
testb %al, %al
jne 0x17051
movq (%rbx), %rax
movq (%rax,%r13,8), %rax
movq %rax, (%r12)
movq 0x8(%rbp), %rax
movq 0x8(%rax), %rax
cmpb $0x0, 0x4(%rbp)
pushq $0x10
popq %rcx
pushq $-0x8
popq %rdx
cmovneq %rdx, %rcx
movq (%rax,%rcx), %r13
movq (%r13), %rax
movq %r13, %rdi
callq *0x8(%rax)
leaq 0x38(%rsp), %r14
testb %al, %al
je 0x170a3
cmpl $0x16, 0xc(%r13)
jne 0x170a3
movq 0x20(%r13), %rax
movl (%rax), %eax
movl %eax, 0x38(%rsp)
leaq 0x8(%rsp), %rdi
movq %r14, %rsi
callq 0x17966
movq (%rax), %rax
movq %rax, (%r12)
cmpl $0x10, 0xc(%r13)
jne 0x170c8
movq 0x20(%r13), %rax
movl (%rax), %eax
movl %eax, 0x38(%rsp)
leaq 0x8(%rsp), %rdi
movq %r14, %rsi
callq 0x17966
movq (%rax), %rax
movq %rax, (%r12)
movq (%r13), %rax
movq %r13, %rdi
callq *0x8(%rax)
testb %al, %al
je 0x1719d
movq (%r13), %rax
movq %r13, %rdi
callq *0x10(%rax)
testb %al, %al
jne 0x1719d
cmpl $0x1, 0xc(%r13)
jne 0x17172
movq 0x18(%r13), %rax
movq (%rax), %rsi
movq %r14, %rdi
callq 0x13efa
leaq 0x21207(%rip), %rdi     # 0x38310
movq %r14, %rsi
callq 0x15a98
movl (%rax), %eax
movl %eax, 0x4(%rsp)
leaq 0x8(%rsp), %rdi
leaq 0x4(%rsp), %rsi
callq 0x17966
addq $0x18, %rbp
movq %rbp, %rdi
movq %rax, %rsi
callq 0x178fa
leaq 0x21204(%rip), %rdi     # 0x38340
movq %r14, %rsi
callq 0x15a98
movl (%rax), %eax
movl %eax, 0x4(%rsp)
leaq 0x8(%rsp), %rdi
leaq 0x4(%rsp), %rsi
callq 0x17966
movq (%rax), %rdi
addq $0x18, %rdi
movq %r12, %rsi
callq 0x178fa
movq %r14, %rdi
callq 0x65c8
jmp 0x1719d
movq 0x20(%r13), %rax
testq %rax, %rax
je 0x1719d
movl (%rax), %eax
movl %eax, 0x38(%rsp)
leaq 0x8(%rsp), %rdi
movq %r14, %rsi
callq 0x17966
addq $0x18, %rbp
movq %rbp, %rdi
movq %rax, %rsi
callq 0x178fa
movq %r15, %rdx
incl %edx
jmp 0x16fc0
leaq 0x8(%rsp), %rdi
callq 0x17a4a
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x17202
jmp 0x17202
jmp 0x171c6
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x65c8
jmp 0x1720f
jmp 0x17202
jmp 0x171d9
movq %rax, %rbx
leaq 0x38(%rsp), %rdi
callq 0x65c8
jmp 0x17205
jmp 0x17202
jmp 0x17202
jmp 0x17202
movq %rax, %rbx
pushq $0x30
popq %rsi
movq %r12, %rdi
callq 0x62e0
jmp 0x17205
jmp 0x17202
jmp 0x17202
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x17a4a
movq %rbx, %rdi
callq 0x6530