Now plugs which aren't being used aren't being compiled anymore.

This commit is contained in:
Matthijs ter Woord 2016-06-24 15:26:31 -04:00
parent a37de93ccb
commit 19160c30d4
15 changed files with 119 additions and 134 deletions

View file

@ -17,7 +17,7 @@ namespace DebugCompiler
var xEngine = new Engine();
// 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
xEngine.AllowedSecondsInKernel = 30;
xEngine.AllowedSecondsInKernel = 300;
// If you want to test only specific platforms, add them to the list, like next line. By default, all platforms are run.
xEngine.RunTargets.Add(RunTargetEnum.Bochs);

View file

@ -7,21 +7,22 @@ namespace Cosmos.Core.Plugs.System
[Plug(Target = typeof(Buffer))]
public class BufferImpl
{
[PlugMethod(IsOptional = true)]
public static unsafe void __Memcpy(byte* src, byte* dest, int count)
{
global::System.Buffer.BlockCopy((Array)(object)*src, 0, (Array)(object)*dest, 0, count);
}
/// <summary>
/// The memmove() function copies n bytes from memory area src to memory area dest.
/// The memory areas may overlap: copying takes place as though the bytes in src
/// are first copied into a temporary array that does not overlap src or dest,
/// The memmove() function copies n bytes from memory area src to memory area dest.
/// The memory areas may overlap: copying takes place as though the bytes in src
/// are first copied into a temporary array that does not overlap src or dest,
/// and the bytes are then copied from the temporary array to dest.
/// </summary>
/// <param name="dest">Destination address to copy data into.</param>
/// <param name="src">Source address from where copy data.</param>
/// <param name="count">Count of bytes to copy.</param>
[PlugMethod(IsOptional = true)]
public static unsafe void __Memmove(byte* dest, byte* src, uint count)
{
uint t;
@ -149,4 +150,4 @@ namespace Cosmos.Core.Plugs.System
global::System.Buffer.BlockCopy(src, srcOffset, dst, dstOffset, count);
}
}
}
}

View file

@ -44,13 +44,11 @@ namespace Cosmos.Core.Plugs.System
return false;
}
public static unsafe bool InternalEqualTypes(uint** a, uint** b)
public static unsafe bool InternalEqualTypes([ObjectPointerAccess] uint** a, [ObjectPointerAccess] uint** b)
{
var xTypeA = a[0][0];
var xTypeB = b[0][0];
return xTypeA == xTypeB;
}
}

View file

@ -5,7 +5,7 @@ namespace Cosmos.Core.Plugs.System
[Plug(Target = typeof(object))]
public class ObjectImpl
{
public static unsafe uint MemberwiseClone(uint aThis)
public static unsafe uint MemberwiseClone([ObjectPointerAccess] uint aThis)
{
// pointers are handles!
@ -27,4 +27,4 @@ namespace Cosmos.Core.Plugs.System
return xResult;
}
}
}
}

View file

@ -820,6 +820,7 @@ namespace Cosmos.Core.Plugs.System
return new string(new char[length]);
}
[PlugMethod(IsOptional = true)]
public static string TrimStart(string aThis, string aSubStr)
{
char[] ci = aThis.ToCharArray();

View file

@ -0,0 +1,2 @@
[*.cs]
indent_size=2

View file

@ -90,6 +90,7 @@
<Compile Include="FieldTypeAttribute.cs" />
<Compile Include="FieldAccessAttribute.cs" />
<Compile Include="InlineAttribute.cs" />
<Compile Include="ObjectAccessPointerAttribute.cs" />
<Compile Include="PlugAttribute.cs" />
<Compile Include="PlugFieldAttribute.cs" />
<Compile Include="PlugMethodAttribute.cs" />
@ -99,6 +100,7 @@
<None Include="Key.snk" />
</ItemGroup>
<ItemGroup>
<None Include=".editorconfig" />
<Content Include="ReadMe.html" />
</ItemGroup>
<ItemGroup>

View file

@ -0,0 +1,13 @@
using System;
namespace Cosmos.IL2CPU.Plugs
{
/// <summary>
/// This attribute is used on plug parameters, that need the unsafe pointer to an object's data area
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public class ObjectPointerAccessAttribute : Attribute
{
}
}

View file

@ -12,5 +12,6 @@ namespace Cosmos.IL2CPU.Plugs
public bool PlugRequired = false;
public bool IsWildcard = false;
public bool WildcardMatchParameters = false;
public bool IsOptional = true;
}
}
}

View file

@ -209,26 +209,21 @@ namespace Cosmos.IL2CPU
{
DebugInfo.AddDocument(mSequences[0].Document);
var xMethod = new Method()
var xMethod = new Method();
xMethod.ID = mCurrentMethodGuid;
xMethod.TypeToken = aMethod.MethodBase.DeclaringType.MetadataToken;
xMethod.MethodToken = aMethod.MethodBase.MetadataToken;
xMethod.LabelStartID = xLabelGuid;
xMethod.LabelEndID = mCurrentMethodLabelEndGuid;
xMethod.LabelCall = xMethodLabel;
long xAssemblyFileID;
if (DebugInfo.AssemblyGUIDs.TryGetValue(aMethod.MethodBase.DeclaringType.Assembly, out xAssemblyFileID))
{
ID = mCurrentMethodGuid,
TypeToken = aMethod.MethodBase.DeclaringType.MetadataToken,
MethodToken = aMethod.MethodBase.MetadataToken,
LabelStartID = xLabelGuid,
LabelEndID = mCurrentMethodLabelEndGuid,
LabelCall = xMethodLabel,
AssemblyFileID = DebugInfo.AssemblyGUIDs[aMethod.MethodBase.DeclaringType.Assembly],
DocumentID = DebugInfo.DocumentGUIDs[mSequences[0].Document.ToLower()],
// Storing Line + Col as one item makes comparisons MUCH easier, otherwise we have to
// check for things like col < start col but line > start line.
//
// () around << are VERY important.. + has precedence over <<
LineColStart = ((Int64)mSequences[0].LineStart << 32) + mSequences[0].ColStart,
LineColEnd = ((Int64)(mSequences[mSequences.Length - 1].LineEnd) << 32) + mSequences[mSequences.Length - 1].ColEnd
};
xMethod.AssemblyFileID = xAssemblyFileID;
}
xMethod.DocumentID = DebugInfo.DocumentGUIDs[mSequences[0].Document.ToLower()];
xMethod.LineColStart = ((Int64)mSequences[0].LineStart << 32) + mSequences[0].ColStart;
xMethod.LineColEnd = ((Int64)(mSequences[mSequences.Length - 1].LineEnd) << 32) + mSequences[mSequences.Length - 1].ColEnd;
DebugInfo.AddMethod(xMethod);
}
}
@ -475,6 +470,11 @@ namespace Cosmos.IL2CPU
throw new Exception("Method needs plug, but no plug was assigned.");
}
if (aMethod.MethodBase.Name == "InitializeArray")
{
;
}
// todo: MtW: how to do this? we need some extra space.
// see ConstructLabel for extra info
if (aMethod.UID > 0x00FFFFFF)
@ -492,7 +492,7 @@ namespace Cosmos.IL2CPU
}
else if (aMethod.IsInlineAssembler)
{
aMethod.MethodBase.Invoke("", new object[aMethod.MethodBase.GetParameters().Length]);
aMethod.MethodBase.Invoke(null, new object[aMethod.MethodBase.GetParameters().Length]);
}
else
{

View file

@ -71,7 +71,7 @@ namespace Cosmos.IL2CPU
mAsmblr = aAsmblr;
mReader = new ILReader();
mPlugManager = new PlugManager(this.LogException, this.ScanMethod, this.Queue);
mPlugManager = new PlugManager(LogException);
}
public bool EnableLogging(string aPathname)
@ -94,6 +94,11 @@ namespace Cosmos.IL2CPU
protected void Queue(_MemberInfo aItem, object aSrc, string aSrcType, string sourceItem = null)
{
if (aItem == null)
{
throw new ArgumentNullException(nameof(aItem));
}
var xMemInfo = aItem as MemberInfo;
//TODO: fix this, as each label/symbol should also contain an assembly specifier.
@ -373,7 +378,6 @@ namespace Cosmos.IL2CPU
// isn't guaranteed.
//string xMethodFullName = LabelName.GenerateFullName(aMethod);
for (int i = 0; i < xParams.Length; i++)
{
xParamTypes[i] = xParams[i].ParameterType;
@ -479,10 +483,19 @@ namespace Cosmos.IL2CPU
MethodBase xPlug = null;
// Plugs may use plugs, but plugs won't be plugged over themself
var inl = aMethod.GetCustomAttribute<InlineAttribute>();
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)
{
//ScanMethod(xPlug, true, "Plug method");
if (inl == null)
{
Queue(xPlug, aMethod, "Plug method");
}
}
}
if (xPlug == null)
@ -517,11 +530,6 @@ namespace Cosmos.IL2CPU
//TODO: Dont queue new items if they are plugged
// or do we need to queue them with a resolved ref in a new list?
InlineAttribute inl = null;
foreach (InlineAttribute inli in aMethod.GetCustomAttributes(typeof(InlineAttribute), false))
{
inl = inli;
}
if (inl != null)
return; // cancel inline
@ -651,6 +659,7 @@ namespace Cosmos.IL2CPU
// and will reduce compares
if (xItem.Item is MethodBase)
{
//if (xItem.QueueReason == "Plug m")
ScanMethod((MethodBase)xItem.Item, false, xItem.SourceItem);
}
else if (xItem.Item is Type)
@ -834,20 +843,33 @@ namespace Cosmos.IL2CPU
var xMethodType = MethodInfo.TypeEnum.Normal;
Type xPlugAssembler = null;
MethodInfo xPlugInfo = null;
var xMethodInline = xMethod.GetCustomAttribute<InlineAttribute>();
if (xMethodInline != null)
{
// inline assembler, shouldn't come here..
continue;
}
var xMethodIdMethod = mItemsList.IndexOf(xMethod);
if (xMethodIdMethod == -1)
{
throw new Exception("Method not in scanner list!");
}
if (xPlug != null)
{
xMethodType = MethodInfo.TypeEnum.NeedsPlug;
PlugMethodAttribute xAttrib = null;
foreach (PlugMethodAttribute attrib in xPlug.GetCustomAttributes(typeof(PlugMethodAttribute), true))
var xAttrib = xPlug.GetCustomAttribute<PlugMethodAttribute>();
var xInline = xPlug.GetCustomAttribute<InlineAttribute>();
var xMethodIdPlug = mItemsList.IndexOf(xPlug);
if (xMethodIdPlug == -1 && xInline == null)
{
xAttrib = attrib;
throw new Exception("Plug method not in scanner list!");
}
if (xAttrib != null)
if (xAttrib != null && xInline == null)
{
xPlugAssembler = xAttrib.Assembler;
xPlugInfo = new MethodInfo(xPlug, (uint)mItemsList.IndexOf(xPlug), MethodInfo.TypeEnum.Plug, null, xPlugAssembler);
xPlugInfo = new MethodInfo(xPlug, (uint)xMethodIdPlug, MethodInfo.TypeEnum.Plug, null, xPlugAssembler);
var xMethodInfo = new MethodInfo(xMethod, (uint)mItemsList.IndexOf(xMethod), xMethodType, xPlugInfo/*, xPlugAssembler*/);
var xMethodInfo = new MethodInfo(xMethod, (uint)xMethodIdMethod, xMethodType, xPlugInfo/*, xPlugAssembler*/);
if (xAttrib != null && xAttrib.IsWildcard)
{
xPlugInfo.PluggedMethod = xMethodInfo;
@ -862,16 +884,16 @@ namespace Cosmos.IL2CPU
}
else
{
InlineAttribute inl = null;
foreach (InlineAttribute inli in xPlug.GetCustomAttributes(typeof(InlineAttribute), false))
if (xInline != null)
{
inl = inli;
}
if (inl != null)
{
xPlugInfo = new MethodInfo(xPlug, (uint)mItemsList.IndexOf(xItem), MethodInfo.TypeEnum.Plug, null, true);
var xMethodID = mItemsList.IndexOf(xItem);
if (xMethodID == -1)
{
throw new Exception("Method not in list!");
}
xPlugInfo = new MethodInfo(xPlug, (uint)xMethodID, MethodInfo.TypeEnum.Plug, null, true);
var xMethodInfo = new MethodInfo(xMethod, (uint)mItemsList.IndexOf(xMethod), xMethodType, xPlugInfo/*, xPlugAssembler*/);
var xMethodInfo = new MethodInfo(xMethod, (uint)xMethodIdMethod, xMethodType, xPlugInfo/*, xPlugAssembler*/);
xPlugInfo.PluggedMethod = xMethodInfo;
var xInstructions = mReader.ProcessMethod(xPlug);
@ -884,19 +906,9 @@ namespace Cosmos.IL2CPU
}
else
{
xPlugInfo = new MethodInfo(xPlug, (uint)mItemsList.IndexOf(xPlug), MethodInfo.TypeEnum.Plug, null, xPlugAssembler);
xPlugInfo = new MethodInfo(xPlug, (uint)xMethodIdPlug, MethodInfo.TypeEnum.Plug, null, xPlugAssembler);
var xMethodInfo = new MethodInfo(xMethod, (uint)mItemsList.IndexOf(xMethod), xMethodType, xPlugInfo/*, xPlugAssembler*/);
if (xAttrib != null && xAttrib.IsWildcard)
{
xPlugInfo.PluggedMethod = xMethodInfo;
var xInstructions = mReader.ProcessMethod(xPlug);
if (xInstructions != null)
{
ProcessInstructions(xInstructions);
mAsmblr.ProcessMethod(xPlugInfo, xInstructions);
}
}
var xMethodInfo = new MethodInfo(xMethod, (uint)xMethodIdMethod, xMethodType, xPlugInfo/*, xPlugAssembler*/);
mAsmblr.GenerateMethodForward(xMethodInfo, xPlugInfo);
}
}
@ -921,7 +933,7 @@ namespace Cosmos.IL2CPU
xPlugAssembler = xAttrib.Assembler;
}
var xMethodInfo = new MethodInfo(xMethod, (uint)mItemsList.IndexOf(xMethod), xMethodType, xPlugInfo, xPlugAssembler);
var xMethodInfo = new MethodInfo(xMethod, (uint)xMethodIdMethod, xMethodType, xPlugInfo, xPlugAssembler);
var xInstructions = mReader.ProcessMethod(xMethod);
if (xInstructions != null)
{

View file

@ -20,10 +20,10 @@ namespace Cosmos.IL2CPU
public LogExceptionDelegate LogException = null;
public delegate void ScanMethodDelegate(MethodBase aMethod, bool aIsPlug, string sourceItem);
public ScanMethodDelegate ScanMethod = null;
public delegate void QueueDelegate(_MemberInfo aItem, object aSrc, string aSrcType, string sourceItem = null);
public QueueDelegate Queue = null;
////public delegate void ScanMethodDelegate(MethodBase aMethod, bool aIsPlug, string sourceItem);
//public ScanMethodDelegate ScanMethod = null;
//public delegate void QueueDelegate(_MemberInfo aItem, object aSrc, string aSrcType, string sourceItem = null);
//public QueueDelegate Queue = null;
// Contains a list of plug implementor classes
// Key = Target Class
@ -67,12 +67,6 @@ namespace Cosmos.IL2CPU
{
LogException = aLogException;
}
public PlugManager(LogExceptionDelegate aLogException, ScanMethodDelegate aScanMethod, QueueDelegate aQueueMethod)
{
LogException = aLogException;
ScanMethod = aScanMethod;
Queue = aQueueMethod;
}
public void FindPlugImpls()
{
@ -184,10 +178,12 @@ namespace Cosmos.IL2CPU
}
else
{
//Skip checking methods related to fields because it's just too messy...
if (xMethod.GetParameters().Where(delegate (ParameterInfo x)
// Skip checking methods related to fields because it's just too messy...
// We also skip methods which do method access.
if (xMethod.GetParameters().Where(x =>
{
return x.GetCustomAttributes(typeof(FieldAccessAttribute)).Count() > 0;
return x.GetCustomAttributes(typeof(FieldAccessAttribute)).Count() > 0
|| x.GetCustomAttributes(typeof(ObjectPointerAccessAttribute)).Count() > 0;
}).Count() > 0)
{
OK = true;
@ -306,41 +302,21 @@ namespace Cosmos.IL2CPU
}
}
if (OK)
if (!OK)
{
if (ScanMethod != null)
if (xAttrib == null
|| xAttrib.IsOptional)
{
ScanMethod(xMethod, true, "Plug Sub Method");
}
}
else
{
if (LogException != null)
{
LogException(new Exception("Invalid plug method! Target method not found. : " + xMethod.GetFullName()));
throw new Exception("Invalid plug method! Target method not found. : " + xMethod.GetFullName());
}
}
}
else
{
if (xAttrib.IsWildcard && xAttrib.Assembler == null)
if (xAttrib.IsWildcard
&& xAttrib.Assembler == null)
{
Exception anEx = new Exception("Wildcard PlugMethods need to use an assembler for now.");
if (ThrowExceptions)
{
throw anEx;
}
else
{
LogException(anEx);
}
}
if (xAttrib.Enabled && !xAttrib.IsMonoOnly)
{
if (ScanMethod != null)
{
ScanMethod(xMethod, true, ".Net plug Method");
}
throw new Exception("Wildcard PlugMethods need to use an assembler for now.");
}
}
}
@ -356,15 +332,7 @@ namespace Cosmos.IL2CPU
}
if (xFields.ContainsKey(xField.FieldId))
{
Exception anEx = new Exception("Duplicate PlugField found for field '" + xField.FieldId + "'!");
if (ThrowExceptions)
{
throw anEx;
}
else
{
LogException(anEx);
}
throw new Exception("Duplicate PlugField found for field '" + xField.FieldId + "'!");
}
xFields.Add(xField.FieldId, xField);
}
@ -644,21 +612,6 @@ namespace Cosmos.IL2CPU
//}
}
InlineAttribute xInlineAttrib = null;
foreach (InlineAttribute inli in xResult.GetCustomAttributes(typeof(InlineAttribute), false))
{
xInlineAttrib = inli;
}
if (xInlineAttrib == null)
{
if (Queue != null)
{
CompilerHelpers.Debug("Queueing Plug:", xResult.DeclaringType, "::", xResult.Name);
Queue(xResult, null, "Plug Method");
}
}
//if (xAttrib != null && xAttrib.Signature != null)
//{
// var xTargetMethods = aTargetType.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

View file

@ -14,6 +14,7 @@ namespace Cosmos.IL2CPU.Plugs.System.Runtime.CompilerServices {
}
[Inline(TargetPlatform = TargetPlatform.x86)]
[PlugMethod]
public static void InitializeArray(Array array, RuntimeFieldHandle fldHandle) {
// Arguments:
// Array aArray, RuntimeFieldHandle aFieldHandle

View file

@ -65,7 +65,7 @@ namespace Cosmos.System.Plugs.System.IO
{
throw new ArgumentNullException((aPath1 == null) ? "path1" : "path2");
}
CheckInvalidPathChars(aPath1);
CheckInvalidPathChars(aPath2);
string result = CombineNoChecks(aPath1, aPath2);
@ -275,6 +275,7 @@ namespace Cosmos.System.Plugs.System.IO
return false;
}
[PlugMethod(IsOptional = true)]
public static bool HasIllegalCharacters(string aPath, bool aCheckAdditional)
{
if (aCheckAdditional)

View file

@ -70,11 +70,11 @@ namespace PlugsInspector
//Force it to load/include all plugs assemblies so all types are correctly found
//Otherwise the CLR's delay loading techniques block us...
AssembliesPreloader.LoadAllAssemblies();
plugManager = new PlugManager((Exception ex) => {
AddExceptionEntry(ex.Message);
}, this.ScanMethod, null);
});
plugManager.ThrowExceptions = false;
}
@ -278,7 +278,7 @@ namespace PlugsInspector
public override string ToString()
{
string name = NetMethodInfo.Name;
name += "(";
var netParams = NetMethodInfo.GetParameters();
var netParamTypes = netParams.Select(q => q.ParameterType).ToArray();