Repository: dotnet/runtime
File: src/coreclr/interpreter/compiler.h (C/C++)

Code before:
#define CALL_ARGS_TERMINATOR -1

struct StackInfo;

enum InterpBBState
{
    BBStateNotEmitted,
    BBStateEmitting,
    BBStateEmitted
};

enum InterpBBClauseType
{
    BBClauseNone,
    BBClauseCatch,
    BBClauseFinally,
    BBClauseFilter,
};

struct InterpBasicBlock
{
    int32_t index;
    int32_t ilOffset, nativeOffset;
    int32_t nativeEndOffset;
    int32_t stackHeight;
    uint32_t bbEHClauseIndex;
    StackInfo *pStackState;

    InterpInst *pFirstIns, *pLastIns;
    InterpBasicBlock *pNextBB;

    // * If this basic block is a finally, this points to a finally call island that is located where the finally
    //   was before all funclets were moved to the end of the method.
    // * If this basic block is a catch, this points to a catch leave island that is located where the catch
    //   was before all funclets were moved to the end of the method.
    // * If this basic block is a call island, this points to the next finally call / catch leave island basic block.
    // * Otherwise, this is NULL.
    InterpBasicBlock *pLeaveChainIslandBB;
    // Target of a leave instruction that is located in this basic block. NULL if there is none.
    InterpBasicBlock *pLeaveTargetBB;

    int inCount, outCount;
    InterpBasicBlock **ppInBBs;
    InterpBasicBlock **ppOutBBs;

    InterpBBState emitState;

    // Type of the innermost try block, catch, filter, or finally that contains this basic block.
    uint8_t clauseType;

    // True indicates that this basic block is the first block of a filter, catch or filtered handler funclet.

Review comment (suggestion):
I wonder if we really actually need the bbEHClauseIndex. If I understand it correctly, it serves for distinguishing between BBs of the leave chain islands from the regular blocks that share the same IL offset. But the BBs of the leave chain islands would never be merged with any other BBs, because they only generate optional INTOP_CALL_FINALLY and INTOP_BR or INTOP_LEAVE_CATCH and can be only entered by a INTOP_BR.

Code after:
#define CALL_ARGS_TERMINATOR -1

struct StackInfo;

enum InterpBBState
{
    BBStateNotEmitted,
    BBStateEmitting,
    BBStateEmitted
};

enum InterpBBClauseType
{
    BBClauseNone,
    BBClauseCatch,
    BBClauseFinally,
    BBClauseFilter,
};

struct InterpBasicBlock
{
    int32_t index;
    int32_t ilOffset, nativeOffset;
    int32_t nativeEndOffset;
    int32_t stackHeight;
    StackInfo *pStackState;

    InterpInst *pFirstIns, *pLastIns;
    InterpBasicBlock *pNextBB;

    // * If this basic block is a finally, this points to a finally call island that is located where the finally
    //   was before all funclets were moved to the end of the method.
    // * If this basic block is a catch, this points to a catch leave island that is located where the catch
    //   was before all funclets were moved to the end of the method.
    // * If this basic block is a call island, this points to the next finally call / catch leave island basic block.
    // * Otherwise, this is NULL.
    InterpBasicBlock *pLeaveChainIslandBB;
    // Target of a leave instruction that is located in this basic block. NULL if there is none.
    InterpBasicBlock *pLeaveTargetBB;

    int inCount, outCount;
    InterpBasicBlock **ppInBBs;
    InterpBasicBlock **ppOutBBs;

    InterpBBState emitState;

    // Type of the innermost try block, catch, filter, or finally that contains this basic block.
    uint8_t clauseType;

    // True indicates that this basic block is the first block of a filter, catch or filtered handler funclet.
    bool isFilterOrCatchFuncletEntry;