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;