singrdk/base/Windows/mkmsil/msil/Instruction.cs

1569 lines
66 KiB
C#
Raw Normal View History

2008-11-17 18:29:00 -05:00
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
using System;
using System.Collections;
using System.IO;
using Bartok.DebugInfo;
namespace Bartok.MSIL
{
public class Instruction {
// Constructor Methods
internal static Instruction[] getInstructions(MetaDataLoader mdLoader,
Stream fileStream,
int codeOffset,
int[] lines,
int[] columns,
int[] offsets,
String srcFileName,
int lineCount,
out EHClause[] ehTable,
out int[] bbTable,
out int maxStack,
out Signature.Type[] locals,
out bool initLocals) {
fileStream.Seek(codeOffset, SeekOrigin.Begin);
BinaryReader reader = new BinaryReader(fileStream);
byte headerByte = reader.ReadByte();
byte formatMask = (byte) (headerByte & 0x7);
int codeSize;
byte[] codeBytes;
ehTable = sharedEmptyTable;
switch ((MethodFormats) formatMask) {
case MethodFormats.Tiny:
case MethodFormats.Tiny1: {
initLocals = false;
maxStack = 8;
codeSize = headerByte >> 2;
locals = null;
codeBytes = new byte[codeSize];
int count = reader.Read(codeBytes, 0, codeSize);
if (count != codeSize) {
throw new IllegalInstructionStreamException("Only got "+count+" out of "+codeSize+" code bytes");
}
break;
}
case MethodFormats.Fat: {
// for Fat format, check for CorILMethod_InitLocals
// Section 24.4.4 of ECMA spec, partition II
initLocals = ((headerByte & 0x10) != 0);
byte headerByte2 = reader.ReadByte();
int size = headerByte2 >> 4;
if (size != 3) {
throw new IllegalInstructionStreamException("Unexpected FAT size: "+size);
}
maxStack = reader.ReadUInt16();
codeSize = reader.ReadInt32();
int localVarSignatureToken = reader.ReadInt32();
if (localVarSignatureToken == 0) {
locals = null;
}
else {
MetaDataStandAloneSig standAloneSig =
(MetaDataStandAloneSig)
mdLoader.getObjectFromToken(localVarSignatureToken);
Signature unresolvedSignature = standAloneSig.Signature;
SignatureLocalVar localVarSignature = (SignatureLocalVar)
unresolvedSignature.resolve(mdLoader);
locals = localVarSignature.Locals;
}
codeBytes = new byte[codeSize];
int count = reader.Read(codeBytes, 0, codeSize);
if (count != codeSize) {
throw new IllegalInstructionStreamException("Only got "+count+" out of "+codeSize+" code bytes");
}
break;
}
default: {
throw new IllegalInstructionStreamException("Unknown format: "+formatMask.ToString("x"));
}
}
int pcLimit = codeBytes.Length;
int[] byteToInstrMapping = new int[pcLimit+1];
int instructionCount = 0;
int instructionLength, operandLength;
for (int pc = 0; pc < pcLimit; pc += instructionLength + operandLength) {
byteToInstrMapping[pc] = instructionCount;
instructionCount++;
Opcode opcode = (Opcode) codeBytes[pc];
switch (opcode) {
case Opcode.PREFIX1:
instructionLength = 2;
opcode = (Opcode) (codeBytes[pc+1] + 256);
if (opcode < 0 || (Opcode) opcode >= Opcode.COUNT) {
throw new IllegalInstructionStreamException("Saw prefixed opcode of "+opcode);
}
break;
case Opcode.PREFIXREF:
case Opcode.PREFIX2:
case Opcode.PREFIX3:
case Opcode.PREFIX4:
case Opcode.PREFIX5:
case Opcode.PREFIX6:
case Opcode.PREFIX7:
throw new IllegalInstructionStreamException("Saw unexpected prefix opcode "+opcode);
default:
instructionLength = 1;
break;
}
OpcodeInfo opcodeInfo = opcodeInfoTable[(int) opcode];
operandLength = opcodeInfo.operandSize;
if (operandLength == 0xFF) {
int operandOffset = pc + instructionLength;
switch (opcodeInfo.operandFormat) {
case OperandFormat.Switch: {
int caseCount =
intFromCodeBytes(codeBytes, operandOffset);
operandLength = 4 + 4 * caseCount;
break;
}
case OperandFormat.InlinePhi: {
int caseCount = codeBytes[operandOffset];
operandLength = 1 + 2 * caseCount;
break;
}
case OperandFormat.BranchTarget: {
int byteCount =
intFromCodeBytes(codeBytes, operandOffset);
operandLength = 4 + byteCount;
break;
}
case OperandFormat.ShortBranchTarget: {
int byteCount = codeBytes[operandOffset];
operandLength = 1 + byteCount;
break;
}
default:
throw new IllegalInstructionStreamException("Unexpected operand format "+opcodeInfo.operandFormat);
}
}
}
byteToInstrMapping[pcLimit] = instructionCount;
BitArray bbStarts = new BitArray(instructionCount+1);
// Check whether or not there is an EH section
if (formatMask == (byte) MethodFormats.Fat &&
(headerByte & 0x08) != 0) {
int sectionPadding = (codeOffset + codeSize) % 4;
if (sectionPadding != 0) {
while (sectionPadding < 4) {
sectionPadding++;
byte padding = reader.ReadByte();
}
}
byte sectionKind = reader.ReadByte();
if ((sectionKind & 0x80) != 0) {
throw new IllegalInstructionStreamException("More than one section after the code");
}
if ((sectionKind & 0x3f) != (int) SectionKind.EHTable) {
throw new IllegalInstructionStreamException("Expected EH table section, got "+sectionKind.ToString("x"));
}
int dataSize;
if ((sectionKind & 0x40) == 0) {
// Small section
int ehByteCount = reader.ReadByte();
dataSize = (ehByteCount) / 12;
int headerSize = (ehByteCount % 12);
if ((headerSize != 0) && (headerSize != 4)) {
throw new IllegalInstructionStreamException("Unexpected byte count for small EH table: "+ehByteCount);
}
int sectSmallReserved = reader.ReadInt16();
ehTable = new EHClause[dataSize];
for (int i = 0; i < dataSize; i++) {
int flags = reader.ReadUInt16();
int tryOffset = reader.ReadUInt16();
int tryLength = reader.ReadByte();
int handlerOffset = reader.ReadUInt16();
int handlerLength = reader.ReadByte();
int tokenOrOffset =
(i+1==dataSize &&
headerSize==0 &&
flags != (int) EHClause.ExceptionFlag.None) ?
0 : // The VC++ compiler did not output a 0 here!
reader.ReadInt32();
int tryInstrOffset =
byteToInstrMapping[tryOffset];
bbStarts[tryInstrOffset] =true;
int tryInstrEnd =
byteToInstrMapping[tryOffset + tryLength];
int handlerInstrOffset =
byteToInstrMapping[handlerOffset];
bbStarts[handlerInstrOffset] = true;
int handlerInstrEnd =
byteToInstrMapping[handlerOffset + handlerLength];
bbStarts[handlerInstrEnd] = true;
MetaDataObject classObject = null;
if ((flags & (int) EHClause.ExceptionFlag.Filter) != 0) {
tokenOrOffset = byteToInstrMapping[tokenOrOffset];
bbStarts[tokenOrOffset] = true;
}
else if (flags == (int) EHClause.ExceptionFlag.None) {
classObject =
mdLoader.getObjectFromToken(tokenOrOffset);
tokenOrOffset = 0;
}
else {
// The VC++ compiler is known to get the ehByteCount
// wrong and generate spurious data for tokenOrOffset
if (headerSize != 0 && tokenOrOffset != 0) {
Console.WriteLine("Unknown token or offset "+tokenOrOffset.ToString("x8"));
}
}
ehTable[i] =
new EHClause(flags,
tryInstrOffset,
tryInstrEnd - tryInstrOffset,
handlerInstrOffset,
handlerInstrEnd - handlerInstrOffset,
tokenOrOffset, classObject);
}
}
else {
// Fat section
int ehByteCount;
ehByteCount = reader.ReadByte();
ehByteCount |= reader.ReadByte() << 8;
ehByteCount |= reader.ReadByte() << 16;
dataSize = ehByteCount / 24;
int headerSize = (ehByteCount % 12);
if ((headerSize != 0) && (headerSize != 4)) {
throw new IllegalInstructionStreamException("Unexpected byte count for fat EH table: "+ehByteCount);
}
ehTable = new EHClause[dataSize];
for (int i = 0; i < dataSize; i++) {
int flags = reader.ReadInt32();
int tryOffset = reader.ReadInt32();
int tryLength = reader.ReadInt32();
int handlerOffset = reader.ReadInt32();
int handlerLength = reader.ReadInt32();
int tokenOrOffset = reader.ReadInt32();
int tryInstrOffset =
byteToInstrMapping[tryOffset];
bbStarts[tryInstrOffset] = true;
int tryInstrEnd =
byteToInstrMapping[tryOffset + tryLength];
int handlerInstrOffset =
byteToInstrMapping[handlerOffset];
bbStarts[handlerInstrOffset] = true;
int handlerInstrEnd =
byteToInstrMapping[handlerOffset + handlerLength];
bbStarts[handlerInstrEnd] = true;
MetaDataObject classObject = null;
if ((flags & (int) EHClause.ExceptionFlag.Filter) != 0) {
tokenOrOffset = byteToInstrMapping[tokenOrOffset];
bbStarts[tokenOrOffset] = true;
}
else if (flags == (int) EHClause.ExceptionFlag.None) {
classObject =
mdLoader.getObjectFromToken(tokenOrOffset);
tokenOrOffset = 0;
}
else {
// The VC++ compiler is known to get the ehByteCount
// wrong and generate spurious data for tokenOrOffset
if (headerSize != 0 && tokenOrOffset != 0) {
Console.WriteLine("Unknown token or offset "+tokenOrOffset.ToString("x8"));
}
}
ehTable[i] =
new EHClause(flags,
tryInstrOffset,
tryInstrEnd - tryInstrOffset,
handlerInstrOffset,
handlerInstrEnd - handlerInstrOffset,
tokenOrOffset, classObject);
}
}
}
Instruction[] instructionTable = new Instruction[instructionCount];
int instructionCounter = 0;
int currLineIndex = 0;
int prevLineNumber = 0;
DebugLineNumber lineInfo = null;
for (int pc = 0; pc < pcLimit;) {
if (pc > 0 && byteToInstrMapping[pc] == 0) {
throw new IllegalInstructionStreamException("Out of sync at "+pc.ToString("x"));
}
// read in the line number information.
int lineNumber = 0;
int column = 0;
if (lineCount != 0) {
if (currLineIndex == lineCount - 1) {
// last line.
lineNumber = lines[currLineIndex];
}
else {
int nextOffset = offsets[currLineIndex+1];
if (pc < nextOffset) {
lineNumber = lines[currLineIndex];
column = columns[currLineIndex];
}
else if (pc == nextOffset) {
// advance to next line record
currLineIndex++;
lineNumber = lines[currLineIndex];
column = columns[currLineIndex];
}
else {
Console.WriteLine("Error! Reading lineNumber");
}
}
}
Opcode opcode = (Opcode) codeBytes[pc];
pc++;
if (opcode == Opcode.PREFIX1) {
opcode = (Opcode) (codeBytes[pc] + 256);
pc++;
}
OpcodeInfo opcodeInfo = opcodeInfoTable[(int) opcode];
Operand operand;
switch (opcodeInfo.operandFormat) {
case OperandFormat.None:
if (opcode == Opcode.RET || opcode == Opcode.THROW
|| opcode == Opcode.RETHROW
|| opcode == Opcode.ENDFINALLY
|| opcode == Opcode.ENDFILTER) {
// mark the instruction after a throw, return, or
// endfinally as the beginning of a basic block.
//
// If we have dead code, then there may be no branch to
// it.
if (pc < pcLimit) {
bbStarts[byteToInstrMapping[pc]] = true;
}
}
operand = null;
break;
case OperandFormat.Var:
operand =
new OperandInt(shortFromCodeBytes(codeBytes, pc));
pc += 2;
break;
case OperandFormat.Int:
case OperandFormat.RVA:
operand = new OperandInt(intFromCodeBytes(codeBytes, pc));
pc += 4;
break;
case OperandFormat.Float:
operand =
new OperandDouble(doubleFromCodeBytes(codeBytes, pc));
pc += 8;
break;
case OperandFormat.BranchTarget: {
int target = intFromCodeBytes(codeBytes, pc);
pc += 4;
if (opcodeInfo.operandSize == 0xFF) {
// Random data inserted into instruction stream
byte[] dataBuffer = new byte[target];
Array.Copy(codeBytes, pc, dataBuffer, 0, target);
pc += target;
operand = new OperandByteArray(dataBuffer);
}
else {
// A real branch target
int instrTarget = byteToInstrMapping[pc+target];
bbStarts[instrTarget] = true;
// Fall through branch should be marked too
bbStarts[instructionCounter+1] = true;
operand = new OperandTarget(instrTarget);
}
break;
}
case OperandFormat.Int8:
operand =
new OperandLong(longFromCodeBytes(codeBytes, pc));
pc += 8;
break;
case OperandFormat.Method: {
int token = intFromCodeBytes(codeBytes, pc);
pc += 4;
MetaDataObject mdMethod =
mdLoader.getObjectFromToken(token);
operand = new OperandObject(mdMethod);
break;
}
case OperandFormat.Field: {
int token = intFromCodeBytes(codeBytes, pc);
pc += 4;
int index = token & 0x00FFFFFF;
MetaDataObject mdField =
mdLoader.getObjectFromToken(token);
operand = new OperandObject(mdField);
break;
}
case OperandFormat.Type: {
int token = intFromCodeBytes(codeBytes, pc);
pc += 4;
MetaDataObject type = mdLoader.getObjectFromToken(token);
operand = new OperandObject(type);
break;
}
case OperandFormat.Token: {
int token = intFromCodeBytes(codeBytes, pc);
pc += 4;
MetaDataObject mdToken =
mdLoader.getObjectFromToken(token);
operand = new OperandObject(mdToken);
break;
}
case OperandFormat.String: {
int token = intFromCodeBytes(codeBytes, pc);
pc += 4;
if (((uint) token & 0xFF000000) != (uint) MetaDataLoader.TokenType.String) {
throw new IllegalInstructionStreamException("Unexpected string token "+token.ToString("x"));
}
int index = token & 0x00FFFFFF;
operand = new OperandString(mdLoader.getUserString(index));
break;
}
case OperandFormat.Sig: {
int token = intFromCodeBytes(codeBytes, pc);
pc += 4;
MetaDataObject calleeDescr =
mdLoader.getObjectFromToken(token);
operand = new OperandObject(calleeDescr);
break;
}
case OperandFormat.Switch: {
int caseCount = intFromCodeBytes(codeBytes, pc);
pc += 4;
int[] branchArray = new int[caseCount];
int nextPC = pc + 4 * caseCount;
for (int j = 0; j < caseCount; j++) {
int target = intFromCodeBytes(codeBytes, pc);
pc += 4;
int instrTarget = byteToInstrMapping[nextPC+target];
bbStarts[instrTarget] = true;
branchArray[j] = instrTarget;
}
bbStarts[instructionCounter+1] = true; // Fall through
operand = new OperandTargetArray(branchArray);
break;
}
case OperandFormat.InlinePhi: {
int caseCount = codeBytes[pc];
pc++;
byte[] varArray = new byte[caseCount];
for (int j = 0; j < caseCount; j++) {
varArray[j] = codeBytes[pc];
pc++;
}
operand = new OperandByteArray(varArray);
break;
}
case OperandFormat.ShortVar:
operand = new OperandInt(codeBytes[pc]);
pc++;
break;
case OperandFormat.ShortInt: {
int value = codeBytes[pc];
pc++;
if (value > 127) {
value = -(256-value);
}
operand = new OperandInt(value);
break;
}
case OperandFormat.ShortFloat:
operand =
new OperandSingle(singleFromCodeBytes(codeBytes, pc));
pc += 4;
break;
case OperandFormat.ShortBranchTarget: {
int offset = codeBytes[pc];
pc++;
if (offset > 127) {
offset = -(256-offset);
}
int instrTarget = byteToInstrMapping[pc+offset];
bbStarts[instrTarget] = true;
// Fall through branch should be marked too
bbStarts[instructionCounter+1] = true;
operand = new OperandTarget(instrTarget);
break;
}
default:
throw new IllegalInstructionStreamException("Unknown operand type "+opcodeInfo.operandFormat);
}
if (lineNumber != prevLineNumber && srcFileName != null) {
lineInfo = new CVLineNumber(lineNumber,
column,
srcFileName);
prevLineNumber = lineNumber;
}
instructionTable[instructionCounter] =
new Instruction(opcode, operand, lineInfo);
instructionCounter++;
}
int bbCount = 1;
for (int i = 1; i < instructionCount; i++) {
if (bbStarts[i]) {
bbCount++;
}
}
bbTable = new int[bbCount];
bbCount = 1;
for (int i = 1; i < instructionCount; i++) {
if (bbStarts[i]) {
bbTable[bbCount] = i;
bbCount++;
}
}
return instructionTable;
}
private Instruction(Opcode opcode, Operand operand,
DebugLineNumber lineNumber) {
this.opcode = opcode;
this.operand = operand;
this.lineNumber = lineNumber;
}
// Access Methods
public Opcode Operator {
get {
return this.opcode;
}
}
public Operand Argument {
get {
return this.operand;
}
}
public DebugLineNumber LineNumber {
get {
return this.lineNumber;
}
}
public bool isControl() {
return opcodeInfoTable[(int) this.opcode].isControl;
}
// Helper Methods
private static int intFromCodeBytes(byte[] codeBytes, int offset) {
return ((codeBytes[offset]) |
(codeBytes[offset+1] << 8) |
(codeBytes[offset+2] << 16) |
(codeBytes[offset+3] << 24));
}
private static short shortFromCodeBytes(byte[] codeBytes, int offset) {
return (short) ((codeBytes[offset]) |
(codeBytes[offset+1] << 8));
}
private static long longFromCodeBytes(byte[] codeBytes, int offset) {
return (((long) ((uint) (codeBytes[offset]) |
(uint) (codeBytes[offset+1] << 8) |
(uint) (codeBytes[offset+2] << 16) |
(uint) (codeBytes[offset+3] << 24))) |
(((long) ((uint) (codeBytes[offset+4]) |
(uint) (codeBytes[offset+5] << 8) |
(uint) (codeBytes[offset+6] << 16) |
(uint) (codeBytes[offset+7] << 24))) << 32));
}
private static float singleFromCodeBytes(byte[] codeBytes, int offset) {
MemoryStream memoryStream = new MemoryStream(codeBytes, offset, 4);
BinaryReader binaryReader = new BinaryReader(memoryStream);
return binaryReader.ReadSingle();
}
private static double doubleFromCodeBytes(byte[] codeBytes, int offset) {
MemoryStream memoryStream = new MemoryStream(codeBytes, offset, 8);
BinaryReader binaryReader = new BinaryReader(memoryStream);
return binaryReader.ReadDouble();
}
// Debug Methods
public override String ToString() {
if (lineNumber != null) {
return (opcodeInfoTable[(int) this.opcode].name +
lineNumber.ToString());
}
else {
return (opcodeInfoTable[(int) this.opcode].name);
}
}
internal static void dumpToConsole(Instruction[] instructions) {
int count = instructions.Length;
for (int i = 0; i < count; i++) {
Console.WriteLine("IL_"+i.ToString("x4")+": "+instructions[i]);
}
}
// State
private readonly Opcode opcode;
private readonly Operand operand;
private readonly DebugLineNumber lineNumber;
// Internal Types
private enum MethodFormats: byte {
Tiny = 2,
Fat = 3,
Tiny1 = 6
}
private enum SectionKind: byte {
Reserved = 0,
EHTable = 1,
OptILTable = 2
}
public enum Opcode: short {
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,
UNUSED49,
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,
ANN_DATA_S,
UNUSED1,
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,
STELEM,
UNBOX_ANY,
UNUSED5,
UNUSED6,
UNUSED7,
UNUSED8,
UNUSED9,
UNUSED10,
UNUSED11,
UNUSED12,
UNUSED13,
UNUSED14,
UNUSED15,
UNUSED16,
UNUSED17,
CONV_OVF_I1,
CONV_OVF_U1,
CONV_OVF_I2,
CONV_OVF_U2,
CONV_OVF_I4,
CONV_OVF_U4,
CONV_OVF_I8,
CONV_OVF_U8,
UNUSED50,
UNUSED18,
UNUSED19,
UNUSED20,
UNUSED21,
UNUSED22,
UNUSED23,
REFANYVAL,
CKFINITE,
UNUSED24,
UNUSED25,
MKREFANY,
ANN_CALL,
ANN_CATCH,
ANN_DEAD,
ANN_HOISTED,
ANN_HOISTED_CALL,
ANN_LAB,
ANN_DEF,
ANN_REF_S,
ANN_PHI,
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,
UNUSED26,
UNUSED27,
UNUSED28,
UNUSED29,
UNUSED30,
UNUSED31,
UNUSED32,
UNUSED33,
UNUSED34,
UNUSED35,
UNUSED36,
UNUSED37,
UNUSED38,
UNUSED39,
UNUSED40,
UNUSED41,
UNUSED42,
UNUSED43,
UNUSED44,
UNUSED45,
UNUSED46,
UNUSED47,
UNUSED48,
PREFIX7,
PREFIX6,
PREFIX5,
PREFIX4,
PREFIX3,
PREFIX2,
PREFIX1,
PREFIXREF,
ARGLIST,
CEQ,
CGT,
CGT_UN,
CLT,
CLT_UN,
LDFTN,
LDVIRTFTN,
UNUSED56,
LDARG,
LDARGA,
STARG,
LDLOC,
LDLOCA,
STLOC,
LOCALLOC,
UNUSED57,
ENDFILTER,
UNALIGNED,
VOLATILE,
TAILCALL,
INITOBJ,
ANN_LIVE,
CPBLK,
INITBLK,
ANN_REF,
RETHROW,
UNUSED51,
SIZEOF,
REFANYTYPE,
UNUSED52,
UNUSED53,
UNUSED54,
UNUSED55,
ANN_DATA,
ILLEGAL,
MACRO_END,
COUNT
}
private enum OperandFormat: byte {
None = 0,
Var = 1,
Int = 2,
Float = 3,
BranchTarget = 4,
Int8 = 5,
Method = 6,
Field = 7,
Type = 8,
String = 9,
Sig = 10,
RVA = 11,
Token = 12,
Switch = 13,
InlinePhi = 14,
PrimaryMask = (ShortOperand-1),
ShortOperand = 16,
Opcode = (ShortOperand + None),
ShortVar = (ShortOperand + Var),
ShortInt = (ShortOperand + Int),
ShortFloat = (ShortOperand + Float),
ShortBranchTarget = (ShortOperand + BranchTarget),
Illegal = 0Xff
}
private static readonly EHClause[] sharedEmptyTable = new EHClause[0];
private static readonly OpcodeInfo[] opcodeInfoTable = new OpcodeInfo[(int) Opcode.COUNT] {
new OpcodeInfo("nop",Opcode.NOP,OperandFormat.None,0,false),
new OpcodeInfo("break",Opcode.BREAK,OperandFormat.None,0,false),
new OpcodeInfo("ldarg.0",Opcode.LDARG_0,OperandFormat.None,0,false),
new OpcodeInfo("ldarg.1",Opcode.LDARG_1,OperandFormat.None,0,false),
new OpcodeInfo("ldarg.2",Opcode.LDARG_2,OperandFormat.None,0,false),
new OpcodeInfo("ldarg.3",Opcode.LDARG_3,OperandFormat.None,0,false),
new OpcodeInfo("ldloc.0",Opcode.LDLOC_0,OperandFormat.None,0,false),
new OpcodeInfo("ldloc.1",Opcode.LDLOC_1,OperandFormat.None,0,false),
new OpcodeInfo("ldloc.2",Opcode.LDLOC_2,OperandFormat.None,0,false),
new OpcodeInfo("ldloc.3",Opcode.LDLOC_3,OperandFormat.None,0,false),
new OpcodeInfo("stloc.0",Opcode.STLOC_0,OperandFormat.None,0,false),
new OpcodeInfo("stloc.1",Opcode.STLOC_1,OperandFormat.None,0,false),
new OpcodeInfo("stloc.2",Opcode.STLOC_2,OperandFormat.None,0,false),
new OpcodeInfo("stloc.3",Opcode.STLOC_3,OperandFormat.None,0,false),
new OpcodeInfo("ldarg.s",Opcode.LDARG_S,OperandFormat.ShortVar,1,false),
new OpcodeInfo("ldarga.s",Opcode.LDARGA_S,OperandFormat.ShortVar,1,false),
new OpcodeInfo("starg.s",Opcode.STARG_S,OperandFormat.ShortVar,1,false),
new OpcodeInfo("ldloc.s",Opcode.LDLOC_S,OperandFormat.ShortVar,1,false),
new OpcodeInfo("ldloca.s",Opcode.LDLOCA_S,OperandFormat.ShortVar,1,false),
new OpcodeInfo("stloc.s",Opcode.STLOC_S,OperandFormat.ShortVar,1,false),
new OpcodeInfo("ldnull",Opcode.LDNULL,OperandFormat.None,0,false),
new OpcodeInfo("ldc.i4.m1",Opcode.LDC_I4_M1,OperandFormat.None,0,false),
new OpcodeInfo("ldc.i4.0",Opcode.LDC_I4_0,OperandFormat.None,0,false),
new OpcodeInfo("ldc.i4.1",Opcode.LDC_I4_1,OperandFormat.None,0,false),
new OpcodeInfo("ldc.i4.2",Opcode.LDC_I4_2,OperandFormat.None,0,false),
new OpcodeInfo("ldc.i4.3",Opcode.LDC_I4_3,OperandFormat.None,0,false),
new OpcodeInfo("ldc.i4.4",Opcode.LDC_I4_4,OperandFormat.None,0,false),
new OpcodeInfo("ldc.i4.5",Opcode.LDC_I4_5,OperandFormat.None,0,false),
new OpcodeInfo("ldc.i4.6",Opcode.LDC_I4_6,OperandFormat.None,0,false),
new OpcodeInfo("ldc.i4.7",Opcode.LDC_I4_7,OperandFormat.None,0,false),
new OpcodeInfo("ldc.i4.8",Opcode.LDC_I4_8,OperandFormat.None,0,false),
new OpcodeInfo("ldc.i4.s",Opcode.LDC_I4_S,OperandFormat.ShortInt,1,false),
new OpcodeInfo("ldc.i4",Opcode.LDC_I4,OperandFormat.Int,4,false),
new OpcodeInfo("ldc.i8",Opcode.LDC_I8,OperandFormat.Int8,8,false),
new OpcodeInfo("ldc.r4",Opcode.LDC_R4,OperandFormat.ShortFloat,4,false),
new OpcodeInfo("ldc.r8",Opcode.LDC_R8,OperandFormat.Float,8,false),
new OpcodeInfo("unused",Opcode.UNUSED49,OperandFormat.Illegal,0,false),
new OpcodeInfo("dup",Opcode.DUP,OperandFormat.None,0,false),
new OpcodeInfo("pop",Opcode.POP,OperandFormat.None,0,false),
new OpcodeInfo("jmp",Opcode.JMP,OperandFormat.Method,4,true),
new OpcodeInfo("call",Opcode.CALL,OperandFormat.Method,4,false),
new OpcodeInfo("calli",Opcode.CALLI,OperandFormat.Sig,4,false),
new OpcodeInfo("ret",Opcode.RET,OperandFormat.None,0,true),
new OpcodeInfo("br.s",Opcode.BR_S,OperandFormat.ShortBranchTarget,1,true),
new OpcodeInfo("brfalse.s",Opcode.BRFALSE_S,OperandFormat.ShortBranchTarget,1,true),
new OpcodeInfo("brtrue.s",Opcode.BRTRUE_S,OperandFormat.ShortBranchTarget,1,true),
new OpcodeInfo("beq.s",Opcode.BEQ_S,OperandFormat.ShortBranchTarget,1,true),
new OpcodeInfo("bge.s",Opcode.BGE_S,OperandFormat.ShortBranchTarget,1,true),
new OpcodeInfo("bgt.s",Opcode.BGT_S,OperandFormat.ShortBranchTarget,1,true),
new OpcodeInfo("ble.s",Opcode.BLE_S,OperandFormat.ShortBranchTarget,1,true),
new OpcodeInfo("blt.s",Opcode.BLT_S,OperandFormat.ShortBranchTarget,1,true),
new OpcodeInfo("bne.un.s",Opcode.BNE_UN_S,OperandFormat.ShortBranchTarget,1,true),
new OpcodeInfo("bge.un.s",Opcode.BGE_UN_S,OperandFormat.ShortBranchTarget,1,true),
new OpcodeInfo("bgt.un.s",Opcode.BGT_UN_S,OperandFormat.ShortBranchTarget,1,true),
new OpcodeInfo("ble.un.s",Opcode.BLE_UN_S,OperandFormat.ShortBranchTarget,1,true),
new OpcodeInfo("blt.un.s",Opcode.BLT_UN_S,OperandFormat.ShortBranchTarget,1,true),
new OpcodeInfo("br",Opcode.BR,OperandFormat.BranchTarget,4,true),
new OpcodeInfo("brfalse",Opcode.BRFALSE,OperandFormat.BranchTarget,4,true),
new OpcodeInfo("brtrue",Opcode.BRTRUE,OperandFormat.BranchTarget,4,true),
new OpcodeInfo("beq",Opcode.BEQ,OperandFormat.BranchTarget,4,true),
new OpcodeInfo("bge",Opcode.BGE,OperandFormat.BranchTarget,4,true),
new OpcodeInfo("bgt",Opcode.BGT,OperandFormat.BranchTarget,4,true),
new OpcodeInfo("ble",Opcode.BLE,OperandFormat.BranchTarget,4,true),
new OpcodeInfo("blt",Opcode.BLT,OperandFormat.BranchTarget,4,true),
new OpcodeInfo("bne.un",Opcode.BNE_UN,OperandFormat.BranchTarget,4,true),
new OpcodeInfo("bge.un",Opcode.BGE_UN,OperandFormat.BranchTarget,4,true),
new OpcodeInfo("bgt.un",Opcode.BGT_UN,OperandFormat.BranchTarget,4,true),
new OpcodeInfo("ble.un",Opcode.BLE_UN,OperandFormat.BranchTarget,4,true),
new OpcodeInfo("blt.un",Opcode.BLT_UN,OperandFormat.BranchTarget,4,true),
new OpcodeInfo("switch",Opcode.SWITCH,OperandFormat.Switch,0xFF,true),
new OpcodeInfo("ldind.i1",Opcode.LDIND_I1,OperandFormat.None,0,false),
new OpcodeInfo("ldind.u1",Opcode.LDIND_U1,OperandFormat.None,0,false),
new OpcodeInfo("ldind.i2",Opcode.LDIND_I2,OperandFormat.None,0,false),
new OpcodeInfo("ldind.u2",Opcode.LDIND_U2,OperandFormat.None,0,false),
new OpcodeInfo("ldind.i4",Opcode.LDIND_I4,OperandFormat.None,0,false),
new OpcodeInfo("ldind.u4",Opcode.LDIND_U4,OperandFormat.None,0,false),
new OpcodeInfo("ldind.i8",Opcode.LDIND_I8,OperandFormat.None,0,false),
new OpcodeInfo("ldind.i",Opcode.LDIND_I,OperandFormat.None,0,false),
new OpcodeInfo("ldind.r4",Opcode.LDIND_R4,OperandFormat.None,0,false),
new OpcodeInfo("ldind.r8",Opcode.LDIND_R8,OperandFormat.None,0,false),
new OpcodeInfo("ldind.ref",Opcode.LDIND_REF,OperandFormat.None,0,false),
new OpcodeInfo("stind.ref",Opcode.STIND_REF,OperandFormat.None,0,false),
new OpcodeInfo("stind.i1",Opcode.STIND_I1,OperandFormat.None,0,false),
new OpcodeInfo("stind.i2",Opcode.STIND_I2,OperandFormat.None,0,false),
new OpcodeInfo("stind.i4",Opcode.STIND_I4,OperandFormat.None,0,false),
new OpcodeInfo("stind.i8",Opcode.STIND_I8,OperandFormat.None,0,false),
new OpcodeInfo("stind.r4",Opcode.STIND_R4,OperandFormat.None,0,false),
new OpcodeInfo("stind.r8",Opcode.STIND_R8,OperandFormat.None,0,false),
new OpcodeInfo("add",Opcode.ADD,OperandFormat.None,0,false),
new OpcodeInfo("sub",Opcode.SUB,OperandFormat.None,0,false),
new OpcodeInfo("mul",Opcode.MUL,OperandFormat.None,0,false),
new OpcodeInfo("div",Opcode.DIV,OperandFormat.None,0,false),
new OpcodeInfo("div.un",Opcode.DIV_UN,OperandFormat.None,0,false),
new OpcodeInfo("rem",Opcode.REM,OperandFormat.None,0,false),
new OpcodeInfo("rem.un",Opcode.REM_UN,OperandFormat.None,0,false),
new OpcodeInfo("and",Opcode.AND,OperandFormat.None,0,false),
new OpcodeInfo("or",Opcode.OR,OperandFormat.None,0,false),
new OpcodeInfo("xor",Opcode.XOR,OperandFormat.None,0,false),
new OpcodeInfo("shl",Opcode.SHL,OperandFormat.None,0,false),
new OpcodeInfo("shr",Opcode.SHR,OperandFormat.None,0,false),
new OpcodeInfo("shr.un",Opcode.SHR_UN,OperandFormat.None,0,false),
new OpcodeInfo("neg",Opcode.NEG,OperandFormat.None,0,false),
new OpcodeInfo("not",Opcode.NOT,OperandFormat.None,0,false),
new OpcodeInfo("conv.i1",Opcode.CONV_I1,OperandFormat.None,0,false),
new OpcodeInfo("conv.i2",Opcode.CONV_I2,OperandFormat.None,0,false),
new OpcodeInfo("conv.i4",Opcode.CONV_I4,OperandFormat.None,0,false),
new OpcodeInfo("conv.i8",Opcode.CONV_I8,OperandFormat.None,0,false),
new OpcodeInfo("conv.r4",Opcode.CONV_R4,OperandFormat.None,0,false),
new OpcodeInfo("conv.r8",Opcode.CONV_R8,OperandFormat.None,0,false),
new OpcodeInfo("conv.u4",Opcode.CONV_U4,OperandFormat.None,0,false),
new OpcodeInfo("conv.u8",Opcode.CONV_U8,OperandFormat.None,0,false),
new OpcodeInfo("callvirt",Opcode.CALLVIRT,OperandFormat.Method,4,false),
new OpcodeInfo("cpobj",Opcode.CPOBJ,OperandFormat.Type,4,false),
new OpcodeInfo("ldobj",Opcode.LDOBJ,OperandFormat.Type,4,false),
new OpcodeInfo("ldstr",Opcode.LDSTR,OperandFormat.String,4,false),
new OpcodeInfo("newobj",Opcode.NEWOBJ,OperandFormat.Method,4,false),
new OpcodeInfo("castclass",Opcode.CASTCLASS,OperandFormat.Type,4,false),
new OpcodeInfo("isinst",Opcode.ISINST,OperandFormat.Type,4,false),
new OpcodeInfo("conv.r.un",Opcode.CONV_R_UN,OperandFormat.None,0,false),
new OpcodeInfo("ann.data.s",Opcode.ANN_DATA_S,OperandFormat.ShortBranchTarget,0xFF,false),
new OpcodeInfo("unused",Opcode.UNUSED1,OperandFormat.Illegal,0,false),
new OpcodeInfo("unbox",Opcode.UNBOX,OperandFormat.Type,4,false),
new OpcodeInfo("throw",Opcode.THROW,OperandFormat.None,0,true),
new OpcodeInfo("ldfld",Opcode.LDFLD,OperandFormat.Field,4,false),
new OpcodeInfo("ldflda",Opcode.LDFLDA,OperandFormat.Field,4,false),
new OpcodeInfo("stfld",Opcode.STFLD,OperandFormat.Field,4,false),
new OpcodeInfo("ldsfld",Opcode.LDSFLD,OperandFormat.Field,4,false),
new OpcodeInfo("ldsflda",Opcode.LDSFLDA,OperandFormat.Field,4,false),
new OpcodeInfo("stsfld",Opcode.STSFLD,OperandFormat.Field,4,false),
new OpcodeInfo("stobj",Opcode.STOBJ,OperandFormat.Type,4,false),
new OpcodeInfo("conv.ovf.i1.un",Opcode.CONV_OVF_I1_UN,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.i2.un",Opcode.CONV_OVF_I2_UN,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.i4.un",Opcode.CONV_OVF_I4_UN,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.i8.un",Opcode.CONV_OVF_I8_UN,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.u1.un",Opcode.CONV_OVF_U1_UN,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.u2.un",Opcode.CONV_OVF_U2_UN,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.u4.un",Opcode.CONV_OVF_U4_UN,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.u8.un",Opcode.CONV_OVF_U8_UN,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.i.un",Opcode.CONV_OVF_I_UN,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.u.un",Opcode.CONV_OVF_U_UN,OperandFormat.None,0,false),
new OpcodeInfo("box",Opcode.BOX,OperandFormat.Type,4,false),
new OpcodeInfo("newarr",Opcode.NEWARR,OperandFormat.Type,4,false),
new OpcodeInfo("ldlen",Opcode.LDLEN,OperandFormat.None,0,false),
new OpcodeInfo("ldelema",Opcode.LDELEMA,OperandFormat.Type,4,false),
new OpcodeInfo("ldelem.i1",Opcode.LDELEM_I1,OperandFormat.None,0,false),
new OpcodeInfo("ldelem.u1",Opcode.LDELEM_U1,OperandFormat.None,0,false),
new OpcodeInfo("ldelem.i2",Opcode.LDELEM_I2,OperandFormat.None,0,false),
new OpcodeInfo("ldelem.u2",Opcode.LDELEM_U2,OperandFormat.None,0,false),
new OpcodeInfo("ldelem.i4",Opcode.LDELEM_I4,OperandFormat.None,0,false),
new OpcodeInfo("ldelem.u4",Opcode.LDELEM_U4,OperandFormat.None,0,false),
new OpcodeInfo("ldelem.i8",Opcode.LDELEM_I8,OperandFormat.None,0,false),
new OpcodeInfo("ldelem.i",Opcode.LDELEM_I,OperandFormat.None,0,false),
new OpcodeInfo("ldelem.r4",Opcode.LDELEM_R4,OperandFormat.None,0,false),
new OpcodeInfo("ldelem.r8",Opcode.LDELEM_R8,OperandFormat.None,0,false),
new OpcodeInfo("ldelem.ref",Opcode.LDELEM_REF,OperandFormat.None,0,false),
new OpcodeInfo("stelem.i",Opcode.STELEM_I,OperandFormat.None,0,false),
new OpcodeInfo("stelem.i1",Opcode.STELEM_I1,OperandFormat.None,0,false),
new OpcodeInfo("stelem.i2",Opcode.STELEM_I2,OperandFormat.None,0,false),
new OpcodeInfo("stelem.i4",Opcode.STELEM_I4,OperandFormat.None,0,false),
new OpcodeInfo("stelem.i8",Opcode.STELEM_I8,OperandFormat.None,0,false),
new OpcodeInfo("stelem.r4",Opcode.STELEM_R4,OperandFormat.None,0,false),
new OpcodeInfo("stelem.r8",Opcode.STELEM_R8,OperandFormat.None,0,false),
new OpcodeInfo("stelem.ref",Opcode.STELEM_REF,OperandFormat.None,0,false),
new OpcodeInfo("ldelem",Opcode.LDELEM,OperandFormat.Type,4,false),
new OpcodeInfo("stelem",Opcode.STELEM,OperandFormat.Type,4,false),
new OpcodeInfo("unbox.any",Opcode.UNBOX_ANY,OperandFormat.Type,4,false),
new OpcodeInfo("unused",Opcode.UNUSED5,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED6,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED7,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED8,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED9,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED10,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED11,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED12,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED13,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED14,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED15,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED16,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED17,OperandFormat.Illegal,0,false),
new OpcodeInfo("conv.ovf.i1",Opcode.CONV_OVF_I1,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.u1",Opcode.CONV_OVF_U1,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.i2",Opcode.CONV_OVF_I2,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.u2",Opcode.CONV_OVF_U2,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.i4",Opcode.CONV_OVF_I4,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.u4",Opcode.CONV_OVF_U4,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.i8",Opcode.CONV_OVF_I8,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.u8",Opcode.CONV_OVF_U8,OperandFormat.None,0,false),
new OpcodeInfo("unused",Opcode.UNUSED50,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED18,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED19,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED20,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED21,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED22,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED23,OperandFormat.Illegal,0,false),
new OpcodeInfo("refanyval",Opcode.REFANYVAL,OperandFormat.Type,4,false),
new OpcodeInfo("ckfinite",Opcode.CKFINITE,OperandFormat.None,0,false),
new OpcodeInfo("unused",Opcode.UNUSED24,OperandFormat.None,0,false),
new OpcodeInfo("unused",Opcode.UNUSED25,OperandFormat.None,0,false),
new OpcodeInfo("mkrefany",Opcode.MKREFANY,OperandFormat.Type,4,false),
new OpcodeInfo("ann.call",Opcode.ANN_CALL,OperandFormat.Method,4,false),
new OpcodeInfo("ann.catch",Opcode.ANN_CATCH,OperandFormat.None,0,false),
new OpcodeInfo("ann.dead",Opcode.ANN_DEAD,OperandFormat.Var,2,false),
new OpcodeInfo("ann.hoisted",Opcode.ANN_HOISTED,OperandFormat.None,0,false),
new OpcodeInfo("ann.hoisted_call",Opcode.ANN_HOISTED_CALL,OperandFormat.Method,4,false),
new OpcodeInfo("ann.lab",Opcode.ANN_LAB,OperandFormat.None,0,false),
new OpcodeInfo("ann.def",Opcode.ANN_DEF,OperandFormat.None,0,false),
new OpcodeInfo("ann.ref.s",Opcode.ANN_REF_S,OperandFormat.ShortVar,1,false),
new OpcodeInfo("ann.phi",Opcode.ANN_PHI,OperandFormat.InlinePhi,0xFF,false),
new OpcodeInfo("ldtoken",Opcode.LDTOKEN,OperandFormat.Token,4,false),
new OpcodeInfo("conv.u2",Opcode.CONV_U2,OperandFormat.None,0,false),
new OpcodeInfo("conv.u1",Opcode.CONV_U1,OperandFormat.None,0,false),
new OpcodeInfo("conv.i",Opcode.CONV_I,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.i",Opcode.CONV_OVF_I,OperandFormat.None,0,false),
new OpcodeInfo("conv.ovf.u",Opcode.CONV_OVF_U,OperandFormat.None,0,false),
new OpcodeInfo("add.ovf",Opcode.ADD_OVF,OperandFormat.None,0,false),
new OpcodeInfo("add.ovf.un",Opcode.ADD_OVF_UN,OperandFormat.None,0,false),
new OpcodeInfo("mul.ovf",Opcode.MUL_OVF,OperandFormat.None,0,false),
new OpcodeInfo("mul.ovf.un",Opcode.MUL_OVF_UN,OperandFormat.None,0,false),
new OpcodeInfo("sub.ovf",Opcode.SUB_OVF,OperandFormat.None,0,false),
new OpcodeInfo("sub.ovf.un",Opcode.SUB_OVF_UN,OperandFormat.None,0,false),
new OpcodeInfo("endfinally",Opcode.ENDFINALLY,OperandFormat.None,0,true),
new OpcodeInfo("leave",Opcode.LEAVE,OperandFormat.BranchTarget,4,true),
new OpcodeInfo("leave.s",Opcode.LEAVE_S,OperandFormat.ShortBranchTarget,1,true),
new OpcodeInfo("stind.i",Opcode.STIND_I,OperandFormat.None,0,false),
new OpcodeInfo("conv.u",Opcode.CONV_U,OperandFormat.None,0,false),
new OpcodeInfo("unused",Opcode.UNUSED26,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED27,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED28,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED29,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED30,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED31,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED32,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED33,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED34,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED35,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED36,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED37,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED38,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED39,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED40,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED41,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED42,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED43,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED44,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED45,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED46,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED47,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED48,OperandFormat.Illegal,0,false),
new OpcodeInfo("prefix7",Opcode.PREFIX7,OperandFormat.Illegal,0,false),
new OpcodeInfo("prefix6",Opcode.PREFIX6,OperandFormat.Illegal,0,false),
new OpcodeInfo("prefix5",Opcode.PREFIX5,OperandFormat.Illegal,0,false),
new OpcodeInfo("prefix4",Opcode.PREFIX4,OperandFormat.Illegal,0,false),
new OpcodeInfo("prefix3",Opcode.PREFIX3,OperandFormat.Illegal,0,false),
new OpcodeInfo("prefix2",Opcode.PREFIX2,OperandFormat.Illegal,0,false),
new OpcodeInfo("prefix1",Opcode.PREFIX1,OperandFormat.None,0,false),
new OpcodeInfo("prefixref",Opcode.PREFIXREF,OperandFormat.Illegal,0,false),
new OpcodeInfo("arglist",Opcode.ARGLIST,OperandFormat.None,0,false),
new OpcodeInfo("ceq",Opcode.CEQ,OperandFormat.None,0,false),
new OpcodeInfo("cgt",Opcode.CGT,OperandFormat.None,0,false),
new OpcodeInfo("cgt.un",Opcode.CGT_UN,OperandFormat.None,0,false),
new OpcodeInfo("clt",Opcode.CLT,OperandFormat.None,0,false),
new OpcodeInfo("clt.un",Opcode.CLT_UN,OperandFormat.None,0,false),
new OpcodeInfo("ldftn",Opcode.LDFTN,OperandFormat.Method,4,false),
new OpcodeInfo("ldvirtftn",Opcode.LDVIRTFTN,OperandFormat.Method,4,false),
new OpcodeInfo("unused",Opcode.UNUSED56,OperandFormat.Illegal,0,false),
new OpcodeInfo("ldarg",Opcode.LDARG,OperandFormat.Var,2,false),
new OpcodeInfo("ldarga",Opcode.LDARGA,OperandFormat.Var,2,false),
new OpcodeInfo("starg",Opcode.STARG,OperandFormat.Var,2,false),
new OpcodeInfo("ldloc",Opcode.LDLOC,OperandFormat.Var,2,false),
new OpcodeInfo("ldloca",Opcode.LDLOCA,OperandFormat.Var,2,false),
new OpcodeInfo("stloc",Opcode.STLOC,OperandFormat.Var,2,false),
new OpcodeInfo("localloc",Opcode.LOCALLOC,OperandFormat.None,0,false),
new OpcodeInfo("unused",Opcode.UNUSED57,OperandFormat.Illegal,0,false),
new OpcodeInfo("endfilter",Opcode.ENDFILTER,OperandFormat.None,0,true),
new OpcodeInfo("unaligned.",Opcode.UNALIGNED,OperandFormat.ShortInt,1,false),
new OpcodeInfo("volatile.",Opcode.VOLATILE,OperandFormat.None,0,false),
new OpcodeInfo("tail.",Opcode.TAILCALL,OperandFormat.None,0,false),
new OpcodeInfo("initobj",Opcode.INITOBJ,OperandFormat.Type,4,false),
new OpcodeInfo("ann.live",Opcode.ANN_LIVE,OperandFormat.Var,2,false),
new OpcodeInfo("cpblk",Opcode.CPBLK,OperandFormat.None,0,false),
new OpcodeInfo("initblk",Opcode.INITBLK,OperandFormat.None,0,false),
new OpcodeInfo("ann.ref",Opcode.ANN_REF,OperandFormat.Var,2,false),
new OpcodeInfo("rethrow",Opcode.RETHROW,OperandFormat.None,0,true),
new OpcodeInfo("unused",Opcode.UNUSED51,OperandFormat.Illegal,0,false),
new OpcodeInfo("sizeof",Opcode.SIZEOF,OperandFormat.Type,4,false),
new OpcodeInfo("refanytype",Opcode.REFANYTYPE,OperandFormat.None,0,false),
new OpcodeInfo("unused",Opcode.UNUSED52,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED53,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED54,OperandFormat.Illegal,0,false),
new OpcodeInfo("unused",Opcode.UNUSED55,OperandFormat.Illegal,0,false),
new OpcodeInfo("ann.data",Opcode.ANN_DATA,OperandFormat.BranchTarget,0xFF,false),
new OpcodeInfo("illegal",Opcode.ILLEGAL,OperandFormat.Illegal,0,false),
new OpcodeInfo("endmac",Opcode.MACRO_END,OperandFormat.Illegal,0,false),
};
static Instruction() {
for (Opcode opcode = 0; opcode < Opcode.COUNT; opcode++) {
if (opcodeInfoTable[(int) opcode].opcode != opcode) {
throw new IllegalInstructionStreamException("opcode invariant failure");
}
}
}
// Internal classes
public abstract class Operand {
}
public class OperandInt: Operand {
// Constructor Methods
internal OperandInt(int value) {
this.value = value;
}
// Access Methods
public int Value {
get {
return this.value;
}
}
// Debug Methods
public override String ToString() {
return ("OperandInt(0x"+this.value.ToString("x")+"/"+this.value+")");
}
// State
private readonly int value;
}
public class OperandTarget: Operand {
// Constructor Methods
internal OperandTarget(int target) {
this.target = target;
}
// Access Methods
public int Target {
get {
return this.target;
}
}
// Debug Methods
public override String ToString() {
return ("OperandTarget(IL_"+this.target.ToString("x4")+")");
}
// State
private readonly int target;
}
public class OperandSingle: Operand {
// Constructor Methods
internal OperandSingle(float value) {
this.value = value;
}
// Access Methods
public float Value {
get {
return this.value;
}
}
// Debug Methods
public override String ToString() {
return ("OperandSingle("+this.value+")");
}
// State
private readonly float value;
}
public class OperandDouble: Operand {
// Constructor Methods
internal OperandDouble(double value) {
this.value = value;
}
// Access Methods
public double Value {
get {
return this.value;
}
}
// Debug Methods
public override String ToString() {
return ("OperandDouble("+this.value+")");
}
// State
private readonly double value;
}
public class OperandTargetArray: Operand {
// Constructor Methods
internal OperandTargetArray(int[] targets) {
this.targets = targets;
}
// Access Methods
public int[] Targets {
get {
return this.targets;
}
}
// Debug Methods
public override String ToString() {
System.Text.StringBuilder sb =
new System.Text.StringBuilder("OperandTargetArray(");
if (this.targets.Length > 0) {
for (int i = 0; i < this.targets.Length - 1; i++) {
sb.Append("IL_");
sb.Append(this.targets[i].ToString("x4"));
sb.Append(",");
}
sb.Append("IL_");
sb.Append(this.targets[this.targets.Length-1].ToString("x4"));
}
sb.Append(")");
return sb.ToString();
}
// State
private readonly int[] targets;
}
public class OperandByteArray: Operand {
// Constructor Methods
internal OperandByteArray(byte[] value) {
this.value = value;
}
// Access Methods
public byte[] Value {
get {
return this.value;
}
}
// Debug Methods
public override String ToString() {
System.Text.StringBuilder sb =
new System.Text.StringBuilder("OperandByteArray(");
if (this.value.Length > 0) {
for (int i = 0; i < this.value.Length - 1; i++) {
sb.Append(this.value[i]);
sb.Append(",");
}
sb.Append(this.value[this.value.Length-1]);
}
sb.Append(")");
return sb.ToString();
}
// State
private readonly byte[] value;
}
public class OperandLong: Operand {
// Constructor Methods
internal OperandLong(long value) {
this.value = value;
}
// Access Methods
public long Value {
get {
return this.value;
}
}
// Debug Methods
public override String ToString() {
return ("OperandLong("+this.value+")");
}
// State
private readonly long value;
}
public class OperandString: Operand {
// Constructor Methods
internal OperandString(String value) {
this.value = value;
}
// Access Methods
public String Value {
get {
return this.value;
}
}
// Debug Methods
public override String ToString() {
return ("OperandString(\""+this.value+"\")");
}
// State
private readonly String value;
}
public class OperandObject: Operand {
// Constructor Methods
internal OperandObject(MetaDataObject value) {
this.value = value;
}
// Access Methods
public MetaDataObject Value {
get {
return this.value;
}
}
// Debug Methods
public override String ToString() {
return ("OperandObject("+this.value+")");
}
// State
private readonly MetaDataObject value;
}
private class OpcodeInfo {
// Constructor Methods
internal OpcodeInfo(String name, Opcode opcode,
OperandFormat operandFormat, byte operandSize,
bool isControl) {
this.name = name;
this.opcode = opcode;
this.operandFormat = operandFormat;
this.operandSize = operandSize;
this.isControl = isControl;
}
// State
internal readonly String name;
internal readonly Opcode opcode;
internal readonly OperandFormat operandFormat;
internal readonly byte operandSize;
internal readonly bool isControl;
}
private class IllegalInstructionStreamException: Exception {
internal IllegalInstructionStreamException(String message):
base(message)
{ }
}
}
}