mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
524 lines
8.4 KiB
524 lines
8.4 KiB
// |
|
// OpCode.cs |
|
// |
|
// Author: |
|
// Jb Evain (jbevain@gmail.com) |
|
// |
|
// Copyright (c) 2008 - 2010 Jb Evain |
|
// |
|
// Permission is hereby granted, free of charge, to any person obtaining |
|
// a copy of this software and associated documentation files (the |
|
// "Software"), to deal in the Software without restriction, including |
|
// without limitation the rights to use, copy, modify, merge, publish, |
|
// distribute, sublicense, and/or sell copies of the Software, and to |
|
// permit persons to whom the Software is furnished to do so, subject to |
|
// the following conditions: |
|
// |
|
// The above copyright notice and this permission notice shall be |
|
// included in all copies or substantial portions of the Software. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
// |
|
|
|
namespace Mono.Cecil.Cil { |
|
|
|
public enum FlowControl { |
|
Branch, |
|
Break, |
|
Call, |
|
Cond_Branch, |
|
Meta, |
|
Next, |
|
Phi, |
|
Return, |
|
Throw, |
|
} |
|
|
|
public enum OpCodeType { |
|
Annotation, |
|
Macro, |
|
Nternal, |
|
Objmodel, |
|
Prefix, |
|
Primitive, |
|
} |
|
|
|
public enum OperandType { |
|
InlineBrTarget, |
|
InlineField, |
|
InlineI, |
|
InlineI8, |
|
InlineMethod, |
|
InlineNone, |
|
InlinePhi, |
|
InlineR, |
|
InlineSig, |
|
InlineString, |
|
InlineSwitch, |
|
InlineTok, |
|
InlineType, |
|
InlineVar, |
|
InlineArg, |
|
ShortInlineBrTarget, |
|
ShortInlineI, |
|
ShortInlineR, |
|
ShortInlineVar, |
|
ShortInlineArg, |
|
} |
|
|
|
public enum StackBehaviour { |
|
Pop0, |
|
Pop1, |
|
Pop1_pop1, |
|
Popi, |
|
Popi_pop1, |
|
Popi_popi, |
|
Popi_popi8, |
|
Popi_popi_popi, |
|
Popi_popr4, |
|
Popi_popr8, |
|
Popref, |
|
Popref_pop1, |
|
Popref_popi, |
|
Popref_popi_popi, |
|
Popref_popi_popi8, |
|
Popref_popi_popr4, |
|
Popref_popi_popr8, |
|
Popref_popi_popref, |
|
PopAll, |
|
Push0, |
|
Push1, |
|
Push1_push1, |
|
Pushi, |
|
Pushi8, |
|
Pushr4, |
|
Pushr8, |
|
Pushref, |
|
Varpop, |
|
Varpush, |
|
} |
|
|
|
public struct OpCode { |
|
|
|
readonly byte op1; |
|
readonly byte op2; |
|
readonly byte code; |
|
readonly byte flow_control; |
|
readonly byte opcode_type; |
|
readonly byte operand_type; |
|
readonly byte stack_behavior_pop; |
|
readonly byte stack_behavior_push; |
|
|
|
public string Name { |
|
get { return OpCodeNames.names [op1 == 0xff ? op2 : op2 + 256]; } |
|
} |
|
|
|
public int Size { |
|
get { return op1 == 0xff ? 1 : 2; } |
|
} |
|
|
|
public byte Op1 { |
|
get { return op1; } |
|
} |
|
|
|
public byte Op2 { |
|
get { return op2; } |
|
} |
|
|
|
public short Value { |
|
get { return (short) ((op1 << 8) | op2); } |
|
} |
|
|
|
public Code Code { |
|
get { return (Code) code; } |
|
} |
|
|
|
public FlowControl FlowControl { |
|
get { return (FlowControl) flow_control; } |
|
} |
|
|
|
public OpCodeType OpCodeType { |
|
get { return (OpCodeType) opcode_type; } |
|
} |
|
|
|
public OperandType OperandType { |
|
get { return (OperandType) operand_type; } |
|
} |
|
|
|
public StackBehaviour StackBehaviourPop { |
|
get { return (StackBehaviour) stack_behavior_pop; } |
|
} |
|
|
|
public StackBehaviour StackBehaviourPush { |
|
get { return (StackBehaviour) stack_behavior_push; } |
|
} |
|
|
|
internal OpCode (int x, int y) |
|
{ |
|
this.op1 = (byte) ((x >> 0) & 0xff); |
|
this.op2 = (byte) ((x >> 8) & 0xff); |
|
this.code = (byte) ((x >> 16) & 0xff); |
|
this.flow_control = (byte) ((x >> 24) & 0xff); |
|
|
|
this.opcode_type = (byte) ((y >> 0) & 0xff); |
|
this.operand_type = (byte) ((y >> 8) & 0xff); |
|
this.stack_behavior_pop = (byte) ((y >> 16) & 0xff); |
|
this.stack_behavior_push = (byte) ((y >> 24) & 0xff); |
|
|
|
if (op1 == 0xff) |
|
OpCodes.OneByteOpCode [op2] = this; |
|
else |
|
OpCodes.TwoBytesOpCode [op2] = this; |
|
} |
|
|
|
public override int GetHashCode () |
|
{ |
|
return Value; |
|
} |
|
|
|
public override bool Equals (object obj) |
|
{ |
|
if (!(obj is OpCode)) |
|
return false; |
|
|
|
var opcode = (OpCode) obj; |
|
return op1 == opcode.op1 && op2 == opcode.op2; |
|
} |
|
|
|
public bool Equals (OpCode opcode) |
|
{ |
|
return op1 == opcode.op1 && op2 == opcode.op2; |
|
} |
|
|
|
public static bool operator == (OpCode one, OpCode other) |
|
{ |
|
return one.op1 == other.op1 && one.op2 == other.op2; |
|
} |
|
|
|
public static bool operator != (OpCode one, OpCode other) |
|
{ |
|
return one.op1 != other.op1 || one.op2 != other.op2; |
|
} |
|
|
|
public override string ToString () |
|
{ |
|
return Name; |
|
} |
|
} |
|
|
|
static class OpCodeNames { |
|
|
|
internal static readonly string [] names = { |
|
"nop", |
|
"break", |
|
"ldarg.0", |
|
"ldarg.1", |
|
"ldarg.2", |
|
"ldarg.3", |
|
"ldloc.0", |
|
"ldloc.1", |
|
"ldloc.2", |
|
"ldloc.3", |
|
"stloc.0", |
|
"stloc.1", |
|
"stloc.2", |
|
"stloc.3", |
|
"ldarg.s", |
|
"ldarga.s", |
|
"starg.s", |
|
"ldloc.s", |
|
"ldloca.s", |
|
"stloc.s", |
|
"ldnull", |
|
"ldc.i4.m1", |
|
"ldc.i4.0", |
|
"ldc.i4.1", |
|
"ldc.i4.2", |
|
"ldc.i4.3", |
|
"ldc.i4.4", |
|
"ldc.i4.5", |
|
"ldc.i4.6", |
|
"ldc.i4.7", |
|
"ldc.i4.8", |
|
"ldc.i4.s", |
|
"ldc.i4", |
|
"ldc.i8", |
|
"ldc.r4", |
|
"ldc.r8", |
|
null, |
|
"dup", |
|
"pop", |
|
"jmp", |
|
"call", |
|
"calli", |
|
"ret", |
|
"br.s", |
|
"brfalse.s", |
|
"brtrue.s", |
|
"beq.s", |
|
"bge.s", |
|
"bgt.s", |
|
"ble.s", |
|
"blt.s", |
|
"bne.un.s", |
|
"bge.un.s", |
|
"bgt.un.s", |
|
"ble.un.s", |
|
"blt.un.s", |
|
"br", |
|
"brfalse", |
|
"brtrue", |
|
"beq", |
|
"bge", |
|
"bgt", |
|
"ble", |
|
"blt", |
|
"bne.un", |
|
"bge.un", |
|
"bgt.un", |
|
"ble.un", |
|
"blt.un", |
|
"switch", |
|
"ldind.i1", |
|
"ldind.u1", |
|
"ldind.i2", |
|
"ldind.u2", |
|
"ldind.i4", |
|
"ldind.u4", |
|
"ldind.i8", |
|
"ldind.i", |
|
"ldind.r4", |
|
"ldind.r8", |
|
"ldind.ref", |
|
"stind.ref", |
|
"stind.i1", |
|
"stind.i2", |
|
"stind.i4", |
|
"stind.i8", |
|
"stind.r4", |
|
"stind.r8", |
|
"add", |
|
"sub", |
|
"mul", |
|
"div", |
|
"div.un", |
|
"rem", |
|
"rem.un", |
|
"and", |
|
"or", |
|
"xor", |
|
"shl", |
|
"shr", |
|
"shr.un", |
|
"neg", |
|
"not", |
|
"conv.i1", |
|
"conv.i2", |
|
"conv.i4", |
|
"conv.i8", |
|
"conv.r4", |
|
"conv.r8", |
|
"conv.u4", |
|
"conv.u8", |
|
"callvirt", |
|
"cpobj", |
|
"ldobj", |
|
"ldstr", |
|
"newobj", |
|
"castclass", |
|
"isinst", |
|
"conv.r.un", |
|
null, |
|
null, |
|
"unbox", |
|
"throw", |
|
"ldfld", |
|
"ldflda", |
|
"stfld", |
|
"ldsfld", |
|
"ldsflda", |
|
"stsfld", |
|
"stobj", |
|
"conv.ovf.i1.un", |
|
"conv.ovf.i2.un", |
|
"conv.ovf.i4.un", |
|
"conv.ovf.i8.un", |
|
"conv.ovf.u1.un", |
|
"conv.ovf.u2.un", |
|
"conv.ovf.u4.un", |
|
"conv.ovf.u8.un", |
|
"conv.ovf.i.un", |
|
"conv.ovf.u.un", |
|
"box", |
|
"newarr", |
|
"ldlen", |
|
"ldelema", |
|
"ldelem.i1", |
|
"ldelem.u1", |
|
"ldelem.i2", |
|
"ldelem.u2", |
|
"ldelem.i4", |
|
"ldelem.u4", |
|
"ldelem.i8", |
|
"ldelem.i", |
|
"ldelem.r4", |
|
"ldelem.r8", |
|
"ldelem.ref", |
|
"stelem.i", |
|
"stelem.i1", |
|
"stelem.i2", |
|
"stelem.i4", |
|
"stelem.i8", |
|
"stelem.r4", |
|
"stelem.r8", |
|
"stelem.ref", |
|
"ldelem.any", |
|
"stelem.any", |
|
"unbox.any", |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
"conv.ovf.i1", |
|
"conv.ovf.u1", |
|
"conv.ovf.i2", |
|
"conv.ovf.u2", |
|
"conv.ovf.i4", |
|
"conv.ovf.u4", |
|
"conv.ovf.i8", |
|
"conv.ovf.u8", |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
"refanyval", |
|
"ckfinite", |
|
null, |
|
null, |
|
"mkrefany", |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
"ldtoken", |
|
"conv.u2", |
|
"conv.u1", |
|
"conv.i", |
|
"conv.ovf.i", |
|
"conv.ovf.u", |
|
"add.ovf", |
|
"add.ovf.un", |
|
"mul.ovf", |
|
"mul.ovf.un", |
|
"sub.ovf", |
|
"sub.ovf.un", |
|
"endfinally", |
|
"leave", |
|
"leave.s", |
|
"stind.i", |
|
"conv.u", |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
"prefix7", |
|
"prefix6", |
|
"prefix5", |
|
"prefix4", |
|
"prefix3", |
|
"prefix2", |
|
"prefix1", |
|
"prefixref", |
|
"arglist", |
|
"ceq", |
|
"cgt", |
|
"cgt.un", |
|
"clt", |
|
"clt.un", |
|
"ldftn", |
|
"ldvirtftn", |
|
null, |
|
"ldarg", |
|
"ldarga", |
|
"starg", |
|
"ldloc", |
|
"ldloca", |
|
"stloc", |
|
"localloc", |
|
null, |
|
"endfilter", |
|
"unaligned.", |
|
"volatile.", |
|
"tail.", |
|
"initobj", |
|
"constrained.", |
|
"cpblk", |
|
"initblk", |
|
"no.", // added by spouliot to match Cecil existing definitions |
|
"rethrow", |
|
null, |
|
"sizeof", |
|
"refanytype", |
|
"readonly.", // added by spouliot to match Cecil existing definitions |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
null, |
|
}; |
|
} |
|
}
|
|
|