using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using ILRuntime.CLR.Method; namespace ILRuntime.Runtime.Intepreter.OpCodes { /// /// IL指令 /// struct OpCode { /// /// 当前指令 /// public OpCodeEnum Code; /// /// Int32 操作数 /// public int TokenInteger; /// /// Int64 操作数 /// public long TokenLong; } /// /// Register machine opcode /// [StructLayout(LayoutKind.Explicit)] struct OpCodeR { [FieldOffset(0)] public OpCodeREnum Code; [FieldOffset(4)] public short Register1; [FieldOffset(6)] public short Register2; [FieldOffset(8)] public short Register3; [FieldOffset(10)] public short Register4; [FieldOffset(8)] public int Operand; [FieldOffset(8)] public float OperandFloat; [FieldOffset(12)] public int Operand2; [FieldOffset(16)] public int Operand3; [FieldOffset(12)] public long OperandLong; [FieldOffset(12)] public double OperandDouble; [FieldOffset(20)] public int Operand4; public override string ToString() { return ToString(null); } public string ToString(Enviorment.AppDomain domain) { string param = null; switch (Code) { case OpCodeREnum.Move: case OpCodeREnum.Ldind_I: case OpCodeREnum.Ldind_I1: case OpCodeREnum.Ldind_I2: case OpCodeREnum.Ldind_I4: case OpCodeREnum.Ldind_I8: case OpCodeREnum.Ldind_R4: case OpCodeREnum.Ldind_R8: case OpCodeREnum.Ldind_U1: case OpCodeREnum.Ldind_U2: case OpCodeREnum.Ldind_U4: case OpCodeREnum.Ldind_Ref: case OpCodeREnum.Ldobj: case OpCodeREnum.Stind_I: case OpCodeREnum.Stind_I1: case OpCodeREnum.Stind_I2: case OpCodeREnum.Stind_I4: case OpCodeREnum.Stind_I8: case OpCodeREnum.Stind_R4: case OpCodeREnum.Stind_R8: case OpCodeREnum.Stind_Ref: case OpCodeREnum.Stobj: case OpCodeREnum.Ldloca: case OpCodeREnum.Ldloca_S: case OpCodeREnum.Ldarga: case OpCodeREnum.Ldarga_S: case OpCodeREnum.Conv_I: case OpCodeREnum.Conv_I1: case OpCodeREnum.Conv_I2: case OpCodeREnum.Conv_I4: case OpCodeREnum.Conv_I8: case OpCodeREnum.Conv_Ovf_I: case OpCodeREnum.Conv_Ovf_I1: case OpCodeREnum.Conv_Ovf_I1_Un: case OpCodeREnum.Conv_Ovf_I2: case OpCodeREnum.Conv_Ovf_I2_Un: case OpCodeREnum.Conv_Ovf_I4: case OpCodeREnum.Conv_Ovf_I4_Un: case OpCodeREnum.Conv_Ovf_I8: case OpCodeREnum.Conv_Ovf_I8_Un: case OpCodeREnum.Conv_Ovf_I_Un: case OpCodeREnum.Conv_Ovf_U: case OpCodeREnum.Conv_Ovf_U1: case OpCodeREnum.Conv_Ovf_U1_Un: case OpCodeREnum.Conv_Ovf_U2: case OpCodeREnum.Conv_Ovf_U2_Un: case OpCodeREnum.Conv_Ovf_U4: case OpCodeREnum.Conv_Ovf_U4_Un: case OpCodeREnum.Conv_Ovf_U8: case OpCodeREnum.Conv_Ovf_U8_Un: case OpCodeREnum.Conv_Ovf_U_Un: case OpCodeREnum.Conv_R4: case OpCodeREnum.Conv_R8: case OpCodeREnum.Conv_R_Un: case OpCodeREnum.Conv_U: case OpCodeREnum.Conv_U1: case OpCodeREnum.Conv_U2: case OpCodeREnum.Conv_U4: case OpCodeREnum.Conv_U8: case OpCodeREnum.Not: case OpCodeREnum.Neg: param = string.Format("r{0}, r{1}", Register1, Register2); break; case OpCodeREnum.Box: case OpCodeREnum.Unbox: case OpCodeREnum.Unbox_Any: case OpCodeREnum.Isinst: if (domain == null) param = string.Format("r{0}, r{1}, {2}", Register1, Register2, Operand); else { var type = domain.GetType(Operand); param = string.Format("r{0}, r{1}, {2}", Register1, Register2, type); } break; case OpCodeREnum.Stfld: case OpCodeREnum.Ldfld: param = string.Format("r{0}, r{1}, 0x{2:X8}", Register1, Register2, OperandLong); break; case OpCodeREnum.Stsfld: case OpCodeREnum.Ldsfld: param = string.Format("r{0}, 0x{1:X8}", Register1, OperandLong); break; case OpCodeREnum.Beqi: case OpCodeREnum.Bgei: case OpCodeREnum.Bgei_Un: case OpCodeREnum.Bgti: case OpCodeREnum.Bgti_Un: case OpCodeREnum.Bnei_Un: case OpCodeREnum.Blei: case OpCodeREnum.Blei_Un: case OpCodeREnum.Blti: case OpCodeREnum.Blti_Un: if (Operand != 0) { param = string.Format("r{0},{1},{2}", Register1, Operand, Operand4); } else if (OperandLong != 0) { param = string.Format("r{0},{1},{2}", Register1, OperandLong, Operand4); } else if (OperandFloat != 0) { param = string.Format("r{0},{1},{2}", Register1, OperandFloat, Operand4); } else if (OperandDouble != 0) { param = string.Format("r{0},{1},{2}", Register1, OperandDouble, Operand4); } else { param = string.Format("r{0},0,{1}", Register1, Operand4); } break; case OpCodeREnum.Ceqi: case OpCodeREnum.Cgti: case OpCodeREnum.Cgti_Un: case OpCodeREnum.Clti: case OpCodeREnum.Clti_Un: case OpCodeREnum.Addi: case OpCodeREnum.Subi: case OpCodeREnum.Muli: case OpCodeREnum.Divi: case OpCodeREnum.Remi: case OpCodeREnum.Remi_Un: case OpCodeREnum.Andi: case OpCodeREnum.Ori: case OpCodeREnum.Xori: case OpCodeREnum.Shli: case OpCodeREnum.Shri: case OpCodeREnum.Shri_Un: if (Operand != 0) { param = string.Format("r{0},r{1},{2}", Register1, Register2, Operand); } else if (OperandLong != 0) { param = string.Format("r{0},r{1},{2}", Register1, Register2, OperandLong); } else if (OperandFloat != 0) { param = string.Format("r{0},r{1},{2}", Register1, Register2, OperandFloat); } else if (OperandDouble != 0) { param = string.Format("r{0},r{1},{2}", Register1, Register2, OperandDouble); } else { param = string.Format("r{0},r{1},0", Register1, Register2); } break; case OpCodeREnum.Add: case OpCodeREnum.Add_Ovf: case OpCodeREnum.Add_Ovf_Un: case OpCodeREnum.Sub: case OpCodeREnum.Sub_Ovf: case OpCodeREnum.Sub_Ovf_Un: case OpCodeREnum.Mul: case OpCodeREnum.Mul_Ovf: case OpCodeREnum.Mul_Ovf_Un: case OpCodeREnum.Div: case OpCodeREnum.Div_Un: case OpCodeREnum.Rem: case OpCodeREnum.Rem_Un: case OpCodeREnum.Xor: case OpCodeREnum.And: case OpCodeREnum.Or: case OpCodeREnum.Shl: case OpCodeREnum.Shr: case OpCodeREnum.Shr_Un: case OpCodeREnum.Clt: case OpCodeREnum.Clt_Un: case OpCodeREnum.Cgt: case OpCodeREnum.Cgt_Un: case OpCodeREnum.Ceq: case OpCodeREnum.Stelem_I1: case OpCodeREnum.Stelem_I2: case OpCodeREnum.Stelem_I: case OpCodeREnum.Stelem_I4: case OpCodeREnum.Stelem_R4: case OpCodeREnum.Stelem_R8: case OpCodeREnum.Stelem_Any: case OpCodeREnum.Stelem_Ref: case OpCodeREnum.Ldelem_I1: case OpCodeREnum.Ldelem_I2: case OpCodeREnum.Ldelem_I: case OpCodeREnum.Ldelem_I4: case OpCodeREnum.Ldelem_R4: case OpCodeREnum.Ldelem_R8: case OpCodeREnum.Ldelem_Ref: case OpCodeREnum.Ldelem_Any: case OpCodeREnum.Ldelema: param = string.Format("r{0},r{1},r{2}", Register1, Register2, Register3); break; case OpCodeREnum.Ldc_I4_0: case OpCodeREnum.Ldc_I4_1: case OpCodeREnum.Ldc_I4_2: case OpCodeREnum.Ldc_I4_3: case OpCodeREnum.Ldc_I4_4: case OpCodeREnum.Ldc_I4_5: case OpCodeREnum.Ldc_I4_6: case OpCodeREnum.Ldc_I4_7: case OpCodeREnum.Ldc_I4_8: case OpCodeREnum.Ldc_I4_M1: case OpCodeREnum.Ldnull: case OpCodeREnum.Ret: case OpCodeREnum.Push: param = string.Format("r{0}", Register1); break; case OpCodeREnum.Brtrue: case OpCodeREnum.Brtrue_S: case OpCodeREnum.Brfalse: case OpCodeREnum.Brfalse_S: case OpCodeREnum.Switch: param = string.Format("r{0}, {1}", Register1, Operand); break; case OpCodeREnum.Ldftn: if (domain == null) { param = string.Format("r{0}, {1}", Register1, Operand2); } else { IMethod m = domain.GetMethod(Operand2); if (m is CLR.Method.CLRMethod) param = m != null ? string.Format("r{0}, {1}::{2}", Register1, m.DeclearingType.FullName, m) : string.Format("r{0}, {1}", Register1, Operand2); else param = m != null ? string.Format("r{0}, {1}", Register1, m) : string.Format("r{0}, {1}", Register1, Operand2); } break; case OpCodeREnum.Ldvirtftn: if (domain == null) { param = string.Format("r{0}, r{1} {2}", Register1, Register2, Operand2); } else { IMethod m = domain.GetMethod(Operand2); if (m is CLR.Method.CLRMethod) param = m != null ? string.Format("r{0}, r{1}, {2}::{3}", Register1, Register2, m.DeclearingType.FullName, m) : string.Format("r{0}, r{1}, {2}", Register1, Register2, Operand2); else param = m != null ? string.Format("r{0}, r{1}, {2}", Register1, Register2, m) : string.Format("r{0}, r{1}, {2}", Register1, Register2, Operand2); } break; case OpCodeREnum.Constrained: { if (domain == null) { param = Operand.ToString(); } else { var m = domain.GetType(Operand); param = m != null ? m.ToString() : Operand.ToString(); } } break; case OpCodeREnum.Call: case OpCodeREnum.Callvirt: case OpCodeREnum.Newobj: { string retR = Register1 >= 0 ? "r" + Register1 : "-"; if (Register2 >= 0) retR += ", r" + Register2; if (Register3 >= 0) retR += ", r" + Register3; if (Register4 >= 0) retR += ", r" + Register4; if (domain == null) { param = string.Format("{0}, {1}", retR, Operand2); } else { IMethod m = domain.GetMethod(Operand2); if (m is CLR.Method.CLRMethod) param = m != null ? string.Format("{0}, {1}::{2}", retR, m.DeclearingType.FullName, m) : string.Format("{0}, {1}", retR, Operand2); else param = m != null ? string.Format("{0}, {1}", retR, m) : string.Format("{0}, {1}", retR, Operand2); } } break; case OpCodeREnum.Blt: case OpCodeREnum.Blt_S: case OpCodeREnum.Blt_Un: case OpCodeREnum.Blt_Un_S: case OpCodeREnum.Ble: case OpCodeREnum.Ble_S: case OpCodeREnum.Ble_Un: case OpCodeREnum.Ble_Un_S: case OpCodeREnum.Bgt: case OpCodeREnum.Bgt_S: case OpCodeREnum.Bgt_Un: case OpCodeREnum.Bgt_Un_S: case OpCodeREnum.Bge: case OpCodeREnum.Bge_S: case OpCodeREnum.Bge_Un: case OpCodeREnum.Bge_Un_S: case OpCodeREnum.Beq: case OpCodeREnum.Beq_S: case OpCodeREnum.Bne_Un: case OpCodeREnum.Bne_Un_S: param = string.Format("r{0}, r{1}, {2}", Register1, Register2, Operand); break; case OpCodeREnum.Br: case OpCodeREnum.Br_S: case OpCodeREnum.Leave: case OpCodeREnum.Leave_S: param = string.Format("{0}", Operand); break; case OpCodeREnum.Ldc_I4: case OpCodeREnum.Ldc_I4_S: param = string.Format("r{0},{1}", Register1, Operand); break; case OpCodeREnum.Ldc_I8: param = string.Format("r{0},{1}", Register1, OperandLong); break; case OpCodeREnum.Ldc_R4: param = string.Format("r{0},{1}", Register1, OperandFloat); break; case OpCodeREnum.Ldc_R8: param = string.Format("r{0},{1}", Register1, OperandDouble); break; case OpCodeREnum.Ldstr: if (domain == null) param = string.Format("r{0},0x{1:X}", Register1, OperandLong); else param = string.Format("r{0},\"{1}\"", Register1, domain.GetString(OperandLong)); break; case OpCodeREnum.Ldtoken: if (domain == null) param = string.Format("r{0},0x{1:X}", Register1, OperandLong); else { switch (Operand) { case 0: { var type = domain.GetType((int)(OperandLong >> 32)); int fieldIdx = (int)OperandLong; param = string.Format("r{0},{1}.{2}", Register1, type.FullName, (type is CLR.TypeSystem.ILType) ? ((CLR.TypeSystem.ILType)type).TypeDefinition.Fields[fieldIdx].Name : ((CLR.TypeSystem.CLRType)type).Fields[fieldIdx].Name); } break; case 1: { var type = domain.GetType((int)OperandLong); param = string.Format("r{0},\"{1}\"", Register1, type); } break; default: throw new NotImplementedException(); } } break; case OpCodeREnum.Initobj: if (domain == null) param = string.Format("r{0}, {1}", Register1, Operand); else { var type = domain.GetType(Operand); param = string.Format("r{0}, {1}", Register1, type); } break; case OpCodeREnum.Newarr: if (domain == null) param = string.Format("r{0}, r{1}", Register1, Register2); else { var type = domain.GetType(Operand); param = string.Format("r{0}, {2}, r{1}", Register1, Register2, type); } break; } return string.Format("{0} {1}", Code.ToString().ToLower().Replace('_', '.'), param); } } }