From e8a3321cf7fb92cc60f510b91fb4a0fa44dd80f5 Mon Sep 17 00:00:00 2001 From: mterwoord_cp <7cd3fd84a0151ea055c2f79e4d2eef9576fe9afesxUZAwxD> Date: Fri, 11 Sep 2009 17:00:39 +0000 Subject: [PATCH] implemented static field scanning. seems to work great. --- source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Stsfld.cs | 2 +- .../Cosmos.IL2CPU/Assembler/Assembler.cs | 83 +++++++++++++++++++ source2/IL2PCU/Cosmos.IL2CPU/ILOp.cs | 2 +- source2/IL2PCU/Cosmos.IL2CPU/ILScanner.cs | 18 ++++ 4 files changed, 103 insertions(+), 2 deletions(-) diff --git a/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Stsfld.cs b/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Stsfld.cs index 581fa5f1a..ed0d893ad 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Stsfld.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Stsfld.cs @@ -39,7 +39,7 @@ namespace Cosmos.IL2CPU.X86.IL xOffset += SizeOfType( xInfo.FieldType ); } - string xDataName = "static_field__" + MethodInfoLabelGenerator.GetFullName( xField.DeclaringType ) + "." + xField.Name; + string xDataName = "static_field__" + DataMember.FilterStringForIncorrectChars(MethodInfoLabelGenerator.GetFullName(xField.DeclaringType) + "." + xField.Name); if( xNeedsGC ) { new CPUx86.Push { DestinationRef = ElementReference.New( xDataName ), DestinationIsIndirect = true }; diff --git a/source2/IL2PCU/Cosmos.IL2CPU/Assembler/Assembler.cs b/source2/IL2PCU/Cosmos.IL2CPU/Assembler/Assembler.cs index b26885c42..6fc71eaac 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU/Assembler/Assembler.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU/Assembler/Assembler.cs @@ -8,6 +8,7 @@ using System.IO; using System.Reflection; using Indy.IL2CPU; using Indy.IL2CPU.IL; +using System.Runtime.InteropServices; namespace Cosmos.IL2CPU { @@ -464,5 +465,87 @@ namespace Cosmos.IL2CPU { } } } + + public void ProcessField(FieldInfo aField) { + string xFieldName = MethodInfoLabelGenerator.GetFullName(aField); + xFieldName = DataMember.GetStaticFieldName(aField); + if (DataMembers.Count(x => x.Name == xFieldName) == 0) { + var xItemList = (from item in aField.GetCustomAttributes(false) + where item.GetType().FullName == "ManifestResourceStreamAttribute" + select item).ToList(); + + object xItem = null; + if (xItemList.Count > 0) + xItem = xItemList[0]; + string xManifestResourceName = null; + if (xItem != null) { + var xItemType = xItem.GetType(); + xManifestResourceName = (string)xItemType.GetField("ResourceName").GetValue(xItem); + } + if (xManifestResourceName != null) { + // todo: add support for manifest streams again + //RegisterType(xCurrentField.FieldType); + //string xFileName = Path.Combine(mOutputDir, + // (xCurrentField.DeclaringType.Assembly.FullName + "__" + xManifestResourceName).Replace(",", + // "_") + ".res"); + //using (var xStream = xCurrentField.DeclaringType.Assembly.GetManifestResourceStream(xManifestResourceName)) { + // if (xStream == null) { + // throw new Exception("Resource '" + xManifestResourceName + "' not found!"); + // } + // using (var xTarget = File.Create(xFileName)) { + // // todo: abstract this array code out. + // xTarget.Write(BitConverter.GetBytes(Engine.RegisterType(Engine.GetType("mscorlib", + // "System.Array"))), + // 0, + // 4); + // xTarget.Write(BitConverter.GetBytes((uint)InstanceTypeEnum.StaticEmbeddedArray), + // 0, + // 4); + // xTarget.Write(BitConverter.GetBytes((int)xStream.Length), 0, 4); + // xTarget.Write(BitConverter.GetBytes((int)1), 0, 4); + // var xBuff = new byte[128]; + // while (xStream.Position < xStream.Length) { + // int xBytesRead = xStream.Read(xBuff, 0, 128); + // xTarget.Write(xBuff, 0, xBytesRead); + // } + // } + //} + //mAssembler.DataMembers.Add(new DataMember("___" + xFieldName + "___Contents", + // "incbin", + // "\"" + xFileName + "\"")); + //mAssembler.DataMembers.Add(new DataMember(xFieldName, + // "dd", + // "___" + xFieldName + "___Contents")); + throw new NotImplementedException(); + } else { + uint xTheSize; + //string theType = "db"; + Type xFieldTypeDef = aField.FieldType; + if (!xFieldTypeDef.IsClass || xFieldTypeDef.IsValueType) { + xTheSize = ILOp.SizeOfType(aField.FieldType); + } else { + xTheSize = 4; + } + byte[] xData = new byte[xTheSize]; + try { + object xValue = aField.GetValue(null); + if (xValue != null) { + try { + xData = new byte[xTheSize]; + if (xValue.GetType().IsValueType) { + for (int x = 0; x < xTheSize; x++) { + xData[x] = Marshal.ReadByte(xValue, + x); + } + } + } catch { + } + } + } catch { + } + DataMembers.Add(new DataMember(xFieldName, xData)); + } + } + } } } \ No newline at end of file diff --git a/source2/IL2PCU/Cosmos.IL2CPU/ILOp.cs b/source2/IL2PCU/Cosmos.IL2CPU/ILOp.cs index f4d28c985..0fc768094 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU/ILOp.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU/ILOp.cs @@ -14,7 +14,7 @@ namespace Cosmos.IL2CPU { // could be used for other things, profiling, analysis, reporting, etc public abstract void Execute(MethodInfo aMethod, ILOpCode aOpCode); - protected static uint SizeOfType(Type aType) { + public static uint SizeOfType(Type aType) { if (aType.FullName == "System.Void") { return 0; } else if ((!aType.IsValueType && aType.IsClass) || aType.IsInterface) { diff --git a/source2/IL2PCU/Cosmos.IL2CPU/ILScanner.cs b/source2/IL2PCU/Cosmos.IL2CPU/ILScanner.cs index 3d08869c1..0dadf4ef2 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU/ILScanner.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU/ILScanner.cs @@ -47,6 +47,8 @@ namespace Cosmos.IL2CPU { protected HashSet mTypesSet = new HashSet(); protected List mTypes = new List(); + protected HashSet mStaticFields = new HashSet(); + // Logging // Only use for debugging and profiling. protected bool mLogEnabled = false; @@ -442,6 +444,11 @@ namespace Cosmos.IL2CPU { ((ILOpCodes.OpMethod)xOpCode).ValueUID = QueueMethod(aMethodInfo.MethodBase, "Call", ((ILOpCodes.OpMethod)xOpCode).Value, false); } else if (xOpCode is ILOpCodes.OpType) { QueueType(aMethodInfo.MethodBase, "OpCode Value", ((ILOpCodes.OpType)xOpCode).Value); + } else if (xOpCode is ILOpCodes.OpField) { + var xOpField = (ILOpCodes.OpField)xOpCode; + if (xOpField.Value.IsStatic) { + QueueField(aMethodInfo.MethodBase, "OpCode Value", xOpField); + } } } @@ -452,6 +459,17 @@ namespace Cosmos.IL2CPU { } } + private void QueueField(object aSrc, string aSrcType, Cosmos.IL2CPU.ILOpCodes.OpField xOpField) { + // todo: add log map thing? + if (!mStaticFields.Contains(xOpField.Value)) { + mStaticFields.Add(xOpField.Value); + mAsmblr.ProcessField(xOpField.Value); + + QueueType(xOpField.Value, "FieldType", xOpField.Value.FieldType); + QueueType(xOpField.Value, "DeclaringType", xOpField.Value.FieldType); + } + } + // System.ThrowHelper exists in MS .NET twice... // Its an internal class that exists in both mscorlib and system assemblies. // They are separate types though, so normally the scanner scans both and