#pragma once

#include "_global.h"

enum BasicBlockFlags : duint
{
    BASIC_BLOCK_FLAG_NONE = 0,                 // No flag

    BASIC_BLOCK_FLAG_FUNCTION = (1 << 1),      // Scanned; also part of a known function
    BASIC_BLOCK_FLAG_CUTOFF = (1 << 3),        // Ends prematurely because of another JMP to location
    BASIC_BLOCK_FLAG_DELETE = (1 << 4),        // Delete element at the next possible time

    BASIC_BLOCK_FLAG_CALL = (1 << 5),          // The block ends with a call
    BASIC_BLOCK_FLAG_RET = (1 << 6),           // The block ends with a retn
    BASIC_BLOCK_FLAG_ABSJMP = (1 << 7),        // Branch is absolute
    BASIC_BLOCK_FLAG_INDIRECT = (1 << 8),      // This block ends with an indirect branch; memory or register
    BASIC_BLOCK_FLAG_INDIRPTR = (1 << 9),      // This block ends with an indirect branch; pointer known

    BASIC_BLOCK_FLAG_CALL_TARGET = (1 << 10),  // Block is pointed to by a call instruction
    //BASIC_BLOCK_FLAG_JMP_TARGET = (1 << 11),

    BASIC_BLOCK_FLAG_PREPAD = (1 << 12),    // Block ends because there was padding afterwards
    BASIC_BLOCK_FLAG_PAD = (1 << 13),       // Block is only a series of padding instructions
};

struct BasicBlock
{
    duint VirtualStart;  // Inclusive
    duint VirtualEnd;    // Inclusive
    duint Flags;
    duint Target;

    duint InstrCount;   // Number of instructions in block

    __forceinline bool GetFlag(duint Flag)
    {
        return (Flags & Flag) == Flag;
    }

    __forceinline void SetFlag(duint Flag)
    {
        Flags |= Flag;
    }

    __forceinline duint Size()
    {
        return VirtualEnd - VirtualStart;
    }

    bool operator< (const BasicBlock & b) const
    {
        return VirtualStart < b.VirtualStart;
    }

    bool operator== (const BasicBlock & b) const
    {
        return VirtualStart == b.VirtualStart;
    }
};

struct FunctionDef
{
    duint VirtualStart;  // Inclusive
    duint VirtualEnd;    // Inclusive

    duint BBlockStart;   // Index of first basic block
    duint BBlockEnd;     // Index of last basic block

    duint InstrCount;   // Number of instructions in function

    bool operator< (const FunctionDef & b) const
    {
        if(VirtualStart == b.VirtualStart)
            return VirtualEnd > b.VirtualEnd;

        return VirtualStart < b.VirtualStart;
    }

    bool operator== (const FunctionDef & b) const
    {
        return VirtualStart == b.VirtualStart;
    }
};

typedef std::vector<BasicBlock> BBlockArray;
typedef std::vector<FunctionDef> FuncDefArray;