From e240641863d24c19155f6ce6169cc595fb924f1c Mon Sep 17 00:00:00 2001 From: fanoI Date: Sun, 25 Feb 2018 15:27:39 +0100 Subject: [PATCH] Created plugs to make Hashtable work (at least when an object is key). There are issue however: 1. IL2CPU modifications are needed (see the PR for the list of the PR of IL2CPU to merge to make this usable) 2. Some fix in IL2CPU seems to give problems with Dictionary (VMT problem again?) 3. Hashtable with valuetype as key doesn't work (ContainsKey() always return false) --- .../Collections/Not Generic/HashtableTest.cs | 57 +++++++++++++++++++ .../RuntimeFieldHandleImpl.cs | 19 +++++++ .../Cosmos.Core_Plugs/System/DelegateImpl.cs | 24 ++++++-- .../System/Globalization/CultureInfoImpl.cs | 7 ++- .../System/Threading/SpinWaitImpl.cs | 15 +++++ .../System/Threading/ThreadImpl.cs | 16 ++++-- .../System/ValueTypeImpl.cs | 5 ++ 7 files changed, 134 insertions(+), 9 deletions(-) create mode 100644 Tests/Cosmos.Compiler.Tests.Bcl/System/Collections/Not Generic/HashtableTest.cs create mode 100644 source/Cosmos.Core_Plugs/RuntimeFieldHandleImpl.cs create mode 100644 source/Cosmos.System2_Plugs/System/Threading/SpinWaitImpl.cs diff --git a/Tests/Cosmos.Compiler.Tests.Bcl/System/Collections/Not Generic/HashtableTest.cs b/Tests/Cosmos.Compiler.Tests.Bcl/System/Collections/Not Generic/HashtableTest.cs new file mode 100644 index 000000000..2074d876e --- /dev/null +++ b/Tests/Cosmos.Compiler.Tests.Bcl/System/Collections/Not Generic/HashtableTest.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections; +using Cosmos.TestRunner; +//using Cosmos.Compiler.Tests.Bcl.Helper; +using Cosmos.Debug.Kernel; + +namespace Cosmos.Compiler.Tests.Bcl.System.Collections.Not_Generic +{ + class HashtableTest + { + private static Debugger myDebugger = new Debugger("System", "HashtableTest"); + + public static void Execute() + { + var h = new Hashtable(); + Assert.IsTrue(h != null, "Hashtable ctor returns but h is null"); + + h.Add("One", "One"); + //h.Add(42, "Test"); + + Assert.IsTrue(h.ContainsKey("One"), "Hashtable.ContainsKey() failed: existing key not found"); + Assert.IsFalse(h.ContainsKey("Two"), "Hashtable.ContainsKey() failed: not existing key not found"); + + Assert.IsTrue((string)h["One"] == "One", "Hashtable indexer failed: existing value not found"); + Assert.IsTrue(h["Two"] == null, "Hashtable indexer failed: not existing value not found"); + + /* The indexer written in this way should be the same thing of Add("Two", "Two") */ + h["Two"] = "Two"; + + Assert.IsTrue((string)h["Two"] == "Two", "Hashtable indexer failed: existing value (II) not found"); + + Assert.IsTrue(h.Count == 2, "Hashtable Count failed: value != 2"); + + /* + * Got Il2CPU exception: + * System.Exception: Original method argument $this is a reference type. Plug attribute first argument is not an argument type, nor was it marked with ObjectPointerAccessAttribute! Method: SystemObjectSystemArrayGetValueSystemInt32 Parameter: aThis + * at Cosmos.IL2CPU.AppAssembler.GenerateMethodForward(_MethodInfo aFrom, _MethodInfo aTo) in C:\Users\fano\Documents\GitHub\Cosmos\IL2CPU\source\Cosmos.IL2CPU\AppAssembler.cs:line 1309 + * at Cosmos.IL2CPU.ILScanner.Assemble() in C:\Users\fano\Documents\GitHub\Cosmos\IL2CPU\source\Cosmos.IL2CPU\ILScanner.cs:line 951 + * at Cosmos.IL2CPU.ILScanner.Execute(MethodBase aStartMethod) in C:\Users\fano\Documents\GitHub\Cosmos\IL2CPU\source\Cosmos.IL2CPU\ILScanner.cs:line 255 + * at Cosmos.IL2CPU.CompilerEngine.Execute() in C:\Users\fano\Documents\GitHub\Cosmos\IL2CPU\source\Cosmos.IL2CPU\CompilerEngine.cs:line 168 + * Error invoking 'dotnet'. + */ +#if false + foreach (var k in h.Keys) + { + Assert.IsTrue((string)k == "One" || (string)k == "Two", "Hashtable key collection returns invalid key"); + } +#endif + Hashtable h2 = new Hashtable(); + + h2.Add(42, "FortyTwo"); + + Assert.IsTrue(h2.ContainsKey(42), "h2.ContainsKey() failed: existing key not found"); + + } + } +} diff --git a/source/Cosmos.Core_Plugs/RuntimeFieldHandleImpl.cs b/source/Cosmos.Core_Plugs/RuntimeFieldHandleImpl.cs new file mode 100644 index 000000000..06f8fb40a --- /dev/null +++ b/source/Cosmos.Core_Plugs/RuntimeFieldHandleImpl.cs @@ -0,0 +1,19 @@ +using Cosmos.Core_Plugs.System; +using IL2CPU.API.Attribs; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; + +namespace Cosmos.Core_Plugs +{ + [Plug(Target = typeof(global::System.RuntimeFieldHandle))] + public static class RuntimeFieldHandleImpl + { + [PlugMethod(Signature = "System_Object__System_RuntimeFieldHandle_GetValue_System_Reflection_RtFieldInfo__System_Object__System_RuntimeType__System_RuntimeType___System_Boolean_")] + public static object GetValue(FieldInfo field, object instance, object fieldType, object declaringType, ref bool domainInitialized) + { + throw new NotImplementedException("RuntimeFieldHandle.GetValue()"); + } + } +} diff --git a/source/Cosmos.Core_Plugs/System/DelegateImpl.cs b/source/Cosmos.Core_Plugs/System/DelegateImpl.cs index 48d81902a..0bc8d281f 100644 --- a/source/Cosmos.Core_Plugs/System/DelegateImpl.cs +++ b/source/Cosmos.Core_Plugs/System/DelegateImpl.cs @@ -5,17 +5,18 @@ using IL2CPU.API.Attribs; namespace Cosmos.Core_Plugs.System { - [Plug(Target = typeof(Delegate), Inheritable = true)] - [PlugField(FieldType = typeof(int), FieldId = "$$ArgSize$$")] - [PlugField(FieldType = typeof(int), FieldId = "$$ReturnsValue$$")] + [Plug(Target = typeof(Delegate))] public static class DelegateImpl { + [PlugMethod(Signature = "System_Boolean__System_Delegate_Equals_System_Object_")] public static bool Equals(Delegate aThis, object aThat) { // todo: implement proper Delegate.Equals(object) - return false; + //return false; + throw new NotImplementedException(); } + [PlugMethod(Signature = "System_Boolean__System_Delegate_InternalEqualTypes_System_Object__System_Object_")] public static unsafe bool InternalEqualTypes([ObjectPointerAccess] uint** a, [ObjectPointerAccess] uint** b) { var xTypeA = a[0][0]; @@ -23,7 +24,13 @@ namespace Cosmos.Core_Plugs.System return xTypeA == xTypeB; } + } + [Plug(Target = typeof(Delegate), Inheritable = true)] + [PlugField(FieldType = typeof(int), FieldId = "$$ArgSize$$")] + [PlugField(FieldType = typeof(int), FieldId = "$$ReturnsValue$$")] + public static class DelegateImplInherit + { [PlugMethod(Signature = "System_MulticastDelegate__System_Delegate_InternalAllocLike_System_Delegate_")] public static unsafe uint InternalAllocLike(uint* aDelegate) { @@ -38,5 +45,14 @@ namespace Cosmos.Core_Plugs.System } return xResultAddr; } + + [PlugMethod(Signature = "System_Boolean__System_Delegate_Equals_System_Object_")] + public static bool Equals(Delegate aThis, object aThat) + { + // todo: implement proper Delegate.Equals(object) + //return false; + throw new NotImplementedException(); + } + } } diff --git a/source/Cosmos.Core_Plugs/System/Globalization/CultureInfoImpl.cs b/source/Cosmos.Core_Plugs/System/Globalization/CultureInfoImpl.cs index a498cbbce..a6f8d5b7b 100644 --- a/source/Cosmos.Core_Plugs/System/Globalization/CultureInfoImpl.cs +++ b/source/Cosmos.Core_Plugs/System/Globalization/CultureInfoImpl.cs @@ -19,7 +19,12 @@ namespace Cosmos.Core_Plugs.System.Globalization public static int GetHashCode(CultureInfo aThis) { - throw new NotImplementedException(); + throw new NotImplementedException("CultureInfo.GetHashCode()"); + } + + public static bool Equals(CultureInfo aThis, object value) + { + throw new NotImplementedException("CultureInfo.Equals()"); } public static void CCtor() diff --git a/source/Cosmos.System2_Plugs/System/Threading/SpinWaitImpl.cs b/source/Cosmos.System2_Plugs/System/Threading/SpinWaitImpl.cs new file mode 100644 index 000000000..899172750 --- /dev/null +++ b/source/Cosmos.System2_Plugs/System/Threading/SpinWaitImpl.cs @@ -0,0 +1,15 @@ +using System; +using System.Threading; +using IL2CPU.API.Attribs; + +namespace Cosmos.System_Plugs.System.Threading +{ + [Plug(Target = typeof(global::System.Threading.SpinWait))] + public static class SpinWaitImpl + { + public static void SpinOnce(ref SpinWait aThis) + { + throw new NotImplementedException("SpinWait.SpinOnce()"); + } + } +} diff --git a/source/Cosmos.System2_Plugs/System/Threading/ThreadImpl.cs b/source/Cosmos.System2_Plugs/System/Threading/ThreadImpl.cs index 98446fb34..0038ebaf5 100644 --- a/source/Cosmos.System2_Plugs/System/Threading/ThreadImpl.cs +++ b/source/Cosmos.System2_Plugs/System/Threading/ThreadImpl.cs @@ -1,13 +1,11 @@ using System; -using System.Threading; - using Cosmos.HAL; - using IL2CPU.API.Attribs; namespace Cosmos.System_Plugs.System.Threading { - [Plug(Target = typeof(Thread))] + //[Plug(Target = typeof(Thread))] + [Plug(TargetName = "System.Threading.Thread")] public static class ThreadImpl { public static void Sleep(TimeSpan timeout) @@ -19,5 +17,15 @@ namespace Cosmos.System_Plugs.System.Threading { Global.PIT.Wait((uint)millisecondsTimeout); } + + public static bool Yield() + { + throw new NotImplementedException("Thread.Yield()"); + } + + public static void SpinWaitInternal(object iterations) + { + throw new NotImplementedException("Thread.SpinWaitInternal()"); + } } } diff --git a/source/Cosmos.System2_Plugs/System/ValueTypeImpl.cs b/source/Cosmos.System2_Plugs/System/ValueTypeImpl.cs index 37a64765b..d1901c8aa 100644 --- a/source/Cosmos.System2_Plugs/System/ValueTypeImpl.cs +++ b/source/Cosmos.System2_Plugs/System/ValueTypeImpl.cs @@ -24,6 +24,11 @@ namespace Cosmos.System_Plugs.System throw new NotImplementedException("ValueType.GetHashCodeOfPtr()"); } + public static bool Equals(ValueType aThis, object obj) + { + throw new NotImplementedException("ValueType.Equals()"); + } + //public static string ToString(ValueType aThis) //{ // return "";