From 44690293e8956dda77c38939cf3c2a5261bf9be2 Mon Sep 17 00:00:00 2001 From: Matthijs ter Woord Date: Sat, 5 Sep 2015 18:11:20 +0200 Subject: [PATCH] Delegates issue solved., --- Demos/Guess/Guess.Cosmos | 36 +++--- .../System/DelegatesTest.cs | 44 +++++++- .../DefaultEngineConfiguration.cs | 10 +- source/Cosmos.IL2CPU/AppAssembler.cs | 2 +- .../Plugs/NEW_PLUGS/InvokeImplAssembler.cs | 105 +++++++++--------- 5 files changed, 115 insertions(+), 82 deletions(-) diff --git a/Demos/Guess/Guess.Cosmos b/Demos/Guess/Guess.Cosmos index 3dba44770..0257764af 100644 --- a/Demos/Guess/Guess.Cosmos +++ b/Demos/Guess/Guess.Cosmos @@ -15,13 +15,13 @@ v4.5 - VMware + Bochs true bin\Debug\ MicrosoftNET False False - Source + IL User PXE Player @@ -30,8 +30,8 @@ ISO False ISO - VMware - True + Bochs + False All PXE None @@ -67,8 +67,8 @@ MicrosoftNET False All - False - False + True + True ISO None False @@ -82,7 +82,7 @@ False false Guess - Use VMware Player or Workstation to deploy and debug. + Use Bochs emulator to deploy and debug. User 001 Creates a bootable ISO image which can be burned to a DVD. After running the selected project, an explorer window will open containing the ISO file. The ISO file can then be burned to a CD or DVD and used to boot a physical or virtual system. Guess @@ -136,7 +136,7 @@ ISO Bochs False - True + False True IL False @@ -150,7 +150,7 @@ All False False - False + True True False False @@ -181,13 +181,13 @@ False - VMware + Bochs true bin\Debug\ MicrosoftNET False False - Source + IL User PXE Player @@ -196,8 +196,8 @@ ISO False ISO - VMware - True + Bochs + False All PXE None @@ -233,8 +233,8 @@ MicrosoftNET False All - False - False + True + True ISO None False @@ -248,7 +248,7 @@ False false Guess - Use VMware Player or Workstation to deploy and debug. + Use Bochs emulator to deploy and debug. User 001 Creates a bootable ISO image which can be burned to a DVD. After running the selected project, an explorer window will open containing the ISO file. The ISO file can then be burned to a CD or DVD and used to boot a physical or virtual system. Guess @@ -308,7 +308,7 @@ ISO Bochs False - True + False True IL False @@ -322,7 +322,7 @@ All False False - False + True True False False diff --git a/Tests/Cosmos.Compiler.Tests.Bcl/System/DelegatesTest.cs b/Tests/Cosmos.Compiler.Tests.Bcl/System/DelegatesTest.cs index 99ec3f720..5bfba9fe3 100644 --- a/Tests/Cosmos.Compiler.Tests.Bcl/System/DelegatesTest.cs +++ b/Tests/Cosmos.Compiler.Tests.Bcl/System/DelegatesTest.cs @@ -5,7 +5,7 @@ using Cosmos.TestRunner; namespace Cosmos.Compiler.Tests.Bcl.System { - public static class DelegatesTest + public class DelegatesTest { private static int mCount; @@ -14,22 +14,54 @@ namespace Cosmos.Compiler.Tests.Bcl.System mCount++; } - private static void IncreaseCounterTwice() + + private void IncreaseCounterTwiceFromInstanceMethod() { - mCount++; + mCount += 2; } public static void Execute() + { + TestDelegateWithoutArguments(); + TestDelegateWithArguments(); + } + + private static void TestDelegateWithoutArguments() { mCount = 0; Action xDelegate = IncreaseCounterOnce; xDelegate(); Assert.AreEqual(1, mCount, "After calling delegate once, Count != 1"); - //xDelegate += IncreaseCounterTwice; - //xDelegate(); - //Assert.AreEqual(4, mCount, "After calling delegate second time, Count != 4"); + var xTestInstance = new DelegatesTest(); + xDelegate = xTestInstance.IncreaseCounterTwiceFromInstanceMethod; + mCount = 0; + xDelegate(); + Assert.AreEqual(2, mCount, "After calling delegate second time, Count != 2"); + } + private static void IncreaseCounter(int number) + { + mCount += number; + } + + private void IncreaseCounterFromInstanceMethod(int number) + { + mCount += number; + } + + private static void TestDelegateWithArguments() + { + mCount = 0; + Action xDelegate = IncreaseCounter; + + xDelegate(2); + Assert.AreEqual(2, mCount, "After calling delegate once, Count != 2"); + var xTestInstance = new DelegatesTest(); + xDelegate = xTestInstance.IncreaseCounterFromInstanceMethod; + mCount = 0; + xDelegate(3); + Assert.AreEqual(3, mCount, "After calling delegate second time, Count != 3"); } } } \ No newline at end of file diff --git a/Tests/Cosmos.TestRunner.Core/DefaultEngineConfiguration.cs b/Tests/Cosmos.TestRunner.Core/DefaultEngineConfiguration.cs index c5cb94095..2fda9e89d 100644 --- a/Tests/Cosmos.TestRunner.Core/DefaultEngineConfiguration.cs +++ b/Tests/Cosmos.TestRunner.Core/DefaultEngineConfiguration.cs @@ -20,12 +20,12 @@ namespace Cosmos.TestRunner.Core // if you're working on the compiler (or other lower parts), you can choose to run the compiler in process // 1 thing to keep in mind though, is that this only works with 1 kernel at a time! //engine.RunIL2CPUInProcess = true; - engine.RunWithGDB = false; + //engine.RunWithGDB = true; - engine.AddKernel(typeof(Cosmos.Compiler.Tests.SimpleWriteLine.Kernel.Kernel).Assembly.Location); - engine.AddKernel(typeof(SimpleStructsAndArraysTest.Kernel).Assembly.Location); - engine.AddKernel(typeof(VGACompilerCrash.Kernel).Assembly.Location); - engine.AddKernel(typeof(Cosmos.Compiler.Tests.SingleEchoTest.Kernel).Assembly.Location); + //engine.AddKernel(typeof(Cosmos.Compiler.Tests.SimpleWriteLine.Kernel.Kernel).Assembly.Location); + //engine.AddKernel(typeof(SimpleStructsAndArraysTest.Kernel).Assembly.Location); + //engine.AddKernel(typeof(VGACompilerCrash.Kernel).Assembly.Location); + //engine.AddKernel(typeof(Cosmos.Compiler.Tests.SingleEchoTest.Kernel).Assembly.Location); engine.AddKernel(typeof(Cosmos.Compiler.Tests.Bcl.Kernel).Assembly.Location); // known bugs, therefor disabled for now: diff --git a/source/Cosmos.IL2CPU/AppAssembler.cs b/source/Cosmos.IL2CPU/AppAssembler.cs index 97cd88c7a..a4fbb8e7f 100644 --- a/source/Cosmos.IL2CPU/AppAssembler.cs +++ b/source/Cosmos.IL2CPU/AppAssembler.cs @@ -1,4 +1,4 @@ -//#define VMT_DEBUG +#define VMT_DEBUG using System; using System.Collections.Generic; using System.Diagnostics.SymbolStore; diff --git a/source/Cosmos.IL2CPU/Plugs/NEW_PLUGS/InvokeImplAssembler.cs b/source/Cosmos.IL2CPU/Plugs/NEW_PLUGS/InvokeImplAssembler.cs index bd5070252..1cdde4923 100644 --- a/source/Cosmos.IL2CPU/Plugs/NEW_PLUGS/InvokeImplAssembler.cs +++ b/source/Cosmos.IL2CPU/Plugs/NEW_PLUGS/InvokeImplAssembler.cs @@ -57,63 +57,64 @@ namespace Cosmos.IL2CPU.X86.Plugs.NEW_PLUGS { new CPU.Comment("ecx = ptr to delegate object"); new CPUx86.Mov { DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = Ldarg.GetArgumentDisplacement(xMethodInfo, 0) };//addrof the delegate new CPU.Comment("ecx points to the size of the delegated methods arguments"); - new CPUx86.Mov { DestinationReg = CPUx86.Registers.ECX,SourceReg = CPUx86.Registers.ECX,SourceIsIndirect = true }; + new CPUx86.Mov { DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.ECX,SourceIsIndirect = true }; new CPUx86.Mov { DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "$$ArgSize$$") };//the size of the arguments to the method? + 12??? -- 12 is the size of the current call stack.. i think new CPUx86.Xor { DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EDX }; ;//make sure edx is 0 new CPU.Label(".BEGIN_OF_LOOP"); { - new CPUx86.Compare { DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EBX };//are we at the end of this list - new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, DestinationLabel = ".END_OF_INVOKE_" };//then we better stop - new CPUx86.Pushad(); - new CPU.Comment("esi points to where we will copy the methods argumetns from"); - new CPUx86.Mov { DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.ESP }; - new CPU.Comment("edi = ptr to delegate object"); - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = Ldarg.GetArgumentDisplacement(xMethodInfo, 0) }; - new CPUx86.Mov {DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true}; // dereference handle - new CPU.Comment("edi = ptr to delegate object should be a pointer to the delgates context ie (this) for the methods "); - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.Object System.Delegate._target") }; - new CPUx86.Compare { DestinationReg = CPUx86.Registers.EDI, SourceValue = 0 }; - new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.Zero, DestinationLabel = ".NO_THIS" }; - new CPUx86.Push { DestinationReg = CPUx86.Registers.EDI }; - - new CPU.Label(".NO_THIS"); - - new CPU.Comment("make space for us to copy the arguments too"); - new CPUx86.Sub { DestinationReg = CPUx86.Registers.ESP, SourceReg = CPUx86.Registers.ECX }; - new CPU.Comment("move the current delegate to edi"); - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true }; - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true }; // dereference - new CPU.Comment("move the methodptr from that delegate to edi "); - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.IntPtr System.Delegate._methodPtr") };// - new CPU.Comment("save methodptr on the stack"); - new CPUx86.Push { DestinationReg = CPUx86.Registers.EDI }; - new CPU.Comment("move location to copy args to"); - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.ESP }; - //new CPU.Comment("get above the saved methodptr"); - //new CPUx86.Sub { DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 }; - //we allocated the argsize on the stack once, and it we need to get above the original args - new CPU.Comment("we allocated argsize on the stack once"); - new CPU.Comment("add 32 for the Pushad + 16 for the current stack + 4 for the return value"); - //uint xToAdd = 32; // skip pushad data - //xToAdd += 4; // method pointer - new CPUx86.Mov { DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.EBP }; - new CPUx86.Add { DestinationReg = CPUx86.Registers.ESI, SourceValue = 8 }; // ebp+8 is first argument - new CPUx86.Movs { Size = 8, Prefixes = CPUx86.InstructionPrefixes.Repeat }; - new CPUx86.Pop { DestinationReg = CPUx86.Registers.EDI }; - new CPU.Label(".BeforeCall"); - new CPUx86.Call { DestinationReg = CPUx86.Registers.EDI }; - new CPU.Comment("store return -- return stored into edi after popad"); - new CPU.Comment("edi = ptr to delegate object"); - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = Ldarg.GetArgumentDisplacement(xMethodInfo, 0) }; - new CPU.Comment("edi = ptr to delegate object should be a pointer to the delgates context ie (this) for the methods "); - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true }; // dereference handle - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.Object System.Delegate._target") };//i really dont get the +12, MtW: that's for the object header - new CPU.Label(".noTHIStoPop"); - new CPUx86.Popad(); - new CPUx86.INC { DestinationReg = CPUx86.Registers.EDX }; - new CPUx86.Add { DestinationReg = CPUx86.Registers.EAX, SourceValue = 4 }; - new CPUx86.Jump { DestinationLabel = ".BEGIN_OF_LOOP" }; + new CPUx86.Compare { DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EBX };//are we at the end of this list + new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, DestinationLabel = ".END_OF_INVOKE_" };//then we better stop + new CPUx86.Pushad(); + new CPU.Comment("esi points to where we will copy the methods argumetns from"); + new CPUx86.Mov { DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.ESP }; + new CPU.Comment("edi = ptr to delegate object"); + new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = Ldarg.GetArgumentDisplacement(xMethodInfo, 0) }; + new CPUx86.Mov {DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true}; // dereference handle + new CPU.Comment("edi = ptr to delegate object should be a pointer to the delgates context ie (this) for the methods "); + new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.Object System.Delegate._target") }; + new CPUx86.Compare { DestinationReg = CPUx86.Registers.EDI, SourceValue = 0 }; + new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.Zero, DestinationLabel = ".NO_THIS" }; + new CPUx86.Push { DestinationReg = CPUx86.Registers.EDI }; + + new CPU.Label(".NO_THIS"); + + new CPU.Comment("make space for us to copy the arguments too"); + new CPUx86.Sub { DestinationReg = CPUx86.Registers.ESP, SourceReg = CPUx86.Registers.ECX }; + new CPU.Comment("move the current delegate to edi"); + new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true }; + new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true }; // dereference + new CPU.Comment("move the methodptr from that delegate to edi "); + new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.IntPtr System.Delegate._methodPtr") };// + new CPU.Comment("save methodptr on the stack"); + new CPUx86.Push { DestinationReg = CPUx86.Registers.EDI }; + new CPU.Comment("move location to copy args to"); + new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.ESP }; + new CPUx86.Add { DestinationReg = CPUx86.Registers.EDI, SourceValue = 4 }; + //new CPU.Comment("get above the saved methodptr"); + //new CPUx86.Sub { DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 }; + //we allocated the argsize on the stack once, and it we need to get above the original args + new CPU.Comment("we allocated argsize on the stack once"); + new CPU.Comment("add 32 for the Pushad + 16 for the current stack + 4 for the return value"); + //uint xToAdd = 32; // skip pushad data + //xToAdd += 4; // method pointer + new CPUx86.Mov { DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.EBP }; + new CPUx86.Add { DestinationReg = CPUx86.Registers.ESI, SourceValue = 8 }; // ebp+8 is first argument + new CPUx86.Movs { Size = 8, Prefixes = CPUx86.InstructionPrefixes.Repeat }; + new CPUx86.Pop { DestinationReg = CPUx86.Registers.EDI }; + new CPU.Label(".BeforeCall"); + new CPUx86.Call { DestinationReg = CPUx86.Registers.EDI }; + new CPU.Comment("store return -- return stored into edi after popad"); + new CPU.Comment("edi = ptr to delegate object"); + new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = Ldarg.GetArgumentDisplacement(xMethodInfo, 0) }; + new CPU.Comment("edi = ptr to delegate object should be a pointer to the delgates context ie (this) for the methods "); + new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true }; // dereference handle + new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.Object System.Delegate._target") };//i really dont get the +12, MtW: that's for the object header + new CPU.Label(".noTHIStoPop"); + new CPUx86.Popad(); + new CPUx86.INC { DestinationReg = CPUx86.Registers.EDX }; + new CPUx86.Add { DestinationReg = CPUx86.Registers.EAX, SourceValue = 4 }; + new CPUx86.Jump { DestinationLabel = ".BEGIN_OF_LOOP" }; } new CPU.Label(".END_OF_INVOKE_"); new CPU.Comment("get the return value");