Instruction.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. //
  2. // Instruction.cs
  3. //
  4. // Author:
  5. // Jb Evain (jbevain@gmail.com)
  6. //
  7. // Copyright (c) 2008 - 2011 Jb Evain
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. using System;
  29. using System.Text;
  30. namespace Mono.Cecil.Cil {
  31. public sealed class Instruction {
  32. internal int offset;
  33. internal OpCode opcode;
  34. internal object operand;
  35. internal Instruction previous;
  36. internal Instruction next;
  37. SequencePoint sequence_point;
  38. public int Offset {
  39. get { return offset; }
  40. set { offset = value; }
  41. }
  42. public OpCode OpCode {
  43. get { return opcode; }
  44. set { opcode = value; }
  45. }
  46. public object Operand {
  47. get { return operand; }
  48. set { operand = value; }
  49. }
  50. public Instruction Previous {
  51. get { return previous; }
  52. set { previous = value; }
  53. }
  54. public Instruction Next {
  55. get { return next; }
  56. set { next = value; }
  57. }
  58. public SequencePoint SequencePoint {
  59. get { return sequence_point; }
  60. set { sequence_point = value; }
  61. }
  62. internal Instruction (int offset, OpCode opCode)
  63. {
  64. this.offset = offset;
  65. this.opcode = opCode;
  66. }
  67. internal Instruction (OpCode opcode, object operand)
  68. {
  69. this.opcode = opcode;
  70. this.operand = operand;
  71. }
  72. public int GetSize ()
  73. {
  74. int size = opcode.Size;
  75. switch (opcode.OperandType) {
  76. case OperandType.InlineSwitch:
  77. return size + (1 + ((Instruction []) operand).Length) * 4;
  78. case OperandType.InlineI8:
  79. case OperandType.InlineR:
  80. return size + 8;
  81. case OperandType.InlineBrTarget:
  82. case OperandType.InlineField:
  83. case OperandType.InlineI:
  84. case OperandType.InlineMethod:
  85. case OperandType.InlineString:
  86. case OperandType.InlineTok:
  87. case OperandType.InlineType:
  88. case OperandType.ShortInlineR:
  89. case OperandType.InlineSig:
  90. return size + 4;
  91. case OperandType.InlineArg:
  92. case OperandType.InlineVar:
  93. return size + 2;
  94. case OperandType.ShortInlineBrTarget:
  95. case OperandType.ShortInlineI:
  96. case OperandType.ShortInlineArg:
  97. case OperandType.ShortInlineVar:
  98. return size + 1;
  99. default:
  100. return size;
  101. }
  102. }
  103. public override string ToString ()
  104. {
  105. var instruction = new StringBuilder ();
  106. AppendLabel (instruction, this);
  107. instruction.Append (':');
  108. instruction.Append (' ');
  109. instruction.Append (opcode.Name);
  110. if (operand == null)
  111. return instruction.ToString ();
  112. instruction.Append (' ');
  113. switch (opcode.OperandType) {
  114. case OperandType.ShortInlineBrTarget:
  115. case OperandType.InlineBrTarget:
  116. AppendLabel (instruction, (Instruction) operand);
  117. break;
  118. case OperandType.InlineSwitch:
  119. var labels = (Instruction []) operand;
  120. for (int i = 0; i < labels.Length; i++) {
  121. if (i > 0)
  122. instruction.Append (',');
  123. AppendLabel (instruction, labels [i]);
  124. }
  125. break;
  126. case OperandType.InlineString:
  127. instruction.Append ('\"');
  128. instruction.Append (operand);
  129. instruction.Append ('\"');
  130. break;
  131. default:
  132. instruction.Append (operand);
  133. break;
  134. }
  135. return instruction.ToString ();
  136. }
  137. static void AppendLabel (StringBuilder builder, Instruction instruction)
  138. {
  139. builder.Append ("IL_");
  140. builder.Append (instruction.offset.ToString ("x4"));
  141. }
  142. public static Instruction Create (OpCode opcode)
  143. {
  144. if (opcode.OperandType != OperandType.InlineNone)
  145. throw new ArgumentException ("opcode");
  146. return new Instruction (opcode, null);
  147. }
  148. public static Instruction Create (OpCode opcode, TypeReference type)
  149. {
  150. if (type == null)
  151. throw new ArgumentNullException ("type");
  152. if (opcode.OperandType != OperandType.InlineType &&
  153. opcode.OperandType != OperandType.InlineTok)
  154. throw new ArgumentException ("opcode");
  155. return new Instruction (opcode, type);
  156. }
  157. public static Instruction Create (OpCode opcode, CallSite site)
  158. {
  159. if (site == null)
  160. throw new ArgumentNullException ("site");
  161. if (opcode.Code != Code.Calli)
  162. throw new ArgumentException ("code");
  163. return new Instruction (opcode, site);
  164. }
  165. public static Instruction Create (OpCode opcode, MethodReference method)
  166. {
  167. if (method == null)
  168. throw new ArgumentNullException ("method");
  169. if (opcode.OperandType != OperandType.InlineMethod &&
  170. opcode.OperandType != OperandType.InlineTok)
  171. throw new ArgumentException ("opcode");
  172. return new Instruction (opcode, method);
  173. }
  174. public static Instruction Create (OpCode opcode, FieldReference field)
  175. {
  176. if (field == null)
  177. throw new ArgumentNullException ("field");
  178. if (opcode.OperandType != OperandType.InlineField &&
  179. opcode.OperandType != OperandType.InlineTok)
  180. throw new ArgumentException ("opcode");
  181. return new Instruction (opcode, field);
  182. }
  183. public static Instruction Create (OpCode opcode, string value)
  184. {
  185. if (value == null)
  186. throw new ArgumentNullException ("value");
  187. if (opcode.OperandType != OperandType.InlineString)
  188. throw new ArgumentException ("opcode");
  189. return new Instruction (opcode, value);
  190. }
  191. public static Instruction Create (OpCode opcode, sbyte value)
  192. {
  193. if (opcode.OperandType != OperandType.ShortInlineI &&
  194. opcode != OpCodes.Ldc_I4_S)
  195. throw new ArgumentException ("opcode");
  196. return new Instruction (opcode, value);
  197. }
  198. public static Instruction Create (OpCode opcode, byte value)
  199. {
  200. if (opcode.OperandType != OperandType.ShortInlineI ||
  201. opcode == OpCodes.Ldc_I4_S)
  202. throw new ArgumentException ("opcode");
  203. return new Instruction (opcode, value);
  204. }
  205. public static Instruction Create (OpCode opcode, int value)
  206. {
  207. if (opcode.OperandType != OperandType.InlineI)
  208. throw new ArgumentException ("opcode");
  209. return new Instruction (opcode, value);
  210. }
  211. public static Instruction Create (OpCode opcode, long value)
  212. {
  213. if (opcode.OperandType != OperandType.InlineI8)
  214. throw new ArgumentException ("opcode");
  215. return new Instruction (opcode, value);
  216. }
  217. public static Instruction Create (OpCode opcode, float value)
  218. {
  219. if (opcode.OperandType != OperandType.ShortInlineR)
  220. throw new ArgumentException ("opcode");
  221. return new Instruction (opcode, value);
  222. }
  223. public static Instruction Create (OpCode opcode, double value)
  224. {
  225. if (opcode.OperandType != OperandType.InlineR)
  226. throw new ArgumentException ("opcode");
  227. return new Instruction (opcode, value);
  228. }
  229. public static Instruction Create (OpCode opcode, Instruction target)
  230. {
  231. if (target == null)
  232. throw new ArgumentNullException ("target");
  233. if (opcode.OperandType != OperandType.InlineBrTarget &&
  234. opcode.OperandType != OperandType.ShortInlineBrTarget)
  235. throw new ArgumentException ("opcode");
  236. return new Instruction (opcode, target);
  237. }
  238. public static Instruction Create (OpCode opcode, Instruction [] targets)
  239. {
  240. if (targets == null)
  241. throw new ArgumentNullException ("targets");
  242. if (opcode.OperandType != OperandType.InlineSwitch)
  243. throw new ArgumentException ("opcode");
  244. return new Instruction (opcode, targets);
  245. }
  246. public static Instruction Create (OpCode opcode, VariableDefinition variable)
  247. {
  248. if (variable == null)
  249. throw new ArgumentNullException ("variable");
  250. if (opcode.OperandType != OperandType.ShortInlineVar &&
  251. opcode.OperandType != OperandType.InlineVar)
  252. throw new ArgumentException ("opcode");
  253. return new Instruction (opcode, variable);
  254. }
  255. public static Instruction Create (OpCode opcode, ParameterDefinition parameter)
  256. {
  257. if (parameter == null)
  258. throw new ArgumentNullException ("parameter");
  259. if (opcode.OperandType != OperandType.ShortInlineArg &&
  260. opcode.OperandType != OperandType.InlineArg)
  261. throw new ArgumentException ("opcode");
  262. return new Instruction (opcode, parameter);
  263. }
  264. }
  265. }