5 // Jb Evain (jbevain@gmail.com)
7 // Copyright (c) 2008 - 2010 Jb Evain
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
32 namespace Mono.Cecil.Cil {
34 public sealed class Instruction {
37 internal OpCode opcode;
38 internal object operand;
40 internal Instruction previous;
41 internal Instruction next;
43 SequencePoint sequence_point;
46 get { return offset; }
47 set { offset = value; }
50 public OpCode OpCode {
51 get { return opcode; }
52 set { opcode = value; }
55 public object Operand {
56 get { return operand; }
57 set { operand = value; }
60 public Instruction Previous {
61 get { return previous; }
62 set { previous = value; }
65 public Instruction Next {
70 public SequencePoint SequencePoint {
71 get { return sequence_point; }
72 set { sequence_point = value; }
75 internal Instruction (int offset, OpCode opCode)
81 internal Instruction (OpCode opcode, object operand)
84 this.operand = operand;
89 int size = opcode.Size;
91 switch (opcode.OperandType) {
92 case OperandType.InlineSwitch:
93 return size + (1 + ((Instruction []) operand).Length) * 4;
94 case OperandType.InlineI8:
95 case OperandType.InlineR:
97 case OperandType.InlineBrTarget:
98 case OperandType.InlineField:
99 case OperandType.InlineI:
100 case OperandType.InlineMethod:
101 case OperandType.InlineString:
102 case OperandType.InlineTok:
103 case OperandType.InlineType:
104 case OperandType.ShortInlineR:
105 case OperandType.InlineSig:
107 case OperandType.InlineArg:
108 case OperandType.InlineVar:
110 case OperandType.ShortInlineBrTarget:
111 case OperandType.ShortInlineI:
112 case OperandType.ShortInlineArg:
113 case OperandType.ShortInlineVar:
120 public override string ToString ()
122 var instruction = new StringBuilder ();
124 AppendLabel (instruction, this);
125 instruction.Append (':');
126 instruction.Append (' ');
127 instruction.Append (opcode.Name);
130 return instruction.ToString ();
132 instruction.Append (' ');
134 switch (opcode.OperandType) {
135 case OperandType.ShortInlineBrTarget:
136 case OperandType.InlineBrTarget:
137 AppendLabel (instruction, (Instruction) operand);
139 case OperandType.InlineSwitch:
140 var labels = (Instruction []) operand;
141 for (int i = 0; i < labels.Length; i++) {
143 instruction.Append (',');
145 AppendLabel (instruction, labels [i]);
148 case OperandType.InlineString:
149 instruction.Append ('\"');
150 instruction.Append (operand);
151 instruction.Append ('\"');
154 instruction.Append (operand);
158 return instruction.ToString ();
161 static void AppendLabel (StringBuilder builder, Instruction instruction)
163 builder.Append ("IL_");
164 builder.Append (instruction.offset.ToString ("x4"));
167 public static Instruction Create (OpCode opcode)
169 if (opcode.OperandType != OperandType.InlineNone)
170 throw new ArgumentException ("opcode");
172 return new Instruction (opcode, null);
175 public static Instruction Create (OpCode opcode, TypeReference type)
178 throw new ArgumentNullException ("type");
179 if (opcode.OperandType != OperandType.InlineType &&
180 opcode.OperandType != OperandType.InlineTok)
181 throw new ArgumentException ("opcode");
183 return new Instruction (opcode, type);
186 public static Instruction Create (OpCode opcode, CallSite site)
189 throw new ArgumentNullException ("site");
190 if (opcode.Code != Code.Calli)
191 throw new ArgumentException ("code");
193 return new Instruction (opcode, site);
196 public static Instruction Create (OpCode opcode, MethodReference method)
199 throw new ArgumentNullException ("method");
200 if (opcode.OperandType != OperandType.InlineMethod &&
201 opcode.OperandType != OperandType.InlineTok)
202 throw new ArgumentException ("opcode");
204 return new Instruction (opcode, method);
207 public static Instruction Create (OpCode opcode, FieldReference field)
210 throw new ArgumentNullException ("field");
211 if (opcode.OperandType != OperandType.InlineField &&
212 opcode.OperandType != OperandType.InlineTok)
213 throw new ArgumentException ("opcode");
215 return new Instruction (opcode, field);
218 public static Instruction Create (OpCode opcode, string value)
221 throw new ArgumentNullException ("value");
222 if (opcode.OperandType != OperandType.InlineString)
223 throw new ArgumentException ("opcode");
225 return new Instruction (opcode, value);
228 public static Instruction Create (OpCode opcode, sbyte value)
230 if (opcode.OperandType != OperandType.ShortInlineI &&
231 opcode != OpCodes.Ldc_I4_S)
232 throw new ArgumentException ("opcode");
234 return new Instruction (opcode, value);
237 public static Instruction Create (OpCode opcode, byte value)
239 if (opcode.OperandType != OperandType.ShortInlineI ||
240 opcode == OpCodes.Ldc_I4_S)
241 throw new ArgumentException ("opcode");
243 return new Instruction (opcode, value);
246 public static Instruction Create (OpCode opcode, int value)
248 if (opcode.OperandType != OperandType.InlineI)
249 throw new ArgumentException ("opcode");
251 return new Instruction (opcode, value);
254 public static Instruction Create (OpCode opcode, long value)
256 if (opcode.OperandType != OperandType.InlineI8)
257 throw new ArgumentException ("opcode");
259 return new Instruction (opcode, value);
262 public static Instruction Create (OpCode opcode, float value)
264 if (opcode.OperandType != OperandType.ShortInlineR)
265 throw new ArgumentException ("opcode");
267 return new Instruction (opcode, value);
270 public static Instruction Create (OpCode opcode, double value)
272 if (opcode.OperandType != OperandType.InlineR)
273 throw new ArgumentException ("opcode");
275 return new Instruction (opcode, value);
278 public static Instruction Create (OpCode opcode, Instruction target)
281 throw new ArgumentNullException ("target");
282 if (opcode.OperandType != OperandType.InlineBrTarget &&
283 opcode.OperandType != OperandType.ShortInlineBrTarget)
284 throw new ArgumentException ("opcode");
286 return new Instruction (opcode, target);
289 public static Instruction Create (OpCode opcode, Instruction [] targets)
292 throw new ArgumentNullException ("targets");
293 if (opcode.OperandType != OperandType.InlineSwitch)
294 throw new ArgumentException ("opcode");
296 return new Instruction (opcode, targets);
299 public static Instruction Create (OpCode opcode, VariableDefinition variable)
301 if (variable == null)
302 throw new ArgumentNullException ("variable");
303 if (opcode.OperandType != OperandType.ShortInlineVar &&
304 opcode.OperandType != OperandType.InlineVar)
305 throw new ArgumentException ("opcode");
307 return new Instruction (opcode, variable);
310 public static Instruction Create (OpCode opcode, ParameterDefinition parameter)
312 if (parameter == null)
313 throw new ArgumentNullException ("parameter");
314 if (opcode.OperandType != OperandType.ShortInlineArg &&
315 opcode.OperandType != OperandType.InlineArg)
316 throw new ArgumentException ("opcode");
318 return new Instruction (opcode, parameter);