From 1d146df18571eb62500da47318166a1bf2d60abc Mon Sep 17 00:00:00 2001 From: kudzu_cp <6d05c8c8ef5431987001abfdb2eadc9593ac9498> Date: Wed, 9 Sep 2009 18:40:49 +0000 Subject: [PATCH] --- .../Indy.IL2CPU/IL/InitVmtImplementationOp.cs | 542 ++++++++---------- .../Cosmos.IL2CPU.Profiler/Assembler.cs | 21 + source2/IL2PCU/Cosmos.IL2CPU.X86/Assembler.cs | 30 + source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Newobj.cs | 1 + .../Cosmos.IL2CPU/Assembler/Assembler.cs | 221 ++++++- source2/IL2PCU/Cosmos.IL2CPU/ILScanner.cs | 2 + source2/Users/Kudzu/HelloWorld/Program.cs | 2 +- 7 files changed, 496 insertions(+), 323 deletions(-) diff --git a/source/Indy.IL2CPU/IL/InitVmtImplementationOp.cs b/source/Indy.IL2CPU/IL/InitVmtImplementationOp.cs index 1a754b0cf..3f31b3b73 100644 --- a/source/Indy.IL2CPU/IL/InitVmtImplementationOp.cs +++ b/source/Indy.IL2CPU/IL/InitVmtImplementationOp.cs @@ -8,326 +8,238 @@ using System.Reflection; using Indy.IL2CPU.Compiler; namespace Indy.IL2CPU.IL { - public class MethodBaseComparer : IComparer, IEqualityComparer - { - #region IComparer Members - public int Compare(MethodBase x, MethodBase y) - { - return x.GetFullName().CompareTo(y.GetFullName()); - } - #endregion - - public bool Equals(MethodBase x, MethodBase y) - { - return Compare(x, y) == 0; - } - - public int GetHashCode(MethodBase obj) - { - return obj.GetFullName().GetHashCode(); - } + public class MethodBaseComparer: IComparer, IEqualityComparer { + #region IComparer Members + public int Compare(MethodBase x, MethodBase y) { + return x.GetFullName().CompareTo(y.GetFullName()); } - public abstract class InitVmtImplementationOp: Op { - public delegate int GetMethodIdentifierEventHandler(MethodBase aMethod); - public InitVmtImplementationOp(ILReader aReader, MethodInformation aMethodInfo) - : base(aReader, aMethodInfo) { - } - private static readonly bool mDebugMode = false; - static InitVmtImplementationOp() { - // flag for conditional debug code for Matthijs, please leave it. - mDebugMode = Environment.MachineName.Equals("laptop-matthijs", StringComparison.InvariantCultureIgnoreCase); + #endregion + + public bool Equals(MethodBase x, MethodBase y) { + return Compare(x, y) == 0; + } + + public int GetHashCode(MethodBase obj) { + return obj.GetFullName().GetHashCode(); + } + } + public abstract class InitVmtImplementationOp: Op { + public delegate int GetMethodIdentifierEventHandler(MethodBase aMethod); + public InitVmtImplementationOp(ILReader aReader, MethodInformation aMethodInfo) + : base(aReader, aMethodInfo) { + } + private static readonly bool mDebugMode = false; + static InitVmtImplementationOp() { + // flag for conditional debug code for Matthijs, please leave it. + mDebugMode = Environment.MachineName.Equals("laptop-matthijs", StringComparison.InvariantCultureIgnoreCase); + } + private IList mTypes; + public MethodBase LoadTypeTableRef; + public MethodBase SetTypeInfoRef; + public MethodBase SetMethodInfoRef; + public FieldInfo TypesFieldRef; + public uint VTableEntrySize; + public uint ArrayTypeId; + public IList Methods; + public event GetMethodIdentifierEventHandler GetMethodIdentifier; + + public IList Types { + get { + return mTypes; + } + set { + mTypes = value; + } + } + + protected abstract void Push(uint aValue); + protected abstract void Push(string aLabelName); + protected abstract void Call(MethodBase aMethod); + protected abstract void Move(string aDestLabelName, int aValue); + + public override void DoAssemble() { + string xTheName = DataMember.GetStaticFieldName(TypesFieldRef); + DataMember xDataMember = (from item in Assembler.DataMembers + where item.Name == xTheName + select item).FirstOrDefault(); + if (xDataMember != null) { + Assembler.DataMembers.Remove((from item in Assembler.DataMembers + where item == xDataMember + select item).First()); + } + var xData = new byte[16 + (mTypes.Count * VTableEntrySize)]; + var xTemp = BitConverter.GetBytes(ArrayTypeId); + xTemp = BitConverter.GetBytes(0x80000002); + Array.Copy(xTemp, 0, xData, 4, 4); + xTemp = BitConverter.GetBytes(mTypes.Count); + Array.Copy(xTemp, 0, xData, 8, 4); + xTemp = BitConverter.GetBytes(VTableEntrySize); + Array.Copy(xTemp, 0, xData, 12, 4); + Assembler.DataMembers.Add(new DataMember(xTheName + "__Contents", xData)); + Assembler.DataMembers.Add(new DataMember(xTheName, ElementReference.New(xTheName + "__Contents"))); + Push((uint)mTypes.Count); + Call(LoadTypeTableRef); + for (int i = 0; i < mTypes.Count; i++) { + Type xType = mTypes[i]; + // value contains true if the method is an interface method definition + SortedList xEmittedMethods = new SortedList(new MethodBaseComparer()); + foreach (MethodBase xMethod in xType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { + if (Methods.Contains(xMethod))//) && !xMethod.IsAbstract) + { + xEmittedMethods.Add(xMethod, false); + } } - private IList mTypes; - public MethodBase LoadTypeTableRef; - public MethodBase SetTypeInfoRef; - public MethodBase SetMethodInfoRef; - public FieldInfo TypesFieldRef; - public uint VTableEntrySize; - public uint ArrayTypeId; - public IList Methods; - public event GetMethodIdentifierEventHandler GetMethodIdentifier; + foreach (MethodBase xCtor in xType.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { + if (Methods.Contains(xCtor))// && !xCtor.IsAbstract) + { + xEmittedMethods.Add(xCtor, false); + } + } + foreach (var xIntf in xType.GetInterfaces()) { + foreach (var xMethodIntf in xIntf.GetMethods()) { + var xActualMethod = xType.GetMethod(xIntf.FullName + "." + xMethodIntf.Name, + (from xParam in xMethodIntf.GetParameters() + select xParam.ParameterType).ToArray()); - public IList Types { - get { - return mTypes; - } - set { - mTypes = value; - } - } - - protected abstract void Push(uint aValue); - protected abstract void Push(string aLabelName); - protected abstract void Call(MethodBase aMethod); - protected abstract void Move(string aDestLabelName, int aValue); - - public override void DoAssemble() { - XmlWriter xDebug=null; - if (mDebugMode) - { - xDebug = XmlWriter.Create(@"d:\vtables.xml"); - xDebug.WriteStartDocument(); - xDebug.WriteStartElement("VTables"); - xDebug.WriteStartElement("AllMethods"); - for (int i = 0; i < Methods.Count; i++) - { - MethodBase xTheMethod = Methods[i]; - xDebug.WriteStartElement("Method"); - xDebug.WriteAttributeString("Id", GetMethodIdentifier(xTheMethod).ToString("X")); - xDebug.WriteAttributeString("Name", xTheMethod.GetFullName()); - xDebug.WriteEndElement(); - } - xDebug.WriteEndElement(); + if (xActualMethod == null) { + // get private implemenation + xActualMethod = xType.GetMethod(xMethodIntf.Name, + (from xParam in xMethodIntf.GetParameters() + select xParam.ParameterType).ToArray()); } - string xTheName = DataMember.GetStaticFieldName(TypesFieldRef); - DataMember xDataMember = (from item in Assembler.DataMembers - where item.Name == xTheName - select item).FirstOrDefault(); - if (xDataMember != null) { - Assembler.DataMembers.Remove((from item in Assembler.DataMembers - where item == xDataMember - select item).First()); - } - var xData = new byte[16 + (mTypes.Count * VTableEntrySize)]; - var xTemp = BitConverter.GetBytes(ArrayTypeId); - Array.Copy(xTemp, 0, xData, 0, 4); - xTemp = BitConverter.GetBytes(0x80000002); - Array.Copy(xTemp, 0, xData, 4, 4); - xTemp = BitConverter.GetBytes(mTypes.Count); - Array.Copy(xTemp, 0, xData, 8, 4); - xTemp = BitConverter.GetBytes(VTableEntrySize); - Array.Copy(xTemp, 0, xData, 12, 4); - Assembler.DataMembers.Add(new DataMember(xTheName + "__Contents", xData)); - Assembler.DataMembers.Add(new DataMember(xTheName, ElementReference.New(xTheName + "__Contents"))); - Push((uint)mTypes.Count); - Call(LoadTypeTableRef); - for (int i = 0; i < mTypes.Count; i++) { - if (mDebugMode) - { - xDebug.WriteStartElement("Type"); - xDebug.WriteAttributeString("Id", i.ToString("X")); - xDebug.WriteAttributeString("Name", MethodInfoLabelGenerator.GetFullName(mTypes[i])); + if (xActualMethod == null) { + try { + var xMap = xType.GetInterfaceMap(xIntf); + for (int k = 0; k < xMap.InterfaceMethods.Length; k++) { + if (xMap.InterfaceMethods[k] == xMethodIntf) { + xActualMethod = xMap.TargetMethods[k]; + break; + } } - try - { - Type xType = mTypes[i]; - if(xType == typeof(ConsoleKey)) - { - Console.Write(""); - } - // value contains true if the method is an interface method definition - SortedList xEmittedMethods = new SortedList(new MethodBaseComparer()); - foreach (MethodBase xMethod in xType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) - { - if (Methods.Contains(xMethod))//) && !xMethod.IsAbstract) - { - xEmittedMethods.Add(xMethod, false); - } - } - foreach (MethodBase xCtor in xType.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) - { - if (Methods.Contains(xCtor))// && !xCtor.IsAbstract) - { - xEmittedMethods.Add(xCtor, false); - } - } - foreach (var xIntf in xType.GetInterfaces()) - { - foreach (var xMethodIntf in xIntf.GetMethods()) - { - var xActualMethod = xType.GetMethod(xIntf.FullName + "." + xMethodIntf.Name, - (from xParam in xMethodIntf.GetParameters() - select xParam.ParameterType).ToArray()); - - if (xActualMethod == null) - { - // get private implemenation - xActualMethod = xType.GetMethod(xMethodIntf.Name, - (from xParam in xMethodIntf.GetParameters() - select xParam.ParameterType).ToArray()); - } if (xActualMethod == null) - { - try - { - var xMap = xType.GetInterfaceMap(xIntf); - for (int k = 0; k < xMap.InterfaceMethods.Length; k++) - { - if (xMap.InterfaceMethods[k] == xMethodIntf) - { - xActualMethod = xMap.TargetMethods[k]; - break; - } - } - } - catch { } - } - if (Methods.Contains(xMethodIntf)) - { - if (!xEmittedMethods.ContainsKey(xMethodIntf)) - { - xEmittedMethods.Add(xMethodIntf, - true); - } - } - - } - } - if (xType == typeof(object)) - { Console.Write(""); } - if (!xType.IsInterface) - { - Push((uint)i); - } - int? xBaseIndex = null; - if (xType.BaseType == null) - { - xBaseIndex = i; - } - else - { - for (int t = 0; t < mTypes.Count; t++) - { - if (mTypes[t].ToString() == xType.BaseType.ToString()) - { - xBaseIndex = t; - break; - } - } - } - if (xBaseIndex == null) - { - throw new Exception("Base type not found!"); - } - if (mDebugMode) - { - xDebug.WriteAttributeString("BaseId", xBaseIndex.Value.ToString("X")); - } - for (int x = xEmittedMethods.Count - 1; x >= 0; x--) { - if (!Methods.Contains(xEmittedMethods.Keys[x])) { xEmittedMethods.RemoveAt(x); } - } - if (!xType.IsInterface) - { - //Move(GetService().GetTypeIdLabel(xType), i); - Assembler.DataMembers.Add( - new DataMember(GetService().GetTypeIdLabel(xType), new int[] {i})); - Push((uint)xBaseIndex.Value); - //Push("0" + xEmittedMethods.Count.ToString("X") + "h"); - xData = new byte[16 + (xEmittedMethods.Count * 4)]; - xTemp = BitConverter.GetBytes(ArrayTypeId); - Array.Copy(xTemp, 0, xData, 0, 4); - xTemp = BitConverter.GetBytes(0x80000002); // embedded array - Array.Copy(xTemp, 0, xData, 4, 4); - xTemp = BitConverter.GetBytes(xEmittedMethods.Count); // embedded array - Array.Copy(xTemp, 0, xData, 8, 4); - xTemp = BitConverter.GetBytes(4); // embedded array - Array.Copy(xTemp, 0, xData, 12, 4); - string xDataName = "____SYSTEM____TYPE___" + DataMember.FilterStringForIncorrectChars(mTypes[i].AssemblyQualifiedName) + "__MethodIndexesArray"; - Assembler.DataMembers.Add(new DataMember(xDataName, xData)); - Push(xDataName); - xDataName = "____SYSTEM____TYPE___" + DataMember.FilterStringForIncorrectChars(mTypes[i].AssemblyQualifiedName) + "__MethodAddressesArray"; - Assembler.DataMembers.Add(new DataMember(xDataName, xData)); - Push(xDataName); - xData = new byte[16 + Encoding.Unicode.GetByteCount(mTypes[i].FullName + ", " + mTypes[i].Module.Assembly.GetName().FullName)]; - xTemp = BitConverter.GetBytes(ArrayTypeId); - Array.Copy(xTemp, 0, xData, 0, 4); - xTemp = BitConverter.GetBytes(0x80000002); // embedded array - Array.Copy(xTemp, 0, xData, 4, 4); - xTemp = BitConverter.GetBytes((mTypes[i].FullName + ", " + mTypes[i].Module.Assembly.GetName().FullName).Length); - Array.Copy(xTemp, 0, xData, 8, 4); - xTemp = BitConverter.GetBytes(2); // embedded array - Array.Copy(xTemp, 0, xData, 12, 4); - xDataName = "____SYSTEM____TYPE___" + DataMember.FilterStringForIncorrectChars(MethodInfoLabelGenerator.GetFullName(mTypes[i])); - mAssembler.DataMembers.Add(new DataMember(xDataName, xData)); - Push((uint)xEmittedMethods.Count); - //Push("0"); - Call(SetTypeInfoRef); - } - for (int j = 0; j < xEmittedMethods.Count; j++) - { - MethodBase xMethod = xEmittedMethods.Keys[j]; - var xMethodId = GetMethodIdentifier(xMethod); - if (mDebugMode) - { - xDebug.WriteStartElement("Method"); - xDebug.WriteAttributeString("Id", xMethodId.ToString("X")); - xDebug.WriteAttributeString("Name", xMethod.GetFullName()); - xDebug.WriteEndElement(); - } - if (!xType.IsInterface) - { - if (xEmittedMethods.Values[j]) - { - var xNewMethod = xType.GetMethod(xMethod.DeclaringType.FullName + "." + xMethod.Name, - (from xParam in xMethod.GetParameters() - select xParam.ParameterType).ToArray()); - - if (xNewMethod == null) - { - // get private implemenation - xNewMethod = xType.GetMethod(xMethod.Name, - (from xParam in xMethod.GetParameters() - select xParam.ParameterType).ToArray()); - } - if (xNewMethod == null) - { - try - { - var xMap = xType.GetInterfaceMap(xMethod.DeclaringType); - for (int k = 0; k < xMap.InterfaceMethods.Length; k++) - { - if (xMap.InterfaceMethods[k] == xMethod) - { - xNewMethod = xMap.TargetMethods[k]; - break; - } - } - } - catch { } - } - if (xNewMethod == null) { System.Diagnostics.Debugger.Break(); } - xMethod = xNewMethod; - } - //Move(GetService().GetMethodIdLabel(xMethod), xMethodId); - Assembler.DataMembers.Add( - new DataMember(GetService().GetMethodIdLabel(xMethod), - new int[] {xMethodId})); - - Push((uint)i); - Push((uint)j); - - Push((uint)xMethodId); - if (xMethod.IsAbstract) - { - // abstract methods dont have bodies, oiw, are not emitted - Push(0); - } - else - { - var xTest = GetService().GetMethodInfo(xMethod, false); - Push(xTest.LabelName); - } - //xDataValue = Encoding.ASCII.GetBytes(GetFullName(xMethod)).Aggregate("", (b, x) => b + x + ",") + "0"; - //xDataName = "____SYSTEM____METHOD___" + DataMember.FilterStringForIncorrectChars(GetFullName(xMethod)); - //mAssembler.DataMembers.Add(new DataMember(xDataName, "db", xDataValue)); - //Push(xDataName); - Push(0); - Call(SetMethodInfoRef); - } - } - } - finally - { - if (mDebugMode) - { - xDebug.WriteEndElement(); - } - } - } - if (mDebugMode) - { - xDebug.Close(); + } catch { + } + } + if (Methods.Contains(xMethodIntf)) { + if (!xEmittedMethods.ContainsKey(xMethodIntf)) { + xEmittedMethods.Add(xMethodIntf, + true); + } } - } - } + } + } + if (!xType.IsInterface) { + Push((uint)i); + } + int? xBaseIndex = null; + if (xType.BaseType == null) { + xBaseIndex = i; + } else { + for (int t = 0; t < mTypes.Count; t++) { + if (mTypes[t].ToString() == xType.BaseType.ToString()) { + xBaseIndex = t; + break; + } + } + } + if (xBaseIndex == null) { + throw new Exception("Base type not found!"); + } + for (int x = xEmittedMethods.Count - 1; x >= 0; x--) { + if (!Methods.Contains(xEmittedMethods.Keys[x])) { + xEmittedMethods.RemoveAt(x); + } + } + if (!xType.IsInterface) { + //Move(GetService().GetTypeIdLabel(xType), i); + Assembler.DataMembers.Add( + new DataMember(GetService().GetTypeIdLabel(xType), new int[] { i })); + Push((uint)xBaseIndex.Value); + //Push("0" + xEmittedMethods.Count.ToString("X") + "h"); + xData = new byte[16 + (xEmittedMethods.Count * 4)]; + xTemp = BitConverter.GetBytes(ArrayTypeId); + Array.Copy(xTemp, 0, xData, 0, 4); + xTemp = BitConverter.GetBytes(0x80000002); // embedded array + Array.Copy(xTemp, 0, xData, 4, 4); + xTemp = BitConverter.GetBytes(xEmittedMethods.Count); // embedded array + Array.Copy(xTemp, 0, xData, 8, 4); + xTemp = BitConverter.GetBytes(4); // embedded array + Array.Copy(xTemp, 0, xData, 12, 4); + string xDataName = "____SYSTEM____TYPE___" + DataMember.FilterStringForIncorrectChars(mTypes[i].AssemblyQualifiedName) + "__MethodIndexesArray"; + Assembler.DataMembers.Add(new DataMember(xDataName, xData)); + Push(xDataName); + xDataName = "____SYSTEM____TYPE___" + DataMember.FilterStringForIncorrectChars(mTypes[i].AssemblyQualifiedName) + "__MethodAddressesArray"; + Assembler.DataMembers.Add(new DataMember(xDataName, xData)); + Push(xDataName); + xData = new byte[16 + Encoding.Unicode.GetByteCount(mTypes[i].FullName + ", " + mTypes[i].Module.Assembly.GetName().FullName)]; + xTemp = BitConverter.GetBytes(ArrayTypeId); + Array.Copy(xTemp, 0, xData, 0, 4); + xTemp = BitConverter.GetBytes(0x80000002); // embedded array + Array.Copy(xTemp, 0, xData, 4, 4); + xTemp = BitConverter.GetBytes((mTypes[i].FullName + ", " + mTypes[i].Module.Assembly.GetName().FullName).Length); + Array.Copy(xTemp, 0, xData, 8, 4); + xTemp = BitConverter.GetBytes(2); // embedded array + Array.Copy(xTemp, 0, xData, 12, 4); + xDataName = "____SYSTEM____TYPE___" + DataMember.FilterStringForIncorrectChars(MethodInfoLabelGenerator.GetFullName(mTypes[i])); + mAssembler.DataMembers.Add(new DataMember(xDataName, xData)); + Push((uint)xEmittedMethods.Count); + //Push("0"); + Call(SetTypeInfoRef); + } + for (int j = 0; j < xEmittedMethods.Count; j++) { + MethodBase xMethod = xEmittedMethods.Keys[j]; + var xMethodId = GetMethodIdentifier(xMethod); + if (!xType.IsInterface) { + if (xEmittedMethods.Values[j]) { + var xNewMethod = xType.GetMethod(xMethod.DeclaringType.FullName + "." + xMethod.Name, + (from xParam in xMethod.GetParameters() + select xParam.ParameterType).ToArray()); + + if (xNewMethod == null) { + // get private implemenation + xNewMethod = xType.GetMethod(xMethod.Name, + (from xParam in xMethod.GetParameters() + select xParam.ParameterType).ToArray()); + } + if (xNewMethod == null) { + try { + var xMap = xType.GetInterfaceMap(xMethod.DeclaringType); + for (int k = 0; k < xMap.InterfaceMethods.Length; k++) { + if (xMap.InterfaceMethods[k] == xMethod) { + xNewMethod = xMap.TargetMethods[k]; + break; + } + } + } catch { + } + } + xMethod = xNewMethod; + } + //Move(GetService().GetMethodIdLabel(xMethod), xMethodId); + Assembler.DataMembers.Add( + new DataMember(GetService().GetMethodIdLabel(xMethod), + new int[] { xMethodId })); + + Push((uint)i); + Push((uint)j); + + Push((uint)xMethodId); + if (xMethod.IsAbstract) { + // abstract methods dont have bodies, oiw, are not emitted + Push(0); + } else { + var xTest = GetService().GetMethodInfo(xMethod, false); + Push(xTest.LabelName); + } + //xDataValue = Encoding.ASCII.GetBytes(GetFullName(xMethod)).Aggregate("", (b, x) => b + x + ",") + "0"; + //xDataName = "____SYSTEM____METHOD___" + DataMember.FilterStringForIncorrectChars(GetFullName(xMethod)); + //mAssembler.DataMembers.Add(new DataMember(xDataName, "db", xDataValue)); + //Push(xDataName); + Push(0); + Call(SetMethodInfoRef); + } + } + } + } + } } diff --git a/source2/IL2PCU/Cosmos.IL2CPU.Profiler/Assembler.cs b/source2/IL2PCU/Cosmos.IL2CPU.Profiler/Assembler.cs index b3927ae32..795d454b5 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU.Profiler/Assembler.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU.Profiler/Assembler.cs @@ -26,5 +26,26 @@ namespace Cosmos.IL2CPU.Profiler { protected override void MethodEnd(MethodInfo aMethod) { } + + protected override void Push(uint aValue) { + throw new NotImplementedException(); + } + + protected override void Push(string aLabelName) { + throw new NotImplementedException(); + } + + protected override void Call(System.Reflection.MethodBase aMethod) { + throw new NotImplementedException(); + } + + protected override void Move(string aDestLabelName, int aValue) { + throw new NotImplementedException(); + } + + protected override int GetVTableEntrySize() { + return 0; + } + } } diff --git a/source2/IL2PCU/Cosmos.IL2CPU.X86/Assembler.cs b/source2/IL2PCU/Cosmos.IL2CPU.X86/Assembler.cs index 9222c40dd..4600346a8 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU.X86/Assembler.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU.X86/Assembler.cs @@ -165,5 +165,35 @@ namespace Cosmos.IL2CPU.X86 { aOutput.WriteLine("org 0x200000"); base.FlushText(aOutput); } + + protected override void Move(string aDestLabelName, int aValue) { + new Move { + DestinationRef = ElementReference.New(aDestLabelName), + DestinationIsIndirect = true, + SourceValue = (uint)aValue + }; + } + + protected override void Push(uint aValue) { + new Push { + DestinationValue = aValue + }; + } + + protected override void Push(string aLabelName) { + new Push { + DestinationRef = ElementReference.New(aLabelName) + }; + } + + protected override void Call(MethodBase aMethod) { + new IL2CPU.X86.Call { + DestinationLabel = CPU.MethodInfoLabelGenerator.GenerateLabelName(aMethod) + }; + } + + protected override int GetVTableEntrySize() { + return 16; // todo: retrieve from actual type info + } } } diff --git a/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Newobj.cs b/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Newobj.cs index 87bf10dc5..4c7b5f749 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Newobj.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Newobj.cs @@ -101,6 +101,7 @@ namespace Cosmos.IL2CPU.X86.IL //select item ).Count(); int xGCFieldCount = xType.GetFields().Count( x => x.FieldType.IsValueType ); + // todo: use a cleaner approach here. this class shouldnt assemble the string string strTypeId = "VMT__TYPE_ID_HOLDER__" + xMethod.Value.DeclaringType.FullName; new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; diff --git a/source2/IL2PCU/Cosmos.IL2CPU/Assembler/Assembler.cs b/source2/IL2PCU/Cosmos.IL2CPU/Assembler/Assembler.cs index 56d47feff..b987930dd 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU/Assembler/Assembler.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU/Assembler/Assembler.cs @@ -5,6 +5,9 @@ using System.Reflection.Emit; using System.Text; using System.Threading; using System.IO; +using System.Reflection; +using Indy.IL2CPU; +using Indy.IL2CPU.IL; namespace Cosmos.IL2CPU { @@ -22,11 +25,15 @@ namespace Cosmos.IL2CPU { private System.IO.TextWriter mLog; #region Properties public List DataMembers { - get { return mDataMembers; } + get { + return mDataMembers; + } } public List Instructions { - get { return mInstructions; } + get { + return mInstructions; + } } public static Assembler CurrentInstance { get { @@ -109,7 +116,6 @@ namespace Cosmos.IL2CPU { new Comment(this, "---------------------------------------------------------"); new Comment(this, "Type: " + aMethod.MethodBase.DeclaringType.ToString()); new Comment(this, "Name: " + aMethod.MethodBase.Name); - new Comment(this, aMethod.Type.ToString()); new Comment(this, "Plugged: " + (aMethod.PlugMethod == null ? "No" : "Yes")); } @@ -143,14 +149,15 @@ namespace Cosmos.IL2CPU { } else { xILOp = mILOpsHi[xOpCodeVal & 0xFF]; } - mLog.WriteLine ( "\t[" + xILOp.ToString() + "] \t Stack start: " + Stack.Count.ToString() ); + //mLog.WriteLine ( "\t[" + xILOp.ToString() + "] \t Stack start: " + Stack.Count.ToString() ); + mLog.WriteLine("\t{0} {1}", Stack.Count, xILOp.GetType().Name); mLog.Flush(); new Comment(this, "[" + xILOp.ToString() + "]"); BeforeOp(aMethod, xOpCode); xILOp.Execute(aMethod, xOpCode); AfterOp(aMethod, xOpCode); - mLog.WriteLine( " end: " + Stack.Count.ToString() ); - + //mLog.WriteLine( " end: " + Stack.Count.ToString() ); + } MethodEnd(aMethod); } @@ -257,5 +264,205 @@ namespace Cosmos.IL2CPU { } } + protected abstract void Push(uint aValue); + protected abstract void Push(string aLabelName); + protected abstract void Call(MethodBase aMethod); + protected abstract void Move(string aDestLabelName, int aValue); + protected abstract int GetVTableEntrySize(); + + private void GenerateVMTCode(IList aTypes, IList aMethods) { + // initialization + var xSetTypeInfoRef = VTablesImplRefs.SetTypeInfoRef; + var xSetMethodInfoRef = VTablesImplRefs.SetMethodInfoRef; + var xLoadTypeTableRef = VTablesImplRefs.LoadTypeTableRef; + var xTypesFieldRef = VTablesImplRefs.VTablesImplDef.GetField("mTypes", + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + // data we need but dont have: + + // end initialization + string xTheName = DataMember.GetStaticFieldName(xTypesFieldRef); + DataMember xDataMember = (from item in Assembler.mCurrentInstance.DataMembers + where item.Name == xTheName + select item).FirstOrDefault(); + if (xDataMember != null) { + Assembler.mCurrentInstance.DataMembers.Remove((from item in Assembler.mCurrentInstance.DataMembers + where item == xDataMember + select item).First()); + } + var xData = new byte[16 + (aTypes.Count * GetVTableEntrySize())]; + var xTemp = BitConverter.GetBytes(aTypes.IndexOf(typeof(Array))); + xTemp = BitConverter.GetBytes(0x80000002); + Array.Copy(xTemp, 0, xData, 4, 4); + xTemp = BitConverter.GetBytes(aTypes.Count); + Array.Copy(xTemp, 0, xData, 8, 4); + xTemp = BitConverter.GetBytes(GetVTableEntrySize()); + Array.Copy(xTemp, 0, xData, 12, 4); + Assembler.mCurrentInstance.DataMembers.Add(new DataMember(xTheName + "__Contents", xData)); + Assembler.mCurrentInstance.DataMembers.Add(new DataMember(xTheName, ElementReference.New(xTheName + "__Contents"))); + Push((uint)aTypes.Count); + Call(xLoadTypeTableRef); + for (int i = 0; i < aTypes.Count; i++) { + Type xType = aTypes[i]; + // value contains true if the method is an interface method definition + SortedList xEmittedMethods = new SortedList(new MethodBaseComparer()); + foreach (MethodBase xMethod in xType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { + if (aMethods.Contains(xMethod))//) && !xMethod.IsAbstract) + { + xEmittedMethods.Add(xMethod, false); + } + } + foreach (MethodBase xCtor in xType.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { + if (aMethods.Contains(xCtor))// && !xCtor.IsAbstract) + { + xEmittedMethods.Add(xCtor, false); + } + } + foreach (var xIntf in xType.GetInterfaces()) { + foreach (var xMethodIntf in xIntf.GetMethods()) { + var xActualMethod = xType.GetMethod(xIntf.FullName + "." + xMethodIntf.Name, + (from xParam in xMethodIntf.GetParameters() + select xParam.ParameterType).ToArray()); + + if (xActualMethod == null) { + // get private implemenation + xActualMethod = xType.GetMethod(xMethodIntf.Name, + (from xParam in xMethodIntf.GetParameters() + select xParam.ParameterType).ToArray()); + } + if (xActualMethod == null) { + try { + var xMap = xType.GetInterfaceMap(xIntf); + for (int k = 0; k < xMap.InterfaceMethods.Length; k++) { + if (xMap.InterfaceMethods[k] == xMethodIntf) { + xActualMethod = xMap.TargetMethods[k]; + break; + } + } + } catch { + } + } + if (aMethods.Contains(xMethodIntf)) { + if (!xEmittedMethods.ContainsKey(xMethodIntf)) { + xEmittedMethods.Add(xMethodIntf, + true); + } + } + + } + } + if (!xType.IsInterface) { + Push((uint)i); + } + int? xBaseIndex = null; + if (xType.BaseType == null) { + xBaseIndex = i; + } else { + for (int t = 0; t < aTypes.Count; t++) { + // todo: optimize check + if (aTypes[t].ToString() == xType.BaseType.ToString()) { + xBaseIndex = t; + break; + } + } + } + if (xBaseIndex == null) { + throw new Exception("Base type not found!"); + } + for (int x = xEmittedMethods.Count - 1; x >= 0; x--) { + if (!aMethods.Contains(xEmittedMethods.Keys[x])) { + xEmittedMethods.RemoveAt(x); + } + } + if (!xType.IsInterface) { + //Move(GetService().GetTypeIdLabel(xType), i); + Assembler.mCurrentInstance.DataMembers.Add( + new DataMember("VMT__TYPE_ID_HOLDER__" + xType.FullName, new int[] { i })); + Push((uint)xBaseIndex.Value); + //Push("0" + xEmittedMethods.Count.ToString("X") + "h"); + xData = new byte[16 + (xEmittedMethods.Count * 4)]; + xTemp = BitConverter.GetBytes(aTypes.IndexOf(typeof(Array))); + Array.Copy(xTemp, 0, xData, 0, 4); + xTemp = BitConverter.GetBytes(0x80000002); // embedded array + Array.Copy(xTemp, 0, xData, 4, 4); + xTemp = BitConverter.GetBytes(xEmittedMethods.Count); // embedded array + Array.Copy(xTemp, 0, xData, 8, 4); + xTemp = BitConverter.GetBytes(4); // embedded array + Array.Copy(xTemp, 0, xData, 12, 4); + string xDataName = "____SYSTEM____TYPE___" + DataMember.FilterStringForIncorrectChars(aTypes[i].AssemblyQualifiedName) + "__MethodIndexesArray"; + Assembler.mCurrentInstance.DataMembers.Add(new DataMember(xDataName, xData)); + Push(xDataName); + xDataName = "____SYSTEM____TYPE___" + DataMember.FilterStringForIncorrectChars(aTypes[i].AssemblyQualifiedName) + "__MethodAddressesArray"; + Assembler.mCurrentInstance.DataMembers.Add(new DataMember(xDataName, xData)); + Push(xDataName); + xData = new byte[16 + Encoding.Unicode.GetByteCount(aTypes[i].FullName + ", " + aTypes[i].Module.Assembly.GetName().FullName)]; + xTemp = BitConverter.GetBytes(aTypes.IndexOf(typeof(Array))); + Array.Copy(xTemp, 0, xData, 0, 4); + xTemp = BitConverter.GetBytes(0x80000002); // embedded array + Array.Copy(xTemp, 0, xData, 4, 4); + xTemp = BitConverter.GetBytes((aTypes[i].FullName + ", " + aTypes[i].Module.Assembly.GetName().FullName).Length); + Array.Copy(xTemp, 0, xData, 8, 4); + xTemp = BitConverter.GetBytes(2); // embedded array + Array.Copy(xTemp, 0, xData, 12, 4); + xDataName = "____SYSTEM____TYPE___" + DataMember.FilterStringForIncorrectChars(MethodInfoLabelGenerator.GetFullName(aTypes[i])); + Assembler.CurrentInstance.DataMembers.Add(new DataMember(xDataName, xData)); + Push((uint)xEmittedMethods.Count); + //Push("0"); + Call(xSetTypeInfoRef); + } + for (int j = 0; j < xEmittedMethods.Count; j++) { + MethodBase xMethod = xEmittedMethods.Keys[j]; + var xMethodId = aMethods.IndexOf(xMethod); + if (!xType.IsInterface) { + if (xEmittedMethods.Values[j]) { + var xNewMethod = xType.GetMethod(xMethod.DeclaringType.FullName + "." + xMethod.Name, + (from xParam in xMethod.GetParameters() + select xParam.ParameterType).ToArray()); + + if (xNewMethod == null) { + // get private implemenation + xNewMethod = xType.GetMethod(xMethod.Name, + (from xParam in xMethod.GetParameters() + select xParam.ParameterType).ToArray()); + } + if (xNewMethod == null) { + try { + var xMap = xType.GetInterfaceMap(xMethod.DeclaringType); + for (int k = 0; k < xMap.InterfaceMethods.Length; k++) { + if (xMap.InterfaceMethods[k] == xMethod) { + xNewMethod = xMap.TargetMethods[k]; + break; + } + } + } catch { + } + } + xMethod = xNewMethod; + } + //Move(GetService().GetMethodIdLabel(xMethod), xMethodId); + //Assembler.DataMembers.Add( + // new DataMember(GetService().GetMethodIdLabel(xMethod), + // new int[] { xMethodId })); + + Push((uint)i); + Push((uint)j); + + Push((uint)xMethodId); + if (xMethod.IsAbstract) { + // abstract methods dont have bodies, oiw, are not emitted + Push(0); + } else { + //var xTest = GetService().GetMethodInfo(xMethod, false); + //Push(xTest.LabelName); + } + //xDataValue = Encoding.ASCII.GetBytes(GetFullName(xMethod)).Aggregate("", (b, x) => b + x + ",") + "0"; + //xDataName = "____SYSTEM____METHOD___" + DataMember.FilterStringForIncorrectChars(GetFullName(xMethod)); + //mAssembler.DataMembers.Add(new DataMember(xDataName, "db", xDataValue)); + //Push(xDataName); + Push(0); + //Call(SetMethodInfoRef); + } + } + } + } } -} +} \ No newline at end of file diff --git a/source2/IL2PCU/Cosmos.IL2CPU/ILScanner.cs b/source2/IL2PCU/Cosmos.IL2CPU/ILScanner.cs index 26cada376..01d65d8ad 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU/ILScanner.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU/ILScanner.cs @@ -198,6 +198,8 @@ namespace Cosmos.IL2CPU { } //TODO: Look for Field plugs } + // register any "system" types: + QueueType(typeof(Array)); } ExecuteInternal( ( System.Reflection.MethodInfo )RuntimeEngineRefs.InitializeApplicationRef, true ); diff --git a/source2/Users/Kudzu/HelloWorld/Program.cs b/source2/Users/Kudzu/HelloWorld/Program.cs index 26d6460c9..f06e34d42 100644 --- a/source2/Users/Kudzu/HelloWorld/Program.cs +++ b/source2/Users/Kudzu/HelloWorld/Program.cs @@ -27,7 +27,7 @@ namespace HelloWorld { var xEntryPoint = typeof(Program).GetMethod("Init", BindingFlags.Public | BindingFlags.Static); xScanner.Execute(xEntryPoint); - + //xScanner.Execute( ( System.Reflection.MethodInfo )RuntimeEngineRefs.InitializeApplicationRef ); //xScanner.Execute( ( System.Reflection.MethodInfo )RuntimeEngineRefs.FinalizeApplicationRef ); ////xScanner.QueueMethod(typeof(CosmosAssembler).GetMethod("PrintException"));