implemented static field scanning. seems to work great.

This commit is contained in:
mterwoord_cp 2009-09-11 17:00:39 +00:00
parent cb5aacad9e
commit e8a3321cf7
4 changed files with 103 additions and 2 deletions

View file

@ -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 };

View file

@ -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));
}
}
}
}
}

View file

@ -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) {

View file

@ -47,6 +47,8 @@ namespace Cosmos.IL2CPU {
protected HashSet<Type> mTypesSet = new HashSet<Type>();
protected List<Type> mTypes = new List<Type>();
protected HashSet<FieldInfo> mStaticFields = new HashSet<FieldInfo>();
// 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