ILInstruction.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection.Emit;
  4. namespace Harmony.ILCopying
  5. {
  6. public enum ExceptionBlockType
  7. {
  8. BeginExceptionBlock,
  9. BeginCatchBlock,
  10. BeginExceptFilterBlock,
  11. BeginFaultBlock,
  12. BeginFinallyBlock,
  13. EndExceptionBlock
  14. }
  15. public class ExceptionBlock
  16. {
  17. public ExceptionBlockType blockType;
  18. public Type catchType;
  19. public ExceptionBlock(ExceptionBlockType blockType, Type catchType)
  20. {
  21. this.blockType = blockType;
  22. this.catchType = catchType;
  23. }
  24. }
  25. public class ILInstruction
  26. {
  27. public int offset;
  28. public OpCode opcode;
  29. public object operand;
  30. public object argument;
  31. public List<Label> labels = new List<Label>();
  32. public List<ExceptionBlock> blocks = new List<ExceptionBlock>();
  33. public ILInstruction(OpCode opcode, object operand = null)
  34. {
  35. this.opcode = opcode;
  36. this.operand = operand;
  37. argument = operand;
  38. }
  39. public CodeInstruction GetCodeInstruction()
  40. {
  41. var instr = new CodeInstruction(opcode, argument);
  42. if (opcode.OperandType == OperandType.InlineNone)
  43. instr.operand = null;
  44. instr.labels = labels;
  45. instr.blocks = blocks;
  46. return instr;
  47. }
  48. public int GetSize()
  49. {
  50. var size = opcode.Size;
  51. switch (opcode.OperandType)
  52. {
  53. case OperandType.InlineSwitch:
  54. size += (1 + ((Array)operand).Length) * 4;
  55. break;
  56. case OperandType.InlineI8:
  57. case OperandType.InlineR:
  58. size += 8;
  59. break;
  60. case OperandType.InlineBrTarget:
  61. case OperandType.InlineField:
  62. case OperandType.InlineI:
  63. case OperandType.InlineMethod:
  64. case OperandType.InlineSig:
  65. case OperandType.InlineString:
  66. case OperandType.InlineTok:
  67. case OperandType.InlineType:
  68. case OperandType.ShortInlineR:
  69. size += 4;
  70. break;
  71. case OperandType.InlineVar:
  72. size += 2;
  73. break;
  74. case OperandType.ShortInlineBrTarget:
  75. case OperandType.ShortInlineI:
  76. case OperandType.ShortInlineVar:
  77. size += 1;
  78. break;
  79. }
  80. return size;
  81. }
  82. public override string ToString()
  83. {
  84. var instruction = "";
  85. AppendLabel(ref instruction, this);
  86. instruction = instruction + ": " + opcode.Name;
  87. if (operand == null)
  88. return instruction;
  89. instruction = instruction + " ";
  90. switch (opcode.OperandType)
  91. {
  92. case OperandType.ShortInlineBrTarget:
  93. case OperandType.InlineBrTarget:
  94. AppendLabel(ref instruction, operand);
  95. break;
  96. case OperandType.InlineSwitch:
  97. var switchLabels = (ILInstruction[])operand;
  98. for (var i = 0; i < switchLabels.Length; i++)
  99. {
  100. if (i > 0)
  101. instruction = instruction + ",";
  102. AppendLabel(ref instruction, switchLabels[i]);
  103. }
  104. break;
  105. case OperandType.InlineString:
  106. instruction = instruction + "\"" + operand + "\"";
  107. break;
  108. default:
  109. instruction = instruction + operand;
  110. break;
  111. }
  112. return instruction;
  113. }
  114. static void AppendLabel(ref string str, object argument)
  115. {
  116. var instruction = argument as ILInstruction;
  117. if (instruction != null)
  118. str = str + "IL_" + instruction.offset.ToString("X4");
  119. else
  120. str = str + "IL_" + argument;
  121. }
  122. }
  123. }