BasicBlockSpliter.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #include "BasicBlockSpliter.h"
  2. #include "../metadata/Opcodes.h"
  3. #include "../metadata/MetadataUtil.h"
  4. using namespace hybridclr::metadata;
  5. namespace hybridclr
  6. {
  7. namespace transform
  8. {
  9. void BasicBlockSpliter::SplitNormal(const byte* ilcodeStart, uint32_t codeSize, Uin32Set& ilOffsets)
  10. {
  11. const byte* codeEnd = ilcodeStart + codeSize;
  12. const byte* ip = ilcodeStart;
  13. while (ip < codeEnd)
  14. {
  15. ilOffsets.insert((uint32_t)(ip - ilcodeStart));
  16. const OpCodeInfo* oc = DecodeOpCodeInfo(ip, codeEnd);
  17. IL2CPP_ASSERT(oc);
  18. int32_t opCodeSize = GetOpCodeSize(ip, oc);
  19. const byte* nextIp = ip + opCodeSize;
  20. int32_t nextOffset = (int32_t)(nextIp - ilcodeStart);
  21. IL2CPP_ASSERT(nextOffset >= 0 && nextOffset <= (int32_t)codeSize);
  22. switch (oc->inlineType)
  23. {
  24. case ArgType::None:
  25. case ArgType::Data:
  26. {
  27. break;
  28. }
  29. case ArgType::StaticBranch:
  30. {
  31. _splitOffsets.insert(nextOffset);
  32. break;
  33. }
  34. case ArgType::BranchTarget:
  35. {
  36. int32_t offset;
  37. switch (oc->inlineParam)
  38. {
  39. case 1:
  40. {
  41. offset = GetI1(ip + 1);
  42. break;
  43. }
  44. case 4:
  45. {
  46. offset = GetI4LittleEndian(ip + 1);
  47. break;
  48. }
  49. default:
  50. {
  51. RaiseExecutionEngineException("invalid BranchTarget param");
  52. offset = -1;
  53. }
  54. }
  55. // don't split 0 offset br
  56. if (offset != 0 || (oc->baseOpValue == OpcodeValue::LEAVE || oc->baseOpValue == OpcodeValue::LEAVE_S))
  57. {
  58. _splitOffsets.insert(nextOffset);
  59. _splitOffsets.insert(nextOffset + offset);
  60. }
  61. break;
  62. }
  63. case ArgType::Switch:
  64. {
  65. uint32_t caseNum = GetI4LittleEndian(ip + 1);
  66. bool splitAny = false;
  67. for (uint32_t caseIdx = 0; caseIdx < caseNum; caseIdx++)
  68. {
  69. int32_t caseOffset = GetI4LittleEndian(ip + 5 + caseIdx * 4);
  70. if (caseOffset != 0)
  71. {
  72. _splitOffsets.insert(nextOffset + caseOffset);
  73. splitAny = true;
  74. }
  75. }
  76. if (splitAny)
  77. {
  78. _splitOffsets.insert(nextOffset);
  79. }
  80. break;
  81. }
  82. default:
  83. {
  84. RaiseExecutionEngineException("unknown inline type");
  85. nextOffset = -1;
  86. }
  87. }
  88. ip = nextIp;
  89. }
  90. IL2CPP_ASSERT(ip == codeEnd);
  91. }
  92. void BasicBlockSpliter::SplitExceptionHandles(const byte* ilcodeStart, uint32_t codeSize, const std::vector<metadata::ExceptionClause>& exceptionClauses)
  93. {
  94. for (auto& eh : exceptionClauses)
  95. {
  96. _splitOffsets.insert(eh.tryOffset);
  97. _splitOffsets.insert(eh.tryOffset + eh.tryLength);
  98. _splitOffsets.insert(eh.handlerOffsets);
  99. _splitOffsets.insert(eh.handlerOffsets + eh.handlerLength);
  100. if (eh.flags == CorILExceptionClauseType::Filter)
  101. {
  102. _splitOffsets.insert(eh.classTokenOrFilterOffset);
  103. }
  104. }
  105. }
  106. void BasicBlockSpliter::SplitBasicBlocks()
  107. {
  108. const byte* ilcodeStart = _body.ilcodes;
  109. uint32_t codeSize = _body.codeSize;
  110. Uin32Set ilOffsets(codeSize);
  111. ilOffsets.insert(codeSize);
  112. SplitNormal(ilcodeStart, codeSize, ilOffsets);
  113. SplitExceptionHandles(ilcodeStart, codeSize, _body.exceptionClauses);
  114. /*if (_splitOffsets.find(0) != _splitOffsets.end())
  115. {
  116. _splitOffsets.erase(0);
  117. }*/
  118. #if DEBUG
  119. for (uint32_t offset : _splitOffsets)
  120. {
  121. IL2CPP_ASSERT(ilOffsets.find(offset) != ilOffsets.end());
  122. }
  123. IL2CPP_ASSERT(_splitOffsets.find(codeSize) != _splitOffsets.end());
  124. #endif
  125. }
  126. }
  127. }