Ejemplo n.º 1
0
        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;
        }
Ejemplo n.º 2
0
        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);
        }