Merge branch 'cecil-light'
[mono.git] / mcs / tools / cil-strip / Mono.Cecil.Cil / CilWorker.cs
1 //
2 // CilWorker.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // (C) 2005 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
29 namespace Mono.Cecil.Cil {
30
31         using System;
32         using SR = System.Reflection;
33
34         internal sealed class CilWorker {
35
36                 MethodBody m_mbody;
37                 InstructionCollection m_instrs;
38
39                 internal CilWorker (MethodBody body)
40                 {
41                         m_mbody = body;
42                         m_instrs = m_mbody.Instructions;
43                 }
44
45                 public MethodBody GetBody ()
46                 {
47                         return m_mbody;
48                 }
49
50                 public Instruction Create (OpCode opcode)
51                 {
52                         if (opcode.OperandType != OperandType.InlineNone)
53                                 throw new ArgumentException ("opcode");
54
55                         return FinalCreate (opcode);
56                 }
57
58                 public Instruction Create (OpCode opcode, TypeReference type)
59                 {
60                         if (type == null)
61                                 throw new ArgumentNullException ("type");
62                         if (opcode.OperandType != OperandType.InlineType &&
63                                 opcode.OperandType != OperandType.InlineTok)
64                                 throw new ArgumentException ("opcode");
65
66                         return FinalCreate (opcode, type);
67                 }
68
69                 public Instruction Create (OpCode opcode, CallSite site)
70                 {
71                         if (site == null)
72                                 throw new ArgumentNullException ("site");
73                         if (opcode.Code != Code.Calli)
74                                 throw new ArgumentException ("code");
75
76                         return FinalCreate (opcode, site);
77                 }
78
79                 public Instruction Create (OpCode opcode, MethodReference method)
80                 {
81                         if (method == null)
82                                 throw new ArgumentNullException ("method");
83                         if (opcode.OperandType != OperandType.InlineMethod &&
84                                 opcode.OperandType != OperandType.InlineTok)
85                                 throw new ArgumentException ("opcode");
86
87                         return FinalCreate (opcode, method);
88                 }
89
90                 public Instruction Create (OpCode opcode, FieldReference field)
91                 {
92                         if (field == null)
93                                 throw new ArgumentNullException ("field");
94                         if (opcode.OperandType != OperandType.InlineField &&
95                                 opcode.OperandType != OperandType.InlineTok)
96                                 throw new ArgumentException ("opcode");
97
98                         return FinalCreate (opcode, field);
99                 }
100
101                 public Instruction Create (OpCode opcode, string str)
102                 {
103                         if (str == null)
104                                 throw new ArgumentNullException ("str");
105                         if (opcode.OperandType != OperandType.InlineString)
106                                 throw new ArgumentException ("opcode");
107
108                         return FinalCreate (opcode, str);
109                 }
110
111                 public Instruction Create (OpCode opcode, sbyte b)
112                 {
113                         if (opcode.OperandType != OperandType.ShortInlineI &&
114                                 opcode != OpCodes.Ldc_I4_S)
115                                 throw new ArgumentException ("opcode");
116
117                         return FinalCreate (opcode, b);
118                 }
119
120                 public Instruction Create (OpCode opcode, byte b)
121                 {
122                         if (opcode.OperandType == OperandType.ShortInlineVar)
123                                 return Create (opcode, m_mbody.Variables [b]);
124
125                         if (opcode.OperandType == OperandType.ShortInlineParam)
126                                 return Create (opcode, CodeReader.GetParameter (m_mbody, b));
127
128                         if (opcode.OperandType != OperandType.ShortInlineI ||
129                                 opcode == OpCodes.Ldc_I4_S)
130                                 throw new ArgumentException ("opcode");
131
132                         return FinalCreate (opcode, b);
133                 }
134
135                 public Instruction Create (OpCode opcode, int i)
136                 {
137                         if (opcode.OperandType == OperandType.InlineVar)
138                                 return Create (opcode, m_mbody.Variables [i]);
139
140                         if (opcode.OperandType == OperandType.InlineParam)
141                                 return Create (opcode, CodeReader.GetParameter (m_mbody, i));
142
143                         if (opcode.OperandType != OperandType.InlineI)
144                                 throw new ArgumentException ("opcode");
145
146                         return FinalCreate (opcode, i);
147                 }
148
149                 public Instruction Create (OpCode opcode, long l)
150                 {
151                         if (opcode.OperandType != OperandType.InlineI8)
152                                 throw new ArgumentException ("opcode");
153
154                         return FinalCreate (opcode, l);
155                 }
156
157                 public Instruction Create (OpCode opcode, float f)
158                 {
159                         if (opcode.OperandType != OperandType.ShortInlineR)
160                                 throw new ArgumentException ("opcode");
161
162                         return FinalCreate (opcode, f);
163                 }
164
165                 public Instruction Create (OpCode opcode, double d)
166                 {
167                         if (opcode.OperandType != OperandType.InlineR)
168                                 throw new ArgumentException ("opcode");
169
170                         return FinalCreate (opcode, d);
171                 }
172
173                 public Instruction Create (OpCode opcode, Instruction label)
174                 {
175                         if (label == null)
176                                 throw new ArgumentNullException ("label");
177                         if (opcode.OperandType != OperandType.InlineBrTarget &&
178                                 opcode.OperandType != OperandType.ShortInlineBrTarget)
179                                 throw new ArgumentException ("opcode");
180
181                         return FinalCreate (opcode, label);
182                 }
183
184                 public Instruction Create (OpCode opcode, Instruction [] labels)
185                 {
186                         if (labels == null)
187                                 throw new ArgumentNullException ("labels");
188                         if (opcode.OperandType != OperandType.InlineSwitch)
189                                 throw new ArgumentException ("opcode");
190
191                         return FinalCreate (opcode, labels);
192                 }
193
194                 public Instruction Create (OpCode opcode, VariableDefinition var)
195                 {
196                         if (var == null)
197                                 throw new ArgumentNullException ("var");
198                         if (opcode.OperandType != OperandType.ShortInlineVar &&
199                                 opcode.OperandType != OperandType.InlineVar)
200                                 throw new ArgumentException ("opcode");
201
202                         return FinalCreate (opcode, var);
203                 }
204
205                 public Instruction Create (OpCode opcode, ParameterDefinition param)
206                 {
207                         if (param == null)
208                                 throw new ArgumentNullException ("param");
209                         if (opcode.OperandType != OperandType.ShortInlineParam &&
210                                 opcode.OperandType != OperandType.InlineParam)
211                                 throw new ArgumentException ("opcode");
212
213                         return FinalCreate (opcode, param);
214                 }
215
216                 static Instruction FinalCreate (OpCode opcode)
217                 {
218                         return FinalCreate (opcode, null);
219                 }
220
221                 static Instruction FinalCreate (OpCode opcode, object operand)
222                 {
223                         return new Instruction (opcode, operand);
224                 }
225
226                 public Instruction Emit (OpCode opcode)
227                 {
228                         Instruction instr = Create (opcode);
229                         Append (instr);
230                         return instr;
231                 }
232
233                 public Instruction Emit (OpCode opcode, TypeReference type)
234                 {
235                         Instruction instr = Create (opcode, type);
236                         Append (instr);
237                         return instr;
238                 }
239
240                 public Instruction Emit (OpCode opcode, MethodReference meth)
241                 {
242                         Instruction instr = Create (opcode, meth);
243                         Append (instr);
244                         return instr;
245                 }
246
247                 public Instruction Emit (OpCode opcode, CallSite site)
248                 {
249                         Instruction instr = Create (opcode, site);
250                         Append (instr);
251                         return instr;
252                 }
253
254                 public Instruction Emit (OpCode opcode, FieldReference field)
255                 {
256                         Instruction instr = Create (opcode, field);
257                         Append (instr);
258                         return instr;
259                 }
260
261                 public Instruction Emit (OpCode opcode, string str)
262                 {
263                         Instruction instr = Create (opcode, str);
264                         Append (instr);
265                         return instr;
266                 }
267
268                 public Instruction Emit (OpCode opcode, byte b)
269                 {
270                         Instruction instr = Create (opcode, b);
271                         Append (instr);
272                         return instr;
273                 }
274
275                 public Instruction Emit (OpCode opcode, sbyte b)
276                 {
277                         Instruction instr = Create (opcode, b);
278                         Append (instr);
279                         return instr;
280                 }
281
282                 public Instruction Emit (OpCode opcode, int i)
283                 {
284                         Instruction instr = Create (opcode, i);
285                         Append (instr);
286                         return instr;
287                 }
288
289                 public Instruction Emit (OpCode opcode, long l)
290                 {
291                         Instruction instr = Create (opcode, l);
292                         Append (instr);
293                         return instr;
294                 }
295
296                 public Instruction Emit (OpCode opcode, float f)
297                 {
298                         Instruction instr = Create (opcode, f);
299                         Append (instr);
300                         return instr;
301                 }
302
303                 public Instruction Emit (OpCode opcode, double d)
304                 {
305                         Instruction instr = Create (opcode, d);
306                         Append (instr);
307                         return instr;
308                 }
309
310                 public Instruction Emit (OpCode opcode, Instruction target)
311                 {
312                         Instruction instr = Create (opcode, target);
313                         Append (instr);
314                         return instr;
315                 }
316
317                 public Instruction Emit (OpCode opcode, Instruction [] targets)
318                 {
319                         Instruction instr = Create (opcode, targets);
320                         Append (instr);
321                         return instr;
322                 }
323
324                 public Instruction Emit (OpCode opcode, VariableDefinition var)
325                 {
326                         Instruction instr = Create (opcode, var);
327                         Append (instr);
328                         return instr;
329                 }
330
331                 public Instruction Emit (OpCode opcode, ParameterDefinition param)
332                 {
333                         Instruction instr = Create (opcode, param);
334                         Append (instr);
335                         return instr;
336                 }
337
338                 public void InsertBefore (Instruction target, Instruction instr)
339                 {
340                         int index = m_instrs.IndexOf (target);
341                         if (index == -1)
342                                 throw new ArgumentOutOfRangeException ("Target instruction not in method body");
343
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;
349                         instr.Next = target;
350                 }
351
352                 public void InsertAfter (Instruction target, Instruction instr)
353                 {
354                         int index = m_instrs.IndexOf (target);
355                         if (index == -1)
356                                 throw new ArgumentOutOfRangeException ("Target instruction not in method body");
357
358                         m_instrs.Insert (index + 1, instr);
359                         instr.Next = target.Next;
360                         if (target.Next != null)
361                                 target.Next.Previous = instr;
362                         target.Next = instr;
363                         instr.Previous = target;
364                 }
365
366                 public void Append (Instruction instr)
367                 {
368                         Instruction last = null, current = instr;
369                         if (m_instrs.Count > 0)
370                                 last = m_instrs [m_instrs.Count - 1];
371
372                         if (last != null) {
373                                 last.Next = instr;
374                                 current.Previous = last;
375                         }
376
377                         m_instrs.Add (current);
378                 }
379
380                 public void Replace (Instruction old, Instruction instr)
381                 {
382                         int index = m_instrs.IndexOf (old);
383                         if (index == -1)
384                                 throw new ArgumentOutOfRangeException ("Target instruction not in method body");
385
386                         InsertAfter (old, instr);
387                         Remove (old);
388                 }
389
390                 public void Remove (Instruction instr)
391                 {
392                         if (!m_instrs.Contains (instr))
393                                 throw new ArgumentException ("Instruction not in method body");
394
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);
400                 }
401         }
402 }