// File: 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:
subq $0x238, %rsp            # imm = 0x238
movq %rdi, 0x230(%rsp)
movq 0x230(%rsp), %rdi
movq %rdi, 0x118(%rsp)
callq 0x33130
shrl $0x5, %eax
addl $0x1, %eax
movl %eax, %eax
movl %eax, %edi
shlq $0x2, %rdi
callq 0x6530
movq 0x118(%rsp), %rdi
movq %rax, 0x228(%rsp)
movq 0x228(%rsp), %rax
movq %rax, 0x110(%rsp)
callq 0x33130
movq 0x110(%rsp), %rdi
shrl $0x5, %eax
addl $0x1, %eax
movl %eax, %eax
movl %eax, %edx
shlq $0x2, %rdx
xorl %esi, %esi
callq 0x61e0
movq 0x118(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0x34ba0
movq %rax, 0x220(%rsp)
movb $0x1, 0x21f(%rsp)
movl $0x0, 0x218(%rsp)
movq 0x118(%rsp), %rax
movl 0x218(%rsp), %ecx
movq %rcx, 0x108(%rsp)
movq 0x8(%rax), %rdi
callq 0x34d30
movq %rax, %rcx
movq 0x108(%rsp), %rax
cmpq %rcx, %rax
je 0x336d1
movq 0x118(%rsp), %rax
movq 0x8(%rax), %rdi
movl 0x218(%rsp), %eax
movl %eax, %esi
callq 0x34d50
movq (%rax), %rax
movq %rax, 0x210(%rsp)
testb $0x1, 0x21f(%rsp)
je 0x3339d
movq 0x228(%rsp), %rax
movq 0x210(%rsp), %rcx
movl 0x8(%rcx), %ecx
shrl $0x5, %ecx
movl %ecx, %ecx
movl (%rax,%rcx,4), %edx
movq 0x210(%rsp), %rax
movl 0x8(%rax), %ecx
andl $0x1f, %ecx
movl $0x1, %eax
shll %cl, %eax
orl %eax, %edx
movq 0x228(%rsp), %rax
movq 0x210(%rsp), %rcx
movl 0x8(%rcx), %ecx
shrl $0x5, %ecx
movl %ecx, %ecx
movl %edx, (%rax,%rcx,4)
movb $0x0, 0x21f(%rsp)
movq 0x210(%rsp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
testb $0x1, %al
jne 0x333b4
jmp 0x336b9
movq 0x210(%rsp), %rax
cmpl $0x1, 0xc(%rax)
jne 0x334fd
movq 0x210(%rsp), %rax
movq 0x18(%rax), %rax
movq (%rax), %rsi
leaq 0x1e8(%rsp), %rdi
movq %rdi, 0xf8(%rsp)
callq 0x295b0
movq 0xf8(%rsp), %rsi
leaq 0x3afef(%rip), %rdi     # 0x6e3e8
callq 0x20cd0
movq %rax, 0x100(%rsp)
jmp 0x33408
movq 0x100(%rsp), %rax
movl (%rax), %eax
movl %eax, 0xdc(%rsp)
leaq 0x1e8(%rsp), %rdi
callq 0x6778
movl 0xdc(%rsp), %eax
movl %eax, 0x20c(%rsp)
movq 0x228(%rsp), %rax
movq %rax, 0xe0(%rsp)
movl 0x20c(%rsp), %eax
movl $0x20, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movq 0xe0(%rsp), %rax
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
movl %eax, 0xe8(%rsp)
movl 0x20c(%rsp), %eax
movl $0x20, %ecx
cltd
idivl %ecx
movl 0xe8(%rsp), %eax
movl %edx, %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
orl %ecx, %eax
movl %eax, 0xec(%rsp)
movq 0x228(%rsp), %rax
movq %rax, 0xf0(%rsp)
movl 0x20c(%rsp), %eax
movl $0x20, %ecx
cltd
idivl %ecx
movl 0xec(%rsp), %edx
movl %eax, %ecx
movq 0xf0(%rsp), %rax
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
movb $0x1, 0x21f(%rsp)
jmp 0x336b7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1e0(%rsp)
movl %eax, 0x1dc(%rsp)
leaq 0x1e8(%rsp), %rdi
callq 0x6778
jmp 0x33d4a
movq 0x210(%rsp), %rax
cmpl $0xf, 0xc(%rax)
jne 0x33646
movq 0x210(%rsp), %rax
movq 0x20(%rax), %rax
movq (%rax), %rsi
leaq 0x1b8(%rsp), %rdi
movq %rdi, 0xc8(%rsp)
callq 0x295b0
movq 0xc8(%rsp), %rsi
leaq 0x3aed6(%rip), %rdi     # 0x6e418
callq 0x20cd0
movq %rax, 0xd0(%rsp)
jmp 0x33551
movq 0xd0(%rsp), %rax
movl (%rax), %eax
movl %eax, 0xac(%rsp)
leaq 0x1b8(%rsp), %rdi
callq 0x6778
movl 0xac(%rsp), %eax
movl %eax, 0x1d8(%rsp)
movq 0x228(%rsp), %rax
movq %rax, 0xb0(%rsp)
movl 0x1d8(%rsp), %eax
movl $0x20, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movq 0xb0(%rsp), %rax
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
movl %eax, 0xb8(%rsp)
movl 0x1d8(%rsp), %eax
movl $0x20, %ecx
cltd
idivl %ecx
movl 0xb8(%rsp), %eax
movl %edx, %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
orl %ecx, %eax
movl %eax, 0xbc(%rsp)
movq 0x228(%rsp), %rax
movq %rax, 0xc0(%rsp)
movl 0x1d8(%rsp), %eax
movl $0x20, %ecx
cltd
idivl %ecx
movl 0xbc(%rsp), %edx
movl %eax, %ecx
movq 0xc0(%rsp), %rax
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
movb $0x1, 0x21f(%rsp)
jmp 0x336b5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1e0(%rsp)
movl %eax, 0x1dc(%rsp)
leaq 0x1b8(%rsp), %rdi
callq 0x6778
jmp 0x33d4a
movq 0x210(%rsp), %rax
cmpq $0x0, 0x20(%rax)
je 0x336b3
movq 0x210(%rsp), %rax
movq 0x20(%rax), %rax
movl (%rax), %eax
movl %eax, 0x1b4(%rsp)
movq 0x228(%rsp), %rax
movl 0x1b4(%rsp), %ecx
shrl $0x5, %ecx
movl %ecx, %ecx
movl (%rax,%rcx,4), %edx
movl 0x1b4(%rsp), %ecx
andl $0x1f, %ecx
movl $0x1, %eax
shll %cl, %eax
orl %eax, %edx
movq 0x228(%rsp), %rax
movl 0x1b4(%rsp), %ecx
shrl $0x5, %ecx
movl %ecx, %ecx
movl %edx, (%rax,%rcx,4)
movb $0x1, 0x21f(%rsp)
jmp 0x336b5
jmp 0x336b7
jmp 0x336b9
jmp 0x336bb
movl 0x218(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x218(%rsp)
jmp 0x332e5
leaq 0x180(%rsp), %rdi
callq 0x34db0
movl $0x0, 0x218(%rsp)
movq 0x118(%rsp), %rax
movl 0x218(%rsp), %ecx
movq %rcx, 0xa0(%rsp)
movq 0x8(%rax), %rdi
callq 0x34d30
movq %rax, %rcx
movq 0xa0(%rsp), %rax
cmpq %rcx, %rax
jae 0x33916
movl $0x30, %edi
callq 0x6390
movq %rax, 0x98(%rsp)
jmp 0x33731
movq 0x98(%rsp), %rdi
xorl %esi, %esi
callq 0x32d00
jmp 0x33742
movq 0x98(%rsp), %rax
movq %rax, 0x178(%rsp)
leaq 0x3ad2f(%rip), %rdi     # 0x6e488
movq %rdi, 0x90(%rsp)
callq 0x34dc0
movq 0x90(%rsp), %rdi
movl %eax, %ecx
movq 0x178(%rsp), %rax
movl %ecx, (%rax)
leaq 0x178(%rsp), %rsi
callq 0x34de0
jmp 0x33789
movq 0x118(%rsp), %rax
movq 0x8(%rax), %rdi
movl 0x218(%rsp), %eax
movl %eax, %esi
callq 0x34d50
movq (%rax), %rax
movq %rax, 0x170(%rsp)
leaq 0x3acd3(%rip), %rdi     # 0x6e488
callq 0x34e50
movq (%rax), %rax
movq %rax, 0x80(%rsp)
movq 0x170(%rsp), %rsi
addq $0x8, %rsi
leaq 0x180(%rsp), %rdi
callq 0x34e90
movq %rax, 0x88(%rsp)
jmp 0x337e8
movq 0x88(%rsp), %rax
movq 0x80(%rsp), %rcx
movq %rcx, (%rax)
leaq 0x3ac86(%rip), %rdi     # 0x6e488
callq 0x34e50
movq (%rax), %rdi
movq 0x170(%rsp), %rsi
xorl %edx, %edx
callq 0x32de0
jmp 0x3381b
movq 0x118(%rsp), %rax
movl 0x218(%rsp), %ecx
addl $0x1, %ecx
movl %ecx, 0x218(%rsp)
movq 0x8(%rax), %rdi
movl 0x218(%rsp), %eax
movl %eax, %esi
callq 0x34d50
movq (%rax), %rax
movq %rax, 0x170(%rsp)
movq 0x118(%rsp), %rax
movl 0x218(%rsp), %ecx
movq %rcx, 0x70(%rsp)
movq 0x8(%rax), %rdi
callq 0x34d30
movq 0x70(%rsp), %rcx
movq %rax, %rdx
xorl %eax, %eax
cmpq %rdx, %rcx
movb %al, 0x7f(%rsp)
jae 0x338c1
movq 0x228(%rsp), %rax
movq 0x170(%rsp), %rcx
movl 0x8(%rcx), %ecx
shrl $0x5, %ecx
movl %ecx, %ecx
movl (%rax,%rcx,4), %eax
movq 0x170(%rsp), %rcx
movl 0x8(%rcx), %ecx
andl $0x1f, %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
movb %al, 0x7f(%rsp)
movb 0x7f(%rsp), %al
testb $0x1, %al
jne 0x337fb
jmp 0x336e9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1e0(%rsp)
movl %eax, 0x1dc(%rsp)
jmp 0x33d3d
movq 0x98(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1e0(%rsp)
movl %eax, 0x1dc(%rsp)
movl $0x30, %esi
callq 0x63a0
jmp 0x33d3d
movq 0x228(%rsp), %rdi
callq 0x64a0
movl $0x0, 0x16c(%rsp)
movl 0x16c(%rsp), %eax
movq %rax, 0x68(%rsp)
leaq 0x3ab47(%rip), %rdi     # 0x6e488
callq 0x34dc0
movq %rax, %rcx
movq 0x68(%rsp), %rax
cmpq %rcx, %rax
je 0x33d28
movl 0x16c(%rsp), %eax
movl %eax, %esi
leaq 0x3ab21(%rip), %rdi     # 0x6e488
callq 0x34f80
movq (%rax), %rax
movq %rax, 0x160(%rsp)
movq 0x160(%rsp), %rax
movq $0x0, 0x10(%rax)
movl 0x16c(%rsp), %eax
addl $0x1, %eax
movl %eax, %eax
movq %rax, 0x60(%rsp)
leaq 0x3aae9(%rip), %rdi     # 0x6e488
callq 0x34dc0
movq %rax, %rcx
movq 0x60(%rsp), %rax
cmpq %rcx, %rax
jae 0x33a50
movl 0x16c(%rsp), %eax
movl %eax, %esi
leaq 0x3aac3(%rip), %rdi     # 0x6e488
callq 0x34f80
movq (%rax), %rdi
callq 0x32ec0
movq %rax, %rdi
movq (%rdi), %rax
movq 0x8(%rax), %rax
callq *%rax
movb %al, 0x5f(%rsp)
jmp 0x339e4
movb 0x5f(%rsp), %al
testb $0x1, %al
jne 0x339ee
jmp 0x33a27
movl 0x16c(%rsp), %eax
movl %eax, %esi
leaq 0x3aa8a(%rip), %rdi     # 0x6e488
callq 0x34f80
movq (%rax), %rdi
callq 0x32ec0
movq %rax, %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movb %al, 0x5e(%rsp)
jmp 0x33a1d
movb 0x5e(%rsp), %al
testb $0x1, %al
jne 0x33a50
jmp 0x33a27
movl 0x16c(%rsp), %eax
addl $0x1, %eax
movl %eax, %eax
movl %eax, %esi
leaq 0x3aa4c(%rip), %rdi     # 0x6e488
callq 0x34f80
movq (%rax), %rcx
movq 0x160(%rsp), %rax
movq %rcx, 0x10(%rax)
movq 0x160(%rsp), %rdi
callq 0x32ec0
movq %rax, 0x158(%rsp)
movq 0x158(%rsp), %rdi
movq (%rdi), %rax
movq 0x8(%rax), %rax
callq *%rax
movb %al, 0x5d(%rsp)
jmp 0x33a7c
movb 0x5d(%rsp), %al
testb $0x1, %al
jne 0x33a86
jmp 0x33ad9
movq 0x158(%rsp), %rax
cmpl $0x16, 0xc(%rax)
jne 0x33ad9
movq 0x158(%rsp), %rax
movq 0x20(%rax), %rax
movl (%rax), %eax
movl %eax, 0x154(%rsp)
leaq 0x180(%rsp), %rdi
leaq 0x154(%rsp), %rsi
callq 0x34fa0
movq %rax, 0x50(%rsp)
jmp 0x33ac5
movq 0x50(%rsp), %rax
movq (%rax), %rcx
movq 0x160(%rsp), %rax
movq %rcx, 0x10(%rax)
movq 0x158(%rsp), %rax
cmpl $0x10, 0xc(%rax)
jne 0x33b2c
movq 0x158(%rsp), %rax
movq 0x20(%rax), %rax
movl (%rax), %eax
movl %eax, 0x150(%rsp)
leaq 0x180(%rsp), %rdi
leaq 0x150(%rsp), %rsi
callq 0x34fa0
movq %rax, 0x48(%rsp)
jmp 0x33b18
movq 0x48(%rsp), %rax
movq (%rax), %rcx
movq 0x160(%rsp), %rax
movq %rcx, 0x10(%rax)
movq 0x158(%rsp), %rdi
movq (%rdi), %rax
movq 0x8(%rax), %rax
callq *%rax
movb %al, 0x47(%rsp)
jmp 0x33b43
movb 0x47(%rsp), %al
testb $0x1, %al
jne 0x33b50
jmp 0x33d10
movq 0x158(%rsp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movb %al, 0x46(%rsp)
jmp 0x33b67
movb 0x46(%rsp), %al
testb $0x1, %al
jne 0x33d10
jmp 0x33b75
movq 0x158(%rsp), %rax
cmpl $0x1, 0xc(%rax)
jne 0x33ca8
movq 0x158(%rsp), %rax
movq 0x18(%rax), %rax
movq (%rax), %rsi
leaq 0x130(%rsp), %rdi
callq 0x295b0
jmp 0x33ba5
movq 0x160(%rsp), %rax
addq $0x18, %rax
movq %rax, 0x30(%rsp)
leaq 0x3a82b(%rip), %rdi     # 0x6e3e8
leaq 0x130(%rsp), %rsi
callq 0x2de90
movq %rax, 0x38(%rsp)
jmp 0x33bd1
movq 0x38(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x12c(%rsp)
leaq 0x180(%rsp), %rdi
leaq 0x12c(%rsp), %rsi
callq 0x34fa0
movq %rax, 0x28(%rsp)
jmp 0x33bfb
movq 0x28(%rsp), %rsi
movq 0x30(%rsp), %rdi
callq 0x34de0
jmp 0x33c0c
leaq 0x3a805(%rip), %rdi     # 0x6e418
leaq 0x130(%rsp), %rsi
callq 0x2de90
movq %rax, 0x20(%rsp)
jmp 0x33c27
movq 0x20(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x128(%rsp)
leaq 0x180(%rsp), %rdi
leaq 0x128(%rsp), %rsi
callq 0x34fa0
movq %rax, 0x18(%rsp)
jmp 0x33c51
movq 0x18(%rsp), %rax
movq (%rax), %rdi
addq $0x18, %rdi
movq 0x160(%rsp), %rsi
addq $0x10, %rsi
callq 0x34de0
jmp 0x33c70
leaq 0x130(%rsp), %rdi
callq 0x6778
jmp 0x33d0e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1e0(%rsp)
movl %eax, 0x1dc(%rsp)
leaq 0x130(%rsp), %rdi
callq 0x6778
jmp 0x33d3d
movq 0x158(%rsp), %rax
cmpq $0x0, 0x20(%rax)
je 0x33d0c
movq 0x160(%rsp), %rax
addq $0x18, %rax
movq %rax, 0x8(%rsp)
movq 0x158(%rsp), %rax
movq 0x20(%rax), %rax
movl (%rax), %eax
movl %eax, 0x124(%rsp)
leaq 0x180(%rsp), %rdi
leaq 0x124(%rsp), %rsi
callq 0x34fa0
movq %rax, 0x10(%rsp)
jmp 0x33cf9
movq 0x10(%rsp), %rsi
movq 0x8(%rsp), %rdi
callq 0x34de0
jmp 0x33d0a
jmp 0x33d0c
jmp 0x33d0e
jmp 0x33d10
jmp 0x33d12
movl 0x16c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x16c(%rsp)
jmp 0x3392e
leaq 0x180(%rsp), %rdi
callq 0x35090
addq $0x238, %rsp            # imm = 0x238
retq
leaq 0x180(%rsp), %rdi
callq 0x35090
movq 0x1e0(%rsp), %rdi
callq 0x66b0
nopw (%rax,%rax)