123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- #include "BasicBlockSpliter.h"
- #include "../metadata/Opcodes.h"
- #include "../metadata/MetadataUtil.h"
- using namespace hybridclr::metadata;
- namespace hybridclr
- {
- namespace transform
- {
- void BasicBlockSpliter::SplitNormal(const byte* ilcodeStart, uint32_t codeSize, Uin32Set& ilOffsets)
- {
- const byte* codeEnd = ilcodeStart + codeSize;
- const byte* ip = ilcodeStart;
- while (ip < codeEnd)
- {
- ilOffsets.insert((uint32_t)(ip - ilcodeStart));
- const OpCodeInfo* oc = DecodeOpCodeInfo(ip, codeEnd);
- IL2CPP_ASSERT(oc);
- int32_t opCodeSize = GetOpCodeSize(ip, oc);
- const byte* nextIp = ip + opCodeSize;
- int32_t nextOffset = (int32_t)(nextIp - ilcodeStart);
- IL2CPP_ASSERT(nextOffset >= 0 && nextOffset <= (int32_t)codeSize);
- switch (oc->inlineType)
- {
- case ArgType::None:
- case ArgType::Data:
- {
- break;
- }
- case ArgType::StaticBranch:
- {
- _splitOffsets.insert(nextOffset);
- break;
- }
- case ArgType::BranchTarget:
- {
- int32_t offset;
- switch (oc->inlineParam)
- {
- case 1:
- {
- offset = GetI1(ip + 1);
- break;
- }
- case 4:
- {
- offset = GetI4LittleEndian(ip + 1);
- break;
- }
- default:
- {
- RaiseExecutionEngineException("invalid BranchTarget param");
- offset = -1;
- }
- }
- // don't split 0 offset br
- if (offset != 0 || (oc->baseOpValue == OpcodeValue::LEAVE || oc->baseOpValue == OpcodeValue::LEAVE_S))
- {
- _splitOffsets.insert(nextOffset);
- _splitOffsets.insert(nextOffset + offset);
- }
- break;
- }
- case ArgType::Switch:
- {
- uint32_t caseNum = GetI4LittleEndian(ip + 1);
- bool splitAny = false;
- for (uint32_t caseIdx = 0; caseIdx < caseNum; caseIdx++)
- {
- int32_t caseOffset = GetI4LittleEndian(ip + 5 + caseIdx * 4);
- if (caseOffset != 0)
- {
- _splitOffsets.insert(nextOffset + caseOffset);
- splitAny = true;
- }
- }
- if (splitAny)
- {
- _splitOffsets.insert(nextOffset);
- }
- break;
- }
- default:
- {
- RaiseExecutionEngineException("unknown inline type");
- nextOffset = -1;
- }
- }
- ip = nextIp;
- }
- IL2CPP_ASSERT(ip == codeEnd);
- }
- void BasicBlockSpliter::SplitExceptionHandles(const byte* ilcodeStart, uint32_t codeSize, const std::vector<metadata::ExceptionClause>& exceptionClauses)
- {
- for (auto& eh : exceptionClauses)
- {
- _splitOffsets.insert(eh.tryOffset);
- _splitOffsets.insert(eh.tryOffset + eh.tryLength);
- _splitOffsets.insert(eh.handlerOffsets);
- _splitOffsets.insert(eh.handlerOffsets + eh.handlerLength);
- if (eh.flags == CorILExceptionClauseType::Filter)
- {
- _splitOffsets.insert(eh.classTokenOrFilterOffset);
- }
- }
- }
- void BasicBlockSpliter::SplitBasicBlocks()
- {
- const byte* ilcodeStart = _body.ilcodes;
- uint32_t codeSize = _body.codeSize;
- Uin32Set ilOffsets(codeSize);
- ilOffsets.insert(codeSize);
- SplitNormal(ilcodeStart, codeSize, ilOffsets);
- SplitExceptionHandles(ilcodeStart, codeSize, _body.exceptionClauses);
- /*if (_splitOffsets.find(0) != _splitOffsets.end())
- {
- _splitOffsets.erase(0);
- }*/
- #if DEBUG
- for (uint32_t offset : _splitOffsets)
- {
- IL2CPP_ASSERT(ilOffsets.find(offset) != ilOffsets.end());
- }
- IL2CPP_ASSERT(_splitOffsets.find(codeSize) != _splitOffsets.end());
- #endif
- }
- }
- }
|