Beispiel #1
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            int       metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            FieldInfo theField      = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);

            bool valueisFloat = Utilities.IsFloat(theField.FieldType);

            Types.TypeInfo fieldTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theField.FieldType);
            int            stackSize     = fieldTypeInfo.SizeOnStackInBytes;

            StackItem objPointer = conversionState.CurrentStackFrame.Stack.Pop();

            if ((OpCodes)theOp.opCode.Value == OpCodes.Ldflda)
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat            = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged        = false
                });
            }
            else
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat            = valueisFloat,
                    sizeOnStackInBytes = stackSize,
                    isGCManaged        = fieldTypeInfo.IsGCManaged
                });
            }
        }
Beispiel #2
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            int       metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            FieldInfo theField      = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);

            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Ldsfld:
            {
                Types.TypeInfo theTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theField.FieldType);
                int            size        = theTypeInfo.SizeOnStackInBytes;
                bool           isFloat     = Utilities.IsFloat(theField.FieldType);

                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = isFloat,
                        sizeOnStackInBytes = (size == 8 ? 8 : 4),
                        isGCManaged        = theTypeInfo.IsGCManaged,
                        isValue            = theTypeInfo.IsValueType
                    });
            }
            break;

            case OpCodes.Ldsflda:
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat            = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged        = false,
                    isValue            = false
                });
                break;
            }
        }
Beispiel #3
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            MethodBase methodToCall = theOp.MethodToCall;

            Types.MethodInfo methodToCallInfo = conversionState.TheILLibrary.GetMethodInfo(methodToCall);

            if (methodToCall is MethodInfo)
            {
                Type           retType     = ((MethodInfo)methodToCall).ReturnType;
                Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                StackItem      returnItem  = new StackItem()
                {
                    isFloat            = Utilities.IsFloat(retType),
                    sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                    isGCManaged        = retTypeInfo.IsGCManaged,
                    isValue            = retTypeInfo.IsValueType
                };

                int         bytesToAdd = 0;
                List <Type> allParams  = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();
                if (!methodToCall.IsStatic)
                {
                    allParams.Insert(0, methodToCall.DeclaringType);
                }
                foreach (Type aParam in allParams)
                {
                    conversionState.CurrentStackFrame.Stack.Pop();
                    bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                }
                if (bytesToAdd > 0)
                {
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);
                    }
                }
                else if (returnItem.sizeOnStackInBytes != 0)
                {
                    conversionState.CurrentStackFrame.Stack.Push(returnItem);
                }
            }
            else if (methodToCall is ConstructorInfo)
            {
                ConstructorInfo aConstructor = (ConstructorInfo)methodToCall;
                if (aConstructor.IsStatic)
                {
                    //Static constructors do not have parameters or return values
                }
                else
                {
                    ParameterInfo[] allParams = methodToCall.GetParameters();
                    foreach (ParameterInfo aParam in allParams)
                    {
                        conversionState.CurrentStackFrame.Stack.Pop();
                    }
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Scans the specified type's non-static fields.
        /// </summary>
        /// <param name="TheLibrary">The library currently being compiled.</param>
        /// <param name="TheTypeInfo">The type to scan the non-static fields of.</param>
        /// <param name="FieldTablesBlock">The ASM block for the fields table for the library currently being compiled.</param>
        private static void ScanFields(ILLibrary TheLibrary, Types.TypeInfo TheTypeInfo, ASM.ASMBlock FieldTablesBlock)
        {
            string currentTypeId   = TheTypeInfo.ID;
            string currentTypeName = TheTypeInfo.UnderlyingType.FullName;
            List <Tuple <string, string, string> > AllFieldInfo = new List <Tuple <string, string, string> >();

            if (TheTypeInfo.UnderlyingType.BaseType == null || (TheTypeInfo.UnderlyingType.BaseType.FullName != "System.Array" &&
                                                                TheTypeInfo.UnderlyingType.BaseType.FullName != "System.MulticastDelegate"))
            {
                foreach (Types.FieldInfo anOwnField in TheTypeInfo.FieldInfos)
                {
                    if (!anOwnField.IsStatic)
                    {
                        Types.TypeInfo FieldTypeInfo = TheLibrary.GetTypeInfo(anOwnField.FieldType);

                        string fieldOffsetVal = anOwnField.OffsetInBytes.ToString();
                        string fieldSizeVal   = (FieldTypeInfo.IsValueType ? FieldTypeInfo.SizeOnHeapInBytes : FieldTypeInfo.SizeOnStackInBytes).ToString();
                        string fieldTypeIdVal = FieldTypeInfo.ID;

                        FieldTablesBlock.AddExternalLabel(fieldTypeIdVal);
                        AllFieldInfo.Add(new Tuple <string, string, string>(fieldOffsetVal, fieldSizeVal, fieldTypeIdVal));
                    }
                }
            }

            string parentTypeFieldTablePtr = "0";
            bool   parentPtrIsExternal     = false;

            if (TheTypeInfo.UnderlyingType.BaseType != null)
            {
                if (!TheTypeInfo.UnderlyingType.BaseType.AssemblyQualifiedName.Contains("mscorlib"))
                {
                    Types.TypeInfo baseTypeInfo = TheLibrary.GetTypeInfo(TheTypeInfo.UnderlyingType.BaseType);
                    parentPtrIsExternal = (ScannedTypes.ContainsKey(baseTypeInfo.ID) &&
                                           ScannedTypes[baseTypeInfo.ID] != TheLibrary) || !TheLibrary.TypeInfos.Contains(baseTypeInfo);
                    parentTypeFieldTablePtr = baseTypeInfo.ID + "_FieldTable";
                }
            }
            {
                string fieldOffsetVal = "0";
                string fieldSizeVal   = "0";
                string fieldTypeIdVal = parentTypeFieldTablePtr;

                if (parentPtrIsExternal)
                {
                    FieldTablesBlock.AddExternalLabel(fieldTypeIdVal);
                }

                AllFieldInfo.Add(new Tuple <string, string, string>(fieldOffsetVal, fieldSizeVal, fieldTypeIdVal));
            }

            List <Tuple <string, int> > TableEntryFieldInfos = GetSpecialClassFieldInfo(TheLibrary, typeof(Attributes.FieldInfoStructAttribute));

            ASM.ASMOp newFieldTableOp = TargetArchitecture.CreateASMOp(ASM.OpCodes.FieldTable,
                                                                       currentTypeId, currentTypeName, AllFieldInfo, TableEntryFieldInfos);
            FieldTablesBlock.Append(newFieldTableOp);
        }
Beispiel #5
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if the value to store is floating point or
        /// if the value is not 4 or 8 bytes in size.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            int       metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            FieldInfo theField      = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);

            Types.TypeInfo  objTypeInfo   = conversionState.TheILLibrary.GetTypeInfo(theField.DeclaringType);
            Types.TypeInfo  fieldTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theField.FieldType);
            Types.FieldInfo theFieldInfo  = conversionState.TheILLibrary.GetFieldInfo(objTypeInfo, theField.Name);


            int offset = theFieldInfo.OffsetInBytes;

            int stackSize = fieldTypeInfo.SizeOnStackInBytes;
            int memSize   = fieldTypeInfo.IsValueType ? fieldTypeInfo.SizeOnHeapInBytes : stackSize;

            StackItem value      = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem objPointer = conversionState.CurrentStackFrame.Stack.Pop();

            if (value.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Storing fields of type float not supported yet!");
            }

            //Get object pointer
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = stackSize.ToString() + "($sp)", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //Pop and mov value
            for (int i = 0; i < memSize; i += 2)
            {
                if (memSize - i == 1)
                {
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Halfword, Dest = "$t0"
                    });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = "$t0", Dest = (offset + i).ToString() + "($t2)" });
                    GlobalMethods.StoreData(conversionState, theOp, "$t2", "$t0", (offset + i), 1);
                }
                else
                {
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Halfword, Dest = "$t0"
                    });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = (offset + i).ToString() + "($t2)" });
                    GlobalMethods.StoreData(conversionState, theOp, "$t2", "$t0", (offset + i), 2);
                }
            }
            //                                                           Rounds down             || Pop object pointer
            conversionState.Append(new ASMOps.Add()
            {
                Src1 = "$sp", Src2 = ((((stackSize - memSize) / 2) * 2) + 4).ToString(), Dest = "$sp"
            });
        }
Beispiel #6
0
        /// <summary>
        /// Scans the specified type's methods.
        /// </summary>
        /// <param name="TheLibrary">The library currently being compiled.</param>
        /// <param name="TheTypeInfo">The type to scan the methods of.</param>
        /// <param name="MethodTablesBlock">The ASM block for the methods table for the library currently being compiled.</param>
        private static void ScanMethods(ILLibrary TheLibrary, Types.TypeInfo TheTypeInfo, ASM.ASMBlock MethodTablesBlock)
        {
            string currentTypeId   = TheTypeInfo.ID;
            string currentTypeName = TheTypeInfo.UnderlyingType.FullName;

            List <Tuple <string, string> > AllMethodInfo = new List <Tuple <string, string> >();

            if (TheTypeInfo.UnderlyingType.BaseType == null || TheTypeInfo.UnderlyingType.BaseType.FullName != "System.Array")
            {
                foreach (Types.MethodInfo aMethodInfo in TheTypeInfo.MethodInfos)
                {
                    if (!aMethodInfo.IsStatic && !aMethodInfo.UnderlyingInfo.IsAbstract)
                    {
                        string methodID      = aMethodInfo.ID;
                        string methodIDValue = aMethodInfo.IDValue.ToString();

                        MethodTablesBlock.AddExternalLabel(methodID);

                        AllMethodInfo.Add(new Tuple <string, string>(methodID, methodIDValue));
                    }
                }
            }

            string parentTypeMethodTablePtr = "0";
            bool   parentPtrIsExternal      = false;

            if (TheTypeInfo.UnderlyingType.BaseType != null)
            {
                if (!TheTypeInfo.UnderlyingType.BaseType.AssemblyQualifiedName.Contains("mscorlib"))
                {
                    Types.TypeInfo baseTypeInfo = TheLibrary.GetTypeInfo(TheTypeInfo.UnderlyingType.BaseType);
                    parentPtrIsExternal = (ScannedTypes.ContainsKey(baseTypeInfo.ID) && ScannedTypes[baseTypeInfo.ID] != TheLibrary) ||
                                          !TheLibrary.TypeInfos.Contains(baseTypeInfo);
                    parentTypeMethodTablePtr = baseTypeInfo.ID + "_MethodTable";
                }
            }
            {
                string methodID      = parentTypeMethodTablePtr;
                string methodIDValue = "0";

                if (parentPtrIsExternal)
                {
                    MethodTablesBlock.AddExternalLabel(methodID);
                }

                AllMethodInfo.Add(new Tuple <string, string>(methodID, methodIDValue));
            }

            List <Tuple <string, int> > TableEntryFieldInfos = GetSpecialClassFieldInfo(TheLibrary, typeof(Attributes.MethodInfoStructAttribute));

            ASM.ASMOp newMethodTableOp = TargetArchitecture.CreateASMOp(ASM.OpCodes.MethodTable,
                                                                        currentTypeId, currentTypeName, AllMethodInfo, TableEntryFieldInfos);
            MethodTablesBlock.Append(newMethodTableOp);
        }
Beispiel #7
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            Type retType = (conversionState.Input.TheMethodInfo.IsConstructor ?
                            typeof(void) : ((MethodInfo)conversionState.Input.TheMethodInfo.UnderlyingInfo).ReturnType);

            Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
            if (retTypeInfo.SizeOnStackInBytes != 0)
            {
                conversionState.CurrentStackFrame.Stack.Pop();
            }
        }
Beispiel #8
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown when loading a static float field.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Load static field

            //Load the metadata token used to get the type info
            int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            //Get the type info for the object to load
            Type theType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);

            Types.TypeInfo theTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theType);

            //Get the object size information
            int size = theTypeInfo.SizeOnStackInBytes;

            //Load the object onto the stack
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Dword, Dest = "ECX"
            });
            for (int i = size - 4; i >= 0; i -= 4)
            {
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "[ECX+" + i.ToString() + "]", Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "EAX"
                });
            }
            int extra = size % 4;

            for (int i = extra - 1; i >= 0; i--)
            {
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Byte, Src = "[ECX+" + i.ToString() + "]", Dest = "AL"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Byte, Src = "AL"
                });
            }

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = false,
                sizeOnStackInBytes = size,
                isGCManaged        = false
            });
        }
Beispiel #9
0
        private static List <Tuple <string, int> > GetSpecialClassFieldInfo(ILLibrary TheLibrary, Type SpecialClassType)
        {
            Types.TypeInfo              InformationAboutInfoStruct         = ILLibrary.SpecialClasses[SpecialClassType].First();
            List <Types.FieldInfo>      InfoStruct_OrderedFields           = InformationAboutInfoStruct.FieldInfos.Where(x => !x.IsStatic).OrderBy(x => x.OffsetInBytes).ToList();
            List <Tuple <string, int> > InfoStruct_OrderedFieldInfo_Subset = new List <Tuple <string, int> >();

            foreach (Types.FieldInfo aField in InfoStruct_OrderedFields)
            {
                Types.TypeInfo FieldTypeInfo = TheLibrary.GetTypeInfo(aField.FieldType);
                InfoStruct_OrderedFieldInfo_Subset.Add(new Tuple <string, int>(aField.Name,
                                                                               FieldTypeInfo.IsValueType ? FieldTypeInfo.SizeOnHeapInBytes : FieldTypeInfo.SizeOnStackInBytes));
            }
            return(InfoStruct_OrderedFieldInfo_Subset);
        }
Beispiel #10
0
        /// <summary>
        /// Scans the specified type (excludes fields and methods).
        /// </summary>
        /// <param name="TheLibrary">The library currently being compiled.</param>
        /// <param name="TheTypeInfo">The type to scan.</param>
        /// <param name="TypesTableBlock">The ASM block for the types table for the library currently being compiled.</param>
        private static void ScanType(ILLibrary TheLibrary, Types.TypeInfo TheTypeInfo, ASM.ASMBlock TypesTableBlock)
        {
            string TypeId             = TheTypeInfo.ID;
            string SizeVal            = TheTypeInfo.SizeOnHeapInBytes.ToString();
            string IdVal              = (TypesScanned++).ToString();
            string StackSizeVal       = TheTypeInfo.SizeOnStackInBytes.ToString();
            string IsValueTypeVal     = (TheTypeInfo.IsValueType ? "1" : "0");
            string MethodTablePointer = TypeId + "_MethodTable";
            string IsPointerTypeVal   = (TheTypeInfo.IsPointer ? "1" : "0");
            string BaseTypeIdVal      = "0";

            if (TheTypeInfo.UnderlyingType.BaseType != null)
            {
                if (!TheTypeInfo.UnderlyingType.BaseType.AssemblyQualifiedName.Contains("mscorlib"))
                {
                    Types.TypeInfo baseTypeInfo = TheLibrary.GetTypeInfo(TheTypeInfo.UnderlyingType.BaseType);
                    BaseTypeIdVal = baseTypeInfo.ID;
                    //Declared external to this library, so won't appear in this library's type tables
                    if ((ScannedTypes.ContainsKey(baseTypeInfo.ID) &&
                         ScannedTypes[baseTypeInfo.ID] != TheLibrary) ||
                        !TheLibrary.TypeInfos.Contains(baseTypeInfo))
                    {
                        TypesTableBlock.AddExternalLabel(BaseTypeIdVal);
                    }
                }
            }
            string FieldTablePointer         = TypeId + "_FieldTable";
            string TypeSignatureLiteralLabel = TheLibrary.AddStringLiteral(TheTypeInfo.UnderlyingType.FullName); // Legacy
            string TypeIdLiteralLabel        = TheLibrary.AddStringLiteral(TheTypeInfo.ID);

            Types.TypeInfo         typeTypeInfo  = ILLibrary.SpecialClasses[typeof(Attributes.TypeClassAttribute)].First();
            List <Types.FieldInfo> OrderedFields = typeTypeInfo.FieldInfos.Where(x => !x.IsStatic).OrderBy(x => x.OffsetInBytes).ToList();
            List <Tuple <string, Types.TypeInfo> > FieldInformation = new List <Tuple <string, Types.TypeInfo> >();

            foreach (Types.FieldInfo aTypeField in OrderedFields)
            {
                Types.TypeInfo FieldTypeInfo = TheLibrary.GetTypeInfo(aTypeField.FieldType);
                FieldInformation.Add(new Tuple <string, Types.TypeInfo>(aTypeField.Name, FieldTypeInfo));
            }

            ASM.ASMOp newTypeTableOp = TargetArchitecture.CreateASMOp(ASM.OpCodes.TypeTable,
                                                                      TypeId, SizeVal, IdVal, StackSizeVal, IsValueTypeVal, MethodTablePointer, IsPointerTypeVal,
                                                                      BaseTypeIdVal, FieldTablePointer, TypeSignatureLiteralLabel, TypeIdLiteralLabel, FieldInformation);
            TypesTableBlock.Append(newTypeTableOp);

            TypesTableBlock.AddExternalLabel(MethodTablePointer);
            TypesTableBlock.AddExternalLabel(FieldTablePointer);
            TypesTableBlock.AddExternalLabel(TypeSignatureLiteralLabel);
            TypesTableBlock.AddExternalLabel(TypeIdLiteralLabel);
        }
Beispiel #11
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            int  metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            Type theType       = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);

            Types.TypeInfo theTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theType);
            int            size        = theTypeInfo.SizeOnStackInBytes;

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = false,
                sizeOnStackInBytes = size,
                isGCManaged        = false
            });
        }
Beispiel #12
0
        /// <summary>
        /// Scans the specified type's static fields.
        /// </summary>
        /// <param name="TheLibrary">The library currently being compiled.</param>
        /// <param name="TheTypeInfo">The type to scan the static fields of.</param>
        /// <param name="StaticFieldsBlock">The ASM block for the static fields for the library currently being compiled.</param>
        private static void ScanStaticFields(ILLibrary TheLibrary, Types.TypeInfo TheTypeInfo, ASM.ASMBlock StaticFieldsBlock)
        {
            foreach (Types.FieldInfo aFieldInfo in TheTypeInfo.FieldInfos)
            {
                if (aFieldInfo.IsStatic)
                {
                    Types.TypeInfo fieldTypeInfo = TheLibrary.GetTypeInfo(aFieldInfo.FieldType);

                    string FieldID = aFieldInfo.ID;
                    string Size    = fieldTypeInfo.SizeOnStackInBytes.ToString();

                    ASM.ASMOp newStaticFieldOp = TargetArchitecture.CreateASMOp(ASM.OpCodes.StaticField, FieldID, Size);
                    StaticFieldsBlock.Append(newStaticFieldOp);
                }
            }
        }
Beispiel #13
0
        /// <summary>
        /// Gets the type info for the specified actual type.
        /// </summary>
        /// <param name="theType">The type to get type info for.</param>
        /// <param name="topLevel">Whether to search the library's dependencies or not. Faslse to search dependencies.</param>
        /// <param name="FullyProcess">Default: true.
        /// Should only be set to false by the TypeScanner.
        /// Used to prevent reentrancy (/circular) processing within the type scanner.
        /// </param>
        /// <returns>The type info or null if not found.</returns>
        private Types.TypeInfo GetTypeInfo(Type theType, bool topLevel, bool FullyProcess)
        {
            foreach (Types.TypeInfo aTypeInfo in TypeInfos)
            {
                if (aTypeInfo.UnderlyingType.Equals(theType))
                {
                    return(aTypeInfo);
                }
            }

            foreach (ILLibrary depLib in Dependencies)
            {
                Types.TypeInfo result = depLib.GetTypeInfo(theType, false, FullyProcess);
                if (result != null)
                {
                    return(result);
                }
            }

            if (topLevel)
            {
                Types.TypeInfo theTypeInfo = Types.TypeScanner.ScanType(this, theType);
                if (FullyProcess)
                {
                    int count = 0;
                    do
                    {
                        count = TypeInfos.Count;
                        int start = count - 1;
                        for (int i = start; i < count; i++)
                        {
                            Types.TypeScanner.ProcessType(this, TypeInfos[i]);
                        }
                        for (int i = start; i < count; i++)
                        {
                            Types.TypeScanner.ProcessTypeFields(this, TypeInfos[i]);
                        }
                    }while (count < TypeInfos.Count);
                }
                return(theTypeInfo);
            }
            else
            {
                return(null);
            }
        }
Beispiel #14
0
        /// <summary>
        /// Gets the field info for the specified field from the specified type.
        /// </summary>
        /// <param name="aTypeInfo">The type to get the field from.</param>
        /// <param name="FieldName">The name of the field to get info for.</param>
        /// <returns>The field info.</returns>
        /// <exception cref="System.NullReferenceException">Thrown if the field is not found.</exception>
        public Types.FieldInfo GetFieldInfo(Types.TypeInfo aTypeInfo, string FieldName)
        {
            foreach (Types.FieldInfo aFieldInfo in aTypeInfo.FieldInfos)
            {
                if (aFieldInfo.Name.Equals(FieldName))
                {
                    return(aFieldInfo);
                }
            }

            if (aTypeInfo.UnderlyingType.BaseType != null &&
                !aTypeInfo.UnderlyingType.AssemblyQualifiedName.Contains("mscorlib"))
            {
                Types.TypeInfo baseTypeInfo = GetTypeInfo(aTypeInfo.UnderlyingType.BaseType);
                return(GetFieldInfo(baseTypeInfo, FieldName));
            }

            throw new NullReferenceException("Field \"" + FieldName + "\" not found in type \"" + aTypeInfo.ToString() + "\".");
        }
Beispiel #15
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            int  metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            Type theType       = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);

            Types.TypeInfo theTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theType);
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Dword,
                Src  = (theTypeInfo.IsValueType ? theTypeInfo.SizeOnHeapInBytes : theTypeInfo.SizeOnStackInBytes).ToString()
            });

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = false,
                sizeOnStackInBytes = 4,
                isGCManaged        = false
            });
        }
Beispiel #16
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown when loading a static float field.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Load the metadata token used to get the type info
            int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            //Get the type info for the object to load
            Type theType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);

            Types.TypeInfo theTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theType);

            //Get the object size information
            int size = theTypeInfo.IsValueType ? theTypeInfo.SizeOnHeapInBytes : theTypeInfo.SizeOnStackInBytes;

            conversionState.CurrentStackFrame.Stack.Pop();
            conversionState.CurrentStackFrame.Stack.Pop();

            //Load the object onto the stack
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Dest = "ECX", Src = "[ESP+" + theTypeInfo.SizeOnStackInBytes + "]"
            });
            if (size == 1)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Byte, Src = "AL", Dest = "[ECX]"
                });
            }
            else if (size == 2)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "AX", Dest = "[ECX]"
                });
            }
            else if (size >= 4)
            {
                for (int i = 0; i < size; i += 4)
                {
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });

                    switch (size - i)
                    {
                    case 1:
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Byte, Src = "AL", Dest = "[ECX+" + i + "]"
                        });
                        break;

                    case 2:
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "AX", Dest = "[ECX+" + i + "]"
                        });
                        break;

                    case 3:
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Byte, Src = "AL", Dest = "[ECX+" + i + "]"
                        });
                        conversionState.Append(new ASMOps.Shr()
                        {
                            Src = "16", Dest = "EAX"
                        });
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "AX", Dest = "[ECX+" + (i + 1) + "]"
                        });
                        break;

                    default:
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Dword, Src = "EAX", Dest = "[ECX+" + i + "]"
                        });
                        break;
                    }
                }
            }
            else
            {
                throw new ArgumentOutOfRangeException("Storing object with unsupported size! Size: " + size.ToString());
            }

            conversionState.Append(new ASMOps.Add()
            {
                Dest = "ESP", Src = "4"
            });
        }
Beispiel #17
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if field to load is a floating value or the field to load
        /// is not of size 4 or 8 bytes.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Get the field's token that is used to get FieldInfo from the assembly
            int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            //Get the field info from the referencing assembly
            FieldInfo theField = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);

            //Get the database type information about the object that contains the field
            Types.TypeInfo objTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theField.DeclaringType);
            int            offset      = conversionState.TheILLibrary.GetFieldInfo(objTypeInfo, theField.Name).OffsetInBytes;

            //Is the value to load a floating pointer number?
            bool valueisFloat = Utilities.IsFloat(theField.FieldType);

            //Get the size of the value to load (in bytes, as it will appear on the stack)
            Types.TypeInfo fieldTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theField.FieldType);
            int            stackSize     = fieldTypeInfo.SizeOnStackInBytes;
            int            memSize       = theField.FieldType.IsValueType ? fieldTypeInfo.SizeOnHeapInBytes : stackSize;

            //Pop the object pointer from our stack
            StackItem objPointer = conversionState.CurrentStackFrame.Stack.Pop();

            //If the value to load is a float, erm...abort...
            if (valueisFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Loading fields of type float not supported yet!");
            }

            //Pop object pointer
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t2"
            });
            if ((OpCodes)theOp.opCode.Value == OpCodes.Ldflda)
            {
                conversionState.Append(new ASMOps.Add()
                {
                    Src1 = "$t2", Src2 = offset.ToString(), Dest = "$t2"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t2"
                });

                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat            = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged        = false
                });
            }
            else
            {
                //Push value at pointer+offset
                int sizeNotInMem = stackSize - memSize;
                int sizeToSub    = (sizeNotInMem / 2) * 2; //Rounds down
                for (int i = 0; i < sizeToSub; i += 2)
                {
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Halfword, Src = "$zero"
                    });
                }
                for (int i = memSize + (memSize % 2); i > 0; i -= 2)
                {
                    if (sizeToSub != sizeNotInMem)
                    {
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Halfword, Src = "0", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                        });
                        //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = (offset + i - 2).ToString() + "($t2)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                        GlobalMethods.LoadData(conversionState, theOp, "$t2", "$t0", (offset + i - 2), 1);
                        conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Halfword, Src = "$t0"
                        });
                    }
                    else
                    {
                        //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Halfword, Src = (offset + i - 2).ToString() + "($t2)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                        GlobalMethods.LoadData(conversionState, theOp, "$t2", "$t0", (offset + i - 2), 2);
                        conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Halfword, Src = "$t0"
                        });
                    }
                }

                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat            = valueisFloat,
                    sizeOnStackInBytes = stackSize,
                    isGCManaged        = fieldTypeInfo.IsGCManaged
                });
            }
        }
Beispiel #18
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown when loading a static float field.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Load static field

            //Load the metadata token used to get the field info
            int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            //Get the field info for the field to load
            FieldInfo theField = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);
            //Get the ID (i.e. ASM label) of the field to load
            string fieldID = conversionState.GetFieldInfo(theField.DeclaringType, theField.Name).ID;

            conversionState.AddExternalLabel(fieldID);

            //Load the field or field address
            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Ldsfld:
            {
                Types.TypeInfo theTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theField.FieldType);
                int            size        = /*theTypeInfo.IsValueType ? theTypeInfo.SizeOnHeapInBytes : */ theTypeInfo.SizeOnStackInBytes;
                bool           isFloat     = Utilities.IsFloat(theField.FieldType);

                if (isFloat)
                {
                    //SUPPORT - floats
                    throw new NotSupportedException("Loading static fields of type float not supported yet!");
                }

                conversionState.Append(new ASMOps.La()
                    {
                        Label = fieldID, Dest = "$t1"
                    });

                if (size == 1)
                {
                    conversionState.Append(new ASMOps.Xor()
                        {
                            Src1 = "$t0", Src2 = "$t0", Dest = "$t0"
                        });
                    conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Byte, Src = "0($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                        });
                    conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "$t0"
                        });
                }
                else if (size == 2)
                {
                    conversionState.Append(new ASMOps.Xor()
                        {
                            Src1 = "$t0", Src2 = "$t0", Dest = "$t0"
                        });
                    conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Halfword, Src = "0($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                        });
                    conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "$t0"
                        });
                }
                else if (size == 4)
                {
                    conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "0($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                        });
                    conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "$t0"
                        });
                }
                else if (size == 8)
                {
                    conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "4($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                        });
                    conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "$t0"
                        });
                    conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "0($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                        });
                    conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "$t0"
                        });
                }
                else
                {
                    throw new ArgumentOutOfRangeException("Loading static field that has stack size greater than 8 not supported!");
                }

                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = isFloat,
                        sizeOnStackInBytes = (size == 8 ? 8 : 4),
                        isGCManaged        = theTypeInfo.IsGCManaged,
                        isValue            = theTypeInfo.IsValueType
                    });
            }
            break;

            case OpCodes.Ldsflda:
                //Load the address of the field i.e. address of the ASM label
                conversionState.Append(new ASMOps.La()
                {
                    Label = fieldID, Dest = "$t4"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t4"
                });

                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat            = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged        = false,
                    isValue            = false
                });
                break;
            }
        }
Beispiel #19
0
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Store the return value
            //Get the return type
            Type retType = (conversionState.Input.TheMethodInfo.IsConstructor ?
                            typeof(void) : ((MethodInfo)conversionState.Input.TheMethodInfo.UnderlyingInfo).ReturnType);

            Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
            //Get the size of the return type on stack
            int retSize = retTypeInfo.SizeOnStackInBytes;

            //If the size isn't 0 (i.e. isn't "void" which has no return value)
            if (retSize != 0)
            {
                //Pop the return value off our stack
                StackItem retItem = conversionState.CurrentStackFrame.Stack.Pop();

                //If it is float, well, we don't support it yet...
                if (retItem.isFloat)
                {
                    //SUPPORT - floats
                    throw new NotSupportedException("Floats return type not supported yet!");
                }
                //Otherwise, store the return value at [ebp+8]
                //[ebp+8] because that is last "argument"
                //      - read the calling convention spec
                else if (retSize == 4)
                {
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "8($fp)", Src = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                    });
                }
                else if (retSize == 8)
                {
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "8($fp)", Src = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                    });

                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "12($fp)", Src = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                    });
                }
                else
                {
                    throw new NotSupportedException("Return type size not supported / invalid!");
                }
            }

            //Once return value is off the stack, remove the locals
            //Deallocate stack space for locals
            //Only bother if there are any locals
            if (conversionState.Input.TheMethodInfo.LocalInfos.Count > 0)
            {
                //Get the total size of all locals
                int totalBytes = 0;
                foreach (Types.VariableInfo aLocal in conversionState.Input.TheMethodInfo.LocalInfos)
                {
                    totalBytes += aLocal.TheTypeInfo.SizeOnStackInBytes;
                }
                //Move esp past the locals
                conversionState.Append(new ASMOps.Add()
                {
                    Src1 = "$sp", Src2 = totalBytes.ToString(), Dest = "$sp"
                });
            }

            //Restore ebp to previous method's ebp
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$fp"
            });
            //This pop also takes last value off the stack which
            //means top item is the return address
            //So ret command can now be correctly executed.
        }
Beispiel #20
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if field to load is a floating value or the field to load
        /// is not of size 4 or 8 bytes.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            conversionState.CurrentStackFrame.Stack.Pop();

            Types.TypeInfo arrayTypeInfo = conversionState.GetArrayTypeInfo();
            int            lengthOffset  = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "length").OffsetInBytes;

            int currOpPosition = conversionState.PositionOf(theOp);

            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);

            // 1. Check array reference is not null
            //      1.1. Move array ref into eax
            //      1.2. Compare eax (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            // 2. Load array length


            //      1.1. Move array ref into eax
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[ESP]", Dest = "EAX"
            });
            //      1.2. Compare eax (array ref) to 0
            conversionState.Append(new ASMOps.Cmp()
            {
                Arg1 = "EAX", Arg2 = "0"
            });
            //      1.3. If not zero, jump to continue execution further down
            conversionState.Append(new ASMOps.Jmp()
            {
                JumpType = ASMOps.JmpOp.JumpNotZero, DestILPosition = currOpPosition, Extension = "ContinueExecution1"
            });
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            conversionState.Append(new ASMOps.Call()
            {
                Target = "GetEIP"
            });
            conversionState.AddExternalLabel("GetEIP");
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "ContinueExecution1"
            });

            //2. Load array length
            //  - Pop array ref
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Dword, Dest = "ECX"
            });
            //  - Load length from array ref
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[ECX+" + lengthOffset.ToString() + "]", Dest = "EAX"
            });
            //  - Push array length
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Dword, Src = "EAX"
            });

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = false,
                sizeOnStackInBytes = 4,
                isGCManaged        = false,
                isValue            = true
            });
        }
Beispiel #21
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if constant is a floating point number.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            int currOpPosition = conversionState.PositionOf(theOp);

            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);
            conversionState.AddExternalLabel(conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID);

            Type elementType = null;
            bool pushValue   = true;
            int  sizeToPush  = 4;
            bool signExtend  = true;
            bool isFloat     = false;

            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Ldelem:
            {
                signExtend = false;
                //Load the metadata token used to get the type info
                int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Get the type info for the element type
                elementType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);
            }
            break;

            case OpCodes.Ldelema:
            {
                signExtend = false;
                //Load the metadata token used to get the type info
                int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Get the type info for the element type
                elementType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);

                pushValue = false;
            }
            break;

            case OpCodes.Ldelem_R4:
            case OpCodes.Ldelem_R8:
                //TODO - Add more LdElem op variants support
                throw new NotSupportedException("Ldelem op variant not supported yet!");

            case OpCodes.Ldelem_I1:
                sizeToPush  = 1;
                elementType = typeof(sbyte);
                break;

            case OpCodes.Ldelem_I2:
                sizeToPush  = 2;
                elementType = typeof(Int16);
                break;

            case OpCodes.Ldelem_U1:
                sizeToPush  = 1;
                signExtend  = false;
                elementType = typeof(byte);
                break;

            case OpCodes.Ldelem_U2:
                sizeToPush  = 2;
                signExtend  = false;
                elementType = typeof(UInt16);
                break;

            case OpCodes.Ldelem_Ref:
                signExtend  = false;
                elementType = null;
                break;

            case OpCodes.Ldelem_U4:
                signExtend  = false;
                elementType = typeof(UInt32);
                break;

            case OpCodes.Ldelem_I4:
                elementType = typeof(Int32);
                break;

            case OpCodes.Ldelem_I8:
                sizeToPush  = 8;
                elementType = typeof(Int64);
                break;
            }

            if (isFloat)
            {
                //TODO - Support floats
                throw new NotSupportedException("LdElem for floats not supported yet!");
            }

            //Get element from array and push the value onto the stack
            //                   (or for LdElemA push the address of the value)

            //This involves:
            // 1. Check array reference is not null
            //          - If it is, throw NullReferenceException
            // 2. Check array element type is correct
            //          - If not, throw ArrayTypeMismatchException
            // 3. Check index to get is > -1 and < array length
            //          - If not, throw IndexOutOfRangeException
            // 4. Calculate address of element
            // 5. Push the element onto the stack

            //Stack setup upon entering this op: (top-most downwards)
            // 0. Index of element to get as Int32 (word)
            // 1. Array object reference as address (word)

            Types.TypeInfo arrayTypeInfo = conversionState.GetArrayTypeInfo();

            // 1. Check array reference is not null
            //      1.1. Move array ref into $t0
            //      1.2. Compare $t0 (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException

            //      1.1. Move array ref into $t0
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "4($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //      1.2. Compare $t0 (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            conversionState.Append(new ASMOps.Branch()
            {
                Src1 = "$t0", BranchType = ASMOps.BranchOp.BranchNotZero, DestILPosition = currOpPosition, Extension = "Continue1", UnsignedTest = true
            });
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            conversionState.Append(new ASMOps.Call()
            {
                Target = "GetEIP"
            });
            conversionState.AddExternalLabel("GetEIP");
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue1"
            });

            // 2. Check array element type is correct
            //      2.1. Move element type ref into $t0
            //      2.2. Move element type ref from array object into $t1
            //      2.3. Compare $t0 to $t1
            //      2.4. If the same, jump to continue execution further down
            //      2.5. Otherwise, call Exceptions.ThrowArrayTypeMismatchException

            //string ContinueExecutionLabel2 = ContinueExecutionLabelBase + "2";
            ////      2.1. Move element type ref into $t0
            int elemTypeOffset = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "elemType").OffsetInBytes;

            // 3. Check index to get is > -1 and < array length
            //      3.1. Move index into $t0
            //      3.2. Move array length into $t1
            //      3.2. Compare $t0 to 0
            //      3.3. Jump if greater than to next test condition (3.5)
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            //      3.5. Compare $t0 to $t1
            //      3.6. Jump if less than to continue execution further down
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException

            //      3.1. Move index into $t0
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "0($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //      3.2. Move array length into $t2
            //              - Calculate the offset of the field from the start of the array object
            int lengthOffset = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "length").OffsetInBytes;

            //              - Move array ref into $t1
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "4($sp)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //              - Move length value (offset($t1)) into $t1
            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = lengthOffset.ToString() + "($t1)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t1", "$t1", lengthOffset, 4);
            //      3.2. Compare $t0 to 0
            //      3.3. Jump if greater than to next test condition (3.5)
            conversionState.Append(new ASMOps.Branch()
            {
                Src1 = "$t0", Src2 = "$zero", BranchType = ASMOps.BranchOp.BranchGreaterThanEqual, DestILPosition = currOpPosition, Extension = "Continue3_1", UnsignedTest = false
            });
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue3_1"
            });
            //      3.5. Compare $t0 to $t1
            //      3.6. Jump if less than to continue execution further down
            conversionState.Append(new ASMOps.Branch()
            {
                Src1 = "$t0", Src2 = "$t1", BranchType = ASMOps.BranchOp.BranchLessThan, DestILPosition = currOpPosition, Extension = "Continue3_2", UnsignedTest = false
            });
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue3_2"
            });
            // 4. Calculate address of element
            //      4.1. Pop index into $t1
            //      4.2. Pop array ref into $t0
            //      4.3. Move element type ref (from array ref) into $t0
            //      4.4. Move IsValueType (from element ref type) into $t2
            //      4.5. If IsValueType, continue to 4.6., else goto 4.8.
            //      4.6. Move Size (from element type ref) into $t0
            //      4.7. Skip over 4.8.
            //      4.8. Move StackSize (from element type ref) into $t0
            //      4.9. Mulitply $t0 by $t1 (index by element size)
            //      4.10. Move array ref into $t1
            //      4.11. Add enough to go past Kernel.FOS_System.Array fields
            //      4.12. Add $t0 and $t1 (array ref + fields + (index * element size))

            //      4.1. Pop index into $t1
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t1"
            });
            //      4.2. Move array ref into $t0
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "0($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //      4.3. Move element type ref (from array ref) into $t0
            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = elemTypeOffset.ToString() + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", elemTypeOffset, 4);
            //      4.4. Move IsValueType (from element ref type) into $t2
            int isValueTypeOffset = conversionState.GetTypeFieldOffset("IsValueType");

            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
            });
            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = isValueTypeOffset.ToString() + "($t0)", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t2", isValueTypeOffset, 1);
            //      4.5. If IsValueType, continue to 4.6., else goto 4.8.
            conversionState.Append(new ASMOps.Branch()
            {
                Src1 = "$t2", BranchType = ASMOps.BranchOp.BranchZero, DestILPosition = currOpPosition, Extension = "Continue4_1", UnsignedTest = true
            });
            //      4.6. Move Size (from element type ref) into $t0
            int sizeOffset = conversionState.GetTypeFieldOffset("Size");

            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = sizeOffset.ToString() + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", sizeOffset, 4);
            //      4.7. Skip over 4.8.
            conversionState.Append(new ASMOps.Branch()
            {
                BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "Continue4_2"
            });
            //      4.8. Move StackSize (from element type ref) into $t0
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue4_1"
            });
            int stackSizeOffset = conversionState.GetTypeFieldOffset("StackSize");

            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = stackSizeOffset + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", stackSizeOffset, 4);
            //      4.9. Mulitply $t0 by $t1 (index by element size)
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue4_2"
            });
            conversionState.Append(new ASMOps.Mul()
            {
                Src1 = "$t1", Src2 = "$t0", Signed = true
            });
            //      4.10. Pop array ref into $t1
            conversionState.Append(new ASMOps.Mflo()
            {
                Dest = "$t0"
            });
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t1"
            });
            //      4.11. Add enough to go past Kernel.FOS_System.Array fields
            int allFieldsOffset = 0;

            #region Offset calculation
            {
                Types.FieldInfo highestOffsetFieldInfo = arrayTypeInfo.FieldInfos.Where(x => !x.IsStatic).OrderByDescending(x => x.OffsetInBytes).First();
                Types.TypeInfo  fieldTypeInfo          = conversionState.TheILLibrary.GetTypeInfo(highestOffsetFieldInfo.UnderlyingInfo.FieldType);
                allFieldsOffset = highestOffsetFieldInfo.OffsetInBytes + (fieldTypeInfo.IsValueType ? fieldTypeInfo.SizeOnHeapInBytes : fieldTypeInfo.SizeOnStackInBytes);
            }
            #endregion
            conversionState.Append(new ASMOps.Add()
            {
                Src1 = "$t1", Src2 = allFieldsOffset.ToString(), Dest = "$t1"
            });
            //      4.12. Add $t0 and $t1 (array ref + fields + (index * element size))
            conversionState.Append(new ASMOps.Add()
            {
                Src1 = "$t1", Src2 = "$t0", Dest = "$t0"
            });

            // 5. Push the element onto the stack
            //      5.1. Push value at ($t0) (except for LdElemA op in which case just push address)
            if (pushValue)
            {
                switch (sizeToPush)
                {
                case 1:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 1, signExtend);
                    break;

                case 2:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Halfword, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 2, signExtend);

                    break;

                case 4:
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 4);
                    break;

                case 8:
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 4);
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "4($t0)", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t2", 4, 4);
                    break;
                }
                if (sizeToPush == 8)
                {
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t2"
                    });
                }
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t1"
                });
            }
            else
            {
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0"
                });
            }

            //      5.2. Pop index and array ref from our stack
            conversionState.CurrentStackFrame.Stack.Pop();
            conversionState.CurrentStackFrame.Stack.Pop();
            //      5.3. Push element onto our stack
            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                sizeOnStackInBytes = sizeToPush > 4 ? 8 : 4,
                isFloat            = isFloat,
                isNewGCObject      = false,
                isGCManaged        = pushValue ? (elementType == null || conversionState.TheILLibrary.GetTypeInfo(elementType).IsGCManaged) : false
            });
        }
Beispiel #22
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if any argument or the return value is a floating point number.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            MethodBase methodToCall = theOp.MethodToCall;

            Types.MethodInfo methodToCallInfo = conversionState.TheILLibrary.GetMethodInfo(methodToCall);

            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);
            conversionState.AddExternalLabel(conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID);

            //The method to call is a method base
            //A method base can be either a method info i.e. a normal method
            //or a constructor method. The two types are treated separately.
            if (methodToCall is MethodInfo)
            {
                //Need to do callvirt related stuff to load address of method to call
                // - Check for invoke of a delegate - if so, treat rather differently from normal callvirt

                if (typeof(Delegate).IsAssignableFrom(((MethodInfo)methodToCall).DeclaringType))
                {
                    //Callvirt to delegate method
                    // - We only support calls to Invoke at the moment
                    if (methodToCall.Name != "Invoke")
                    {
                        throw new NotSupportedException("Callvirt to Delegate method not supported! Method name: " + methodToCall.Name);
                    }
                    int bytesForAllParams = ((MethodInfo)methodToCall).GetParameters().Select(x => conversionState.TheILLibrary.GetTypeInfo(x.ParameterType).SizeOnStackInBytes).Sum();

                    // - Move into $t0 address of function to call from stack - delegate reference is function pointer

                    //All the parameters for the method that was called
                    List <Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();

                    int bytesForParams = allParams.Select(x => conversionState.TheILLibrary.GetTypeInfo(x).SizeOnStackInBytes).Sum();
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = bytesForParams + "($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });


                    //Allocate space on the stack for the return value as necessary
                    Type           retType     = ((MethodInfo)methodToCall).ReturnType;
                    Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                    StackItem      returnItem  = new StackItem()
                    {
                        isFloat            = Utilities.IsFloat(retType),
                        sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                        isGCManaged        = retTypeInfo.IsGCManaged,
                        isValue            = retTypeInfo.IsValueType
                    };
                    //We do not push the return value onto the stack unless it has size > 0
                    //We do not push the return value onto our stack at this point - it is pushed after the call is done

                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        if (returnItem.isFloat)
                        {
                            //SUPPORT - floats
                            throw new NotSupportedException("Cannot handle float return values!");
                        }
                        else if (returnItem.sizeOnStackInBytes == 4)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$zero"
                            });
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$zero"
                            });
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$zero"
                            });
                        }
                        else
                        {
                            throw new NotSupportedException("Invalid return stack operand size!");
                        }
                    }



                    //Append the actual call
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = "$t0"
                    });


                    //After a call, we need to remove the return value and parameters from the stack
                    //This is most easily done by just adding the total number of bytes for params and
                    //return value to the stack pointer ($sp register).

                    //Stores the number of bytes to add
                    // - Initially at least 4 for the delegate (method) ref/pointer
                    int bytesToAdd = 4;
                    //Go through all params that must be removed
                    foreach (Type aParam in allParams)
                    {
                        //Pop the paramter off our stack
                        //(Note: Return value was never pushed onto our stack. See above)
                        conversionState.CurrentStackFrame.Stack.Pop();
                        //Add the size of the paramter to the total number of bytes to pop
                        bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                    }

                    //If there is a return value on the stack
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //We need to store the return value then pop all the params

                        //We now push the return value onto our stack as,
                        //after all is said and done below, it will be the
                        //top item on the stack
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);

                        //SUPPORT - floats (with above)

                        //Pop the return value into the $t0 register
                        //We will push it back on after params are skipped over.
                        if (returnItem.sizeOnStackInBytes == 4)
                        {
                            conversionState.Append(new ASMOps.Pop()
                            {
                                Size = ASMOps.OperandSize.Word, Dest = "$t0"
                            });
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            conversionState.Append(new ASMOps.Pop()
                            {
                                Size = ASMOps.OperandSize.Word, Dest = "$t0"
                            });
                            conversionState.Append(new ASMOps.Pop()
                            {
                                Size = ASMOps.OperandSize.Word, Dest = "$t3"
                            });
                        }
                    }
                    //Skip over the params
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src1 = "$sp", Src2 = bytesToAdd.ToString(), Dest = "$sp"
                    });
                    //If necessary, push the return value onto the stack.
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //SUPPORT - floats (with above)

                        //The return value was stored in $t0
                        //So push it back onto the stack
                        if (returnItem.sizeOnStackInBytes == 4)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$t0"
                            });
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$t3"
                            });
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$t0"
                            });
                        }
                    }
                }
                else
                {
                    //Normal callvirt
                    // - Get object ref from loaded args
                    // - Check object ref not null
                    // - Get type table entry from object ref
                    // - Get method table from type table entry
                    // - Scan method table for the method we want
                    //      - If found, load method address
                    // - Else, check for parent type method table
                    //      - If no parent type method table, throw exception
                    // - Else, scan parent type method table

                    string methodIDValueWanted = methodToCallInfo.IDValue.ToString();
                    int    currOpPosition      = conversionState.PositionOf(theOp);

                    Types.TypeInfo declaringTypeInfo = conversionState.TheILLibrary.GetTypeInfo(methodToCall.DeclaringType);
                    //DB_Type declaringDBType = DebugDatabase.GetType(conversionState.GetTypeID(methodToCall.DeclaringType));

                    //Get object ref
                    int bytesForAllParams = ((MethodInfo)methodToCall).GetParameters().Select(x => conversionState.TheILLibrary.GetTypeInfo(x.ParameterType).SizeOnStackInBytes).Sum();
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = bytesForAllParams + "($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });

                    //Check object ref
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.BranchNotZero, Src1 = "$t0", Src2 = "$zero", DestILPosition = currOpPosition, Extension = "NotNull"
                    });

                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = "GetEIP"
                    });
                    conversionState.AddExternalLabel("GetEIP");
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "NotNull"
                    });

                    //Get type ref
                    int typeOffset = conversionState.TheILLibrary.GetFieldInfo(declaringTypeInfo, "_Type").OffsetInBytes;
                    //conversionState.Append(new ASMOps.La() { Dest = "$t1", Label = "type_Testing1_String" });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = typeOffset.ToString() + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", typeOffset, 4);

                    //Get method table ref
                    int methodTablePtrOffset = conversionState.GetTypeFieldOffset("MethodTablePtr");
                    //conversionState.Append(new ASMOps.La() { Dest = "$t0", Label = "type_Testing1_String_MethodTable" });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = methodTablePtrOffset.ToString() + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", methodTablePtrOffset, 4);

                    //Loop through entries
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "LoopMethodTable"
                    });
                    //Load ID Val for current entry
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 4);
                    //Compare to wanted ID value
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Src = methodIDValueWanted, Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    //If equal, load method address into $t0
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.BranchNotEqual, Src1 = "$t1", Src2 = "$t4", DestILPosition = currOpPosition, Extension = "NotEqual"
                    });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "4($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", 4, 4);
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "Call"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "NotEqual"
                    });
                    //Else, compare to 0 to check for end of table
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.BranchZero, Src1 = "$t1", DestILPosition = currOpPosition, Extension = "EndOfTable"
                    });
                    //Not 0? Move to next entry then loop again
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src1 = "$t0", Src2 = "8", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "LoopMethodTable"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "EndOfTable"
                    });
                    //Compare address value to 0
                    //If not zero, there is a parent method table to check
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "4($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 4, 4);
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.BranchZero, Src1 = "$t1", DestILPosition = currOpPosition, Extension = "NotFound"
                    });
                    //Load parent method table and loop
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t1", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.RegToReg
                    });
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "LoopMethodTable"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "NotFound"
                    });
                    //Throw exception!
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = "GetEIP"
                    });
                    conversionState.AddExternalLabel("GetEIP");
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
                    });

                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "Call"
                    });

                    //Allocate space on the stack for the return value as necessary
                    Type           retType     = ((MethodInfo)methodToCall).ReturnType;
                    Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                    StackItem      returnItem  = new StackItem()
                    {
                        isFloat            = Utilities.IsFloat(retType),
                        sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                        isGCManaged        = retTypeInfo.IsGCManaged,
                        isValue            = retTypeInfo.IsValueType
                    };
                    //We do not push the return value onto the stack unless it has size > 0
                    //We do not push the return value onto our stack at this point - it is pushed after the call is done

                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        if (returnItem.isFloat)
                        {
                            //SUPPORT - floats
                            throw new NotSupportedException("Cannot handle float return values!");
                        }
                        else if (returnItem.sizeOnStackInBytes == 4)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$zero"
                            });
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$zero"
                            });
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$zero"
                            });
                        }
                        else
                        {
                            throw new NotSupportedException("Invalid return stack operand size!");
                        }
                    }


                    //Append the actual call
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = "$t0"
                    });



                    //After a call, we need to remove the return value and parameters from the stack
                    //This is most easily done by just adding the total number of bytes for params and
                    //return value to the stack pointer ($sp register).

                    //Stores the number of bytes to add
                    int bytesToAdd = 0;
                    //All the parameters for the method that was called
                    List <Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();
                    //Go through each one
                    if (!methodToCall.IsStatic)
                    {
                        allParams.Insert(0, methodToCall.DeclaringType);
                    }
                    foreach (Type aParam in allParams)
                    {
                        //Pop the parameter off our stack
                        //(Note: Return value was never pushed onto our stack. See above)
                        conversionState.CurrentStackFrame.Stack.Pop();
                        //Add the size of the parameter to the total number of bytes to pop
                        bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                    }
                    //If the number of bytes to add to skip over params is > 0
                    if (bytesToAdd > 0)
                    {
                        //If there is a return value on the stack
                        if (returnItem.sizeOnStackInBytes != 0)
                        {
                            //We need to store the return value then pop all the params

                            //We now push the return value onto our stack as,
                            //after all is said and done below, it will be the
                            //top item on the stack
                            conversionState.CurrentStackFrame.Stack.Push(returnItem);

                            //SUPPORT - floats (with above)

                            //Pop the return value into the $t0 register
                            //We will push it back on after params are skipped over.
                            if (returnItem.sizeOnStackInBytes == 4)
                            {
                                conversionState.Append(new ASMOps.Pop()
                                {
                                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                                });
                            }
                            else if (returnItem.sizeOnStackInBytes == 8)
                            {
                                conversionState.Append(new ASMOps.Pop()
                                {
                                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                                });
                                conversionState.Append(new ASMOps.Pop()
                                {
                                    Size = ASMOps.OperandSize.Word, Dest = "$t3"
                                });
                            }
                        }
                        //Skip over the params
                        conversionState.Append(new ASMOps.Add()
                        {
                            Src1 = "$sp", Src2 = bytesToAdd.ToString(), Dest = "$sp"
                        });
                        //If necessary, push the return value onto the stack.
                        if (returnItem.sizeOnStackInBytes != 0)
                        {
                            //SUPPORT - floats (with above)

                            //The return value was stored in $t0
                            //So push it back onto the stack
                            if (returnItem.sizeOnStackInBytes == 4)
                            {
                                conversionState.Append(new ASMOps.Push()
                                {
                                    Size = ASMOps.OperandSize.Word, Src = "$t0"
                                });
                            }
                            else if (returnItem.sizeOnStackInBytes == 8)
                            {
                                conversionState.Append(new ASMOps.Push()
                                {
                                    Size = ASMOps.OperandSize.Word, Src = "$t3"
                                });
                                conversionState.Append(new ASMOps.Push()
                                {
                                    Size = ASMOps.OperandSize.Word, Src = "$t0"
                                });
                            }
                        }
                    }
                    //No params to skip over but we might still need to store return value
                    else if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //The return value will be the top item on the stack.
                        //So all we need to do is push the return item onto our stack.
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);
                    }
                }
            }
            else if (methodToCall is ConstructorInfo)
            {
                throw new NotSupportedException("How the hell are we getting callvirts to constructor methods?!");
            }
        }
Beispiel #23
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            MethodBase methodToCall = theOp.MethodToCall;

            Types.MethodInfo methodToCallInfo = conversionState.TheILLibrary.GetMethodInfo(methodToCall);

            if (methodToCall is MethodInfo)
            {
                if (typeof(Delegate).IsAssignableFrom(((MethodInfo)methodToCall).DeclaringType))
                {
                    List <Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();

                    Type           retType     = ((MethodInfo)methodToCall).ReturnType;
                    Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                    StackItem      returnItem  = new StackItem()
                    {
                        isFloat            = Utilities.IsFloat(retType),
                        sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                        isGCManaged        = retTypeInfo.IsGCManaged,
                        isValue            = retTypeInfo.IsValueType
                    };


                    int bytesToAdd = 4;
                    foreach (Type aParam in allParams)
                    {
                        conversionState.CurrentStackFrame.Stack.Pop();
                        bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                    }

                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);
                    }
                }
                else
                {
                    string methodIDValueWanted = methodToCallInfo.IDValue.ToString();
                    int    currOpPosition      = conversionState.PositionOf(theOp);

                    Types.TypeInfo declaringTypeInfo = conversionState.TheILLibrary.GetTypeInfo(methodToCall.DeclaringType);

                    Type           retType     = ((MethodInfo)methodToCall).ReturnType;
                    Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                    StackItem      returnItem  = new StackItem()
                    {
                        isFloat            = Utilities.IsFloat(retType),
                        sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                        isGCManaged        = retTypeInfo.IsGCManaged,
                        isValue            = retTypeInfo.IsValueType
                    };

                    int         bytesToAdd = 0;
                    List <Type> allParams  = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();
                    if (!methodToCall.IsStatic)
                    {
                        allParams.Insert(0, methodToCall.DeclaringType);
                    }
                    foreach (Type aParam in allParams)
                    {
                        conversionState.CurrentStackFrame.Stack.Pop();
                        bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                    }
                    if (bytesToAdd > 0)
                    {
                        if (returnItem.sizeOnStackInBytes != 0)
                        {
                            conversionState.CurrentStackFrame.Stack.Push(returnItem);
                        }
                    }
                    else if (returnItem.sizeOnStackInBytes != 0)
                    {
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);
                    }
                }
            }
        }
Beispiel #24
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if the value to store is floating point.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            int       metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            FieldInfo theField      = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);

            Types.FieldInfo theFieldInfo     = conversionState.GetFieldInfo(theField.DeclaringType, theField.Name);
            Types.TypeInfo  theFieldTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theFieldInfo.FieldType);

            string fieldId = theFieldInfo.ID;
            int    size    = /*theFieldTypeInfo.IsValueType ? theFieldTypeInfo.SizeOnHeapInBytes : */ theFieldTypeInfo.SizeOnStackInBytes;
            bool   isFloat = Utilities.IsFloat(theField.FieldType);

            conversionState.AddExternalLabel(fieldId);

            StackItem value = conversionState.CurrentStackFrame.Stack.Pop();

            if (isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Storing static fields of type float not supported yet!");
            }

            conversionState.Append(new ASMOps.La()
            {
                Dest = "$t4", Label = fieldId
            });

            if (size == 1)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Byte, Src = "$t1", Dest = "0($t4)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                });
            }
            else if (size == 2)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Halfword, Src = "$t1", Dest = "0($t4)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                });
            }
            else if (size == 4)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = "0($t4)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                });
            }
            else if (size == 8)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = "0($t4)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                });
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = "4($t4)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                });
            }
            else
            {
                throw new ArgumentOutOfRangeException("Storing static field that has stack size greater than 8 not supported!");
            }

            if (value.sizeOnStackInBytes - size > 0)
            {
                conversionState.Append(new ASMOps.Add()
                {
                    Src1 = "$sp", Src2 = (value.sizeOnStackInBytes - size).ToString(), Dest = "$sp"
                });
            }
        }
Beispiel #25
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if any argument or the return value is a floating point number.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            MethodBase methodToCall = theOp.MethodToCall;

            Types.MethodInfo methodToCallInfo = conversionState.TheILLibrary.GetMethodInfo(methodToCall);

            conversionState.AddExternalLabel(methodToCallInfo.ID);

            //The method to call is a method base
            //A method base can be either a method info i.e. a normal method
            //or a constructor method. The two types are treated separately.
            if (methodToCall is MethodInfo)
            {
                //Allocate space on the stack for the return value as necessary
                Type           retType     = ((MethodInfo)methodToCall).ReturnType;
                Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                StackItem      returnItem  = new StackItem()
                {
                    isFloat            = Utilities.IsFloat(retType),
                    sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                    isGCManaged        = retTypeInfo.IsGCManaged
                };
                //We do not push the return value onto the stack unless it has size > 0
                //We do not push the return value onto our stack at this point - it is pushed after the call is done

                if (returnItem.sizeOnStackInBytes != 0)
                {
                    if (returnItem.isFloat)
                    {
                        //SUPPORT - floats
                        throw new NotSupportedException("Cannot handle float return values!");
                    }
                    else if (returnItem.sizeOnStackInBytes == 4)
                    {
                        conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Dword, Src = "0"
                        });
                    }
                    else if (returnItem.sizeOnStackInBytes == 8)
                    {
                        conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Dword, Src = "0"
                        });
                        conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Dword, Src = "0"
                        });
                    }
                    else
                    {
                        throw new NotSupportedException("Invalid return stack operand size!");
                    }
                }

                //Append the actual call
                conversionState.Append(new ASMOps.Call()
                {
                    Target = methodToCallInfo.ID
                });

                //After a call, we need to remove the return value and parameters from the stack
                //This is most easily done by just adding the total number of bytes for params and
                //return value to the stack pointer (ESP register).

                //Stores the number of bytes to add
                int bytesToAdd = 0;
                //All the parameters for the method that was called
                List <Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();
                //Go through each one
                if (!methodToCall.IsStatic)
                {
                    allParams.Insert(0, methodToCall.DeclaringType);
                }
                foreach (Type aParam in allParams)
                {
                    //Pop the paramter off our stack
                    //(Note: Return value was never pushed onto our stack. See above)
                    conversionState.CurrentStackFrame.Stack.Pop();
                    //Add the size of the paramter to the total number of bytes to pop
                    bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                }
                //If the number of bytes to add to skip over params is > 0
                if (bytesToAdd > 0)
                {
                    //If there is a return value on the stack
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //We need to store the return value then pop all the params

                        //We now push the return value onto our stack as,
                        //after all is said and done below, it will be the
                        //top item on the stack
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);

                        //SUPPORT - floats (with above)

                        //Pop the return value into the eax register
                        //We will push it back on after params are skipped over.
                        if (returnItem.sizeOnStackInBytes == 4)
                        {
                            conversionState.Append(new ASMOps.Pop()
                            {
                                Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                            });
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            conversionState.Append(new ASMOps.Pop()
                            {
                                Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                            });
                            conversionState.Append(new ASMOps.Pop()
                            {
                                Size = ASMOps.OperandSize.Dword, Dest = "EDX"
                            });
                        }
                    }
                    //Skip over the params
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src = bytesToAdd.ToString(), Dest = "ESP"
                    });
                    //If necessary, push the return value onto the stack.
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //SUPPORT - floats (with above)

                        //The return value was stored in eax
                        //So push it back onto the stack
                        if (returnItem.sizeOnStackInBytes == 4)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Dword, Src = "EAX"
                            });
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Dword, Src = "EDX"
                            });
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Dword, Src = "EAX"
                            });
                        }
                    }
                }
                //No params to skip over but we might still need to store return value
                else if (returnItem.sizeOnStackInBytes != 0)
                {
                    //The return value will be the top item on the stack.
                    //So all we need to do is push the return item onto our stack.
                    conversionState.CurrentStackFrame.Stack.Push(returnItem);
                }
            }
            else if (methodToCall is ConstructorInfo)
            {
                ConstructorInfo aConstructor = (ConstructorInfo)methodToCall;
                if (aConstructor.IsStatic)
                {
                    //Static constructors do not have parameters or return values

                    //Append the actual call
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = methodToCallInfo.ID
                    });
                }
                else
                {
                    //Append the actual call
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = methodToCallInfo.ID
                    });

                    //After a call, we need to remove the parameters from the stack
                    //This is most easily done by just adding the total number of bytes for params
                    //to the stack pointer (ESP register).

                    //Stores the number of bytes to add
                    int bytesToAdd = 0;
                    //All the parameters for the method that was called
                    ParameterInfo[] allParams = methodToCall.GetParameters();
                    //Go through each one
                    foreach (ParameterInfo aParam in allParams)
                    {
                        //Pop the paramter off our stack
                        //(Note: Return value was never pushed onto our stack. See above)
                        conversionState.CurrentStackFrame.Stack.Pop();
                        //Add the size of the paramter to the total number of bytes to pop
                        bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam.ParameterType).SizeOnStackInBytes;
                    }
                    //Add 4 bytes for the instance ref
                    bytesToAdd += 4;
                    //If the number of bytes to add to skip over params is > 0
                    if (bytesToAdd > 0)
                    {
                        //Skip over the params
                        conversionState.Append(new ASMOps.Add()
                        {
                            Src = bytesToAdd.ToString(), Dest = "ESP"
                        });
                    }
                }
            }
        }
Beispiel #26
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if constant is a floating point number.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            int currOpPosition = conversionState.PositionOf(theOp);

            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);
            conversionState.AddExternalLabel(conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID);

            Type elementType = null;
            bool pushValue   = true;
            int  sizeToPush  = 4;
            bool signExtend  = true;
            bool isFloat     = false;

            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Ldelem:
            {
                signExtend = false;
                //Load the metadata token used to get the type info
                int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Get the type info for the element type
                elementType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);
            }
            break;

            case OpCodes.Ldelema:
            {
                signExtend = false;
                //Load the metadata token used to get the type info
                int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Get the type info for the element type
                elementType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);

                pushValue = false;
            }
            break;

            case OpCodes.Ldelem_R4:
            case OpCodes.Ldelem_R8:
                //TODO - Add more LdElem op variants support
                throw new NotSupportedException("Ldelem op variant not supported yet!");

            case OpCodes.Ldelem_I1:
                sizeToPush  = 1;
                elementType = typeof(sbyte);
                break;

            case OpCodes.Ldelem_I2:
                sizeToPush  = 2;
                elementType = typeof(Int16);
                break;

            case OpCodes.Ldelem_U1:
                sizeToPush  = 1;
                signExtend  = false;
                elementType = typeof(byte);
                break;

            case OpCodes.Ldelem_U2:
                sizeToPush  = 2;
                signExtend  = false;
                elementType = typeof(UInt16);
                break;

            case OpCodes.Ldelem_Ref:
                signExtend  = false;
                elementType = null;
                break;

            case OpCodes.Ldelem_U4:
                signExtend  = false;
                elementType = typeof(UInt32);
                break;

            case OpCodes.Ldelem_I4:
                elementType = typeof(Int32);
                break;

            case OpCodes.Ldelem_I8:
                sizeToPush  = 8;
                elementType = typeof(Int64);
                break;
            }

            if (isFloat)
            {
                //TODO - Support floats
                throw new NotSupportedException("LdElem for floats not supported yet!");
            }

            //Get element from array and push the value onto the stack
            //                   (or for LdElemA push the address of the value)

            //This involves:
            // 1. Check array reference is not null
            //          - If it is, throw NullReferenceException
            // 2. Check array element type is correct
            //          - If not, throw ArrayTypeMismatchException
            // 3. Check index to get is > -1 and < array length
            //          - If not, throw IndexOutOfRangeException
            // 4. Calculate address of element
            // 5. Push the element onto the stack

            //Stack setup upon entering this op: (top-most downwards)
            // 0. Index of element to get as Int32 (dword)
            // 1. Array object reference as address (dword)

            Types.TypeInfo arrayTypeInfo = conversionState.GetArrayTypeInfo();

            // 1. Check array reference is not null
            //      1.1. Move array ref into EAX
            //      1.2. Compare EAX (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException

            //      1.1. Move array ref into EAX
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[ESP+4]", Dest = "EAX"
            });
            //      1.2. Compare EAX (array ref) to 0
            conversionState.Append(new ASMOps.Cmp()
            {
                Arg1 = "EAX", Arg2 = "0"
            });
            //      1.3. If not zero, jump to continue execution further down
            conversionState.Append(new ASMOps.Jmp()
            {
                JumpType = ASMOps.JmpOp.JumpNotZero, DestILPosition = currOpPosition, Extension = "Continue1"
            });
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            conversionState.Append(new ASMOps.Call()
            {
                Target = "GetEIP"
            });
            conversionState.AddExternalLabel("GetEIP");
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue1"
            });

            // 2. Check array element type is correct
            //      2.1. Move element type ref into EAX
            //      2.2. Move element type ref from array object into EBX
            //      2.3. Compare EAX to EBX
            //      2.4. If the same, jump to continue execution further down
            //      2.5. Otherwise, call Exceptions.ThrowArrayTypeMismatchException

            //string ContinueExecutionLabel2 = ContinueExecutionLabelBase + "2";
            ////      2.1. Move element type ref into EAX
            int elemTypeOffset = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "elemType").OffsetInBytes;

            //if (elementType != null)
            //{
            //    result.AppendLine(string.Format("mov EAX, {0}", conversionState.GetTypeIdString(conversionState.GetTypeID(elementType))));
            //    //      2.2. Move element type ref from array object into EBX
            //    //              - Calculate the offset of the field from the start of the array object
            //    //              - Move array ref into EBX
            //GlobalMethods.CheckAddrFromRegister(result, conversionState, "ESP", 4);
            //    result.AppendLine("mov EBX, [ESP+4]");
            //    //              - Move elemType ref ([EBX+offset]) into EBX
            //    GlobalMethods.CheckAddrFromRegister(result, conversionState, "EBX", elemTypeOffset);
            //    result.AppendLine(string.Format("mov EBX, [EBX+{0}]", elemTypeOffset));
            //    //      2.3. Compare EAX to EBX
            //    result.AppendLine("cmp EAX, EBX");
            //    //      2.4. If the same, jump to continue execution further down
            //    result.AppendLine("je " + ContinueExecutionLabel2);
            //    //      2.5. Otherwise, call Exceptions.ThrowArrayTypeMismatchException
            //    result.AppendLine(string.Format("call {0}", conversionState.GetMethodID(conversionState.ThrowArrayTypeMismatchExceptionMethod)));
            //    result.AppendLine(ContinueExecutionLabel2 + ":");
            //}

            // 3. Check index to get is > -1 and < array length
            //      3.1. Move index into EAX
            //      3.2. Move array length into EBX
            //      3.2. Compare EAX to 0
            //      3.3. Jump if greater than to next test condition (3.5)
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            //      3.5. Compare EAX to EBX
            //      3.6. Jump if less than to continue execution further down
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException

            //      3.1. Move index into EAX
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[ESP]", Dest = "EAX"
            });
            //      3.2. Move array length into ECX
            //              - Calculate the offset of the field from the start of the array object
            int lengthOffset = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "length").OffsetInBytes;

            //              - Move array ref into EBX
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[ESP+4]", Dest = "EBX"
            });
            //              - Move length value ([EBX+offset]) into EBX
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[EBX+" + lengthOffset.ToString() + "]", Dest = "EBX"
            });
            //      3.2. Compare EAX to 0
            conversionState.Append(new ASMOps.Cmp()
            {
                Arg1 = "EAX", Arg2 = "0"
            });
            //      3.3. Jump if greater than to next test condition (3.5)
            conversionState.Append(new ASMOps.Jmp()
            {
                JumpType = ASMOps.JmpOp.JumpGreaterThanEqual, DestILPosition = currOpPosition, Extension = "Continue3_1"
            });
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue3_1"
            });
            //      3.5. Compare EAX to EBX
            conversionState.Append(new ASMOps.Cmp()
            {
                Arg1 = "EAX", Arg2 = "EBX"
            });
            //      3.6. Jump if less than to continue execution further down
            conversionState.Append(new ASMOps.Jmp()
            {
                JumpType = ASMOps.JmpOp.JumpLessThan, DestILPosition = currOpPosition, Extension = "Continue3_2"
            });
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue3_2"
            });

            // 4. Calculate address of element
            //      4.1. Pop index into EBX
            //      4.2. Pop array ref into EAX
            //      4.3. Move element type ref (from array ref) into EAX
            //      4.4. Move IsValueType (from element ref type) into ECX
            //      4.5. If IsValueType, continue to 4.6., else goto 4.8.
            //      4.6. Move Size (from element type ref) into EAX
            //      4.7. Skip over 4.8.
            //      4.8. Move StackSize (from element type ref) into EAX
            //      4.9. Mulitply EAX by EBX (index by element size)
            //      4.10. Move array ref into EBX
            //      4.11. Add enough to go past Kernel.FOS_System.Array fields
            //      4.12. Add EAX and EBX (array ref + fields + (index * element size))

            //      4.1. Pop index into EBX
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Dword, Dest = "EBX"
            });
            //      4.2. Move array ref into EAX
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[ESP]", Dest = "EAX"
            });
            //      4.3. Move element type ref (from array ref) into EAX
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[EAX+" + elemTypeOffset.ToString() + "]", Dest = "EAX"
            });
            //      4.4. Move IsValueType (from element ref type) into ECX
            int isValueTypeOffset = conversionState.GetTypeFieldOffset("IsValueType");

            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "0", Dest = "ECX"
            });
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Byte, Src = "[EAX+" + isValueTypeOffset.ToString() + "]", Dest = "CL"
            });
            //      4.5. If IsValueType, continue to 4.6., else goto 4.8.
            conversionState.Append(new ASMOps.Cmp()
            {
                Arg1 = "ECX", Arg2 = "0"
            });
            conversionState.Append(new ASMOps.Jmp()
            {
                JumpType = ASMOps.JmpOp.JumpZero, DestILPosition = currOpPosition, Extension = "Continue4_1"
            });
            //      4.6. Move Size (from element type ref) into EAX
            int sizeOffset = conversionState.GetTypeFieldOffset("Size");

            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[EAX+" + sizeOffset.ToString() + "]", Dest = "EAX"
            });
            //      4.7. Skip over 4.8.
            conversionState.Append(new ASMOps.Jmp()
            {
                JumpType = ASMOps.JmpOp.Jump, DestILPosition = currOpPosition, Extension = "Continue4_2"
            });
            //      4.8. Move StackSize (from element type ref) into EAX
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue4_1"
            });
            int stackSizeOffset = conversionState.GetTypeFieldOffset("StackSize");

            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[EAX+" + stackSizeOffset + "]", Dest = "EAX"
            });
            //      4.9. Mulitply EAX by EBX (index by element size)
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue4_2"
            });
            conversionState.Append(new ASMOps.Mul()
            {
                Arg = "EBX"
            });
            //      4.10. Pop array ref into EBX
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Dword, Dest = "EBX"
            });
            //      4.11. Add enough to go past Kernel.FOS_System.Array fields
            int allFieldsOffset = 0;

            #region Offset calculation
            {
                Types.FieldInfo highestOffsetFieldInfo = arrayTypeInfo.FieldInfos.Where(x => !x.IsStatic).OrderByDescending(x => x.OffsetInBytes).First();
                Types.TypeInfo  fieldTypeInfo          = conversionState.TheILLibrary.GetTypeInfo(highestOffsetFieldInfo.UnderlyingInfo.FieldType);
                allFieldsOffset = highestOffsetFieldInfo.OffsetInBytes + (fieldTypeInfo.IsValueType ? fieldTypeInfo.SizeOnHeapInBytes : fieldTypeInfo.SizeOnStackInBytes);
            }
            #endregion
            conversionState.Append(new ASMOps.Add()
            {
                Src = allFieldsOffset.ToString(), Dest = "EBX"
            });
            //      4.12. Add EAX and EBX (array ref + fields + (index * element size))
            conversionState.Append(new ASMOps.Add()
            {
                Src = "EBX", Dest = "EAX"
            });

            // 5. Push the element onto the stack
            //      5.1. Push value at [EAX] (except for LdElemA op in which case just push address)
            if (pushValue)
            {
                switch (sizeToPush)
                {
                case 1:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "0", Dest = "EBX"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "[EAX]", Dest = "BL"
                    });
                    if (signExtend)
                    {
                        throw new NotSupportedException("Sign extend byte to 4 bytes in LdElem not supported!");
                    }
                    break;

                case 2:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "0", Dest = "EBX"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "[EAX]", Dest = "BX"
                    });
                    if (signExtend)
                    {
                        conversionState.Append(new ASMOps.Cwde());
                    }
                    break;

                case 4:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "[EAX]", Dest = "EBX"
                    });
                    break;

                case 8:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "[EAX]", Dest = "EBX"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "[EAX+4]", Dest = "ECX"
                    });
                    break;
                }
                if (sizeToPush == 8)
                {
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "ECX"
                    });
                }
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "EBX"
                });
            }
            else
            {
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "EAX"
                });
            }

            //      5.2. Pop index and array ref from our stack
            conversionState.CurrentStackFrame.Stack.Pop();
            conversionState.CurrentStackFrame.Stack.Pop();
            //      5.3. Push element onto our stack
            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                sizeOnStackInBytes = sizeToPush > 4 ? 8 : 4,
                isFloat            = isFloat,
                isNewGCObject      = false,
                isGCManaged        = pushValue ? (elementType == null || conversionState.TheILLibrary.GetTypeInfo(elementType).IsGCManaged) : false
            });
        }
Beispiel #27
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if field to load is a floating value or the field to load
        /// is not of size 4 or 8 bytes.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            conversionState.CurrentStackFrame.Stack.Pop();

            Types.TypeInfo arrayTypeInfo = conversionState.GetArrayTypeInfo();
            int            lengthOffset  = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "length").OffsetInBytes;

            int currOpPosition = conversionState.PositionOf(theOp);

            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);

            // 1. Check array reference is not null
            //      1.1. Move array ref into $t0
            //      1.2. Compare $t0 (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            // 2. Load array length


            //      1.1. Move array ref into eax
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "0($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //      1.2. Compare eax (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            conversionState.Append(new ASMOps.Branch()
            {
                Src1 = "$t0", Src2 = "0", BranchType = ASMOps.BranchOp.BranchNotZero, DestILPosition = currOpPosition, Extension = "ContinueExecution1", UnsignedTest = false
            });
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            conversionState.Append(new ASMOps.Call()
            {
                Target = "GetEIP"
            });
            conversionState.AddExternalLabel("GetEIP");
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "ContinueExecution1"
            });

            //2. Load array length
            //  - Pop array ref
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t2"
            });
            //  - Load length from array ref
            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = lengthOffset.ToString() + "($t2)", Dest = "$t0" });
            GlobalMethods.LoadData(conversionState, theOp, "$t2", "$t0", lengthOffset, 4);
            //  - Push array length
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Word, Src = "$t0"
            });

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = false,
                sizeOnStackInBytes = 4,
                isGCManaged        = false,
                isValue            = true
            });
        }
Beispiel #28
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown when loading a static float field.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Load static field

            //Load the metadata token used to get the field info
            int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            //Get the field info for the field to load
            FieldInfo theField = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);
            //Get the ID (i.e. ASM label) of the field to load
            string fieldID = conversionState.GetFieldInfo(theField.DeclaringType, theField.Name).ID;

            conversionState.AddExternalLabel(fieldID);

            //Load the field or field address
            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Ldsfld:
            {
                Types.TypeInfo theTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theField.FieldType);
                int            size        = theTypeInfo.IsValueType ? theTypeInfo.SizeOnHeapInBytes : theTypeInfo.SizeOnStackInBytes;
                bool           isFloat     = Utilities.IsFloat(theField.FieldType);

                if (isFloat)
                {
                    //SUPPORT - floats
                    throw new NotSupportedException("Loading static fields of type float not supported yet!");
                }

                if (size == 1)
                {
                    conversionState.Append(new ASMOps.Xor()
                        {
                            Src = "EAX", Dest = "EAX"
                        });
                    conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Byte, Src = "[" + fieldID + "]", Dest = "AL"
                        });
                    conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Dword, Src = "EAX"
                        });
                }
                else if (size == 2)
                {
                    conversionState.Append(new ASMOps.Xor()
                        {
                            Src = "EAX", Dest = "EAX"
                        });
                    conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "[" + fieldID + "]", Dest = "AX"
                        });
                    conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Dword, Src = "EAX"
                        });
                }
                else
                {
                    for (int i = size; i > 0;)
                    {
                        int diff = i % 4;
                        diff = diff == 0 ? 4 : diff;
                        i   -= diff;
                        switch (diff)
                        {
                        case 1:
                            conversionState.Append(new ASMOps.Xor()
                                {
                                    Src = "EAX", Dest = "EAX"
                                });
                            conversionState.Append(new ASMOps.Mov()
                                {
                                    Size = ASMOps.OperandSize.Byte, Src = "[" + fieldID + " + " + i + "]", Dest = "AL"
                                });
                            conversionState.Append(new ASMOps.Push()
                                {
                                    Size = ASMOps.OperandSize.Dword, Src = "EAX"
                                });
                            break;

                        case 2:
                            conversionState.Append(new ASMOps.Xor()
                                {
                                    Src = "EAX", Dest = "EAX"
                                });
                            conversionState.Append(new ASMOps.Mov()
                                {
                                    Size = ASMOps.OperandSize.Word, Src = "[" + fieldID + " + " + i + "]", Dest = "AX"
                                });
                            conversionState.Append(new ASMOps.Push()
                                {
                                    Size = ASMOps.OperandSize.Dword, Src = "EAX"
                                });
                            break;

                        case 3:
                            conversionState.Append(new ASMOps.Xor()
                                {
                                    Src = "EAX", Dest = "EAX"
                                });
                            conversionState.Append(new ASMOps.Mov()
                                {
                                    Size = ASMOps.OperandSize.Byte, Src = "[" + fieldID + " + " + i + "]", Dest = "AL"
                                });
                            conversionState.Append(new ASMOps.Push()
                                {
                                    Size = ASMOps.OperandSize.Word, Src = "AX"
                                });
                            conversionState.Append(new ASMOps.Mov()
                                {
                                    Size = ASMOps.OperandSize.Word, Src = "[" + fieldID + " + " + (i + 1) + "]", Dest = "AX"
                                });
                            conversionState.Append(new ASMOps.Push()
                                {
                                    Size = ASMOps.OperandSize.Word, Src = "AX"
                                });
                            break;

                        default:
                            conversionState.Append(new ASMOps.Mov()
                                {
                                    Size = ASMOps.OperandSize.Dword, Src = "[" + fieldID + " + " + i + "]", Dest = "EAX"
                                });
                            conversionState.Append(new ASMOps.Push()
                                {
                                    Size = ASMOps.OperandSize.Dword, Src = "EAX"
                                });
                            break;
                        }
                    }
                }

                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = isFloat,
                        sizeOnStackInBytes = theTypeInfo.SizeOnStackInBytes,
                        isGCManaged        = theTypeInfo.IsGCManaged,
                        isValue            = theTypeInfo.IsValueType
                    });
            }
            break;

            case OpCodes.Ldsflda:
                //Load the address of the field i.e. address of the ASM label
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Dword, Src = fieldID
                });

                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat            = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged        = false,
                    isValue            = false
                });
                break;
            }
        }
Beispiel #29
0
        /// <summary>
        /// Scans the specified library and any dependencies.
        /// </summary>
        /// <param name="TheLibrary">The library to scan.</param>
        /// <returns>
        /// CompileResult.OK if completed successfully.
        /// Otherwise CompileResult.PartialFail or CompileResult.Error depending on
        /// the extent of the problem.
        /// </returns>
        public static CompileResult Scan(ILLibrary TheLibrary)
        {
            CompileResult result = CompileResult.OK;

            if (TheLibrary.ILScanned)
            {
                return(result);
            }
            TheLibrary.ILScanned = true;

            foreach (ILLibrary depLib in TheLibrary.Dependencies)
            {
                Scan(depLib);
            }

            // Create / Add Static Fields ASM Block
            ASM.ASMBlock StaticFieldsBlock = new ASM.ASMBlock()
            {
                Priority = (long.MinValue / 2) - 9
            };
            TheLibrary.TheASMLibrary.ASMBlocks.Add(StaticFieldsBlock);

            // Create / Add Types Table ASM Block
            ASM.ASMBlock TypesTableBlock = new ASM.ASMBlock()
            {
                Priority = (long.MinValue / 2) - 8
            };
            TheLibrary.TheASMLibrary.ASMBlocks.Add(TypesTableBlock);

            // Create / Add Method Tables ASM Block
            ASM.ASMBlock MethodTablesBlock = new ASM.ASMBlock()
            {
                Priority = (long.MinValue / 2) + 0
            };
            TheLibrary.TheASMLibrary.ASMBlocks.Add(MethodTablesBlock);

            // Create / Add Field Tables ASM Block
            ASM.ASMBlock FieldTablesBlock = new ASM.ASMBlock()
            {
                Priority = (long.MinValue / 2) + 1
            };
            TheLibrary.TheASMLibrary.ASMBlocks.Add(FieldTablesBlock);

            // Don't use foreach or you get collection modified exceptions
            for (int i = 0; i < TheLibrary.TypeInfos.Count; i++)
            {
                Types.TypeInfo aTypeInfo = TheLibrary.TypeInfos[i];
                if (!ScannedTypes.ContainsKey(aTypeInfo.ID))
                {
                    ScannedTypes.Add(aTypeInfo.ID, TheLibrary);
                    ScanStaticFields(TheLibrary, aTypeInfo, StaticFieldsBlock);
                    ScanType(TheLibrary, aTypeInfo, TypesTableBlock);
                    ScanMethods(TheLibrary, aTypeInfo, MethodTablesBlock);
                    ScanFields(TheLibrary, aTypeInfo, FieldTablesBlock);
                }
            }

            foreach (Types.MethodInfo aMethodInfo in TheLibrary.ILBlocks.Keys)
            {
                ILBlock       anILBlock    = TheLibrary.ILBlocks[aMethodInfo];
                CompileResult singleResult = CompileResult.OK;

                if (anILBlock.Plugged)
                {
                    singleResult = ScanPluggedILBlock(TheLibrary, aMethodInfo, anILBlock);
                }
                else
                {
                    singleResult = ScanNonpluggedILBlock(TheLibrary, aMethodInfo, anILBlock);
                }

                if (result != CompileResult.OK)
                {
                    result = singleResult;
                }
            }

            // Create / Add String Literals ASM Block
            #region String Literals Block

            ASM.ASMBlock StringLiteralsBlock = new ASM.ASMBlock()
            {
                Priority = (long.MinValue / 2) - 10
            };
            TheLibrary.TheASMLibrary.ASMBlocks.Add(StringLiteralsBlock);

            string StringTypeId = ILLibrary.SpecialClasses[typeof(Attributes.StringClassAttribute)].First().ID;
            StringLiteralsBlock.AddExternalLabel(StringTypeId);
            foreach (KeyValuePair <string, string> aStringLiteral in TheLibrary.StringLiterals)
            {
                string value       = aStringLiteral.Value;
                byte[] lengthBytes = BitConverter.GetBytes(value.Length);

                ASM.ASMOp newLiteralOp = TargetArchitecture.CreateASMOp(ASM.OpCodes.StringLiteral,
                                                                        aStringLiteral.Key, StringTypeId, lengthBytes, value.ToCharArray());

                StringLiteralsBlock.Append(newLiteralOp);
            }

            #endregion

            return(result);
        }
Beispiel #30
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown when loading a static float field.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Load the metadata token used to get the type info
            int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            //Get the type info for the object to load
            Type theType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);

            Types.TypeInfo theTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theType);

            //Get the object size information
            int memSize = theTypeInfo.IsValueType ? theTypeInfo.SizeOnHeapInBytes : theTypeInfo.SizeOnStackInBytes;

            //Load the object onto the stack
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Dword, Dest = "ECX"
            });

            int irregularSize = memSize % 4;

            if (irregularSize > 0)
            {
                conversionState.Append(new ASMOps.Xor()
                {
                    Src = "EAX", Dest = "EAX"
                });
                switch (irregularSize)
                {
                case 1:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "[ECX+" + (memSize - 1).ToString() + "]", Dest = "AL"
                    });
                    break;

                case 2:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "[ECX+" + (memSize - 2).ToString() + "]", Dest = "AX"
                    });
                    break;

                case 3:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "[ECX+" + (memSize - 1).ToString() + "]", Dest = "AL"
                    });
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Dest = "EAX", Src = "16"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "[ECX+" + (memSize - 3).ToString() + "]", Dest = "AX"
                    });
                    break;
                }
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "EAX"
                });
            }

            for (int i = memSize - irregularSize - 4; i >= 0; i -= 4)
            {
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "[ECX+" + i.ToString() + "]", Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "EAX"
                });
            }

            // Pop address
            conversionState.CurrentStackFrame.Stack.Pop();
            // Push value
            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = false,
                sizeOnStackInBytes = memSize,
                isGCManaged        = false,
                isValue            = theTypeInfo.IsValueType
            });
        }