Generic plugs work now.

This commit is contained in:
Matthijs ter Woord 2016-06-25 10:52:50 -04:00
parent 0af938b0b8
commit 1433340ba5
8 changed files with 127 additions and 11 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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)
{

View file

@ -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<Type, List<Type>> mPlugImplsInhrt = new Dictionary<Type, List<Type>>();
// same as above 2 fields, except for generic plugs
protected Dictionary<Type, List<Type>> mGenericPlugImpls = new Dictionary<Type, List<Type>>();
protected Dictionary<Type, List<Type>> mGenericPlugImplsInhrt = new Dictionary<Type, List<Type>>();
// list of field plugs
protected IDictionary<Type, IDictionary<string, PlugFieldAttribute>> mPlugFields = new Dictionary<Type, IDictionary<string, PlugFieldAttribute>>();
@ -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<Type, List<Type>> mPlugs;
if (xTargetType.ContainsGenericParameters)
{
mPlugs = xAttrib.Inheritable ? mGenericPlugImplsInhrt : mGenericPlugImpls;
}
else
{
mPlugs = xAttrib.Inheritable ? mPlugImplsInhrt : mPlugImpls;
}
List<Type> xImpls;
if (mPlugs.TryGetValue(xTargetType, out xImpls))
{
@ -145,6 +158,7 @@ namespace Cosmos.IL2CPU
ScanPlugs(mPlugImpls);
ScanPlugs(mPlugImplsInhrt);
}
public void ScanPlugs(Dictionary<Type, List<Type>> aPlugs)
{
foreach (var xPlug in aPlugs)
@ -341,7 +355,7 @@ namespace Cosmos.IL2CPU
}
}
public MethodBase ResolvePlug(Type aTargetType, List<Type> aImpls, MethodBase aMethod, Type[] aParamTypes)
private MethodBase ResolvePlug(Type aTargetType, List<Type> 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<Type> 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);

View file

@ -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) {

View file

@ -88,6 +88,7 @@
<Reference Include="System.Drawing" />
</ItemGroup>
<ItemGroup>
<Compile Include="System\Collections\Generic\EqualityComparerImpl.cs" />
<Compile Include="System\DecimalImpl.cs" />
<Compile Include="System\Mda.cs" />
<Compile Include="System\Security\Cryptography\CryptoConfigImpl.cs" />

View file

@ -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';
}
}
}
}

View file

@ -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<T>
{
public static EqualityComparer<T> CreateComparer()
{
throw new Exception("Create comparer not yet implemented!");
}
}
}