// File: /workspace/github_cpp_makefile_star2_O3/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 0x1b7e6
shrl $0x5, %eax
leal 0x4(,%rax,4), %edi
callq 0x6400
movq %rax, %r14
movq %rbx, %rdi
callq 0x1b7e6
shrl $0x5, %eax
leal 0x4(,%rax,4), %edx
movq %r14, %rdi
xorl %esi, %esi
callq 0x6190
movq 0x8(%rbx), %rax
movq (%rax), %rcx
cmpq %rcx, 0x8(%rax)
je 0x1bac9
leaq 0x38(%rsp), %r12
movb $0x1, %al
movl $0x1, %r13d
xorl %edx, %edx
leaq 0x28(%rsp), %r15
movq (%rcx,%rdx,8), %rbp
testb $0x1, %al
je 0x1b8c8
movl 0x8(%rbp), %ecx
movl %ecx, %eax
movl $0x1, %edx
shll %cl, %edx
shrl $0x5, %eax
orl %edx, (%r14,%rax,4)
movq (%rbp), %rax
movq %rbp, %rdi
callq *0x8(%rax)
testb %al, %al
je 0x1b973
movl 0xc(%rbp), %eax
cmpl $0xf, %eax
je 0x1b907
cmpl $0x1, %eax
jne 0x1b954
movq 0x18(%rbp), %rax
movq (%rax), %rsi
movq %r15, %rdi
callq 0x17ff4
leaq 0x23a1b(%rip), %rdi     # 0x3f318
movq %r15, %rsi
callq 0x168c4
jmp 0x1b925
movq 0x20(%rbp), %rax
movq (%rax), %rsi
movq %r15, %rdi
callq 0x17ff4
leaq 0x23a2b(%rip), %rdi     # 0x3f348
movq %r15, %rsi
callq 0x168c4
movl (%rax), %ebp
movq 0x28(%rsp), %rdi
cmpq %r12, %rdi
je 0x1b93e
movq 0x38(%rsp), %rsi
incq %rsi
callq 0x6300
leal 0x1f(%rbp), %eax
testl %ebp, %ebp
cmovnsl %ebp, %eax
sarl $0x5, %eax
cltq
movl $0x1, %edx
movl %ebp, %ecx
jmp 0x1b969
movq 0x20(%rbp), %rax
testq %rax, %rax
je 0x1b973
movl (%rax), %ecx
movl %ecx, %eax
shrl $0x5, %eax
movl $0x1, %edx
shll %cl, %edx
orl %edx, (%r14,%rax,4)
movb $0x1, %al
jmp 0x1b975
xorl %eax, %eax
movl %r13d, %edx
movq 0x8(%rbx), %rsi
movq (%rsi), %rcx
movq 0x8(%rsi), %rsi
movq %rsi, %rdi
subq %rcx, %rdi
sarq $0x3, %rdi
incl %r13d
cmpq %rdx, %rdi
jne 0x1b8ad
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)
cmpq %rcx, %rsi
je 0x1bae6
leaq 0x239f1(%rip), %r15     # 0x3f3b8
xorl %r13d, %r13d
movl $0x30, %edi
callq 0x62f0
movq %rax, %rbp
xorps %xmm0, %xmm0
movups %xmm0, 0x18(%rax)
movq $0x0, 0x28(%rax)
movb $0x0, 0x4(%rax)
movl $0x18, %edi
callq 0x62f0
movq %rax, 0x8(%rax)
movq %rax, (%rax)
movq $0x0, 0x10(%rax)
movq %rax, 0x8(%rbp)
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 0x1ba34
movq %rbp, (%rsi)
movq 0x8(%r15), %rax
addq $0x8, %rax
movq %rax, 0x8(%r15)
jmp 0x1ba45
movq %r15, %rdi
leaq 0x8(%rsp), %rdx
callq 0x1cc26
movq 0x8(%r15), %rax
movq 0x8(%rbx), %rcx
movq (%rcx), %rcx
movq (%rcx,%r13,8), %rbp
movq -0x8(%rax), %r13
leaq 0x8(%rbp), %rsi
leaq 0x28(%rsp), %rdi
callq 0x1c946
movq %r13, (%rax)
incl %r12d
movl %r12d, %edx
movl %edx, %r12d
movq 0x8(%r15), %rax
movq -0x8(%rax), %rdi
movq %rbp, %rsi
xorl %edx, %edx
callq 0x1b5bc
movq 0x8(%rbx), %rax
movl %r12d, %r13d
movq (%rax), %rdx
movq 0x8(%rax), %rcx
movq %rcx, %rsi
subq %rdx, %rsi
sarq $0x3, %rsi
cmpq %r13, %rsi
jbe 0x1bab7
movq (%rdx,%r13,8), %rbp
movl 0x8(%rbp), %esi
movl %esi, %edx
shrl $0x5, %edx
movl (%r14,%rdx,4), %edi
leal 0x1(%r12), %edx
btl %esi, %edi
jae 0x1ba6b
subq (%rax), %rcx
sarq $0x3, %rcx
cmpq %r13, %rcx
ja 0x1b9ca
jmp 0x1bae6
leaq 0x30(%rsp), %rax
movl $0x0, (%rax)
xorl %ecx, %ecx
movq %rcx, 0x8(%rax)
movq %rax, 0x10(%rax)
movq %rax, 0x18(%rax)
movq %rcx, 0x20(%rax)
movq %r14, %rdi
callq 0x63b0
leaq 0x238c3(%rip), %r12     # 0x3f3b8
movq (%r12), %rax
movq 0x8(%r12), %rcx
subq %rax, %rcx
je 0x1bd67
sarq $0x3, %rcx
movl $0x1, %edx
xorl %r14d, %r14d
movq $-0x8, %rbx
movq %r14, %r13
movq (%rax,%r14,8), %r15
leaq 0x10(%r15), %rbp
movq $0x0, 0x10(%r15)
movl %edx, %r14d
cmpq %r14, %rcx
jbe 0x1bb93
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 0x1bb87
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 0x1bb93
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 0x1bbe2
cmpl $0x16, 0xc(%r13)
jne 0x1bbe2
movq 0x20(%r13), %rax
movl (%rax), %eax
movl %eax, 0x8(%rsp)
leaq 0x28(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x1c9ac
movq (%rax), %rax
movq %rax, (%rbp)
cmpl $0x10, 0xc(%r13)
jne 0x1bc09
movq 0x20(%r13), %rax
movl (%rax), %eax
movl %eax, 0x8(%rsp)
leaq 0x28(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x1c9ac
movq (%rax), %rax
movq %rax, (%rbp)
movq (%r13), %rax
movq %r13, %rdi
callq *0x8(%rax)
testb %al, %al
je 0x1bd4a
movq (%r13), %rax
movq %r13, %rdi
callq *0x10(%rax)
testb %al, %al
jne 0x1bd4a
cmpl $0x1, 0xc(%r13)
jne 0x1bc83
movq 0x18(%r13), %rax
movq (%rax), %rsi
leaq 0x8(%rsp), %r13
movq %r13, %rdi
callq 0x17ff4
leaq 0x236c9(%rip), %rdi     # 0x3f318
movq %r13, %rsi
callq 0x1a360
movl (%rax), %eax
movl %eax, 0x4(%rsp)
leaq 0x28(%rsp), %rdi
leaq 0x4(%rsp), %rsi
callq 0x1c9ac
movq 0x20(%r15), %rsi
cmpq 0x28(%r15), %rsi
je 0x1bcc3
movq (%rax), %rax
movq %rax, (%rsi)
addq $0x8, 0x20(%r15)
jmp 0x1bcd2
movq 0x20(%r13), %rax
testq %rax, %rax
je 0x1bd4a
movl (%rax), %eax
movl %eax, 0x8(%rsp)
leaq 0x28(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x1c9ac
movq 0x20(%r15), %rsi
cmpq 0x28(%r15), %rsi
je 0x1bd3b
movq (%rax), %rax
movq %rax, (%rsi)
addq $0x8, 0x20(%r15)
jmp 0x1bd4a
addq $0x18, %r15
movq %r15, %rdi
movq %rax, %rdx
callq 0x1cc26
leaq 0x2366f(%rip), %rdi     # 0x3f348
movq %r13, %rsi
callq 0x1a360
movl (%rax), %eax
movl %eax, 0x4(%rsp)
leaq 0x28(%rsp), %rdi
leaq 0x4(%rsp), %rsi
callq 0x1c9ac
movq (%rax), %rdi
movq 0x20(%rdi), %rsi
cmpq 0x28(%rdi), %rsi
je 0x1bd11
movq (%rbp), %rax
movq %rax, (%rsi)
addq $0x8, 0x20(%rdi)
jmp 0x1bd1d
addq $0x18, %rdi
movq %rbp, %rdx
callq 0x1cc26
movq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rdi
je 0x1bd4a
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x6300
jmp 0x1bd4a
addq $0x18, %r15
movq %r15, %rdi
movq %rax, %rdx
callq 0x1cc26
movq (%r12), %rax
movq 0x8(%r12), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
leal 0x1(%r14), %edx
cmpq %r14, %rcx
jne 0x1bb1a
leaq 0x28(%rsp), %rdi
callq 0x1ca9a
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x1bdde
jmp 0x1bdde
jmp 0x1bd86
movq %rax, %rbx
movq 0x28(%rsp), %rdi
cmpq %r12, %rdi
je 0x1bdeb
movq 0x38(%rsp), %rsi
incq %rsi
callq 0x6300
jmp 0x1bdeb
jmp 0x1bdde
jmp 0x1bda6
movq %rax, %rbx
movq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rdi
je 0x1bde1
movq 0x18(%rsp), %rsi
incq %rsi
jmp 0x1bdcf
jmp 0x1bdde
movq %rax, %rbx
movl $0x30, %esi
movq %rbp, %rdi
callq 0x6300
jmp 0x1bde1
jmp 0x1bdde
jmp 0x1bdde
jmp 0x1bdde
jmp 0x1bdde
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x1ca9a
movq %rbx, %rdi
callq 0x6560