CodeBasicBlock.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using ILRuntime.Mono.Cecil;
  6. using ILRuntime.Mono.Cecil.Cil;
  7. using ILRuntime.CLR.TypeSystem;
  8. using ILRuntime.CLR.Method;
  9. using ILRuntime.Runtime.Intepreter.OpCodes;
  10. namespace ILRuntime.Runtime.Intepreter.RegisterVM
  11. {
  12. class RegisterVMSymbolLink
  13. {
  14. public int BaseRegisterIndex;
  15. public RegisterVMSymbol Value;
  16. }
  17. struct InlineMethodInfo
  18. {
  19. public short LocalStartRegister;
  20. public ILMethod Method;
  21. }
  22. struct RegisterVMSymbol
  23. {
  24. public Instruction Instruction;
  25. public ILMethod Method;
  26. public RegisterVMSymbolLink ParentSymbol;
  27. }
  28. class CodeBasicBlock
  29. {
  30. List<Instruction> instructions = new List<Instruction>();
  31. List<OpCodeR> finalInstructions = new List<OpCodeR>();
  32. HashSet<int> canRemove = new HashSet<int>();
  33. HashSet<int> pendingCP = new HashSet<int>();
  34. HashSet<CodeBasicBlock> prevBlocks = new HashSet<CodeBasicBlock>();
  35. HashSet<CodeBasicBlock> nextBlocks = new HashSet<CodeBasicBlock>();
  36. Dictionary<int, RegisterVMSymbol> instructionMapping = new Dictionary<int, RegisterVMSymbol>();
  37. short endRegister = -1;
  38. Instruction entry;
  39. public List<Instruction> Instructions { get { return instructions; } }
  40. public List<OpCodeR> FinalInstructions { get { return finalInstructions; } }
  41. public HashSet<int> CanRemove { get { return canRemove; } }
  42. public HashSet<int> PendingCP { get { return pendingCP; } }
  43. public HashSet<CodeBasicBlock> PreviousBlocks { get { return prevBlocks; } }
  44. public HashSet<CodeBasicBlock> NextBlocks { get { return nextBlocks; } }
  45. public Dictionary<int, RegisterVMSymbol> InstructionMapping { get { return instructionMapping; } }
  46. public bool NeedLoadConstantElimination { get; set; }
  47. public short EndRegister
  48. {
  49. get
  50. { return endRegister; }
  51. set
  52. {
  53. endRegister = value;
  54. }
  55. }
  56. public void AddInstruction(Instruction op)
  57. {
  58. if (instructions.Count == 0)
  59. entry = op;
  60. instructions.Add(op);
  61. }
  62. public static List<CodeBasicBlock> BuildBasicBlocks(MethodBody body, out Dictionary<Instruction, int> entryMapping)
  63. {
  64. entryMapping = new Dictionary<Instruction, int>();
  65. HashSet<Instruction> branchTargets = new HashSet<Instruction>();
  66. foreach (var i in body.Instructions)
  67. {
  68. switch (i.OpCode.OperandType)
  69. {
  70. case OperandType.InlineBrTarget:
  71. case OperandType.ShortInlineBrTarget:
  72. branchTargets.Add((Instruction)i.Operand);
  73. break;
  74. case OperandType.InlineSwitch:
  75. {
  76. var arr = i.Operand as Instruction[];
  77. foreach (var j in arr)
  78. branchTargets.Add(j);
  79. }
  80. break;
  81. }
  82. }
  83. List<CodeBasicBlock> res = new List<CodeBasicBlock>();
  84. CodeBasicBlock cur = new CodeBasicBlock();
  85. res.Add(cur);
  86. foreach (var i in body.Instructions)
  87. {
  88. if (branchTargets.Contains(i))
  89. {
  90. if(cur.entry != null && cur.entry != i)
  91. {
  92. entryMapping[cur.entry] = res.Count - 1;
  93. cur = new CodeBasicBlock();
  94. res.Add(cur);
  95. }
  96. }
  97. cur.AddInstruction(i);
  98. if (i.OpCode.Code == Code.Switch || i.OpCode.Code == Code.Throw || i.OpCode.OperandType == OperandType.InlineBrTarget || i.OpCode.OperandType == OperandType.ShortInlineBrTarget || i.OpCode.Code == Code.Endfinally)
  99. {
  100. if (cur.entry != null)
  101. {
  102. if (i.OpCode.OperandType == OperandType.InlineBrTarget || i.OpCode.OperandType == OperandType.ShortInlineBrTarget)
  103. {
  104. if (cur.entry != (Instruction)i.Operand)
  105. {
  106. entryMapping[cur.entry] = res.Count - 1;
  107. cur = new CodeBasicBlock();
  108. res.Add(cur);
  109. }
  110. }
  111. else
  112. {
  113. if (i.Operand is Instruction)
  114. {
  115. if (cur.entry != (Instruction)i.Operand)
  116. {
  117. entryMapping[cur.entry] = res.Count - 1;
  118. cur = new CodeBasicBlock();
  119. res.Add(cur);
  120. }
  121. }
  122. else
  123. {
  124. entryMapping[cur.entry] = res.Count - 1;
  125. cur = new CodeBasicBlock();
  126. res.Add(cur);
  127. }
  128. }
  129. }
  130. }
  131. }
  132. if (cur.entry != null)
  133. entryMapping[cur.entry] = res.Count - 1;
  134. else
  135. res.RemoveAt(res.Count - 1);
  136. for (int i = 0; i < res.Count; i++)
  137. {
  138. var block = res[i];
  139. var lastIns = block.instructions[block.instructions.Count - 1];
  140. switch (lastIns.OpCode.OperandType)
  141. {
  142. case OperandType.ShortInlineBrTarget:
  143. case OperandType.InlineBrTarget:
  144. {
  145. var dstBlock = res[entryMapping[(Instruction)lastIns.Operand]];
  146. dstBlock.prevBlocks.Add(block);
  147. block.nextBlocks.Add(dstBlock);
  148. switch (lastIns.OpCode.Code)
  149. {
  150. case Code.Brfalse:
  151. case Code.Brfalse_S:
  152. case Code.Brtrue:
  153. case Code.Brtrue_S:
  154. case Code.Beq:
  155. case Code.Beq_S:
  156. case Code.Bge:
  157. case Code.Bge_S:
  158. case Code.Bge_Un:
  159. case Code.Bge_Un_S:
  160. case Code.Bgt:
  161. case Code.Bgt_S:
  162. case Code.Bgt_Un:
  163. case Code.Bgt_Un_S:
  164. case Code.Ble:
  165. case Code.Ble_S:
  166. case Code.Ble_Un:
  167. case Code.Ble_Un_S:
  168. case Code.Blt:
  169. case Code.Blt_S:
  170. case Code.Blt_Un:
  171. case Code.Blt_Un_S:
  172. case Code.Bne_Un:
  173. case Code.Bne_Un_S:
  174. if (i < res.Count - 1)
  175. {
  176. var next = res[i + 1];
  177. block.nextBlocks.Add(next);
  178. next.prevBlocks.Add(block);
  179. }
  180. break;
  181. default:
  182. continue;
  183. }
  184. }
  185. break;
  186. case OperandType.InlineSwitch:
  187. {
  188. Instruction[] targets = (Instruction[])lastIns.Operand;
  189. foreach(var t in targets)
  190. {
  191. var dstBlock = res[entryMapping[t]];
  192. dstBlock.prevBlocks.Add(block);
  193. block.nextBlocks.Add(dstBlock);
  194. }
  195. }
  196. break;
  197. }
  198. if (i < res.Count - 1)
  199. {
  200. var next = res[i + 1];
  201. block.nextBlocks.Add(next);
  202. next.prevBlocks.Add(block);
  203. }
  204. }
  205. return res;
  206. }
  207. }
  208. }