5
// Jb Evain (jbevain@gmail.com)
7
// Copyright (c) 2008 - 2011 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);