using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace Indy.IL2CPU.IL { // TODO: abstract this one out to a X86 specific one public class MethodInformation { public struct Variable { public Variable(int aOffset, int aSize, bool aIsReferenceTypeField, Type aVariableType) { Offset = aOffset; Size = aSize; VirtualAddresses = new string[Size / 4]; for (int i = 0; i < (Size / 4); i++) { VirtualAddresses[i] = "ebp - 0" + (Offset + ((i + 1) * 4) + 0).ToString("X") + "h"; } IsReferenceType = aIsReferenceTypeField; VariableType = aVariableType; } public readonly int Offset; public readonly int Size; public readonly bool IsReferenceType; public readonly Type VariableType; /// /// Gives the list of addresses to access this variable. This field contains multiple entries if the is larger than 4. /// public readonly string[] VirtualAddresses; } public struct Argument { public enum KindEnum { In, ByRef, Out } public Argument(int aSize, int aOffset, KindEnum aKind, bool mIsReferenceType, Type aArgumentType) { Size = aSize; Offset = aOffset; VirtualAddresses = new string[Size / 4]; for (int i = 0; i < (Size / 4); i++) { VirtualAddresses[i] = "ebp + 0" + (Offset + ((i + 1) * 4) + 4).ToString("X") + "h"; } Kind = aKind; ArgumentType = aArgumentType; IsReferenceType = mIsReferenceType; } public readonly string[] VirtualAddresses; public readonly int Size; public readonly bool IsReferenceType; public readonly int Offset; public readonly KindEnum Kind; public readonly Type ArgumentType; } public MethodInformation(string aLabelName, Variable[] aLocals, Argument[] aArguments, int aReturnSize, bool aIsInstanceMethod, TypeInformation aTypeInfo, MethodBase aMethod, Type aReturnType) { Locals = aLocals; LabelName = aLabelName; Arguments = aArguments; ReturnSize = aReturnSize; IsInstanceMethod = aIsInstanceMethod; TypeInfo = aTypeInfo; Method = aMethod; ReturnType = aReturnType; LocalsSize = (from item in aLocals let xSize = (item.Size % 4 == 0) ? item.Size : (item.Size + (4 - (item.Size % 4))) select xSize).Sum(); } /// /// This variable is only updated when the MethodInformation instance is supplied by the Engine.ProcessAllMethods method /// public ExceptionHandlingClause CurrentHandler; public readonly MethodBase Method; public readonly string LabelName; public readonly Variable[] Locals; public readonly Argument[] Arguments; public readonly int ReturnSize; public readonly Type ReturnType; public readonly bool IsInstanceMethod; public readonly TypeInformation TypeInfo; public readonly int LocalsSize; public override string ToString() { StringBuilder xSB = new StringBuilder(); xSB.AppendLine(String.Format("Method '{0}'\r\n", Method.GetFullName())); xSB.AppendLine("Locals:"); if (Locals.Length == 0) { xSB.AppendLine("\t(none)"); } int xCurIndex = 0; foreach (Variable xVar in Locals) { xSB.AppendFormat("\t({0}) {1}\t{2}\t{3} (Type = {4})\r\n\r\n", xCurIndex++, xVar.Offset, xVar.Size, xVar.VirtualAddresses.FirstOrDefault(), xVar.VariableType.FullName); } xSB.AppendLine("Arguments:"); if (Arguments.Length == 0) { xSB.AppendLine("\t(none)"); } xCurIndex = 0; foreach (Argument xArg in Arguments) { xSB.AppendLine(String.Format("\t({0}) {1}\t{2}\t{3} (Type = {4})\r\n", xCurIndex++, xArg.Offset, xArg.Size, xArg.VirtualAddresses.FirstOrDefault(), xArg.ArgumentType.FullName)); } xSB.AppendLine("\tReturnSize: " + ReturnSize); return xSB.ToString(); } } }