HRESULT ImportIL()

in ProfilingAPI/ReJITEnterLeaveHooks/ILRewriter.cpp [229:366]


    HRESULT ImportIL(LPCBYTE pIL)
    {
        m_pOffsetToInstr = new ILInstr*[m_CodeSize + 1];
        IfNullRet(m_pOffsetToInstr);

        ZeroMemory(m_pOffsetToInstr, m_CodeSize * sizeof(ILInstr*));

        // Set the sentinel instruction
        m_pOffsetToInstr[m_CodeSize] = &m_IL;
        m_IL.m_opcode = -1;

        bool fBranch = false;
        unsigned offset = 0;
        while (offset < m_CodeSize)
        {
            unsigned startOffset = offset;
            unsigned opcode = pIL[offset++];

            if (opcode == CEE_PREFIX1)
            {
                if (offset >= m_CodeSize)
                {
                    assert(false);
                    return COR_E_INVALIDPROGRAM;
                }
                opcode = 0x100 + pIL[offset++];
            }

            if ((CEE_PREFIX7 <= opcode) && (opcode <= CEE_PREFIX2))
            {
                // NOTE: CEE_PREFIX2-7 are currently not supported
                assert(false);
                return COR_E_INVALIDPROGRAM;
            }

            if (opcode >= CEE_COUNT)
            {
                assert(false);
                return COR_E_INVALIDPROGRAM;
            }

            BYTE flags = s_OpCodeFlags[opcode];

            int size = (flags & OPCODEFLAGS_SizeMask);
            if (offset + size > m_CodeSize)
            {
                assert(false);
                return COR_E_INVALIDPROGRAM;
            }

            ILInstr * pInstr = NewILInstr();
            IfNullRet(pInstr);

            pInstr->m_opcode = opcode;

            InsertBefore(&m_IL, pInstr);

            m_pOffsetToInstr[startOffset] = pInstr;

            switch (flags)
            {
            case 0:
                break;
            case 1:
                pInstr->m_Arg8 = *(UNALIGNED INT8 *)&(pIL[offset]);
                break;
            case 2:
                pInstr->m_Arg16 = *(UNALIGNED INT16 *)&(pIL[offset]);
                break;
            case 4:
                pInstr->m_Arg32 = *(UNALIGNED INT32 *)&(pIL[offset]);
                break;
            case 8:
                pInstr->m_Arg64 = *(UNALIGNED INT64 *)&(pIL[offset]);
                break;
            case 1 | OPCODEFLAGS_BranchTarget:
                pInstr->m_Arg32 = offset + 1 + *(UNALIGNED INT8 *)&(pIL[offset]);
                fBranch = true;
                break;
            case 4 | OPCODEFLAGS_BranchTarget:
                pInstr->m_Arg32 = offset + 4 + *(UNALIGNED INT32 *)&(pIL[offset]);
                fBranch = true;
                break;
            case 0 | OPCODEFLAGS_Switch:
            {
                if (offset + sizeof(INT32) > m_CodeSize)
                {
                    assert(false);
                    return COR_E_INVALIDPROGRAM;
                }

                unsigned nTargets = *(UNALIGNED INT32 *)&(pIL[offset]);
                pInstr->m_Arg32 = nTargets;
                offset += sizeof(INT32);

                unsigned base = offset + nTargets * sizeof(INT32);

                for (unsigned iTarget = 0; iTarget < nTargets; iTarget++)
                {
                    if (offset + sizeof(INT32) > m_CodeSize)
                    {
                        assert(false);
                        return COR_E_INVALIDPROGRAM;
                    }

                    pInstr = NewILInstr();
                    IfNullRet(pInstr);

                    pInstr->m_opcode = CEE_SWITCH_ARG;

                    pInstr->m_Arg32 = base + *(UNALIGNED INT32 *)&(pIL[offset]);
                    offset += sizeof(INT32);

                    InsertBefore(&m_IL, pInstr);
                }
                fBranch = true;
                break;
            }
            default:
                assert(false);
                break;
            }
            offset += size;
        }
        assert(offset == m_CodeSize);

        if (fBranch)
        {
            // Go over all control flow instructions and resolve the targets
            for (ILInstr * pInstr = m_IL.m_pNext; pInstr != &m_IL; pInstr = pInstr->m_pNext)
            {
                if (s_OpCodeFlags[pInstr->m_opcode] & OPCODEFLAGS_BranchTarget)
                    pInstr->m_pTarget = GetInstrFromOffset(pInstr->m_Arg32);
            }
        }

        return S_OK;
    }