protected List<EcmaCil.IL.BaseInstruction> ScanMethodBody_DoIt(MethodBase aMethod, EcmaCil.MethodMeta aMethodMeta, IDictionary<int, int> aILOffsetToInstructionIndex, IDictionary<int, int> aInstructionIndexToILOffset) { var xResult = new List<EcmaCil.IL.BaseInstruction>(aILOffsetToInstructionIndex.Count); var xBody = aMethod.GetMethodBody(); // Cache for use in field and method resolution Type[] xTypeGenArgs = null; Type[] xMethodGenArgs = null; if (aMethod.DeclaringType.IsGenericType) { xTypeGenArgs = aMethod.DeclaringType.GetGenericArguments(); } if (aMethod.IsGenericMethod) { xMethodGenArgs = aMethod.GetGenericArguments(); } // Some methods return no body. Not sure why.. have to investigate // They arent abstracts or icalls... // MtW: how about externs (pinvoke, etc) if (xBody == null) { return null; } var xIL = xBody.GetILAsByteArray(); int xPos = 0; var xInstructionIndex = 0; var xInitSecondStage = new List<Action>(aILOffsetToInstructionIndex.Count); while (xPos < xIL.Length) { ExceptionHandlingClause xCurrentHandler = null; #region Determine current handler // todo: add support for nested handlers using a stack or so.. foreach (ExceptionHandlingClause xHandler in xBody.ExceptionHandlingClauses) { if (xHandler.TryOffset > 0) { if (xHandler.TryOffset <= xPos && (xHandler.TryLength + xHandler.TryOffset + 1) > xPos) // + 1 because index should be less than the try { if (xCurrentHandler == null) { xCurrentHandler = xHandler; continue; } else if (xHandler.TryOffset > xCurrentHandler.TryOffset && (xHandler.TryLength + xHandler.TryOffset) < (xCurrentHandler.TryLength + xCurrentHandler.TryOffset)) { // only replace if the current found handler is narrower xCurrentHandler = xHandler; continue; } } } if (xHandler.HandlerOffset > 0) { if (xHandler.HandlerOffset <= xPos && (xHandler.HandlerOffset + xHandler.HandlerLength + 1) > xPos) { if (xCurrentHandler == null) { xCurrentHandler = xHandler; continue; } else if (xHandler.HandlerOffset > xCurrentHandler.HandlerOffset && (xHandler.HandlerOffset + xHandler.HandlerLength) < (xCurrentHandler.HandlerOffset + xCurrentHandler.HandlerLength)) { // only replace if the current found handler is narrower xCurrentHandler = xHandler; continue; } } } if ((xHandler.Flags & ExceptionHandlingClauseOptions.Filter) > 0) { if (xHandler.FilterOffset > 0) { if (xHandler.FilterOffset <= xPos) { if (xCurrentHandler == null) { xCurrentHandler = xHandler; continue; } else if (xHandler.FilterOffset > xCurrentHandler.FilterOffset) { // only replace if the current found handler is narrower xCurrentHandler = xHandler; continue; } } } } } #endregion OpCodeEnum xOpCodeVal; OpCode xOpCode; int xOpPos = xPos; if (xIL[xPos] == 0xFE) { xOpCodeVal = (OpCodeEnum)(0xFE00 | xIL[xPos + 1]); xOpCode = mOpCodesHi[xIL[xPos + 1]]; xPos = xPos + 2; } else { xOpCodeVal = (OpCodeEnum)xIL[xPos]; xOpCode = mOpCodesLo[xIL[xPos]]; xPos++; } EcmaCil.IL.BaseInstruction xILOpCode = null; Cil.InstructionBranch xBranch; Console.WriteLine(xOpCode.ToString() + " " + xOpCode.OperandType); #region switch(xOpCode.OperandType) switch (xOpCode.OperandType) { // No operand. case OperandType.InlineNone: { #region Inline none options // These shortcut translation regions expand shortcut ops into full ops // This elminates the amount of code required in the assemblers // by allowing them to ignore the shortcuts switch (xOpCodeVal) { case OpCodeEnum.Ldarg_0: xILOpCode = new Cil.InstructionArgument(EcmaCil.IL.InstructionKindEnum.Ldarg, xInstructionIndex, aMethodMeta.Parameters[0]); break; case OpCodeEnum.Ldarg_1: xILOpCode = new Cil.InstructionArgument(EcmaCil.IL.InstructionKindEnum.Ldarg, xInstructionIndex, aMethodMeta.Parameters[1]); break; case OpCodeEnum.Ldarg_2: xILOpCode = new Cil.InstructionArgument(EcmaCil.IL.InstructionKindEnum.Ldarg, xInstructionIndex, aMethodMeta.Parameters[2]); break; case OpCodeEnum.Ldarg_3: xILOpCode = new Cil.InstructionArgument(EcmaCil.IL.InstructionKindEnum.Ldarg, xInstructionIndex, aMethodMeta.Parameters[3]); break; case OpCodeEnum.Ldc_I4_0: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 0); break; case OpCodeEnum.Ldc_I4_1: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 1); break; case OpCodeEnum.Ldc_I4_2: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 2); break; case OpCodeEnum.Ldc_I4_3: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 3); break; case OpCodeEnum.Ldc_I4_4: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 4); break; case OpCodeEnum.Ldc_I4_5: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 5); break; case OpCodeEnum.Ldc_I4_6: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 6); break; case OpCodeEnum.Ldc_I4_7: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 7); break; case OpCodeEnum.Ldc_I4_8: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 8); break; case OpCodeEnum.Ldc_I4_M1: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, -1); break; case OpCodeEnum.Ldloc_0: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Ldloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[0]); break; case OpCodeEnum.Ldloc_1: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Ldloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[1]); break; case OpCodeEnum.Ldloc_2: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Ldloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[2]); break; case OpCodeEnum.Ldloc_3: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Ldloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[3]); break; case OpCodeEnum.Stloc_0: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Stloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[0]); break; case OpCodeEnum.Stloc_1: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Stloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[1]); break; case OpCodeEnum.Stloc_2: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Stloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[2]); break; case OpCodeEnum.Stloc_3: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Stloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[3]); break; default: xILOpCode = new Cil.InstructionNone((EcmaCil.IL.InstructionKindEnum)xOpCodeVal, xInstructionIndex); break; } #endregion break; } case OperandType.ShortInlineBrTarget: { #region Inline branch // By calculating target, we assume all branches are within a method // So far at least wtih csc, its true. We check it with CheckBranch // just in case. int xTarget = xPos + 1 + (sbyte)xIL[xPos]; CheckBranch(xTarget, xIL.Length); switch (xOpCodeVal) { case OpCodeEnum.Beq_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Beq, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Bge_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Bge, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Bge_Un_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Bge_Un, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Bgt_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Bgt, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Bgt_Un_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Bgt_Un, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Ble_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Ble, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Ble_Un_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Ble_Un, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Blt_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Blt, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Blt_Un_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Blt_Un, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Bne_Un_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Bne_Un, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Br_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Br, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Brfalse_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Brfalse, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Brtrue_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Brtrue, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Leave_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Leave, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; default: xBranch = new Cil.InstructionBranch((EcmaCil.IL.InstructionKindEnum)xOpCodeVal, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; } xPos = xPos + 1; break; #endregion } case OperandType.InlineBrTarget: { int xTarget = xPos + 4 + (Int32)ReadInt32(xIL, xPos); CheckBranch(xTarget, xIL.Length); xILOpCode = xBranch = new Cil.InstructionBranch((EcmaCil.IL.InstructionKindEnum)xOpCodeVal, xInstructionIndex); xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); xPos = xPos + 4; break; } case OperandType.ShortInlineI: switch (xOpCodeVal) { case OpCodeEnum.Ldc_I4_S: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, xIL[xPos]); break; default: xILOpCode = new Cil.InstructionInt32((EcmaCil.IL.InstructionKindEnum)xOpCodeVal, xInstructionIndex, xIL[xPos]); break; } xPos = xPos + 1; break; case OperandType.InlineI: xILOpCode = new Cil.InstructionInt32((Cil.InstructionKindEnum)xOpCodeVal, xInstructionIndex, ReadInt32(xIL, xPos)); xPos = xPos + 4; break; case OperandType.InlineI8: xILOpCode = new Cil.InstructionInt64((Cil.InstructionKindEnum)xOpCodeVal, xInstructionIndex, ReadInt64(xIL, xPos)); xPos = xPos + 8; break; case OperandType.ShortInlineR: // this is not correct: //xILOpCode = new Cil.InstructionSingle( //xILOpCode = new ILOpCodes.OpSingle(xOpCodeVal, xOpPos, xPos + 4, BitConverter.ToSingle(xIL, xPos), xCurrentHandler); //xPos = xPos + 4; //break; throw new NotImplementedException(); case OperandType.InlineR: // this is not correct //xILOpCode = new ILOpCodes.OpDouble(xOpCodeVal, xOpPos, xPos + 8, BitConverter.ToDouble(xIL, xPos), xCurrentHandler); //xPos = xPos + 8; //break; throw new NotImplementedException(); // The operand is a 32-bit metadata token. case OperandType.InlineField: throw new NotImplementedException(); //{ // var xValue = aMethod.Module.ResolveField((int)ReadInt32(xIL, xPos), xTypeGenArgs, xMethodGenArgs); // xILOpCode = new ILOpCodes.OpField(xOpCodeVal, xOpPos, xPos + 4, xValue, xCurrentHandler); // xPos = xPos + 4; // break; //} // The operand is a 32-bit metadata token. case OperandType.InlineMethod: var xTargetMethod = EnqueueMethod(aMethod.DeclaringType.Module.ResolveMethod(ReadInt32(xIL, xPos)), aMethod, "Method Call"); xILOpCode = new Cil.InstructionMethod((Cil.InstructionKindEnum)xOpCodeVal, xInstructionIndex, xTargetMethod); xPos = xPos + 4; break; //{ // var xValue = aMethod.Module.ResolveMethod((int)ReadInt32(xIL, xPos), xTypeGenArgs, xMethodGenArgs); // xILOpCode = new ILOpCodes.OpMethod(xOpCodeVal, xOpPos, xPos + 4, xValue, xCurrentHandler); // xPos = xPos + 4; // break; //} // 32-bit metadata signature token. case OperandType.InlineSig: throw new NotImplementedException(); case OperandType.InlineString: xILOpCode = new Cil.InstructionString(Cil.InstructionKindEnum.Ldstr, xInstructionIndex, aMethod.Module.ResolveString(ReadInt32(xIL, xPos))); xPos = xPos + 4; break; case OperandType.InlineSwitch: throw new NotImplementedException(); //{ // int xCount = (int)ReadInt32(xIL, xPos); // xPos = xPos + 4; // int xNextOpPos = xPos + xCount * 4; // int[] xBranchLocations = new int[xCount]; // for (int i = 0; i < xCount; i++) // { // xBranchLocations[i] = xNextOpPos + (int)ReadInt32(xIL, xPos + i * 4); // CheckBranch(xBranchLocations[i], xIL.Length); // } // xILOpCode = new ILOpCodes.OpSwitch(xOpCodeVal, xOpPos, xPos, xBranchLocations, xCurrentHandler); // xPos = xNextOpPos; // break; //} // The operand is a FieldRef, MethodRef, or TypeRef token. case OperandType.InlineTok: throw new NotImplementedException(); //xILOpCode = new ILOpCodes.OpToken(xOpCodeVal, xOpPos, xPos + 4, ReadInt32(xIL, xPos), aMethod.Module, xTypeGenArgs, xMethodGenArgs, xCurrentHandler); // xPos = xPos + 4; // break; // 32-bit metadata token. case OperandType.InlineType: throw new NotImplementedException(); //{ // var xValue = aMethod.Module.ResolveType((int)ReadInt32(xIL, xPos), xTypeGenArgs, xMethodGenArgs); // xILOpCode = new ILOpCodes.OpType(xOpCodeVal, xOpPos, xPos + 4, xValue, xCurrentHandler); // xPos = xPos + 4; // break; //} case OperandType.ShortInlineVar: switch (xOpCodeVal) { case OpCodeEnum.Ldloc_S: xILOpCode = new Cil.InstructionLocal(Cil.InstructionKindEnum.Ldloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[xIL[xPos]]); break; case OpCodeEnum.Ldloca_S: xILOpCode = new Cil.InstructionLocal(Cil.InstructionKindEnum.Ldloca, xInstructionIndex, aMethodMeta.Body.LocalVariables[xIL[xPos]]); break; case OpCodeEnum.Ldarg_S: xILOpCode = new Cil.InstructionArgument(Cil.InstructionKindEnum.Ldarg, xInstructionIndex, aMethodMeta.Parameters[xIL[xPos]]); break; case OpCodeEnum.Ldarga_S: xILOpCode = new Cil.InstructionArgument(Cil.InstructionKindEnum.Ldarga, xInstructionIndex, aMethodMeta.Parameters[xIL[xPos]]); break; case OpCodeEnum.Starg_S: xILOpCode = new Cil.InstructionArgument(Cil.InstructionKindEnum.Starg, xInstructionIndex, aMethodMeta.Parameters[xIL[xPos]]); break; case OpCodeEnum.Stloc_S: xILOpCode = new Cil.InstructionLocal(Cil.InstructionKindEnum.Stloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[xIL[xPos]]); break; default: throw new NotImplementedException(); //xILOpCode = new ILOpCodes.OpVar(xOpCodeVal, xOpPos, xPos + 1, xIL[xPos], xCurrentHandler); //break; } xPos = xPos + 1; break; case OperandType.InlineVar: //xILOpCode = new ILOpCodes.OpVar(xOpCodeVal, xOpPos, xPos + 2, ReadUInt16(xIL, xPos), xCurrentHandler); //xPos = xPos + 2; throw new NotImplementedException(); break; default: throw new Exception("Unknown OperandType"); } #endregion switch(xOpCode.OperandType) xResult.Add(xILOpCode); xInstructionIndex++; } foreach (var xAction in xInitSecondStage) { xAction(); } return xResult; }
protected List <EcmaCil.IL.BaseInstruction> ScanMethodBody_DoIt(MethodBase aMethod, EcmaCil.MethodMeta aMethodMeta, IDictionary <int, int> aILOffsetToInstructionIndex, IDictionary <int, int> aInstructionIndexToILOffset) { var xResult = new List <EcmaCil.IL.BaseInstruction>(aILOffsetToInstructionIndex.Count); var xBody = aMethod.GetMethodBody(); // Cache for use in field and method resolution Type[] xTypeGenArgs = null; Type[] xMethodGenArgs = null; if (aMethod.DeclaringType.IsGenericType) { xTypeGenArgs = aMethod.DeclaringType.GetGenericArguments(); } if (aMethod.IsGenericMethod) { xMethodGenArgs = aMethod.GetGenericArguments(); } // Some methods return no body. Not sure why.. have to investigate // They arent abstracts or icalls... // MtW: how about externs (pinvoke, etc) if (xBody == null) { return(null); } var xIL = xBody.GetILAsByteArray(); int xPos = 0; var xInstructionIndex = 0; var xInitSecondStage = new List <Action>(aILOffsetToInstructionIndex.Count); while (xPos < xIL.Length) { ExceptionHandlingClause xCurrentHandler = null; #region Determine current handler // todo: add support for nested handlers using a stack or so.. foreach (ExceptionHandlingClause xHandler in xBody.ExceptionHandlingClauses) { if (xHandler.TryOffset > 0) { if (xHandler.TryOffset <= xPos && (xHandler.TryLength + xHandler.TryOffset + 1) > xPos) // + 1 because index should be less than the try { if (xCurrentHandler == null) { xCurrentHandler = xHandler; continue; } else if (xHandler.TryOffset > xCurrentHandler.TryOffset && (xHandler.TryLength + xHandler.TryOffset) < (xCurrentHandler.TryLength + xCurrentHandler.TryOffset)) { // only replace if the current found handler is narrower xCurrentHandler = xHandler; continue; } } } if (xHandler.HandlerOffset > 0) { if (xHandler.HandlerOffset <= xPos && (xHandler.HandlerOffset + xHandler.HandlerLength + 1) > xPos) { if (xCurrentHandler == null) { xCurrentHandler = xHandler; continue; } else if (xHandler.HandlerOffset > xCurrentHandler.HandlerOffset && (xHandler.HandlerOffset + xHandler.HandlerLength) < (xCurrentHandler.HandlerOffset + xCurrentHandler.HandlerLength)) { // only replace if the current found handler is narrower xCurrentHandler = xHandler; continue; } } } if ((xHandler.Flags & ExceptionHandlingClauseOptions.Filter) > 0) { if (xHandler.FilterOffset > 0) { if (xHandler.FilterOffset <= xPos) { if (xCurrentHandler == null) { xCurrentHandler = xHandler; continue; } else if (xHandler.FilterOffset > xCurrentHandler.FilterOffset) { // only replace if the current found handler is narrower xCurrentHandler = xHandler; continue; } } } } } #endregion OpCodeEnum xOpCodeVal; OpCode xOpCode; int xOpPos = xPos; if (xIL[xPos] == 0xFE) { xOpCodeVal = (OpCodeEnum)(0xFE00 | xIL[xPos + 1]); xOpCode = mOpCodesHi[xIL[xPos + 1]]; xPos = xPos + 2; } else { xOpCodeVal = (OpCodeEnum)xIL[xPos]; xOpCode = mOpCodesLo[xIL[xPos]]; xPos++; } EcmaCil.IL.BaseInstruction xILOpCode = null; Cil.InstructionBranch xBranch; Console.WriteLine(xOpCode.ToString() + " " + xOpCode.OperandType); #region switch(xOpCode.OperandType) switch (xOpCode.OperandType) { // No operand. case OperandType.InlineNone: { #region Inline none options // These shortcut translation regions expand shortcut ops into full ops // This elminates the amount of code required in the assemblers // by allowing them to ignore the shortcuts switch (xOpCodeVal) { case OpCodeEnum.Ldarg_0: xILOpCode = new Cil.InstructionArgument(EcmaCil.IL.InstructionKindEnum.Ldarg, xInstructionIndex, aMethodMeta.Parameters[0]); break; case OpCodeEnum.Ldarg_1: xILOpCode = new Cil.InstructionArgument(EcmaCil.IL.InstructionKindEnum.Ldarg, xInstructionIndex, aMethodMeta.Parameters[1]); break; case OpCodeEnum.Ldarg_2: xILOpCode = new Cil.InstructionArgument(EcmaCil.IL.InstructionKindEnum.Ldarg, xInstructionIndex, aMethodMeta.Parameters[2]); break; case OpCodeEnum.Ldarg_3: xILOpCode = new Cil.InstructionArgument(EcmaCil.IL.InstructionKindEnum.Ldarg, xInstructionIndex, aMethodMeta.Parameters[3]); break; case OpCodeEnum.Ldc_I4_0: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 0); break; case OpCodeEnum.Ldc_I4_1: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 1); break; case OpCodeEnum.Ldc_I4_2: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 2); break; case OpCodeEnum.Ldc_I4_3: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 3); break; case OpCodeEnum.Ldc_I4_4: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 4); break; case OpCodeEnum.Ldc_I4_5: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 5); break; case OpCodeEnum.Ldc_I4_6: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 6); break; case OpCodeEnum.Ldc_I4_7: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 7); break; case OpCodeEnum.Ldc_I4_8: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, 8); break; case OpCodeEnum.Ldc_I4_M1: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, -1); break; case OpCodeEnum.Ldloc_0: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Ldloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[0]); break; case OpCodeEnum.Ldloc_1: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Ldloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[1]); break; case OpCodeEnum.Ldloc_2: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Ldloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[2]); break; case OpCodeEnum.Ldloc_3: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Ldloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[3]); break; case OpCodeEnum.Stloc_0: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Stloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[0]); break; case OpCodeEnum.Stloc_1: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Stloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[1]); break; case OpCodeEnum.Stloc_2: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Stloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[2]); break; case OpCodeEnum.Stloc_3: xILOpCode = new Cil.InstructionLocal(EcmaCil.IL.InstructionKindEnum.Stloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[3]); break; default: xILOpCode = new Cil.InstructionNone((EcmaCil.IL.InstructionKindEnum)xOpCodeVal, xInstructionIndex); break; } #endregion break; } case OperandType.ShortInlineBrTarget: { #region Inline branch // By calculating target, we assume all branches are within a method // So far at least wtih csc, its true. We check it with CheckBranch // just in case. int xTarget = xPos + 1 + (sbyte)xIL[xPos]; CheckBranch(xTarget, xIL.Length); switch (xOpCodeVal) { case OpCodeEnum.Beq_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Beq, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Bge_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Bge, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Bge_Un_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Bge_Un, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Bgt_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Bgt, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Bgt_Un_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Bgt_Un, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Ble_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Ble, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Ble_Un_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Ble_Un, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Blt_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Blt, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Blt_Un_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Blt_Un, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Bne_Un_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Bne_Un, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Br_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Br, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Brfalse_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Brfalse, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Brtrue_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Brtrue, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; case OpCodeEnum.Leave_S: xBranch = new Cil.InstructionBranch(EcmaCil.IL.InstructionKindEnum.Leave, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; default: xBranch = new Cil.InstructionBranch((EcmaCil.IL.InstructionKindEnum)xOpCodeVal, xInstructionIndex); xILOpCode = xBranch; xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); break; } xPos = xPos + 1; break; #endregion } case OperandType.InlineBrTarget: { int xTarget = xPos + 4 + (Int32)ReadInt32(xIL, xPos); CheckBranch(xTarget, xIL.Length); xILOpCode = xBranch = new Cil.InstructionBranch((EcmaCil.IL.InstructionKindEnum)xOpCodeVal, xInstructionIndex); xInitSecondStage.Add(delegate { xBranch.Target = xResult[aILOffsetToInstructionIndex[xTarget]]; }); xPos = xPos + 4; break; } case OperandType.ShortInlineI: switch (xOpCodeVal) { case OpCodeEnum.Ldc_I4_S: xILOpCode = new Cil.InstructionInt32(EcmaCil.IL.InstructionKindEnum.Ldc_I4, xInstructionIndex, xIL[xPos]); break; default: xILOpCode = new Cil.InstructionInt32((EcmaCil.IL.InstructionKindEnum)xOpCodeVal, xInstructionIndex, xIL[xPos]); break; } xPos = xPos + 1; break; case OperandType.InlineI: xILOpCode = new Cil.InstructionInt32((Cil.InstructionKindEnum)xOpCodeVal, xInstructionIndex, ReadInt32(xIL, xPos)); xPos = xPos + 4; break; case OperandType.InlineI8: xILOpCode = new Cil.InstructionInt64((Cil.InstructionKindEnum)xOpCodeVal, xInstructionIndex, ReadInt64(xIL, xPos)); xPos = xPos + 8; break; case OperandType.ShortInlineR: // this is not correct: //xILOpCode = new Cil.InstructionSingle( //xILOpCode = new ILOpCodes.OpSingle(xOpCodeVal, xOpPos, xPos + 4, BitConverter.ToSingle(xIL, xPos), xCurrentHandler); //xPos = xPos + 4; //break; throw new NotImplementedException(); case OperandType.InlineR: // this is not correct //xILOpCode = new ILOpCodes.OpDouble(xOpCodeVal, xOpPos, xPos + 8, BitConverter.ToDouble(xIL, xPos), xCurrentHandler); //xPos = xPos + 8; //break; throw new NotImplementedException(); // The operand is a 32-bit metadata token. case OperandType.InlineField: throw new NotImplementedException(); //{ // var xValue = aMethod.Module.ResolveField((int)ReadInt32(xIL, xPos), xTypeGenArgs, xMethodGenArgs); // xILOpCode = new ILOpCodes.OpField(xOpCodeVal, xOpPos, xPos + 4, xValue, xCurrentHandler); // xPos = xPos + 4; // break; //} // The operand is a 32-bit metadata token. case OperandType.InlineMethod: var xTargetMethod = EnqueueMethod(aMethod.DeclaringType.Module.ResolveMethod(ReadInt32(xIL, xPos)), aMethod, "Method Call"); xILOpCode = new Cil.InstructionMethod((Cil.InstructionKindEnum)xOpCodeVal, xInstructionIndex, xTargetMethod); xPos = xPos + 4; break; //{ // var xValue = aMethod.Module.ResolveMethod((int)ReadInt32(xIL, xPos), xTypeGenArgs, xMethodGenArgs); // xILOpCode = new ILOpCodes.OpMethod(xOpCodeVal, xOpPos, xPos + 4, xValue, xCurrentHandler); // xPos = xPos + 4; // break; //} // 32-bit metadata signature token. case OperandType.InlineSig: throw new NotImplementedException(); case OperandType.InlineString: xILOpCode = new Cil.InstructionString(Cil.InstructionKindEnum.Ldstr, xInstructionIndex, aMethod.Module.ResolveString(ReadInt32(xIL, xPos))); xPos = xPos + 4; break; case OperandType.InlineSwitch: throw new NotImplementedException(); //{ // int xCount = (int)ReadInt32(xIL, xPos); // xPos = xPos + 4; // int xNextOpPos = xPos + xCount * 4; // int[] xBranchLocations = new int[xCount]; // for (int i = 0; i < xCount; i++) // { // xBranchLocations[i] = xNextOpPos + (int)ReadInt32(xIL, xPos + i * 4); // CheckBranch(xBranchLocations[i], xIL.Length); // } // xILOpCode = new ILOpCodes.OpSwitch(xOpCodeVal, xOpPos, xPos, xBranchLocations, xCurrentHandler); // xPos = xNextOpPos; // break; //} // The operand is a FieldRef, MethodRef, or TypeRef token. case OperandType.InlineTok: throw new NotImplementedException(); //xILOpCode = new ILOpCodes.OpToken(xOpCodeVal, xOpPos, xPos + 4, ReadInt32(xIL, xPos), aMethod.Module, xTypeGenArgs, xMethodGenArgs, xCurrentHandler); // xPos = xPos + 4; // break; // 32-bit metadata token. case OperandType.InlineType: throw new NotImplementedException(); //{ // var xValue = aMethod.Module.ResolveType((int)ReadInt32(xIL, xPos), xTypeGenArgs, xMethodGenArgs); // xILOpCode = new ILOpCodes.OpType(xOpCodeVal, xOpPos, xPos + 4, xValue, xCurrentHandler); // xPos = xPos + 4; // break; //} case OperandType.ShortInlineVar: switch (xOpCodeVal) { case OpCodeEnum.Ldloc_S: xILOpCode = new Cil.InstructionLocal(Cil.InstructionKindEnum.Ldloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[xIL[xPos]]); break; case OpCodeEnum.Ldloca_S: xILOpCode = new Cil.InstructionLocal(Cil.InstructionKindEnum.Ldloca, xInstructionIndex, aMethodMeta.Body.LocalVariables[xIL[xPos]]); break; case OpCodeEnum.Ldarg_S: xILOpCode = new Cil.InstructionArgument(Cil.InstructionKindEnum.Ldarg, xInstructionIndex, aMethodMeta.Parameters[xIL[xPos]]); break; case OpCodeEnum.Ldarga_S: xILOpCode = new Cil.InstructionArgument(Cil.InstructionKindEnum.Ldarga, xInstructionIndex, aMethodMeta.Parameters[xIL[xPos]]); break; case OpCodeEnum.Starg_S: xILOpCode = new Cil.InstructionArgument(Cil.InstructionKindEnum.Starg, xInstructionIndex, aMethodMeta.Parameters[xIL[xPos]]); break; case OpCodeEnum.Stloc_S: xILOpCode = new Cil.InstructionLocal(Cil.InstructionKindEnum.Stloc, xInstructionIndex, aMethodMeta.Body.LocalVariables[xIL[xPos]]); break; default: throw new NotImplementedException(); //xILOpCode = new ILOpCodes.OpVar(xOpCodeVal, xOpPos, xPos + 1, xIL[xPos], xCurrentHandler); //break; } xPos = xPos + 1; break; case OperandType.InlineVar: //xILOpCode = new ILOpCodes.OpVar(xOpCodeVal, xOpPos, xPos + 2, ReadUInt16(xIL, xPos), xCurrentHandler); //xPos = xPos + 2; throw new NotImplementedException(); break; default: throw new Exception("Unknown OperandType"); } #endregion switch(xOpCode.OperandType) xResult.Add(xILOpCode); xInstructionIndex++; } foreach (var xAction in xInitSecondStage) { xAction(); } return(xResult); }