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
public 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);