5 // Jb Evain (jbevain@gmail.com)
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.
29 namespace Mono.Cecil.Cil {
32 using SR = System.Reflection;
34 internal sealed class CilWorker {
37 InstructionCollection m_instrs;
39 internal CilWorker (MethodBody body)
42 m_instrs = m_mbody.Instructions;
45 public MethodBody GetBody ()
50 public Instruction Create (OpCode opcode)
52 if (opcode.OperandType != OperandType.InlineNone)
53 throw new ArgumentException ("opcode");
55 return FinalCreate (opcode);
58 public Instruction Create (OpCode opcode, TypeReference type)
61 throw new ArgumentNullException ("type");
62 if (opcode.OperandType != OperandType.InlineType &&
63 opcode.OperandType != OperandType.InlineTok)
64 throw new ArgumentException ("opcode");
66 return FinalCreate (opcode, type);
69 public Instruction Create (OpCode opcode, CallSite site)
72 throw new ArgumentNullException ("site");
73 if (opcode.Code != Code.Calli)
74 throw new ArgumentException ("code");
76 return FinalCreate (opcode, site);
79 public Instruction Create (OpCode opcode, MethodReference method)
82 throw new ArgumentNullException ("method");
83 if (opcode.OperandType != OperandType.InlineMethod &&
84 opcode.OperandType != OperandType.InlineTok)
85 throw new ArgumentException ("opcode");
87 return FinalCreate (opcode, method);
90 public Instruction Create (OpCode opcode, FieldReference field)
93 throw new ArgumentNullException ("field");
94 if (opcode.OperandType != OperandType.InlineField &&
95 opcode.OperandType != OperandType.InlineTok)
96 throw new ArgumentException ("opcode");
98 return FinalCreate (opcode, field);
101 public Instruction Create (OpCode opcode, string str)
104 throw new ArgumentNullException ("str");
105 if (opcode.OperandType != OperandType.InlineString)
106 throw new ArgumentException ("opcode");
108 return FinalCreate (opcode, str);
111 public Instruction Create (OpCode opcode, sbyte b)
113 if (opcode.OperandType != OperandType.ShortInlineI &&
114 opcode != OpCodes.Ldc_I4_S)
115 throw new ArgumentException ("opcode");
117 return FinalCreate (opcode, b);
120 public Instruction Create (OpCode opcode, byte b)
122 if (opcode.OperandType == OperandType.ShortInlineVar)
123 return Create (opcode, m_mbody.Variables [b]);
125 if (opcode.OperandType == OperandType.ShortInlineParam)
126 return Create (opcode, CodeReader.GetParameter (m_mbody, b));
128 if (opcode.OperandType != OperandType.ShortInlineI ||
129 opcode == OpCodes.Ldc_I4_S)
130 throw new ArgumentException ("opcode");
132 return FinalCreate (opcode, b);
135 public Instruction Create (OpCode opcode, int i)
137 if (opcode.OperandType == OperandType.InlineVar)
138 return Create (opcode, m_mbody.Variables [i]);
140 if (opcode.OperandType == OperandType.InlineParam)
141 return Create (opcode, CodeReader.GetParameter (m_mbody, i));
143 if (opcode.OperandType != OperandType.InlineI)
144 throw new ArgumentException ("opcode");
146 return FinalCreate (opcode, i);
149 public Instruction Create (OpCode opcode, long l)
151 if (opcode.OperandType != OperandType.InlineI8)
152 throw new ArgumentException ("opcode");
154 return FinalCreate (opcode, l);
157 public Instruction Create (OpCode opcode, float f)
159 if (opcode.OperandType != OperandType.ShortInlineR)
160 throw new ArgumentException ("opcode");
162 return FinalCreate (opcode, f);
165 public Instruction Create (OpCode opcode, double d)
167 if (opcode.OperandType != OperandType.InlineR)
168 throw new ArgumentException ("opcode");
170 return FinalCreate (opcode, d);
173 public Instruction Create (OpCode opcode, Instruction label)
176 throw new ArgumentNullException ("label");
177 if (opcode.OperandType != OperandType.InlineBrTarget &&
178 opcode.OperandType != OperandType.ShortInlineBrTarget)
179 throw new ArgumentException ("opcode");
181 return FinalCreate (opcode, label);
184 public Instruction Create (OpCode opcode, Instruction [] labels)
187 throw new ArgumentNullException ("labels");
188 if (opcode.OperandType != OperandType.InlineSwitch)
189 throw new ArgumentException ("opcode");
191 return FinalCreate (opcode, labels);
194 public Instruction Create (OpCode opcode, VariableDefinition var)
197 throw new ArgumentNullException ("var");
198 if (opcode.OperandType != OperandType.ShortInlineVar &&
199 opcode.OperandType != OperandType.InlineVar)
200 throw new ArgumentException ("opcode");
202 return FinalCreate (opcode, var);
205 public Instruction Create (OpCode opcode, ParameterDefinition param)
208 throw new ArgumentNullException ("param");
209 if (opcode.OperandType != OperandType.ShortInlineParam &&
210 opcode.OperandType != OperandType.InlineParam)
211 throw new ArgumentException ("opcode");
213 return FinalCreate (opcode, param);
216 static Instruction FinalCreate (OpCode opcode)
218 return FinalCreate (opcode, null);
221 static Instruction FinalCreate (OpCode opcode, object operand)
223 return new Instruction (opcode, operand);
226 public Instruction Emit (OpCode opcode)
228 Instruction instr = Create (opcode);
233 public Instruction Emit (OpCode opcode, TypeReference type)
235 Instruction instr = Create (opcode, type);
240 public Instruction Emit (OpCode opcode, MethodReference meth)
242 Instruction instr = Create (opcode, meth);
247 public Instruction Emit (OpCode opcode, CallSite site)
249 Instruction instr = Create (opcode, site);
254 public Instruction Emit (OpCode opcode, FieldReference field)
256 Instruction instr = Create (opcode, field);
261 public Instruction Emit (OpCode opcode, string str)
263 Instruction instr = Create (opcode, str);
268 public Instruction Emit (OpCode opcode, byte b)
270 Instruction instr = Create (opcode, b);
275 public Instruction Emit (OpCode opcode, sbyte b)
277 Instruction instr = Create (opcode, b);
282 public Instruction Emit (OpCode opcode, int i)
284 Instruction instr = Create (opcode, i);
289 public Instruction Emit (OpCode opcode, long l)
291 Instruction instr = Create (opcode, l);
296 public Instruction Emit (OpCode opcode, float f)
298 Instruction instr = Create (opcode, f);
303 public Instruction Emit (OpCode opcode, double d)
305 Instruction instr = Create (opcode, d);
310 public Instruction Emit (OpCode opcode, Instruction target)
312 Instruction instr = Create (opcode, target);
317 public Instruction Emit (OpCode opcode, Instruction [] targets)
319 Instruction instr = Create (opcode, targets);
324 public Instruction Emit (OpCode opcode, VariableDefinition var)
326 Instruction instr = Create (opcode, var);
331 public Instruction Emit (OpCode opcode, ParameterDefinition param)
333 Instruction instr = Create (opcode, param);
338 public void InsertBefore (Instruction target, Instruction instr)
340 int index = m_instrs.IndexOf (target);
342 throw new ArgumentOutOfRangeException ("Target instruction not in method body");
344 m_instrs.Insert (index, instr);
345 instr.Previous = target.Previous;
346 if (target.Previous != null)
347 target.Previous.Next = instr;
348 target.Previous = instr;
352 public void InsertAfter (Instruction target, Instruction instr)
354 int index = m_instrs.IndexOf (target);
356 throw new ArgumentOutOfRangeException ("Target instruction not in method body");
358 m_instrs.Insert (index + 1, instr);
359 instr.Next = target.Next;
360 if (target.Next != null)
361 target.Next.Previous = instr;
363 instr.Previous = target;
366 public void Append (Instruction instr)
368 Instruction last = null, current = instr;
369 if (m_instrs.Count > 0)
370 last = m_instrs [m_instrs.Count - 1];
374 current.Previous = last;
377 m_instrs.Add (current);
380 public void Replace (Instruction old, Instruction instr)
382 int index = m_instrs.IndexOf (old);
384 throw new ArgumentOutOfRangeException ("Target instruction not in method body");
386 InsertAfter (old, instr);
390 public void Remove (Instruction instr)
392 if (!m_instrs.Contains (instr))
393 throw new ArgumentException ("Instruction not in method body");
395 if (instr.Previous != null)
396 instr.Previous.Next = instr.Next;
397 if (instr.Next != null)
398 instr.Next.Previous = instr.Previous;
399 m_instrs.Remove (instr);