diff --git a/Tests/Cosmos.TestRunner.Core/DefaultEngineConfiguration.cs b/Tests/Cosmos.TestRunner.Core/DefaultEngineConfiguration.cs index e71c66175..66fd46e66 100644 --- a/Tests/Cosmos.TestRunner.Core/DefaultEngineConfiguration.cs +++ b/Tests/Cosmos.TestRunner.Core/DefaultEngineConfiguration.cs @@ -15,14 +15,14 @@ namespace Cosmos.TestRunner.Core // Sets the time before an error is registered. For example if set to 60 then if a kernel runs for more than 60 seconds then // that kernel will be marked as a failure and terminated - engine.AllowedSecondsInKernel = 1800; + engine.AllowedSecondsInKernel = 30; // If you want to test only specific platforms, add them to the list, like next line. By default, all platforms are run. engine.RunTargets.Add(RunTargetEnum.Bochs); // If you're working on the compiler (or other lower parts), you can choose to run the compiler in process // one thing to keep in mind though, is that this only works with 1 kernel at a time! - //engine.RunIL2CPUInProcess = true; + engine.RunIL2CPUInProcess = true; engine.TraceAssembliesLevel = TraceAssemblies.User; engine.EnableStackCorruptionChecks = true; engine.StackCorruptionChecksLevel = StackCorruptionDetectionLevel.AllInstructions; diff --git a/Users/Matthijs/DebugCompiler/MyEngine.cs b/Users/Matthijs/DebugCompiler/MyEngine.cs index f5b1d0b54..c599630e7 100644 --- a/Users/Matthijs/DebugCompiler/MyEngine.cs +++ b/Users/Matthijs/DebugCompiler/MyEngine.cs @@ -12,6 +12,7 @@ namespace DebugCompiler [TestCaseSource(typeof(MySource), nameof(MySource.ProvideData))] public void Test(Type kernelToRun) { + Assert.Fail(); Environment.CurrentDirectory = Path.GetDirectoryName(typeof(RunKernels).Assembly.Location); var xEngine = new Engine(); @@ -25,7 +26,7 @@ namespace DebugCompiler //xEngine.RunWithGDB = true; // If you're working on the compiler (or other lower parts), you can choose to run the compiler in process // one thing to keep in mind though, is that this only works with 1 kernel at a time! - xEngine.RunIL2CPUInProcess = false; + xEngine.RunIL2CPUInProcess = true; xEngine.TraceAssembliesLevel = TraceAssemblies.User; xEngine.EnableStackCorruptionChecks = true; diff --git a/source/Cosmos.IL2CPU/ILScanner.cs b/source/Cosmos.IL2CPU/ILScanner.cs index 2fae8b27b..6ed7a0ee9 100644 --- a/source/Cosmos.IL2CPU/ILScanner.cs +++ b/source/Cosmos.IL2CPU/ILScanner.cs @@ -398,7 +398,10 @@ namespace Cosmos.IL2CPU { Queue(((SysReflection.MethodInfo)aMethod).ReturnType, aMethod, "Return Type"); } - + if (aMethod.GetFullName().IndexOf("CreateComparer", StringComparison.OrdinalIgnoreCase)!=-1) + { + ; + } // Scan virtuals #region Virtuals scan if (!xIsDynamicMethod && aMethod.IsVirtual) @@ -487,6 +490,7 @@ namespace Cosmos.IL2CPU if (!aIsPlug && !xIsDynamicMethod) { // Check to see if method is plugged, if it is we don't scan body + xPlug = mPlugManager.ResolvePlug(aMethod, xParamTypes); if (xPlug != null) { diff --git a/source/Cosmos.IL2CPU/PlugManager.cs b/source/Cosmos.IL2CPU/PlugManager.cs index bf171453d..522b5fd47 100644 --- a/source/Cosmos.IL2CPU/PlugManager.cs +++ b/source/Cosmos.IL2CPU/PlugManager.cs @@ -32,6 +32,11 @@ namespace Cosmos.IL2CPU // List of inheritable plugs. Plugs that start at an ancestor and plug all // descendants. For example, delegates protected Dictionary> mPlugImplsInhrt = new Dictionary>(); + + // same as above 2 fields, except for generic plugs + protected Dictionary> mGenericPlugImpls = new Dictionary>(); + protected Dictionary> mGenericPlugImplsInhrt = new Dictionary>(); + // list of field plugs protected IDictionary> mPlugFields = new Dictionary>(); @@ -121,7 +126,15 @@ namespace Cosmos.IL2CPU // TODO: Integrate with builder options to allow Mono support again. if (!xAttrib.IsMonoOnly) { - var mPlugs = xAttrib.Inheritable ? mPlugImplsInhrt : mPlugImpls; + Dictionary> mPlugs; + if (xTargetType.ContainsGenericParameters) + { + mPlugs = xAttrib.Inheritable ? mGenericPlugImplsInhrt : mGenericPlugImpls; + } + else + { + mPlugs = xAttrib.Inheritable ? mPlugImplsInhrt : mPlugImpls; + } List xImpls; if (mPlugs.TryGetValue(xTargetType, out xImpls)) { @@ -145,6 +158,7 @@ namespace Cosmos.IL2CPU ScanPlugs(mPlugImpls); ScanPlugs(mPlugImplsInhrt); } + public void ScanPlugs(Dictionary> aPlugs) { foreach (var xPlug in aPlugs) @@ -341,7 +355,7 @@ namespace Cosmos.IL2CPU } } - public MethodBase ResolvePlug(Type aTargetType, List aImpls, MethodBase aMethod, Type[] aParamTypes) + private MethodBase ResolvePlug(Type aTargetType, List aImpls, MethodBase aMethod, Type[] aParamTypes) { //TODO: This method is "reversed" from old - remember that when porting MethodBase xResult = null; @@ -526,6 +540,10 @@ namespace Cosmos.IL2CPU xResult = xSigMethod; break; } + //if (aMethod.DeclaringType.IsGenericTypeDefinition) + //{ + // if (xTargetMethod.GetF) + //} if (xAttrib != null && xAttrib.Signature != null) { var xName = DataMember.FilterStringForIncorrectChars(LabelName.GenerateFullName(aMethod)); @@ -642,9 +660,14 @@ namespace Cosmos.IL2CPU //} return xResult; } + public MethodBase ResolvePlug(MethodBase aMethod, Type[] aParamTypes) { MethodBase xResult = null; + if (aMethod.Name == "CreateComparer") + { + ; + } var xMethodKey = BuildMethodKeyName(aMethod); if (ResolvedPlugs.Contains(xMethodKey, out xResult)) { @@ -652,10 +675,6 @@ namespace Cosmos.IL2CPU } else { - // TODO: Right now plugs are compiled in, even if they are not needed. - // Maybe change this so plugs that are not needed are not compiled in? - // To do so, maybe plugs could be marked as they are used - List xImpls; // Check for exact type plugs first, they have precedence if (mPlugImpls.TryGetValue(aMethod.DeclaringType, out xImpls)) @@ -683,6 +702,62 @@ namespace Cosmos.IL2CPU } } } + if (xResult == null) + { + xImpls = null; + if (aMethod.DeclaringType.IsGenericType) + { + var xMethodDeclaringTypeDef = aMethod.DeclaringType.GetGenericTypeDefinition(); + if (mGenericPlugImpls.TryGetValue(xMethodDeclaringTypeDef, out xImpls)) + { + var xBindingFlagsToFindMethod = BindingFlags.Default; + if (aMethod.IsPublic) + { + xBindingFlagsToFindMethod = BindingFlags.Public; + } + else + { + // private + xBindingFlagsToFindMethod = BindingFlags.NonPublic; + } + if (aMethod.IsStatic) + { + xBindingFlagsToFindMethod |= BindingFlags.Static; + } + else + { + xBindingFlagsToFindMethod |= BindingFlags.Instance; + } + var xGenericMethod = (from item in xMethodDeclaringTypeDef.GetMethods(xBindingFlagsToFindMethod) + where item.Name == aMethod.Name + && item.GetParameters().Length == aParamTypes.Length + select item).SingleOrDefault(); + if (xGenericMethod != null) + { + var xTempResult = ResolvePlug(xMethodDeclaringTypeDef, xImpls, xGenericMethod, aParamTypes); + + if (xTempResult != null) + { + if (xTempResult.DeclaringType.IsGenericTypeDefinition) + { + var xConcreteTempResultType = xTempResult.DeclaringType.MakeGenericType(aMethod.DeclaringType.GetGenericArguments()); + xResult = (from item in xConcreteTempResultType.GetMethods(BindingFlags.Static | BindingFlags.Public) + where item.Name == aMethod.Name + && item.GetParameters().Length == aParamTypes.Length + select item).SingleOrDefault(); + } + } + ; + ; + ; + ; + + } + + /// + } + } + } ResolvedPlugs.Add(xMethodKey, xResult); diff --git a/source/Cosmos.IL2CPU/Plugs/System/Runtime/CompilerServices/RuntimeHelpersImpl.cs b/source/Cosmos.IL2CPU/Plugs/System/Runtime/CompilerServices/RuntimeHelpersImpl.cs index 1f7ec8b0c..7723bf18a 100644 --- a/source/Cosmos.IL2CPU/Plugs/System/Runtime/CompilerServices/RuntimeHelpersImpl.cs +++ b/source/Cosmos.IL2CPU/Plugs/System/Runtime/CompilerServices/RuntimeHelpersImpl.cs @@ -13,6 +13,21 @@ namespace Cosmos.IL2CPU.Plugs.System.Runtime.CompilerServices { //TODO: do something } + public new static bool Equals(object o1, object o2) + { + if (o1 == null + && o2 == null) + { + return true; + } + if (o1 == null + || o2 == null) + { + return false; + } + return object.Equals(o1, o2); + } + [Inline(TargetPlatform = TargetPlatform.x86)] [PlugMethod] public static void InitializeArray(Array array, RuntimeFieldHandle fldHandle) { diff --git a/source/Cosmos.System.Plugs/Cosmos.System.Plugs.csproj b/source/Cosmos.System.Plugs/Cosmos.System.Plugs.csproj index be071ea18..8d71fc9b1 100644 --- a/source/Cosmos.System.Plugs/Cosmos.System.Plugs.csproj +++ b/source/Cosmos.System.Plugs/Cosmos.System.Plugs.csproj @@ -88,6 +88,7 @@ + diff --git a/source/Cosmos.System.Plugs/System/CharImpl.cs b/source/Cosmos.System.Plugs/System/CharImpl.cs index 6d6de0526..7b0c83153 100644 --- a/source/Cosmos.System.Plugs/System/CharImpl.cs +++ b/source/Cosmos.System.Plugs/System/CharImpl.cs @@ -39,6 +39,11 @@ namespace Cosmos.System.Plugs.System return new string(xResult); } + public static bool Equals(ref char aThis, char that) + { + return aThis == that; + } + public static char ToUpper(char aThis) { // todo: properly implement Char.ToUpper() @@ -50,4 +55,4 @@ namespace Cosmos.System.Plugs.System return aChar == ' ' || aChar == '\t'; } } -} \ No newline at end of file +} diff --git a/source/Cosmos.System.Plugs/System/Collections/Generic/EqualityComparerImpl.cs b/source/Cosmos.System.Plugs/System/Collections/Generic/EqualityComparerImpl.cs new file mode 100644 index 000000000..d733871fd --- /dev/null +++ b/source/Cosmos.System.Plugs/System/Collections/Generic/EqualityComparerImpl.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using Cosmos.IL2CPU.Plugs; + +namespace Cosmos.System.Plugs.System.Collections.Generic +{ + [Plug(Target = typeof(EqualityComparer<>))] + public static class EqualityComparerImpl + { + public static EqualityComparer CreateComparer() + { + throw new Exception("Create comparer not yet implemented!"); + } + } +}