From 1ea78b247fd84f91f6a032d87f0a0fd89aee12f7 Mon Sep 17 00:00:00 2001 From: mterwoord_cp <7cd3fd84a0151ea055c2f79e4d2eef9576fe9afesxUZAwxD> Date: Wed, 26 Sep 2007 09:12:43 +0000 Subject: [PATCH] Some more ops are working now. Still working on the VTables support. Next Op to implement is Switch --- .../Indy.IL2CPU.Assembler.X86.csproj | 1 + source/Indy.IL2CPU.Assembler.X86/Neg.cs | 17 ++++ source/Indy.IL2CPU.IL.X86/Box.cs | 12 ++- source/Indy.IL2CPU.IL.X86/Castclass.cs | 30 +++++- source/Indy.IL2CPU.IL.X86/Conv_I1.cs | 2 +- source/Indy.IL2CPU.IL.X86/Conv_I2.cs | 2 +- source/Indy.IL2CPU.IL.X86/Conv_R4.cs | 2 +- source/Indy.IL2CPU.IL.X86/Conv_R8.cs | 2 +- source/Indy.IL2CPU.IL.X86/Conv_U1.cs | 2 +- source/Indy.IL2CPU.IL.X86/Conv_U2.cs | 2 +- source/Indy.IL2CPU.IL.X86/Isinst.cs | 29 +++++- source/Indy.IL2CPU.IL.X86/Ldfld.cs | 4 +- source/Indy.IL2CPU.IL.X86/Ldtoken.cs | 18 ++-- source/Indy.IL2CPU.IL.X86/Neg.cs | 4 +- source/Indy.IL2CPU.IL.X86/Unbox.cs | 29 +++++- source/Indy.IL2CPU.IL.X86/Unbox_Any.cs | 5 +- .../CustomMethodImplementationProxyOp.cs | 3 - .../System/EnvironmentImpl.cs | 13 +++ source/Indy.IL2CPU/Engine.cs | 97 +++++++++++++++---- source/Indy.IL2CPU/Indy.IL2CPU.csproj | 1 + source/Indy.IL2CPU/VTablesImpl.cs | 26 +++-- 21 files changed, 243 insertions(+), 58 deletions(-) create mode 100644 source/Indy.IL2CPU.Assembler.X86/Neg.cs create mode 100644 source/Indy.IL2CPU/CustomImplementation/System/EnvironmentImpl.cs diff --git a/source/Indy.IL2CPU.Assembler.X86/Indy.IL2CPU.Assembler.X86.csproj b/source/Indy.IL2CPU.Assembler.X86/Indy.IL2CPU.Assembler.X86.csproj index 317a32da6..04c39f6fb 100644 --- a/source/Indy.IL2CPU.Assembler.X86/Indy.IL2CPU.Assembler.X86.csproj +++ b/source/Indy.IL2CPU.Assembler.X86/Indy.IL2CPU.Assembler.X86.csproj @@ -64,6 +64,7 @@ + diff --git a/source/Indy.IL2CPU.Assembler.X86/Neg.cs b/source/Indy.IL2CPU.Assembler.X86/Neg.cs new file mode 100644 index 000000000..d07c79cc4 --- /dev/null +++ b/source/Indy.IL2CPU.Assembler.X86/Neg.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Indy.IL2CPU.Assembler.X86 { + [OpCode(0xFFFFFFFF, "neg")] + public class Neg: Instruction { + private string mDestination; + public Neg(string aDestination) { + mDestination = aDestination; + } + public override string ToString() { + return "neg " + mDestination; + } + } +} \ No newline at end of file diff --git a/source/Indy.IL2CPU.IL.X86/Box.cs b/source/Indy.IL2CPU.IL.X86/Box.cs index db314a7b0..55946e7c6 100644 --- a/source/Indy.IL2CPU.IL.X86/Box.cs +++ b/source/Indy.IL2CPU.IL.X86/Box.cs @@ -19,17 +19,21 @@ namespace Indy.IL2CPU.IL.X86 { throw new Exception("Couldn't determine Type!"); } mTheSize = Engine.GetFieldStorageSize(xTypeRef); - if (mTheSize != 4) { - throw new Exception("Storage size not supported yet!"); + if(((mTheSize/4)*4) != mTheSize) { + throw new Exception("Incorrect Datasize. ( ((mTheSize / 4) * 4) === mTheSize should evaluate to true!"); } Engine.RegisterType(Engine.GetDefinitionFromTypeReference(xTypeRef)); } public override void DoAssemble() { - Pushd("0" + mTheSize.ToString("X").ToUpper() + "h"); + Pushd("0" + (mTheSize + ObjectImpl.FieldDataOffset).ToString("X").ToUpper() + "h"); Call(new Label(RuntimeEngineRefs.Heap_AllocNewObjectRef).Name); - Pushd("eax"); Move(Assembler, "dword [eax + 4]", "0" + InstanceTypeEnum.NormalObject.ToString("X") + "h"); + for (int i = 0; i < (mTheSize / 4); i++ ) { + Pop("edx"); + Move(Assembler, "dword [eax + 0" + (ObjectImpl.FieldDataOffset + (i * 4)).ToString("X") + "h]", "edx"); + } + Pushd("eax"); } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU.IL.X86/Castclass.cs b/source/Indy.IL2CPU.IL.X86/Castclass.cs index a1a12ab5b..998281535 100644 --- a/source/Indy.IL2CPU.IL.X86/Castclass.cs +++ b/source/Indy.IL2CPU.IL.X86/Castclass.cs @@ -2,16 +2,42 @@ using System; using System.IO; using Mono.Cecil; using Mono.Cecil.Cil; -using CPU = Indy.IL2CPU.Assembler.X86; +using CPU = Indy.IL2CPU.Assembler; namespace Indy.IL2CPU.IL.X86 { [OpCode(Code.Castclass, false)] public class Castclass: Op { + private int mTypeId; + private string mThisLabel; + private string mNextOpLabel; public Castclass(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo) : base(aInstruction, aMethodInfo) { + TypeReference xType = aInstruction.Operand as TypeReference; + if(xType==null) { + throw new Exception("Unable to determine Type!"); + } + TypeDefinition xTypeDef = Engine.GetDefinitionFromTypeReference(xType); + mTypeId = Engine.RegisterType(xTypeDef); + mThisLabel = GetInstructionLabel(aInstruction); + mNextOpLabel = GetInstructionLabel(aInstruction.Next); } + public override void DoAssemble() { - throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!"); + // todo: throw an exception when the class does not support the cast! + string mReturnNullLabel = mThisLabel + "_ReturnNull"; + Pop("eax"); + Compare("eax", "0"); + JumpIfZero(mReturnNullLabel); + Pushd("[eax]", "0" + mTypeId + "h"); + MethodDefinition xMethodIsInstance = Engine.GetMethodDefinition(Engine.GetTypeDefinition("", "Indy.IL2CPU.VTablesImpl"), "IsInstance", "System.Int32", "System.Int32"); + Engine.QueueMethod(xMethodIsInstance); + Call(new CPU.Label(xMethodIsInstance).Name); + Compare("eax", "0"); + JumpIfEquals(mReturnNullLabel); + Pushd("eax"); + JumpAlways(mNextOpLabel); + Label(mReturnNullLabel); + Pushd("0"); } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU.IL.X86/Conv_I1.cs b/source/Indy.IL2CPU.IL.X86/Conv_I1.cs index 6910866d3..effa621bd 100644 --- a/source/Indy.IL2CPU.IL.X86/Conv_I1.cs +++ b/source/Indy.IL2CPU.IL.X86/Conv_I1.cs @@ -11,7 +11,7 @@ namespace Indy.IL2CPU.IL.X86 { : base(aInstruction, aMethodInfo) { } public override void DoAssemble() { - throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!"); + // todo: implement correct truncating } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU.IL.X86/Conv_I2.cs b/source/Indy.IL2CPU.IL.X86/Conv_I2.cs index a6e1b61ee..87c2883e6 100644 --- a/source/Indy.IL2CPU.IL.X86/Conv_I2.cs +++ b/source/Indy.IL2CPU.IL.X86/Conv_I2.cs @@ -11,7 +11,7 @@ namespace Indy.IL2CPU.IL.X86 { : base(aInstruction, aMethodInfo) { } public override void DoAssemble() { - throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!"); + // todo: implement correct truncating } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU.IL.X86/Conv_R4.cs b/source/Indy.IL2CPU.IL.X86/Conv_R4.cs index 12cf5c030..c365a0089 100644 --- a/source/Indy.IL2CPU.IL.X86/Conv_R4.cs +++ b/source/Indy.IL2CPU.IL.X86/Conv_R4.cs @@ -11,7 +11,7 @@ namespace Indy.IL2CPU.IL.X86 { : base(aInstruction, aMethodInfo) { } public override void DoAssemble() { - throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!"); + // todo: implement correct conversion } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU.IL.X86/Conv_R8.cs b/source/Indy.IL2CPU.IL.X86/Conv_R8.cs index 4cd45bb43..dd687d592 100644 --- a/source/Indy.IL2CPU.IL.X86/Conv_R8.cs +++ b/source/Indy.IL2CPU.IL.X86/Conv_R8.cs @@ -11,7 +11,7 @@ namespace Indy.IL2CPU.IL.X86 { : base(aInstruction, aMethodInfo) { } public override void DoAssemble() { - throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!"); + // todo: implement correct conversion } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU.IL.X86/Conv_U1.cs b/source/Indy.IL2CPU.IL.X86/Conv_U1.cs index b359962db..2f6641175 100644 --- a/source/Indy.IL2CPU.IL.X86/Conv_U1.cs +++ b/source/Indy.IL2CPU.IL.X86/Conv_U1.cs @@ -11,7 +11,7 @@ namespace Indy.IL2CPU.IL.X86 { : base(aInstruction, aMethodInfo) { } public override void DoAssemble() { - throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!"); + // todo: implement correct truncating } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU.IL.X86/Conv_U2.cs b/source/Indy.IL2CPU.IL.X86/Conv_U2.cs index 8891f1ba5..e79adb84e 100644 --- a/source/Indy.IL2CPU.IL.X86/Conv_U2.cs +++ b/source/Indy.IL2CPU.IL.X86/Conv_U2.cs @@ -11,7 +11,7 @@ namespace Indy.IL2CPU.IL.X86 { : base(aInstruction, aMethodInfo) { } public override void DoAssemble() { - throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!"); + // todo: implement correct truncating } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU.IL.X86/Isinst.cs b/source/Indy.IL2CPU.IL.X86/Isinst.cs index 62f6e91e8..a1a1e39b7 100644 --- a/source/Indy.IL2CPU.IL.X86/Isinst.cs +++ b/source/Indy.IL2CPU.IL.X86/Isinst.cs @@ -2,16 +2,41 @@ using System; using System.IO; using Mono.Cecil; using Mono.Cecil.Cil; -using CPU = Indy.IL2CPU.Assembler.X86; +using CPU = Indy.IL2CPU.Assembler; +using CPUx86 = Indy.IL2CPU.Assembler.X86; namespace Indy.IL2CPU.IL.X86 { [OpCode(Code.Isinst)] public class Isinst: Op { + private int mTypeId; + private string mThisLabel; + private string mNextOpLabel; public Isinst(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo) : base(aInstruction, aMethodInfo) { + TypeReference xType = aInstruction.Operand as TypeReference; + if(xType==null) { + throw new Exception("Unable to determine Type!"); + } + TypeDefinition xTypeDef = Engine.GetDefinitionFromTypeReference(xType); + mTypeId = Engine.RegisterType(xTypeDef); + mThisLabel = GetInstructionLabel(aInstruction); + mNextOpLabel = GetInstructionLabel(aInstruction.Next); } public override void DoAssemble() { - throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!"); + string mReturnNullLabel = mThisLabel + "_ReturnNull"; + Pop("eax"); + Compare("eax", "0"); + JumpIfZero(mReturnNullLabel); + Pushd("[eax]", "0" + mTypeId + "h"); + MethodDefinition xMethodIsInstance = Engine.GetMethodDefinition(Engine.GetTypeDefinition("", "Indy.IL2CPU.VTablesImpl"), "IsInstance", "System.Int32", "System.Int32"); + Engine.QueueMethod(xMethodIsInstance); + Call(new CPU.Label(xMethodIsInstance).Name); + Compare("eax", "0"); + JumpIfEquals(mReturnNullLabel); + Pushd("eax"); + JumpAlways(mNextOpLabel); + Label(mReturnNullLabel); + Pushd("0"); } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU.IL.X86/Ldfld.cs b/source/Indy.IL2CPU.IL.X86/Ldfld.cs index fc941652c..b45f139f4 100644 --- a/source/Indy.IL2CPU.IL.X86/Ldfld.cs +++ b/source/Indy.IL2CPU.IL.X86/Ldfld.cs @@ -15,8 +15,8 @@ namespace Indy.IL2CPU.IL.X86 { } string xFieldId = xField.ToString(); TypeInformation.Field xTheField; - uint xStorageSize; - xTheField = Engine.GetTypeFieldInfo(Engine.GetDefinitionFromTypeReference(xField.DeclaringType), out xStorageSize)[xFieldId]; + uint xStorageSize; + xTheField = Engine.GetTypeFieldInfo(Engine.GetDefinitionFromTypeReference(xField.DeclaringType), out xStorageSize)[xFieldId]; RelativeAddress = xTheField.RelativeAddress; FieldSize = xTheField.Size; if (FieldSize != 4) { diff --git a/source/Indy.IL2CPU.IL.X86/Ldtoken.cs b/source/Indy.IL2CPU.IL.X86/Ldtoken.cs index a258dcc03..024ecb3b2 100644 --- a/source/Indy.IL2CPU.IL.X86/Ldtoken.cs +++ b/source/Indy.IL2CPU.IL.X86/Ldtoken.cs @@ -12,14 +12,20 @@ namespace Indy.IL2CPU.IL.X86 { public Ldtoken(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo) : base(aInstruction, aMethodInfo) { FieldDefinition xFieldDef = aInstruction.Operand as FieldDefinition; - if (xFieldDef == null) { - throw new Exception("Unsupported Token type!"); + if (xFieldDef != null) { + if (!xFieldDef.IsStatic) { + throw new Exception("Nonstatic field-backed tokens not supported yet!"); + } + Engine.QueueStaticField(xFieldDef); + mTokenAddress = DataMember.GetStaticFieldName(xFieldDef); + return; } - if (!xFieldDef.IsStatic) { - throw new Exception("Nonstatic field-backed tokens not supported yet!"); + TypeReference xTypeRef = aInstruction.Operand as TypeReference; + if(xTypeRef!=null) { + mTokenAddress = "0" + Engine.RegisterType(Engine.GetDefinitionFromTypeReference(xTypeRef)).ToString("X") + "h"; + return; } - Engine.QueueStaticField(xFieldDef); - mTokenAddress=DataMember.GetStaticFieldName(xFieldDef); + throw new Exception("Token type not supported yet!"); } public override void DoAssemble() { diff --git a/source/Indy.IL2CPU.IL.X86/Neg.cs b/source/Indy.IL2CPU.IL.X86/Neg.cs index c8ecfd9fd..6f89c301f 100644 --- a/source/Indy.IL2CPU.IL.X86/Neg.cs +++ b/source/Indy.IL2CPU.IL.X86/Neg.cs @@ -11,7 +11,9 @@ namespace Indy.IL2CPU.IL.X86 { : base(aInstruction, aMethodInfo) { } public override void DoAssemble() { - throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!"); + Pop("eax"); + Assembler.Add(new CPU.Neg("eax")); + Pushd("eax"); } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU.IL.X86/Unbox.cs b/source/Indy.IL2CPU.IL.X86/Unbox.cs index 55175f50e..6ba7ecd33 100644 --- a/source/Indy.IL2CPU.IL.X86/Unbox.cs +++ b/source/Indy.IL2CPU.IL.X86/Unbox.cs @@ -2,16 +2,41 @@ using System; using System.IO; using Mono.Cecil; using Mono.Cecil.Cil; -using CPU = Indy.IL2CPU.Assembler.X86; +using CPU = Indy.IL2CPU.Assembler; +using CPUx86 = Indy.IL2CPU.Assembler.X86; namespace Indy.IL2CPU.IL.X86 { [OpCode(Code.Unbox)] public class Unbox: Op { + private int mTypeId; + private string mThisLabel; + private string mNextOpLabel; public Unbox(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo) : base(aInstruction, aMethodInfo) { + TypeReference xType = aInstruction.Operand as TypeReference; + if(xType==null) { + throw new Exception("Unable to determine Type!"); + } + TypeDefinition xTypeDef = Engine.GetDefinitionFromTypeReference(xType); + mTypeId = Engine.RegisterType(xTypeDef); + mThisLabel = GetInstructionLabel(aInstruction); + mNextOpLabel = GetInstructionLabel(aInstruction.Next); } public override void DoAssemble() { - throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!"); + string mReturnNullLabel = mThisLabel + "_ReturnNull"; + Pop("eax"); + Compare("eax", "0"); + JumpIfZero(mReturnNullLabel); + Pushd("[eax]", "0" + mTypeId + "h"); + MethodDefinition xMethodIsInstance = Engine.GetMethodDefinition(Engine.GetTypeDefinition("", "Indy.IL2CPU.VTablesImpl"), "IsInstance", "System.Int32", "System.Int32"); + Engine.QueueMethod(xMethodIsInstance); + Call(new CPU.Label(xMethodIsInstance).Name); + Compare("eax", "0"); + JumpIfEquals(mReturnNullLabel); + Pushd("eax"); + JumpAlways(mNextOpLabel); + Label(mReturnNullLabel); + Pushd("0"); } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU.IL.X86/Unbox_Any.cs b/source/Indy.IL2CPU.IL.X86/Unbox_Any.cs index 46f1cd2fd..65b3b9607 100644 --- a/source/Indy.IL2CPU.IL.X86/Unbox_Any.cs +++ b/source/Indy.IL2CPU.IL.X86/Unbox_Any.cs @@ -6,12 +6,9 @@ using CPU = Indy.IL2CPU.Assembler.X86; namespace Indy.IL2CPU.IL.X86 { [OpCode(Code.Unbox_Any)] - public class Unbox_Any: Op { + public class Unbox_Any: Unbox { public Unbox_Any(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo) : base(aInstruction, aMethodInfo) { } - public override void DoAssemble() { - throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!"); - } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU.IL/CustomMethodImplementationProxyOp.cs b/source/Indy.IL2CPU.IL/CustomMethodImplementationProxyOp.cs index 2effcd852..8d3502a74 100644 --- a/source/Indy.IL2CPU.IL/CustomMethodImplementationProxyOp.cs +++ b/source/Indy.IL2CPU.IL/CustomMethodImplementationProxyOp.cs @@ -45,9 +45,6 @@ namespace Indy.IL2CPU.IL { } CallProxiedMethod(); DoQueueMethod(ProxiedMethod); - if (MethodInfo.HasReturnValue) { - Ldloc(0); - } } } } diff --git a/source/Indy.IL2CPU/CustomImplementation/System/EnvironmentImpl.cs b/source/Indy.IL2CPU/CustomImplementation/System/EnvironmentImpl.cs new file mode 100644 index 000000000..30a183131 --- /dev/null +++ b/source/Indy.IL2CPU/CustomImplementation/System/EnvironmentImpl.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Indy.IL2CPU.CustomImplementation.System { + public static class EnvironmentImpl { + [MethodAlias(Name = "System.Environment.GetResourceFromDefault(System.String)")] + public static string GetResourceFromDefault(string aResource) { + return aResource; + } + } +} \ No newline at end of file diff --git a/source/Indy.IL2CPU/Engine.cs b/source/Indy.IL2CPU/Engine.cs index d3cbc9849..b05ca6c6f 100644 --- a/source/Indy.IL2CPU/Engine.cs +++ b/source/Indy.IL2CPU/Engine.cs @@ -117,6 +117,7 @@ namespace Indy.IL2CPU { IL.Op.QueueMethod += QueueMethod; IL.Op.QueueStaticField += QueueStaticField; try { + mTypes.Add(GetTypeDefinition("mscorlib", "System.Object")); mMethods.Add(RuntimeEngineRefs.InitializeApplicationRef, false); mMethods.Add(RuntimeEngineRefs.FinalizeApplicationRef, false); mMethods.Add(mCrawledAssembly.EntryPoint, false); @@ -131,7 +132,14 @@ namespace Indy.IL2CPU { } mAssembler.Add(new Assembler.X86.Call(new Label(RuntimeEngineRefs.FinalizeApplicationRef).Name)); ProcessAllMethods(); - ScanForMethodToIncludeForVMT(); + do { + int xOldCount = mMethods.Count; + ScanForMethodToIncludeForVMT(); + ProcessAllMethods(); + if (xOldCount == mMethods.Count) { + break; + } + } while (true); ProcessAllStaticFields(); } finally { mAssembler.Flush(); @@ -145,15 +153,26 @@ namespace Indy.IL2CPU { } private void ScanForMethodToIncludeForVMT() { - for (int i = mMethods.Count - 1; i >= 0; i--) { - MethodDefinition xCurrentInspectedMethod = mMethods.Keys[i]; - TypeDefinition xCurrentType = GetDefinitionFromTypeReference(xCurrentInspectedMethod.DeclaringType); + List xCheckedTypes = new List(); + foreach (MethodDefinition xMethod in mMethods.Keys) { + if (xMethod.IsStatic) { + continue; + } + TypeDefinition xCurrentType = GetDefinitionFromTypeReference(xMethod.DeclaringType); + if (!xCheckedTypes.Contains(xCurrentType, mTypesEqualityComparer)) { + xCheckedTypes.Add(xCurrentType); + } + } + foreach (TypeDefinition xType in mTypes) { + if (!xCheckedTypes.Contains(xType, mTypesEqualityComparer)) { + xCheckedTypes.Add(xType); + } + } + for (int i = 0; i < xCheckedTypes.Count; i++) { + TypeDefinition xCurrentType = xCheckedTypes[i]; while (xCurrentType != null) { - foreach (MethodDefinition xCurrentMethod in xCurrentType.Methods) { - if (xCurrentMethod.IsAbstract || xCurrentMethod.Overrides.Count > 0) { - QueueMethod(xCurrentMethod); - continue; - } + if (!xCheckedTypes.Contains(xCurrentType, mTypesEqualityComparer)) { + xCheckedTypes.Add(xCurrentType); } if (xCurrentType.FullName == "System.Object") { break; @@ -161,6 +180,15 @@ namespace Indy.IL2CPU { xCurrentType = GetDefinitionFromTypeReference(xCurrentType.BaseType); } } + foreach (TypeDefinition xTD in xCheckedTypes) { + foreach (MethodDefinition xMethod in xTD.Methods) { + if (!xMethod.IsStatic) { + if (xMethod.IsVirtual || xMethod.Overrides.Count > 0) { + QueueMethod(xMethod); + } + } + } + } } public static MethodDefinition GetDefinitionFromMethodReference(MethodReference aRef) { @@ -177,15 +205,19 @@ namespace Indy.IL2CPU { } public static TypeDefinition GetDefinitionFromTypeReference(TypeReference aRef) { + if (aRef == null) { + throw new ArgumentNullException("aRef"); + } if (mCurrent == null) { throw new Exception("No Current engine found!"); } + TypeDefinition xTempResult = aRef as TypeDefinition; + if (xTempResult != null) { + return xTempResult; + } if (aRef.FullName.Contains("modreq")) { aRef = aRef.GetOriginalType(); } - if (aRef.FullName.EndsWith("[]")) { - return GetTypeDefinition(aRef.Module.Assembly.Name.Name, aRef.FullName.Substring(0, aRef.FullName.Length - 2)); - } AssemblyNameReference xAssemblyNameReference = aRef.Scope as AssemblyNameReference; if (xAssemblyNameReference != null) { AssemblyDefinition xReferencedFieldAssembly; @@ -200,6 +232,12 @@ namespace Indy.IL2CPU { if (xReferencedType != null) { return xReferencedType; } + if (aRef.FullName.EndsWith("[]")) { + xReferencedType = xModule.Types[aRef.FullName.Substring(0, aRef.FullName.Length - 2)]; + if (xReferencedType != null) { + return xReferencedType; + } + } } } } else { @@ -209,6 +247,12 @@ namespace Indy.IL2CPU { if (xReferencedType != null) { return xReferencedType; } + if (aRef.FullName.EndsWith("[]")) { + xReferencedType = xReferencedModule.Types[aRef.FullName.Substring(0, aRef.FullName.Length - 2)]; + if (xReferencedType != null) { + return xReferencedType; + } + } } else { mCurrent.OnDebugLog("Error: Unhandled scope: " + aRef.Scope == null ? "**NULL**" : aRef.Scope.GetType().FullName); } @@ -228,13 +272,13 @@ namespace Indy.IL2CPU { } switch (aType.FullName) { case "System.Char": - return 2; + return 4; case "System.Byte": case "System.SByte": - return 1; + return 4; case "System.UInt16": case "System.Int16": - return 2; + return 4; case "System.UInt32": case "System.Int32": return 4; @@ -245,8 +289,20 @@ namespace Indy.IL2CPU { case "System.UIntPtr": case "System.IntPtr": return 4; + case "System.Boolean": + return 4; + case "System.Single": + return 4; + case "System.Double": + return 8; + case "System.Decimal": + return 16; + case "System.Guid": + return 16; + case "System.DateTime": + return 8; // todo: check for correct size } - throw new Exception("Unable to determine ValueType size!"); + throw new Exception("Unable to determine ValueType size! (Type = " + aType.FullName + ")"); } private void ProcessAllStaticFields() { @@ -458,8 +514,6 @@ namespace Indy.IL2CPU { } public static SortedList GetTypeFieldInfo(MethodDefinition aCurrentMethod, out uint aObjectStorageSize) { - SortedList xTypeFields = new SortedList(); - aObjectStorageSize = ObjectImpl.FieldDataOffset; TypeDefinition xCurrentInspectedType = GetDefinitionFromTypeReference(aCurrentMethod.DeclaringType); return GetTypeFieldInfo(xCurrentInspectedType, out aObjectStorageSize); } @@ -483,7 +537,7 @@ namespace Indy.IL2CPU { xTypeFields.Add(xField.ToString(), new TypeInformation.Field(aObjectStorageSize, xFieldSize)); aObjectStorageSize += xFieldSize; } - if (aType.FullName != "System.Object") { + if (aType.FullName != "System.Object" && aType.BaseType != null) { aType = GetDefinitionFromTypeReference(aType.BaseType); } else { break; @@ -596,13 +650,16 @@ namespace Indy.IL2CPU { /// /// public static int RegisterType(TypeDefinition aType) { + if (aType == null) { + throw new ArgumentNullException("aType"); + } if (mCurrent == null) { throw new Exception("ERROR: No Current Engine found!"); } TypeDefinition xFoundItem = mCurrent.mTypes.FirstOrDefault(x => x.FullName.Equals(aType.FullName)); if (xFoundItem == null) { mCurrent.mTypes.Add(aType); - if (aType.FullName != "System.Object") { + if (aType.FullName != "System.Object" && aType.BaseType != null) { TypeDefinition xCurInspectedType = GetDefinitionFromTypeReference(aType.BaseType); RegisterType(xCurInspectedType); } diff --git a/source/Indy.IL2CPU/Indy.IL2CPU.csproj b/source/Indy.IL2CPU/Indy.IL2CPU.csproj index e6961481a..20415b8ac 100644 --- a/source/Indy.IL2CPU/Indy.IL2CPU.csproj +++ b/source/Indy.IL2CPU/Indy.IL2CPU.csproj @@ -77,6 +77,7 @@ + diff --git a/source/Indy.IL2CPU/VTablesImpl.cs b/source/Indy.IL2CPU/VTablesImpl.cs index 300a40f93..3a595d00d 100644 --- a/source/Indy.IL2CPU/VTablesImpl.cs +++ b/source/Indy.IL2CPU/VTablesImpl.cs @@ -5,12 +5,26 @@ using System.Text; namespace Indy.IL2CPU { public static class VTablesImpl { - // method VTable, indexed by the type - /// - /// This array contains a list of types in the first dimension and a list - /// of method indexes in the second dimension. - /// - private static IntPtr[][] mMethods; + public struct VTable { + public int TypeIdentifier; + public int BaseTypeIdentifier; + public int[] MethodIndexes; + public int[] MethodAddresses; + } + private static VTable[] mTypes; + public static bool IsInstance(int aObjectType, int aDesiredObjectType) { + int xCurrentType = aObjectType; + if (aObjectType == 0) { + return true; + } + do { + if (xCurrentType == aDesiredObjectType) { + return true; + } + xCurrentType = mTypes[xCurrentType].BaseTypeIdentifier; + } while (xCurrentType != 0); + return false; + } } }