Beispiel #1
0
        public static void Assemble(Cosmos.Assembler.Assembler aAssembler, OpType aOpType, uint aElementSize, bool debugEnabled)
        {
            XS.Comment("Arraytype: " + aOpType.StackPopTypes.Last().FullName);
            XS.Comment("Size: " + aElementSize);

            DoNullReferenceCheck(aAssembler, debugEnabled, 4);
            // calculate element offset into array memory (including header)
            XS.Pop(XSRegisters.EAX);
            XS.Set(XSRegisters.EDX, aElementSize);
            XS.Multiply(XSRegisters.EDX);
            XS.Add(XSRegisters.EAX, (uint)(ObjectImpl.FieldDataOffset + 4));

            // pop the array now
            XS.Pop(XSRegisters.EDX);
            // translate it to actual memory
            XS.Set(XSRegisters.EDX, XSRegisters.EDX, sourceIsIndirect: true);

            if (aOpType.StackPopTypes.Last().GetElementType().IsClass)
            {
                XS.Set(XSRegisters.EDX, XSRegisters.EDX, sourceIsIndirect: true);
            }

            XS.Add(XSRegisters.EDX, XSRegisters.EAX);
            XS.Push(XSRegisters.EDX);
        }
Beispiel #2
0
        public static void Assemble(Cosmos.Assembler.Assembler aAssembler, OpType aOpType, uint aElementSize, bool debugEnabled)
        {
            new Comment("Arraytype: " + aOpType.StackPopTypes.Last().FullName);
            new Comment("Size: " + aElementSize);

            DoNullReferenceCheck(aAssembler, debugEnabled, 4);
            // calculate element offset into array memory (including header)
            new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX };
            new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDX, SourceValue = aElementSize };
            new CPUx86.Multiply { DestinationReg = CPUx86.Registers.EDX };
            new CPUx86.Add { DestinationReg = CPUx86.Registers.EAX, SourceValue = (uint)(ObjectImpl.FieldDataOffset + 4) };

            // pop the array now
            new CPUx86.Pop { DestinationReg = CPUx86.Registers.EDX };
            // translate it to actual memory
            new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.RegistersEnum.EDX, SourceIsIndirect = true };

            if (aOpType.StackPopTypes.Last().GetElementType().IsClass)
            {
                new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.RegistersEnum.EDX, SourceIsIndirect = true };
            }

            new CPUx86.Add { DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EAX };
            new CPUx86.Push { DestinationReg = CPUx86.Registers.EDX };
        }
Beispiel #3
0
    private void DoExecute(Assembler.Assembler assembler, MethodInfo aMethod, ILOpCode aOpCode, OpType aTargetType, bool debugEnabled)
    {
      new Comment(assembler, $"Type = {aTargetType.Value}");
      if (aTargetType.Value.BaseType == typeof(ValueType))
      {

      }
      else if (aTargetType.Value.BaseType == typeof(object))
      {
        throw new NotImplementedException($"Constrained not implemented for {aTargetType.Value}");
      }
    }
Beispiel #4
0
    public static void Assemble(Cosmos.Assembler.Assembler aAssembler, OpType aOpType, uint aElementSize, bool debugEnabled)
    {
      XS.Comment("Arraytype: " + aOpType.StackPopTypes.Last().FullName);
      XS.Comment("Size: " + aElementSize);

      DoNullReferenceCheck(aAssembler, debugEnabled, 8);
      // calculate element offset into array memory (including header)
      XS.Pop(EAX);
      XS.Set(EDX, aElementSize);
      XS.Multiply(EDX);
      XS.Add(EAX, (uint) (ObjectImpl.FieldDataOffset + 4));

      // pop the array now
      XS.Add(ESP, 4);
      XS.Pop(EDX);

      XS.Add(EDX, EAX);
      XS.Push(EDX);
    }
Beispiel #5
0
        private void DoExecute(Assembler.Assembler assembler, MethodInfo aMethod, ILOpCode aOpCode, OpType aTargetType, bool debugEnabled)
        {
            // If thisType is a reference type (as opposed to a value type) then
            //     ptr is dereferenced and passed as the ‘this’ pointer to the callvirt of method
            // If thisType is a value type and thisType implements method then
            //     ptr is passed unmodified as the ‘this’ pointer to a call of method implemented by thisType
            // If thisType is a value type and thisType does not implement method then
            //     ptr is dereferenced, boxed, and passed as the ‘this’ pointer to the callvirt of method

            new Comment(assembler, $"Type = {aTargetType.Value}");
            if (aTargetType.Value.BaseType == typeof (ValueType))
            {
                
            }
            else if (aTargetType.Value.BaseType == typeof (object))
            {
                throw new NotImplementedException($"Constrained not implemented for {aTargetType.Value}");
            }
        }
Beispiel #6
0
        public List <ILOpCode> ProcessMethod(MethodBase aMethod)
        {
            var xResult = new List <ILOpCode>();
            var xBody   = aMethod.GetMethodBody();
            var xModule = aMethod.Module;

            if (aMethod.DeclaringType.FullName == "System.Runtime.CompilerServices.Unsafe")
            {
                var xUnsafeMethod = Type.GetType("System.Runtime.CompilerServices.Unsafe, System.Runtime.CompilerServices.Unsafe")
                                    .GetMethod(aMethod.Name, Array.ConvertAll(aMethod.GetParameters(), p => p.ParameterType));
                xBody   = xUnsafeMethod.GetMethodBody();
                xModule = xUnsafeMethod.Module;
            }

            // Cache for use in field and method resolution
            Type[] xTypeGenArgs   = Type.EmptyTypes;
            Type[] xMethodGenArgs = Type.EmptyTypes;
            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...
            if (xBody == null)
            {
                return(null);
            }

            var xIL  = xBody.GetILAsByteArray();
            int xPos = 0;

            while (xPos < xIL.Length)
            {
                _ExceptionRegionInfo xCurrentExceptionRegion = null;
                #region Determine current handler
                // todo: add support for nested handlers using a stack or so..
                foreach (_ExceptionRegionInfo xHandler in aMethod.GetExceptionRegionInfos())
                {
                    if (xHandler.TryOffset >= 0)
                    {
                        if (xHandler.TryOffset <= xPos && (xHandler.TryLength + xHandler.TryOffset) > xPos)
                        {
                            if (xCurrentExceptionRegion == null)
                            {
                                xCurrentExceptionRegion = xHandler;
                                continue;
                            }
                            else if (xHandler.TryOffset > xCurrentExceptionRegion.TryOffset && (xHandler.TryLength + xHandler.TryOffset) < (xCurrentExceptionRegion.TryLength + xCurrentExceptionRegion.TryOffset))
                            {
                                // only replace if the current found handler is narrower
                                xCurrentExceptionRegion = xHandler;
                                continue;
                            }
                        }
                    }
                    // todo: handler offset can be 0 like try offset?
                    if (xHandler.HandlerOffset > 0)
                    {
                        if (xHandler.HandlerOffset <= xPos && (xHandler.HandlerOffset + xHandler.HandlerLength) > xPos)
                        {
                            if (xCurrentExceptionRegion == null)
                            {
                                xCurrentExceptionRegion = xHandler;
                                continue;
                            }
                            else if (xHandler.HandlerOffset > xCurrentExceptionRegion.HandlerOffset && (xHandler.HandlerOffset + xHandler.HandlerLength) < (xCurrentExceptionRegion.HandlerOffset + xCurrentExceptionRegion.HandlerLength))
                            {
                                // only replace if the current found handler is narrower
                                xCurrentExceptionRegion = xHandler;
                                continue;
                            }
                        }
                    }
                    if (xHandler.Kind.HasFlag(ExceptionRegionKind.Filter))
                    {
                        if (xHandler.FilterOffset > 0)
                        {
                            if (xHandler.FilterOffset <= xPos)
                            {
                                if (xCurrentExceptionRegion == null)
                                {
                                    xCurrentExceptionRegion = xHandler;
                                    continue;
                                }
                                else if (xHandler.FilterOffset > xCurrentExceptionRegion.FilterOffset)
                                {
                                    // only replace if the current found handler is narrower
                                    xCurrentExceptionRegion = xHandler;
                                    continue;
                                }
                            }
                        }
                    }
                }
                #endregion
                ILOpCode.Code xOpCodeVal;
                OpCode        xOpCode;
                int           xOpPos = xPos;
                if (xIL[xPos] == 0xFE)
                {
                    xOpCodeVal = (ILOpCode.Code)(0xFE00 | xIL[xPos + 1]);
                    xOpCode    = mOpCodesHi[xIL[xPos + 1]];
                    xPos       = xPos + 2;
                }
                else
                {
                    xOpCodeVal = (ILOpCode.Code)xIL[xPos];
                    xOpCode    = mOpCodesLo[xIL[xPos]];
                    xPos++;
                }

                ILOpCode xILOpCode = null;
                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 ILOpCode.Code.Ldarg_0:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos, 0, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldarg_1:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos, 1, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldarg_2:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos, 2, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldarg_3:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos, 3, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_0:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 0, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_1:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 1, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_2:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 2, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_3:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 3, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_4:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 4, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_5:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 5, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_6:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 6, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_7:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 7, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_8:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 8, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_M1:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, -1, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldloc_0:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos, 0, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldloc_1:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos, 1, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldloc_2:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos, 2, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldloc_3:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos, 3, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Stloc_0:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos, 0, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Stloc_1:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos, 1, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Stloc_2:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos, 2, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Stloc_3:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos, 3, xCurrentExceptionRegion);
                        break;

                    default:
                        xILOpCode = new ILOpCodes.OpNone(xOpCodeVal, xOpPos, xPos, xCurrentExceptionRegion);
                        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 ILOpCode.Code.Beq_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Beq, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Bge_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bge, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Bge_Un_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bge_Un, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Bgt_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bgt, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Bgt_Un_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bgt_Un, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ble_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Ble, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ble_Un_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Ble_Un, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Blt_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Blt, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Blt_Un_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Blt_Un, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Bne_Un_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bne_Un, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Br_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Br, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Brfalse_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Brfalse, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Brtrue_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Brtrue, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Leave_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Leave, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    default:
                        xILOpCode = new ILOpCodes.OpBranch(xOpCodeVal, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;
                    }
                    xPos = xPos + 1;
                    break;
                    #endregion
                }

                case OperandType.InlineBrTarget:
                {
                    int xTarget = xPos + 4 + ReadInt32(xIL, xPos);
                    CheckBranch(xTarget, xIL.Length);
                    xILOpCode = new ILOpCodes.OpBranch(xOpCodeVal, xOpPos, xPos + 4, xTarget, xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;
                }

                case OperandType.ShortInlineI:
                    switch (xOpCodeVal)
                    {
                    case ILOpCode.Code.Ldc_I4_S:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos + 1, ((sbyte)xIL[xPos]), xCurrentExceptionRegion);
                        break;

                    default:
                        xILOpCode = new ILOpCodes.OpInt(xOpCodeVal, xOpPos, xPos + 1, ((sbyte)xIL[xPos]), xCurrentExceptionRegion);
                        break;
                    }
                    xPos = xPos + 1;
                    break;

                case OperandType.InlineI:
                    xILOpCode = new ILOpCodes.OpInt(xOpCodeVal, xOpPos, xPos + 4, ReadInt32(xIL, xPos), xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;

                case OperandType.InlineI8:
                    xILOpCode = new ILOpCodes.OpInt64(xOpCodeVal, xOpPos, xPos + 8, ReadUInt64(xIL, xPos), xCurrentExceptionRegion);
                    xPos      = xPos + 8;
                    break;

                case OperandType.ShortInlineR:
                    xILOpCode = new ILOpCodes.OpSingle(xOpCodeVal, xOpPos, xPos + 4, BitConverter.ToSingle(xIL, xPos), xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;

                case OperandType.InlineR:
                    xILOpCode = new ILOpCodes.OpDouble(xOpCodeVal, xOpPos, xPos + 8, BitConverter.ToDouble(xIL, xPos), xCurrentExceptionRegion);
                    xPos      = xPos + 8;
                    break;

                // The operand is a 32-bit metadata token.
                case OperandType.InlineField:
                {
                    var xValue = xModule.ResolveField(ReadInt32(xIL, xPos), xTypeGenArgs, xMethodGenArgs);
                    xILOpCode = new ILOpCodes.OpField(xOpCodeVal, xOpPos, xPos + 4, xValue, xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;
                }

                // The operand is a 32-bit metadata token.
                case OperandType.InlineMethod:
                {
                    var xValue = xModule.ResolveMethod(ReadInt32(xIL, xPos), xTypeGenArgs, xMethodGenArgs);
                    xILOpCode = new ILOpCodes.OpMethod(xOpCodeVal, xOpPos, xPos + 4, xValue, xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;
                }

                // 32-bit metadata signature token.
                case OperandType.InlineSig:
                    xILOpCode = new ILOpCodes.OpSig(xOpCodeVal, xOpPos, xPos + 4, ReadInt32(xIL, xPos), xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;

                case OperandType.InlineString:
                    xILOpCode = new ILOpCodes.OpString(xOpCodeVal, xOpPos, xPos + 4, xModule.ResolveString(ReadInt32(xIL, xPos)), xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;

                case OperandType.InlineSwitch:
                {
                    int xCount = ReadInt32(xIL, xPos);
                    xPos = xPos + 4;
                    int xNextOpPos       = xPos + xCount * 4;
                    var xBranchLocations = new int[xCount];
                    for (int i = 0; i < xCount; i++)
                    {
                        xBranchLocations[i] = xNextOpPos + ReadInt32(xIL, xPos + i * 4);
                        CheckBranch(xBranchLocations[i], xIL.Length);
                    }
                    xILOpCode = new ILOpCodes.OpSwitch(xOpCodeVal, xOpPos, xNextOpPos, xBranchLocations, xCurrentExceptionRegion);
                    xPos      = xNextOpPos;
                    break;
                }

                // The operand is a FieldRef, MethodRef, or TypeRef token.
                case OperandType.InlineTok:
                    xILOpCode = new ILOpCodes.OpToken(xOpCodeVal, xOpPos, xPos + 4, ReadInt32(xIL, xPos), xModule, xTypeGenArgs, xMethodGenArgs, xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;

                // 32-bit metadata token.
                case OperandType.InlineType:
                {
                    var xValue = xModule.ResolveType(ReadInt32(xIL, xPos), xTypeGenArgs, xMethodGenArgs);
                    xILOpCode = new ILOpCodes.OpType(xOpCodeVal, xOpPos, xPos + 4, xValue, xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;
                }

                case OperandType.ShortInlineVar:
                    switch (xOpCodeVal)
                    {
                    case ILOpCode.Code.Ldloc_S:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos + 1, xIL[xPos], xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldloca_S:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloca, xOpPos, xPos + 1, xIL[xPos], xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldarg_S:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos + 1, xIL[xPos], xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldarga_S:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarga, xOpPos, xPos + 1, xIL[xPos], xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Starg_S:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Starg, xOpPos, xPos + 1, xIL[xPos], xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Stloc_S:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos + 1, xIL[xPos], xCurrentExceptionRegion);
                        break;

                    default:
                        xILOpCode = new ILOpCodes.OpVar(xOpCodeVal, xOpPos, xPos + 1, xIL[xPos], xCurrentExceptionRegion);
                        break;
                    }
                    xPos = xPos + 1;
                    break;

                case OperandType.InlineVar:
                    xILOpCode = new ILOpCodes.OpVar(xOpCodeVal, xOpPos, xPos + 2, ReadUInt16(xIL, xPos), xCurrentExceptionRegion);
                    xPos      = xPos + 2;
                    break;

                default:
                    throw new Exception("Unknown OperandType");
                }
                xILOpCode.InitStackAnalysis(aMethod);
                xResult.Add(xILOpCode);
            }
            return(xResult);
        }
Beispiel #7
0
    public List<ILOpCode> ProcessMethod(MethodBase aMethod) {
      var xResult = new List<ILOpCode>();
      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...
      if (xBody == null) {
        return null;
      }

      var xIL = xBody.GetILAsByteArray();
      int xPos = 0;
      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
          ILOpCode.Code xOpCodeVal;
        OpCode xOpCode;
        int xOpPos = xPos;
        if (xIL[xPos] == 0xFE) {
          xOpCodeVal = (ILOpCode.Code)(0xFE00 | xIL[xPos + 1]);
          xOpCode = mOpCodesHi[xIL[xPos + 1]];
          xPos = xPos + 2;
        } else {
          xOpCodeVal = (ILOpCode.Code)xIL[xPos];
          xOpCode = mOpCodesLo[xIL[xPos]];
          xPos++;
        }

        ILOpCode xILOpCode = null;
        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 ILOpCode.Code.Ldarg_0:
                      xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos, 0, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldarg_1:
                  xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos, 1, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldarg_2:
                  xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos, 2, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldarg_3:
                  xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos, 3, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldc_I4_0:
                  xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 0, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldc_I4_1:
                  xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 1, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldc_I4_2:
                  xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 2, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldc_I4_3:
                  xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 3, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldc_I4_4:
                  xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 4, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldc_I4_5:
                  xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 5, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldc_I4_6:
                  xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 6, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldc_I4_7:
                  xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 7, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldc_I4_8:
                  xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 8, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldc_I4_M1:
                  xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, -1, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldloc_0:
                  xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos, 0, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldloc_1:
                  xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos, 1, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldloc_2:
                  xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos, 2, xCurrentHandler);
                  break;
                case ILOpCode.Code.Ldloc_3:
                  xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos, 3, xCurrentHandler);
                  break;
                case ILOpCode.Code.Stloc_0:
                  xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos, 0, xCurrentHandler);
                  break;
                case ILOpCode.Code.Stloc_1:
                  xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos, 1, xCurrentHandler);
                  break;
                case ILOpCode.Code.Stloc_2:
                  xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos, 2, xCurrentHandler);
                  break;
                case ILOpCode.Code.Stloc_3:
                  xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos, 3, xCurrentHandler);
                  break;
                default:
                  xILOpCode = new ILOpCodes.OpNone(xOpCodeVal, xOpPos, xPos, xCurrentHandler);
                  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 ILOpCode.Code.Beq_S:
                            xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Beq, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                        case ILOpCode.Code.Bge_S:
                            xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bge, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                        case ILOpCode.Code.Bge_Un_S:
                            xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bge_Un, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                        case ILOpCode.Code.Bgt_S:
                            xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bgt, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                        case ILOpCode.Code.Bgt_Un_S:
                            xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bgt_Un, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                        case ILOpCode.Code.Ble_S:
                            xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Ble, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                        case ILOpCode.Code.Ble_Un_S:
                            xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Ble_Un, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                        case ILOpCode.Code.Blt_S:
                            xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Blt, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                        case ILOpCode.Code.Blt_Un_S:
                            xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Blt_Un, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                        case ILOpCode.Code.Bne_Un_S:
                            xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bne_Un, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                        case ILOpCode.Code.Br_S:
                            xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Br, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                        case ILOpCode.Code.Brfalse_S:
                            xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Brfalse, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                        case ILOpCode.Code.Brtrue_S:
                            xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Brtrue, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                        case ILOpCode.Code.Leave_S:
                            xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Leave, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                        default:
                            xILOpCode = new ILOpCodes.OpBranch(xOpCodeVal, xOpPos, xPos + 1, xTarget, xCurrentHandler);
                            break;
                    }
                    xPos = xPos + 1;
                    break;
                    #endregion
                }
          case OperandType.InlineBrTarget: {
              int xTarget = xPos + 4 + ReadInt32(xIL, xPos);
              CheckBranch(xTarget, xIL.Length);
              xILOpCode = new ILOpCodes.OpBranch(xOpCodeVal, xOpPos, xPos + 4, xTarget, xCurrentHandler);
              xPos = xPos + 4;
              break;
            }

          case OperandType.ShortInlineI:
            switch (xOpCodeVal) {
              case ILOpCode.Code.Ldc_I4_S:
                    xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos + 1, ((sbyte)xIL[xPos]), xCurrentHandler);
                break;
              default:
                xILOpCode = new ILOpCodes.OpInt(xOpCodeVal, xOpPos, xPos + 1, ((sbyte)xIL[xPos]), xCurrentHandler);
                break;
            }
            xPos = xPos + 1;
            break;
          case OperandType.InlineI:
            xILOpCode = new ILOpCodes.OpInt(xOpCodeVal, xOpPos, xPos + 4, ReadInt32(xIL, xPos), xCurrentHandler);
            xPos = xPos + 4;
            break;
          case OperandType.InlineI8:
            xILOpCode = new ILOpCodes.OpInt64(xOpCodeVal, xOpPos, xPos + 8, ReadUInt64(xIL, xPos), xCurrentHandler);
            xPos = xPos + 8;
            break;

          case OperandType.ShortInlineR:
            xILOpCode = new ILOpCodes.OpSingle(xOpCodeVal, xOpPos, xPos + 4, BitConverter.ToSingle(xIL, xPos), xCurrentHandler);
            xPos = xPos + 4;
            break;
          case OperandType.InlineR:
            xILOpCode = new ILOpCodes.OpDouble(xOpCodeVal, xOpPos, xPos + 8, BitConverter.ToDouble(xIL, xPos), xCurrentHandler);
            xPos = xPos + 8;
            break;

          // The operand is a 32-bit metadata token.
          case OperandType.InlineField: {
              var xValue = aMethod.Module.ResolveField(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 xValue = aMethod.Module.ResolveMethod(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:
            xILOpCode = new ILOpCodes.OpSig(xOpCodeVal, xOpPos, xPos + 4, ReadInt32(xIL, xPos), xCurrentHandler);
            xPos = xPos + 4;
            break;

          case OperandType.InlineString:
            xILOpCode = new ILOpCodes.OpString(xOpCodeVal, xOpPos, xPos + 4, aMethod.Module.ResolveString(ReadInt32(xIL, xPos)), xCurrentHandler);
            xPos = xPos + 4;
            break;

          case OperandType.InlineSwitch: {
              int xCount = ReadInt32(xIL, xPos);
              xPos = xPos + 4;
              int xNextOpPos = xPos + xCount * 4;
              var xBranchLocations = new int[xCount];
              for (int i = 0; i < xCount; i++) {
                xBranchLocations[i] = xNextOpPos + ReadInt32(xIL, xPos + i * 4);
                CheckBranch(xBranchLocations[i], xIL.Length);
              }
              xILOpCode = new ILOpCodes.OpSwitch(xOpCodeVal, xOpPos, xNextOpPos, xBranchLocations, xCurrentHandler);
              xPos = xNextOpPos;
              break;
            }

          // The operand is a FieldRef, MethodRef, or TypeRef token.
          case OperandType.InlineTok:
              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: {
              var xValue = aMethod.Module.ResolveType(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 ILOpCode.Code.Ldloc_S:
                    xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos + 1, xIL[xPos], xCurrentHandler);
                break;
              case ILOpCode.Code.Ldloca_S:
                xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloca, xOpPos, xPos + 1, xIL[xPos], xCurrentHandler);
                break;
              case ILOpCode.Code.Ldarg_S:
                xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos + 1, xIL[xPos], xCurrentHandler);
                break;
              case ILOpCode.Code.Ldarga_S:
                xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarga, xOpPos, xPos + 1, xIL[xPos], xCurrentHandler);
                break;
              case ILOpCode.Code.Starg_S:
                xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Starg, xOpPos, xPos + 1, xIL[xPos], xCurrentHandler);
                break;
              case ILOpCode.Code.Stloc_S:
                xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos + 1, xIL[xPos], xCurrentHandler);
                break;
              default:
                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;
            break;

          default:
            throw new Exception("Unknown OperandType");
        }
        xILOpCode.InitStackAnalysis(aMethod);
        xResult.Add(xILOpCode);
      }
      return xResult;
    }
Beispiel #8
0
        public List <ILOpCode> ProcessMethod(MethodBase aMethod)
        {
            var xResult = new List <ILOpCode>();

            var xBody   = aMethod.GetMethodBody();
            var xModule = aMethod.Module;

            // Cache for use in field and method resolution
            Type[] xTypeGenArgs   = Type.EmptyTypes;
            Type[] xMethodGenArgs = Type.EmptyTypes;
            if (aMethod.DeclaringType.IsGenericType)
            {
                xTypeGenArgs = aMethod.DeclaringType.GetGenericArguments();
            }
            if (aMethod.IsGenericMethod)
            {
                xMethodGenArgs = aMethod.GetGenericArguments();
            }

            #region Unsafe Intrinsic

            if (aMethod.DeclaringType.FullName == "Internal.Runtime.CompilerServices.Unsafe")
            {
                var xUnsafeType   = Type.GetType("System.Runtime.CompilerServices.Unsafe, System.Runtime.CompilerServices.Unsafe");
                var xUnsafeMethod = xUnsafeType.GetMethods()
                                    .Where(
                    m => m.Name == aMethod.Name &&
                    m.GetGenericArguments().Length == aMethod.GetGenericArguments().Length &&
                    m.GetParameters().Length == aMethod.GetParameters().Length)
                                    .SingleOrDefault(
                    m =>
                {
                    var xParamTypes         = Array.ConvertAll(m.GetParameters(), p => p.ParameterType);
                    var xOriginalParamTypes = Array.ConvertAll(
                        ((MethodInfo)aMethod).GetParameters(), p => p.ParameterType);

                    for (int i = 0; i < xParamTypes.Length; i++)
                    {
                        var xParamType         = xParamTypes[i];
                        var xOriginalParamType = xOriginalParamTypes[i];

                        while (xParamType.HasElementType)
                        {
                            if (!xOriginalParamType.HasElementType)
                            {
                                return(false);
                            }

                            if ((xParamType.IsArray && !xOriginalParamType.IsArray) ||
                                (xParamType.IsByRef && !xOriginalParamType.IsByRef) ||
                                (xParamType.IsPointer && !xOriginalParamType.IsPointer))
                            {
                                return(false);
                            }

                            xParamType         = xParamType.GetElementType();
                            xOriginalParamType = xOriginalParamType.GetElementType();
                        }

                        if (!xParamType.IsAssignableFrom(xOriginalParamType) &&
                            (!xParamType.IsGenericParameter || (xParamType.HasElementType && !xParamType.IsArray)))
                        {
                            return(false);
                        }
                    }

                    return(true);
                });

                if (xUnsafeMethod != null)
                {
                    xBody   = xUnsafeMethod.GetMethodBody();
                    xModule = xUnsafeMethod.Module;
                }
            }

            #endregion


            #region ByReference Intrinsic

            if (aMethod.DeclaringType.IsGenericType &&
                aMethod.DeclaringType.GetGenericTypeDefinition().FullName == "System.ByReference`1")
            {
                var valueField = aMethod.DeclaringType.GetField("_value", BindingFlags.Instance | BindingFlags.NonPublic);

                switch (aMethod.Name)
                {
                case ".ctor":

                    // push $this
                    xResult.Add(new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, 0, 1, 0, null));

                    // push value (arg 1)
                    xResult.Add(new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, 1, 2, 1, null));

                    // store value into $this._value
                    xResult.Add(new ILOpCodes.OpField(ILOpCode.Code.Stfld, 2, 8, valueField, null));

                    // return
                    xResult.Add(new ILOpCodes.OpNone(ILOpCode.Code.Ret, 8, 9, null));

                    break;

                case "get_Value":

                    // push $this
                    xResult.Add(new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, 0, 1, 0, null));

                    // push $this._value
                    xResult.Add(new ILOpCodes.OpField(ILOpCode.Code.Ldfld, 1, 6, valueField, null));

                    // return
                    xResult.Add(new ILOpCodes.OpNone(ILOpCode.Code.Ret, 6, 7, null));

                    break;

                default:
                    throw new NotImplementedException($"ByReference intrinsic method '{aMethod}' not implemented!");
                }

                foreach (var op in xResult)
                {
                    op.InitStackAnalysis(aMethod);
                }

                return(xResult);
            }

            #endregion

            #region RuntimeTypeHandle

            if (aMethod.DeclaringType.Name == "RuntimeType")
            {
                if (aMethod.Name == ".ctor")
                {
                    var op = new ILOpCodes.OpNone(ILOpCode.Code.Ret, 0, 1, null);
                    op.InitStackAnalysis(aMethod);

                    xResult.Add(op);

                    return(xResult);
                }
            }

            if (aMethod.DeclaringType.Name == "TypeImpl")
            {
                if (aMethod.Name == "CreateRuntimeTypeHandle")
                {
                    // the idea of this method is to first create a RuntimeType object, set its handle and then create a RuntimeTypeHandle from it
                    // we are manually coding in il here since we have to call a internal method on an internal class
                    var runtimeType = Type.GetType("System.RuntimeType");
                    var ctor        = runtimeType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] {  }, null);
                    xResult.Add(new ILOpCodes.OpMethod(ILOpCode.Code.Newobj, 0, 1, ctor, null)
                    {
                        StackPopTypes  = Array.Empty <Type>(),
                        StackPushTypes = new[] { runtimeType },
                    });
                    xResult.Add(new ILOpCodes.OpNone(ILOpCode.Code.Dup, 1, 2, null)
                    {
                        StackPopTypes  = new[] { runtimeType },
                        StackPushTypes = new[] { runtimeType, runtimeType }
                    });
                    xResult.Add(new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, 2, 3, 0, null)
                    {
                        StackPopTypes  = Array.Empty <Type>(),
                        StackPushTypes = new[] { typeof(int) },
                    });
                    var m_handle = runtimeType.GetField("m_handle", BindingFlags.Instance | BindingFlags.NonPublic);
                    xResult.Add(new ILOpCodes.OpField(ILOpCode.Code.Stfld, 3, 4, m_handle, null)
                    {
                        StackPopTypes  = new[] { typeof(int), runtimeType },
                        StackPushTypes = Array.Empty <Type>(),
                    });
                    var runtimeTypeHandle = Type.GetType("System.RuntimeTypeHandle");
                    ctor = runtimeTypeHandle.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { runtimeType }, null);
                    xResult.Add(new ILOpCodes.OpMethod(ILOpCode.Code.Newobj, 4, 5, ctor, null)
                    {
                        StackPopTypes  = new[] { runtimeType },
                        StackPushTypes = new[] { runtimeTypeHandle },
                    });
                    xResult.Add(new ILOpCodes.OpNone(ILOpCode.Code.Ret, 5, 6, null)
                    {
                        StackPopTypes  = Array.Empty <Type>(),
                        StackPushTypes = Array.Empty <Type>(),
                    });

                    return(xResult);
                }
            }
            #endregion

            #region ArrayPool ("hacked" generic plug)

            if (aMethod.DeclaringType.IsGenericType &&
                aMethod.DeclaringType.GetGenericTypeDefinition().FullName == "System.Buffers.ArrayPool`1")
            {
                if (aMethod.Name == ".cctor")
                {
                    var op = new ILOpCodes.OpNone(ILOpCode.Code.Ret, 0, 1, null);
                    op.InitStackAnalysis(aMethod);

                    xResult.Add(op);

                    return(xResult);
                }
            }

            #endregion

            #region RuntimeHelpers

            if (aMethod.DeclaringType.FullName == "System.Runtime.CompilerServices.RuntimeHelpers")
            {
                if (aMethod.Name == "IsBitwiseEquatable")
                {
                    // This is a generic method so we emit true or false depending on the type
                    ILOpCode op;
                    if (ILOp.IsIntegralTypeOrPointer(xMethodGenArgs[0]))
                    {
                        op = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, 0, 1, 1, null);
                    }
                    else
                    {
                        op = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, 0, 1, 1, null);
                    }
                    op.InitStackAnalysis(aMethod);
                    xResult.Add(op);

                    op = new ILOpCodes.OpNone(ILOpCode.Code.Ret, 1, 2, null);
                    op.InitStackAnalysis(aMethod);

                    xResult.Add(op);

                    return(xResult);
                }
            }

            #endregion

            // Some methods return no body. Not sure why.. have to investigate
            // They arent abstracts or icalls...
            if (xBody == null)
            {
                return(null);
            }

            var xIL  = xBody.GetILAsByteArray();
            int xPos = 0;
            while (xPos < xIL.Length)
            {
                _ExceptionRegionInfo xCurrentExceptionRegion = null;
                #region Determine current handler
                // todo: add support for nested handlers using a stack or so..
                foreach (_ExceptionRegionInfo xHandler in aMethod.GetExceptionRegionInfos())
                {
                    if (xHandler.TryOffset >= 0)
                    {
                        if (xHandler.TryOffset <= xPos && (xHandler.TryLength + xHandler.TryOffset) > xPos)
                        {
                            if (xCurrentExceptionRegion == null)
                            {
                                xCurrentExceptionRegion = xHandler;
                                continue;
                            }
                            else if (xHandler.TryOffset > xCurrentExceptionRegion.TryOffset && (xHandler.TryLength + xHandler.TryOffset) < (xCurrentExceptionRegion.TryLength + xCurrentExceptionRegion.TryOffset))
                            {
                                // only replace if the current found handler is narrower
                                xCurrentExceptionRegion = xHandler;
                                continue;
                            }
                        }
                    }
                    // todo: handler offset can be 0 like try offset?
                    if (xHandler.HandlerOffset > 0)
                    {
                        if (xHandler.HandlerOffset <= xPos && (xHandler.HandlerOffset + xHandler.HandlerLength) > xPos)
                        {
                            if (xCurrentExceptionRegion == null)
                            {
                                xCurrentExceptionRegion = xHandler;
                                continue;
                            }
                            else if (xHandler.HandlerOffset > xCurrentExceptionRegion.HandlerOffset && (xHandler.HandlerOffset + xHandler.HandlerLength) < (xCurrentExceptionRegion.HandlerOffset + xCurrentExceptionRegion.HandlerLength))
                            {
                                // only replace if the current found handler is narrower
                                xCurrentExceptionRegion = xHandler;
                                continue;
                            }
                        }
                    }
                    if (xHandler.Kind.HasFlag(ExceptionRegionKind.Filter))
                    {
                        if (xHandler.FilterOffset > 0)
                        {
                            if (xHandler.FilterOffset <= xPos)
                            {
                                if (xCurrentExceptionRegion == null)
                                {
                                    xCurrentExceptionRegion = xHandler;
                                    continue;
                                }
                                else if (xHandler.FilterOffset > xCurrentExceptionRegion.FilterOffset)
                                {
                                    // only replace if the current found handler is narrower
                                    xCurrentExceptionRegion = xHandler;
                                    continue;
                                }
                            }
                        }
                    }
                }
                #endregion
                ILOpCode.Code xOpCodeVal;
                OpCode        xOpCode;
                int           xOpPos = xPos;
                if (xIL[xPos] == 0xFE)
                {
                    xOpCodeVal = (ILOpCode.Code)(0xFE00 | xIL[xPos + 1]);
                    xOpCode    = mOpCodesHi[xIL[xPos + 1]];
                    xPos       = xPos + 2;
                }
                else
                {
                    xOpCodeVal = (ILOpCode.Code)xIL[xPos];
                    xOpCode    = mOpCodesLo[xIL[xPos]];
                    xPos++;
                }

                ILOpCode xILOpCode = null;
                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 ILOpCode.Code.Ldarg_0:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos, 0, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldarg_1:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos, 1, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldarg_2:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos, 2, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldarg_3:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos, 3, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_0:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 0, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_1:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 1, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_2:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 2, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_3:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 3, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_4:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 4, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_5:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 5, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_6:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 6, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_7:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 7, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_8:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, 8, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldc_I4_M1:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos, -1, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldloc_0:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos, 0, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldloc_1:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos, 1, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldloc_2:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos, 2, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldloc_3:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos, 3, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Stloc_0:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos, 0, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Stloc_1:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos, 1, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Stloc_2:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos, 2, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Stloc_3:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos, 3, xCurrentExceptionRegion);
                        break;

                    default:
                        xILOpCode = new ILOpCodes.OpNone(xOpCodeVal, xOpPos, xPos, xCurrentExceptionRegion);
                        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 ILOpCode.Code.Beq_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Beq, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Bge_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bge, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Bge_Un_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bge_Un, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Bgt_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bgt, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Bgt_Un_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bgt_Un, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ble_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Ble, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ble_Un_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Ble_Un, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Blt_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Blt, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Blt_Un_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Blt_Un, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Bne_Un_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Bne_Un, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Br_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Br, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Brfalse_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Brfalse, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Brtrue_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Brtrue, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Leave_S:
                        xILOpCode = new ILOpCodes.OpBranch(ILOpCode.Code.Leave, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;

                    default:
                        xILOpCode = new ILOpCodes.OpBranch(xOpCodeVal, xOpPos, xPos + 1, xTarget, xCurrentExceptionRegion);
                        break;
                    }
                    xPos = xPos + 1;
                    break;
                    #endregion
                }

                case OperandType.InlineBrTarget:
                {
                    int xTarget = xPos + 4 + ReadInt32(xIL, xPos);
                    CheckBranch(xTarget, xIL.Length);
                    xILOpCode = new ILOpCodes.OpBranch(xOpCodeVal, xOpPos, xPos + 4, xTarget, xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;
                }

                case OperandType.ShortInlineI:
                    switch (xOpCodeVal)
                    {
                    case ILOpCode.Code.Ldc_I4_S:
                        xILOpCode = new ILOpCodes.OpInt(ILOpCode.Code.Ldc_I4, xOpPos, xPos + 1, ((sbyte)xIL[xPos]), xCurrentExceptionRegion);
                        break;

                    default:
                        xILOpCode = new ILOpCodes.OpInt(xOpCodeVal, xOpPos, xPos + 1, ((sbyte)xIL[xPos]), xCurrentExceptionRegion);
                        break;
                    }
                    xPos = xPos + 1;
                    break;

                case OperandType.InlineI:
                    xILOpCode = new ILOpCodes.OpInt(xOpCodeVal, xOpPos, xPos + 4, ReadInt32(xIL, xPos), xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;

                case OperandType.InlineI8:
                    xILOpCode = new ILOpCodes.OpInt64(xOpCodeVal, xOpPos, xPos + 8, ReadUInt64(xIL, xPos), xCurrentExceptionRegion);
                    xPos      = xPos + 8;
                    break;

                case OperandType.ShortInlineR:
                    xILOpCode = new ILOpCodes.OpSingle(xOpCodeVal, xOpPos, xPos + 4, BitConverter.ToSingle(xIL, xPos), xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;

                case OperandType.InlineR:
                    xILOpCode = new ILOpCodes.OpDouble(xOpCodeVal, xOpPos, xPos + 8, BitConverter.ToDouble(xIL, xPos), xCurrentExceptionRegion);
                    xPos      = xPos + 8;
                    break;

                // The operand is a 32-bit metadata token.
                case OperandType.InlineField:
                {
                    var xValue = xModule.ResolveField(ReadInt32(xIL, xPos), xTypeGenArgs, xMethodGenArgs);
                    xILOpCode = new ILOpCodes.OpField(xOpCodeVal, xOpPos, xPos + 4, xValue, xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;
                }

                // The operand is a 32-bit metadata token.
                case OperandType.InlineMethod:
                {
                    var xValue = xModule.ResolveMethod(ReadInt32(xIL, xPos), xTypeGenArgs, xMethodGenArgs);
                    xILOpCode = new ILOpCodes.OpMethod(xOpCodeVal, xOpPos, xPos + 4, xValue, xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;
                }

                // 32-bit metadata signature token.
                case OperandType.InlineSig:
                    xILOpCode = new ILOpCodes.OpSig(xOpCodeVal, xOpPos, xPos + 4, ReadInt32(xIL, xPos), xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;

                case OperandType.InlineString:
                    xILOpCode = new ILOpCodes.OpString(xOpCodeVal, xOpPos, xPos + 4, xModule.ResolveString(ReadInt32(xIL, xPos)), xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;

                case OperandType.InlineSwitch:
                {
                    int xCount = ReadInt32(xIL, xPos);
                    xPos = xPos + 4;
                    int xNextOpPos       = xPos + xCount * 4;
                    var xBranchLocations = new int[xCount];
                    for (int i = 0; i < xCount; i++)
                    {
                        xBranchLocations[i] = xNextOpPos + ReadInt32(xIL, xPos + i * 4);
                        CheckBranch(xBranchLocations[i], xIL.Length);
                    }
                    xILOpCode = new ILOpCodes.OpSwitch(xOpCodeVal, xOpPos, xNextOpPos, xBranchLocations, xCurrentExceptionRegion);
                    xPos      = xNextOpPos;
                    break;
                }

                // The operand is a FieldRef, MethodRef, or TypeRef token.
                case OperandType.InlineTok:
                    xILOpCode = new ILOpCodes.OpToken(xOpCodeVal, xOpPos, xPos + 4, ReadInt32(xIL, xPos), xModule, xTypeGenArgs, xMethodGenArgs, xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;

                // 32-bit metadata token.
                case OperandType.InlineType:
                {
                    var xValue = xModule.ResolveType(ReadInt32(xIL, xPos), xTypeGenArgs, xMethodGenArgs);
                    xILOpCode = new ILOpCodes.OpType(xOpCodeVal, xOpPos, xPos + 4, xValue, xCurrentExceptionRegion);
                    xPos      = xPos + 4;
                    break;
                }

                case OperandType.ShortInlineVar:
                    switch (xOpCodeVal)
                    {
                    case ILOpCode.Code.Ldloc_S:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloc, xOpPos, xPos + 1, xIL[xPos], xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldloca_S:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldloca, xOpPos, xPos + 1, xIL[xPos], xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldarg_S:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarg, xOpPos, xPos + 1, xIL[xPos], xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Ldarga_S:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Ldarga, xOpPos, xPos + 1, xIL[xPos], xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Starg_S:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Starg, xOpPos, xPos + 1, xIL[xPos], xCurrentExceptionRegion);
                        break;

                    case ILOpCode.Code.Stloc_S:
                        xILOpCode = new ILOpCodes.OpVar(ILOpCode.Code.Stloc, xOpPos, xPos + 1, xIL[xPos], xCurrentExceptionRegion);
                        break;

                    default:
                        xILOpCode = new ILOpCodes.OpVar(xOpCodeVal, xOpPos, xPos + 1, xIL[xPos], xCurrentExceptionRegion);
                        break;
                    }
                    xPos = xPos + 1;
                    break;

                case OperandType.InlineVar:
                    xILOpCode = new ILOpCodes.OpVar(xOpCodeVal, xOpPos, xPos + 2, ReadUInt16(xIL, xPos), xCurrentExceptionRegion);
                    xPos      = xPos + 2;
                    break;

                default:
                    throw new Exception("Unknown OperandType");
                }
                xILOpCode.InitStackAnalysis(aMethod);
                xResult.Add(xILOpCode);
            }

            return(xResult);
        }