From 8f9b9bd80d7caaff2f12d6d83a49b4e04dbe34ad Mon Sep 17 00:00:00 2001 From: mterwoord_cp <7cd3fd84a0151ea055c2f79e4d2eef9576fe9afesxUZAwxD> Date: Fri, 26 Oct 2007 15:03:48 +0000 Subject: [PATCH] non-multicast events work now. --- source/Indy.IL2CPU.IL.X86/Callvirt.cs | 20 +++++++++-- .../System/EventHandlerImpl.cs | 17 +++++++++ .../System/EventHandlerImplRefs.cs | 36 +++++++++++++++++++ .../System/MulticastDelegateImpl.cs | 17 +++++++++ .../System/MulticastDelegateImplRefs.cs | 36 +++++++++++++++++++ .../Indy.IL2CPU.IL.X86.csproj | 4 +++ source/Indy.IL2CPU.IL.X86/X86OpCodeMap.cs | 33 ++++++++++++++++- source/Indy.IL2CPU.IL/MethodInformation.cs | 5 +-- .../System/DelegateImpl.cs | 13 +++++++ .../System/MulticastDelegateImpl.cs | 13 +++++++ source/Indy.IL2CPU/Indy.IL2CPU.csproj | 2 ++ source/Indy.IL2CPU/ObjectUtilities.cs | 13 +++++++ 12 files changed, 202 insertions(+), 7 deletions(-) create mode 100644 source/Indy.IL2CPU.IL.X86/CustomImplementations/System/EventHandlerImpl.cs create mode 100644 source/Indy.IL2CPU.IL.X86/CustomImplementations/System/EventHandlerImplRefs.cs create mode 100644 source/Indy.IL2CPU.IL.X86/CustomImplementations/System/MulticastDelegateImpl.cs create mode 100644 source/Indy.IL2CPU.IL.X86/CustomImplementations/System/MulticastDelegateImplRefs.cs create mode 100644 source/Indy.IL2CPU/CustomImplementation/System/DelegateImpl.cs create mode 100644 source/Indy.IL2CPU/CustomImplementation/System/MulticastDelegateImpl.cs diff --git a/source/Indy.IL2CPU.IL.X86/Callvirt.cs b/source/Indy.IL2CPU.IL.X86/Callvirt.cs index f57390d34..4b7d724a7 100644 --- a/source/Indy.IL2CPU.IL.X86/Callvirt.cs +++ b/source/Indy.IL2CPU.IL.X86/Callvirt.cs @@ -12,6 +12,7 @@ namespace Indy.IL2CPU.IL.X86 { private bool mHasReturn; private string mNormalAddress; private string mMethodDescription; + private string[] mThisAddresses; public Callvirt(Instruction aInstruction, MethodInformation aMethodInfo) : base(aInstruction, aMethodInfo) { int xThisOffSet = (from item in aMethodInfo.Locals @@ -31,6 +32,11 @@ namespace Indy.IL2CPU.IL.X86 { Engine.QueueMethodRef(VTablesImplRefs.GetMethodAddressForTypeRef); MethodInformation xTheMethodInfo = Engine.GetMethodInfo(xMethodDef, xMethodDef, mMethodDescription, null); mHasReturn = xTheMethodInfo.ReturnSize != 0; + Console.WriteLine("Debug: " + xTheMethodInfo.ToString()); + mThisAddresses = xTheMethodInfo.Arguments[0].VirtualAddresses; + if (mThisAddresses.Length > 1) { + throw new Exception("In x86, object addresses are 4 bytes. Found different size!"); + } } public override void DoAssemble() { @@ -40,8 +46,18 @@ namespace Indy.IL2CPU.IL.X86 { if (Assembler.InMetalMode) { throw new Exception("Virtual methods not supported in Metal mode! (Called method = '" + mMethodDescription + "')"); } - Assembler.Add(new CPUx86.Pop("eax")); - Assembler.Add(new CPUx86.Pushd("eax")); + string[] xAddrParts = mThisAddresses[0].Split('+'); + Pushd(4, xAddrParts[0].Trim()); + Pushd(4, xAddrParts[1].Trim()); + Pushd(4, "8"); + new Sub(null, null) { + Assembler = this.Assembler + }.Assemble(); + new Sub(null, null) { + Assembler = this.Assembler + }.Assemble(); + Pop("ecx"); + Move(Assembler, "eax", "[ecx]"); Assembler.Add(new CPUx86.Pushd("[eax]")); Assembler.Add(new CPUx86.Pushd("0" + mMethodIdentifier.ToString("X") + "h")); Call(new CPU.Label(VTablesImplRefs.GetMethodAddressForTypeRef).Name); diff --git a/source/Indy.IL2CPU.IL.X86/CustomImplementations/System/EventHandlerImpl.cs b/source/Indy.IL2CPU.IL.X86/CustomImplementations/System/EventHandlerImpl.cs new file mode 100644 index 000000000..68222249f --- /dev/null +++ b/source/Indy.IL2CPU.IL.X86/CustomImplementations/System/EventHandlerImpl.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Indy.IL2CPU.IL.X86.CustomImplementations.System { + public static unsafe class EventHandlerImpl { + public static void Ctor(uint* aThis, uint aObject, uint aMethod) { + // move forward 8 bytes + uint* xThis = aThis; + aThis += 2; + *aThis = aObject; + aThis += 1; + *aThis = aMethod; + } + } +} diff --git a/source/Indy.IL2CPU.IL.X86/CustomImplementations/System/EventHandlerImplRefs.cs b/source/Indy.IL2CPU.IL.X86/CustomImplementations/System/EventHandlerImplRefs.cs new file mode 100644 index 000000000..4dfd38a66 --- /dev/null +++ b/source/Indy.IL2CPU.IL.X86/CustomImplementations/System/EventHandlerImplRefs.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using Mono.Cecil; + +namespace Indy.IL2CPU.IL.X86.CustomImplementations.System { + public static class EventHandlerImplRefs { + public static readonly AssemblyDefinition RuntimeAssemblyDef; + public static readonly MethodDefinition CtorRef; + + static EventHandlerImplRefs() { + RuntimeAssemblyDef = AssemblyFactory.GetAssembly(typeof(EventHandlerImpl).Assembly.Location); + TypeDefinition xType = null; + foreach (ModuleDefinition xMod in RuntimeAssemblyDef.Modules) { + if (xMod.Types.Contains(typeof(EventHandlerImpl).FullName)) { + xType = xMod.Types[typeof(EventHandlerImpl).FullName]; + break; + } + } + if (xType == null) { + throw new Exception("EventHandlerImpl type not found!"); + } + foreach (FieldInfo xField in typeof(EventHandlerImplRefs).GetFields()) { + if (xField.Name.EndsWith("Ref")) { + MethodDefinition xTempMethod = xType.Methods.GetMethod(xField.Name.Substring(0, xField.Name.Length - "Ref".Length)).FirstOrDefault(); + if (xTempMethod == null) { + throw new Exception("Method '" + xField.Name.Substring(0, xField.Name.Length - "Ref".Length) + "' not found on DelegateImpl!"); + } + xField.SetValue(null, xTempMethod); + } + } + } + } +} diff --git a/source/Indy.IL2CPU.IL.X86/CustomImplementations/System/MulticastDelegateImpl.cs b/source/Indy.IL2CPU.IL.X86/CustomImplementations/System/MulticastDelegateImpl.cs new file mode 100644 index 000000000..68222249f --- /dev/null +++ b/source/Indy.IL2CPU.IL.X86/CustomImplementations/System/MulticastDelegateImpl.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Indy.IL2CPU.IL.X86.CustomImplementations.System { + public static unsafe class EventHandlerImpl { + public static void Ctor(uint* aThis, uint aObject, uint aMethod) { + // move forward 8 bytes + uint* xThis = aThis; + aThis += 2; + *aThis = aObject; + aThis += 1; + *aThis = aMethod; + } + } +} diff --git a/source/Indy.IL2CPU.IL.X86/CustomImplementations/System/MulticastDelegateImplRefs.cs b/source/Indy.IL2CPU.IL.X86/CustomImplementations/System/MulticastDelegateImplRefs.cs new file mode 100644 index 000000000..4dfd38a66 --- /dev/null +++ b/source/Indy.IL2CPU.IL.X86/CustomImplementations/System/MulticastDelegateImplRefs.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using Mono.Cecil; + +namespace Indy.IL2CPU.IL.X86.CustomImplementations.System { + public static class EventHandlerImplRefs { + public static readonly AssemblyDefinition RuntimeAssemblyDef; + public static readonly MethodDefinition CtorRef; + + static EventHandlerImplRefs() { + RuntimeAssemblyDef = AssemblyFactory.GetAssembly(typeof(EventHandlerImpl).Assembly.Location); + TypeDefinition xType = null; + foreach (ModuleDefinition xMod in RuntimeAssemblyDef.Modules) { + if (xMod.Types.Contains(typeof(EventHandlerImpl).FullName)) { + xType = xMod.Types[typeof(EventHandlerImpl).FullName]; + break; + } + } + if (xType == null) { + throw new Exception("EventHandlerImpl type not found!"); + } + foreach (FieldInfo xField in typeof(EventHandlerImplRefs).GetFields()) { + if (xField.Name.EndsWith("Ref")) { + MethodDefinition xTempMethod = xType.Methods.GetMethod(xField.Name.Substring(0, xField.Name.Length - "Ref".Length)).FirstOrDefault(); + if (xTempMethod == null) { + throw new Exception("Method '" + xField.Name.Substring(0, xField.Name.Length - "Ref".Length) + "' not found on DelegateImpl!"); + } + xField.SetValue(null, xTempMethod); + } + } + } + } +} diff --git a/source/Indy.IL2CPU.IL.X86/Indy.IL2CPU.IL.X86.csproj b/source/Indy.IL2CPU.IL.X86/Indy.IL2CPU.IL.X86.csproj index 1148e1995..fab663d26 100644 --- a/source/Indy.IL2CPU.IL.X86/Indy.IL2CPU.IL.X86.csproj +++ b/source/Indy.IL2CPU.IL.X86/Indy.IL2CPU.IL.X86.csproj @@ -127,6 +127,10 @@ + + + + diff --git a/source/Indy.IL2CPU.IL.X86/X86OpCodeMap.cs b/source/Indy.IL2CPU.IL.X86/X86OpCodeMap.cs index 01922c090..47e6b48bd 100644 --- a/source/Indy.IL2CPU.IL.X86/X86OpCodeMap.cs +++ b/source/Indy.IL2CPU.IL.X86/X86OpCodeMap.cs @@ -52,6 +52,9 @@ namespace Indy.IL2CPU.IL.X86 { } goto default; } + case "System_Void___System_EventHandler__ctor___System_Object__System_IntPtr___": { + return CustomImplementations.System.EventHandlerImplRefs.CtorRef; + } default: return base.GetCustomMethodImplementation(aOrigMethodName, aInMetalMode); } @@ -61,13 +64,16 @@ namespace Indy.IL2CPU.IL.X86 { switch (aMethodName) { case "System_Object___System_Threading_Interlocked_CompareExchange___System_Object___System_Object__System_Object___": { return true; - } + } case "System_Int32___System_Threading_Interlocked_CompareExchange___System_Int32___System_Int32__System_Int32___": { return true; } case "System_String___System_String_FastAllocateString___System_Int32___": { return true; } + case "System_Void___System_EventHandler_Invoke___System_Object__System_EventArgs___": { + return true; + } default: return base.HasCustomAssembleImplementation(aMethodName, aInMetalMode); } @@ -83,6 +89,10 @@ namespace Indy.IL2CPU.IL.X86 { Assemble_System_Threading_Interlocked_CompareExchange__Object(aAssembler, aMethodInfo); break; } + case "System_Void___System_EventHandler_Invoke___System_Object__System_EventArgs___": { + Assemble_System_EventHandler_Invoke___System_Object__System_EventArgs___(aAssembler, aMethodInfo); + break; + } default: base.DoCustomAssembleImplementation(aMethodName, aInMetalMode, aAssembler, aMethodInfo); break; @@ -108,5 +118,26 @@ namespace Indy.IL2CPU.IL.X86 { aAssembler.Add(new CPUx86.Move("[eax]", "ecx")); aAssembler.Add(new CPUx86.Pushd("eax")); } + + private static void Assemble_System_EventHandler_Invoke___System_Object__System_EventArgs___(Assembler.Assembler aAssembler, MethodInformation aMethodInfo) { + // param 0 is instance of eventhandler + // param 1 is sender + // param 2 is eventargs + Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0].VirtualAddresses, aMethodInfo.Arguments[0].Size); + Ldarg.Push(aAssembler, 4, "0x" + (ObjectImpl.FieldDataOffset + 4).ToString("X")); + Ldarg.Add(aAssembler); + aAssembler.Add(new CPUx86.Pop("eax")); + aAssembler.Add(new CPUx86.Pushd("[eax]")); + Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[1].VirtualAddresses, aMethodInfo.Arguments[1].Size); + Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[2].VirtualAddresses, aMethodInfo.Arguments[2].Size); + Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0].VirtualAddresses, aMethodInfo.Arguments[0].Size); + Ldarg.Push(aAssembler, 4, "0x" + ObjectImpl.FieldDataOffset.ToString("X")); + Ldarg.Add(aAssembler); + aAssembler.Add(new CPUx86.Pop("eax")); + aAssembler.Add(new CPUx86.Pushd("[eax]")); + aAssembler.Add(new CPUx86.Pop("eax")); + aAssembler.Add(new CPUx86.Call("eax")); + aAssembler.Add(new CPUx86.Pop("eax")); + } } } diff --git a/source/Indy.IL2CPU.IL/MethodInformation.cs b/source/Indy.IL2CPU.IL/MethodInformation.cs index 6a223d5a8..0362a87dd 100644 --- a/source/Indy.IL2CPU.IL/MethodInformation.cs +++ b/source/Indy.IL2CPU.IL/MethodInformation.cs @@ -35,7 +35,6 @@ namespace Indy.IL2CPU.IL { public Argument(int aSize, int aOffset, KindEnum aKind) { Size = aSize; Offset = aOffset; - VirtualAddress = "ebp + 0" + (Offset + Size + 4).ToString("X") + "h"; 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"; @@ -43,8 +42,6 @@ namespace Indy.IL2CPU.IL { Kind = aKind; } - [Obsolete("Start using VirtualAddresses")] - public readonly string VirtualAddress; public readonly string[] VirtualAddresses; public readonly int Size; public readonly int Offset; @@ -88,7 +85,7 @@ namespace Indy.IL2CPU.IL { } xCurIndex = 0; foreach (Argument xArg in Arguments) { - xSB.AppendLine(String.Format("\t({0}) {1}\t{2}\t{3}\r\n", xCurIndex++, xArg.Offset, xArg.Size, xArg.VirtualAddress)); + xSB.AppendLine(String.Format("\t({0}) {1}\t{2}\t{3}\r\n", xCurIndex++, xArg.Offset, xArg.Size, xArg.VirtualAddresses.FirstOrDefault())); } xSB.AppendLine("\tReturnSize: " + ReturnSize); return xSB.ToString(); diff --git a/source/Indy.IL2CPU/CustomImplementation/System/DelegateImpl.cs b/source/Indy.IL2CPU/CustomImplementation/System/DelegateImpl.cs new file mode 100644 index 000000000..ce200312b --- /dev/null +++ b/source/Indy.IL2CPU/CustomImplementation/System/DelegateImpl.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Indy.IL2CPU.CustomImplementation.System { + public static unsafe class DelegateImpl { + [MethodAlias(Name = "System.Boolean System.Delegate.InternalEqualTypes(System.Object,System.Object)")] + public static bool InternalEqualTypes(uint* aDelegate1, uint* aDelegate2) { + return *aDelegate1 == *aDelegate2; + } + } +} diff --git a/source/Indy.IL2CPU/CustomImplementation/System/MulticastDelegateImpl.cs b/source/Indy.IL2CPU/CustomImplementation/System/MulticastDelegateImpl.cs new file mode 100644 index 000000000..54fab2181 --- /dev/null +++ b/source/Indy.IL2CPU/CustomImplementation/System/MulticastDelegateImpl.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Indy.IL2CPU.CustomImplementation.System { + public static unsafe class MulticastDelegateImpl { + //[MethodAlias("System_IntPtr___System_Delegate_GetInvokeMethod____")] + public static uint Test(uint* aThis) { + return 0; + } + } +} diff --git a/source/Indy.IL2CPU/Indy.IL2CPU.csproj b/source/Indy.IL2CPU/Indy.IL2CPU.csproj index af9d05cfe..3a304fd23 100644 --- a/source/Indy.IL2CPU/Indy.IL2CPU.csproj +++ b/source/Indy.IL2CPU/Indy.IL2CPU.csproj @@ -86,7 +86,9 @@ + + diff --git a/source/Indy.IL2CPU/ObjectUtilities.cs b/source/Indy.IL2CPU/ObjectUtilities.cs index f7cae39d4..95577e260 100644 --- a/source/Indy.IL2CPU/ObjectUtilities.cs +++ b/source/Indy.IL2CPU/ObjectUtilities.cs @@ -4,8 +4,21 @@ using Mono.Cecil; namespace Indy.IL2CPU { public static class ObjectUtilities { + private static bool IsDelegate(TypeDefinition aType) { + if(aType.BaseType.FullName == "System.Delegate") { + return true; + } + if (aType.BaseType.FullName == "System.Object") { + return false; + } + return IsDelegate(Engine.GetDefinitionFromTypeReference(aType.BaseType)); + } + public static int GetObjectStorageSize(TypeDefinition aType) { int xResult = ObjectImpl.FieldDataOffset; + if (IsDelegate(aType)) { + xResult += 8; + } foreach (FieldDefinition xField in aType.Fields) { if (xField.IsStatic) { continue;