mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-24 12:35:31 +00:00
g3
This commit is contained in:
parent
e19dfd6b33
commit
a438fb076c
5 changed files with 106 additions and 209 deletions
|
|
@ -9,5 +9,8 @@ cd source\kernel-x86
|
||||||
copy "00-CPU\Cosmos.CPU_Plugs\bin\Debug\netstandard1.5\Cosmos.CPU_Plugs.dll" "%USERPROFILE%\AppData\Roaming\Cosmos User Kit\Kernel\"
|
copy "00-CPU\Cosmos.CPU_Plugs\bin\Debug\netstandard1.5\Cosmos.CPU_Plugs.dll" "%USERPROFILE%\AppData\Roaming\Cosmos User Kit\Kernel\"
|
||||||
copy "00-CPU\Cosmos.CPU_Asm\bin\Debug\netstandard1.5\Cosmos.CPU_Asm.dll" "%USERPROFILE%\AppData\Roaming\Cosmos User Kit\Kernel\"
|
copy "00-CPU\Cosmos.CPU_Asm\bin\Debug\netstandard1.5\Cosmos.CPU_Asm.dll" "%USERPROFILE%\AppData\Roaming\Cosmos User Kit\Kernel\"
|
||||||
copy "80-System\Cosmos.System_Plugs\bin\Debug\netstandard1.5\Cosmos.System_Plugs.dll" "%USERPROFILE%\AppData\Roaming\Cosmos User Kit\Kernel\"
|
copy "80-System\Cosmos.System_Plugs\bin\Debug\netstandard1.5\Cosmos.System_Plugs.dll" "%USERPROFILE%\AppData\Roaming\Cosmos User Kit\Kernel\"
|
||||||
|
cd ..\..
|
||||||
|
|
||||||
|
copy source\IL2CPU\bin\Debug\netcoreapp1.0 "%USERPROFILE%\AppData\Roaming\Cosmos User Kit\Build\IL2CPU"
|
||||||
|
|
||||||
@timeout 3
|
@timeout 3
|
||||||
|
|
|
||||||
|
|
@ -306,6 +306,7 @@ namespace Cosmos.IL2CPU {
|
||||||
|
|
||||||
foreach (var xType in xAssembly.ExportedTypes) {
|
foreach (var xType in xAssembly.ExportedTypes) {
|
||||||
var xTypeInfo = xType.GetTypeInfo();
|
var xTypeInfo = xType.GetTypeInfo();
|
||||||
|
|
||||||
if (!xTypeInfo.IsGenericTypeDefinition && !xTypeInfo.IsAbstract) {
|
if (!xTypeInfo.IsGenericTypeDefinition && !xTypeInfo.IsAbstract) {
|
||||||
CompilerHelpers.Debug($"Checking type {xType.FullName}");
|
CompilerHelpers.Debug($"Checking type {xType.FullName}");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,15 +14,12 @@ using Cosmos.IL2CPU.Extensions;
|
||||||
using Cosmos.IL2CPU.X86.IL;
|
using Cosmos.IL2CPU.X86.IL;
|
||||||
using XSharp.Common;
|
using XSharp.Common;
|
||||||
|
|
||||||
namespace Cosmos.IL2CPU
|
namespace Cosmos.IL2CPU {
|
||||||
{
|
public abstract class ILOp {
|
||||||
public abstract class ILOp
|
|
||||||
{
|
|
||||||
public static PlugManager mPlugManager;
|
public static PlugManager mPlugManager;
|
||||||
protected readonly Assembler.Assembler Assembler;
|
protected readonly Assembler.Assembler Assembler;
|
||||||
|
|
||||||
protected ILOp(Assembler.Assembler aAsmblr)
|
protected ILOp(Assembler.Assembler aAsmblr) {
|
||||||
{
|
|
||||||
Assembler = aAsmblr;
|
Assembler = aAsmblr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,90 +29,72 @@ namespace Cosmos.IL2CPU
|
||||||
// could be used for other things, profiling, analysis, reporting, etc
|
// could be used for other things, profiling, analysis, reporting, etc
|
||||||
public abstract void Execute(_MethodInfo aMethod, ILOpCode aOpCode);
|
public abstract void Execute(_MethodInfo aMethod, ILOpCode aOpCode);
|
||||||
|
|
||||||
public static string GetTypeIDLabel(Type aType)
|
public static string GetTypeIDLabel(Type aType) {
|
||||||
{
|
|
||||||
return "VMT__TYPE_ID_HOLDER__" + DataMember.FilterStringForIncorrectChars(LabelName.GetFullName(aType) + " ASM_IS__" + aType.GetTypeInfo().Assembly.GetName().Name);
|
return "VMT__TYPE_ID_HOLDER__" + DataMember.FilterStringForIncorrectChars(LabelName.GetFullName(aType) + " ASM_IS__" + aType.GetTypeInfo().Assembly.GetName().Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint Align(uint aSize, uint aAlign)
|
public static uint Align(uint aSize, uint aAlign) {
|
||||||
{
|
|
||||||
var xSize = aSize;
|
var xSize = aSize;
|
||||||
if ((xSize % aAlign) != 0)
|
if ((xSize % aAlign) != 0) {
|
||||||
{
|
|
||||||
xSize += aAlign - (xSize % aAlign);
|
xSize += aAlign - (xSize % aAlign);
|
||||||
}
|
}
|
||||||
return xSize;
|
return xSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int SignedAlign(int aSize, int aAlign)
|
public static int SignedAlign(int aSize, int aAlign) {
|
||||||
{
|
|
||||||
int xSize = aSize;
|
int xSize = aSize;
|
||||||
if ((xSize % aAlign) != 0)
|
if ((xSize % aAlign) != 0) {
|
||||||
{
|
|
||||||
xSize += aAlign - (xSize % aAlign);
|
xSize += aAlign - (xSize % aAlign);
|
||||||
}
|
}
|
||||||
return xSize;
|
return xSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetLabel(_MethodInfo aMethod, ILOpCode aOpCode)
|
public static string GetLabel(_MethodInfo aMethod, ILOpCode aOpCode) {
|
||||||
{
|
|
||||||
return GetLabel(aMethod, aOpCode.Position);
|
return GetLabel(aMethod, aOpCode.Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetLabel(MethodBase aMethod)
|
public static string GetLabel(MethodBase aMethod) {
|
||||||
{
|
|
||||||
return LabelName.Get(aMethod);
|
return LabelName.Get(aMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetLabel(_MethodInfo aMethod)
|
public static string GetLabel(_MethodInfo aMethod) {
|
||||||
{
|
if (aMethod.PluggedMethod != null) {
|
||||||
if (aMethod.PluggedMethod != null)
|
|
||||||
{
|
|
||||||
return "PLUG_FOR___" + GetLabel(aMethod.PluggedMethod.MethodBase);
|
return "PLUG_FOR___" + GetLabel(aMethod.PluggedMethod.MethodBase);
|
||||||
}
|
}
|
||||||
return GetLabel(aMethod.MethodBase);
|
return GetLabel(aMethod.MethodBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetLabel(_MethodInfo aMethod, int aPos)
|
public static string GetLabel(_MethodInfo aMethod, int aPos) {
|
||||||
{
|
|
||||||
return LabelName.Get(GetLabel(aMethod), aPos);
|
return LabelName.Get(GetLabel(aMethod), aPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString() {
|
||||||
{
|
|
||||||
return GetType().Name;
|
return GetType().Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void Jump_Exception(_MethodInfo aMethod)
|
protected static void Jump_Exception(_MethodInfo aMethod) {
|
||||||
{
|
|
||||||
// todo: port to numeric labels
|
// todo: port to numeric labels
|
||||||
XS.Jump(GetLabel(aMethod) + AppAssembler.EndOfMethodLabelNameException);
|
XS.Jump(GetLabel(aMethod) + AppAssembler.EndOfMethodLabelNameException);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void Jump_End(_MethodInfo aMethod)
|
protected static void Jump_End(_MethodInfo aMethod) {
|
||||||
{
|
|
||||||
XS.Jump(GetLabel(aMethod) + AppAssembler.EndOfMethodLabelNameNormal);
|
XS.Jump(GetLabel(aMethod) + AppAssembler.EndOfMethodLabelNameNormal);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint GetStackCountForLocal(_MethodInfo aMethod, Type aField)
|
public static uint GetStackCountForLocal(_MethodInfo aMethod, Type aField) {
|
||||||
{
|
|
||||||
var xSize = SizeOfType(aField);
|
var xSize = SizeOfType(aField);
|
||||||
var xResult = xSize / 4;
|
var xResult = xSize / 4;
|
||||||
if (xSize % 4 != 0)
|
if (xSize % 4 != 0) {
|
||||||
{
|
|
||||||
xResult++;
|
xResult++;
|
||||||
}
|
}
|
||||||
return xResult;
|
return xResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint GetEBPOffsetForLocal(_MethodInfo aMethod, int localIndex)
|
public static uint GetEBPOffsetForLocal(_MethodInfo aMethod, int localIndex) {
|
||||||
{
|
|
||||||
var xLocalInfos = aMethod.MethodBase.GetLocalVariables();
|
var xLocalInfos = aMethod.MethodBase.GetLocalVariables();
|
||||||
uint xOffset = 4;
|
uint xOffset = 4;
|
||||||
for (int i = 0; i < xLocalInfos.Count; i++)
|
for (int i = 0; i < xLocalInfos.Count; i++) {
|
||||||
{
|
if (i == localIndex) {
|
||||||
if (i == localIndex)
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var xField = xLocalInfos[i];
|
var xField = xLocalInfos[i];
|
||||||
|
|
@ -124,8 +103,7 @@ namespace Cosmos.IL2CPU
|
||||||
return xOffset;
|
return xOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint GetEBPOffsetForLocalForDebugger(_MethodInfo aMethod, int localIndex)
|
public static uint GetEBPOffsetForLocalForDebugger(_MethodInfo aMethod, int localIndex) {
|
||||||
{
|
|
||||||
// because the memory is read in positive direction, we need to add additional size if greater than 4
|
// because the memory is read in positive direction, we need to add additional size if greater than 4
|
||||||
uint xOffset = GetEBPOffsetForLocal(aMethod, localIndex);
|
uint xOffset = GetEBPOffsetForLocal(aMethod, localIndex);
|
||||||
var xLocalInfos = aMethod.MethodBase.GetLocalVariables();
|
var xLocalInfos = aMethod.MethodBase.GetLocalVariables();
|
||||||
|
|
@ -134,40 +112,32 @@ namespace Cosmos.IL2CPU
|
||||||
return xOffset;
|
return xOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void ThrowNotImplementedException(string aMessage)
|
protected void ThrowNotImplementedException(string aMessage) {
|
||||||
{
|
|
||||||
XS.Push(LdStr.GetContentsArrayName(aMessage));
|
XS.Push(LdStr.GetContentsArrayName(aMessage));
|
||||||
new CPU.Call
|
new CPU.Call {
|
||||||
{
|
|
||||||
DestinationLabel = LabelName.Get(typeof(ExceptionHelper).GetMethod("ThrowNotImplemented", BindingFlags.Static | BindingFlags.Public))
|
DestinationLabel = LabelName.Get(typeof(ExceptionHelper).GetMethod("ThrowNotImplemented", BindingFlags.Static | BindingFlags.Public))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void ThrowOverflowException()
|
protected void ThrowOverflowException() {
|
||||||
{
|
new CPU.Call {
|
||||||
new CPU.Call
|
|
||||||
{
|
|
||||||
DestinationLabel = LabelName.Get(typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public))
|
DestinationLabel = LabelName.Get(typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DoGetFieldsInfo(Type aType, List<_FieldInfo> aFields, bool includeStatic)
|
private static void DoGetFieldsInfo(Type aType, List<_FieldInfo> aFields, bool includeStatic) {
|
||||||
{
|
|
||||||
var xCurList = new Dictionary<string, _FieldInfo>();
|
var xCurList = new Dictionary<string, _FieldInfo>();
|
||||||
var xBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
var xBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
||||||
if (includeStatic)
|
if (includeStatic) {
|
||||||
{
|
|
||||||
xBindingFlags |= BindingFlags.Static;
|
xBindingFlags |= BindingFlags.Static;
|
||||||
}
|
}
|
||||||
var xFields = (from item in aType.GetFields(xBindingFlags)
|
var xFields = (from item in aType.GetFields(xBindingFlags)
|
||||||
orderby item.Name, item.DeclaringType.ToString()
|
orderby item.Name, item.DeclaringType.ToString()
|
||||||
select item).ToArray();
|
select item).ToArray();
|
||||||
for (int i = 0; i < xFields.Length; i++)
|
for (int i = 0; i < xFields.Length; i++) {
|
||||||
{
|
|
||||||
var xField = xFields[i];
|
var xField = xFields[i];
|
||||||
// todo: should be possible to have GetFields only return fields from a given type, thus removing need of next statement
|
// todo: should be possible to have GetFields only return fields from a given type, thus removing need of next statement
|
||||||
if (xField.DeclaringType != aType)
|
if (xField.DeclaringType != aType) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,8 +149,7 @@ namespace Cosmos.IL2CPU
|
||||||
|
|
||||||
var xFieldOffsetAttrib =
|
var xFieldOffsetAttrib =
|
||||||
xField.GetCustomAttributes<FieldOffsetAttribute>(true).FirstOrDefault();
|
xField.GetCustomAttributes<FieldOffsetAttribute>(true).FirstOrDefault();
|
||||||
if (xFieldOffsetAttrib != null)
|
if (xFieldOffsetAttrib != null) {
|
||||||
{
|
|
||||||
xInfo.Offset = (uint)xFieldOffsetAttrib.Value;
|
xInfo.Offset = (uint)xFieldOffsetAttrib.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,25 +159,19 @@ namespace Cosmos.IL2CPU
|
||||||
|
|
||||||
// now check plugs
|
// now check plugs
|
||||||
IDictionary<string, PlugFieldAttribute> xPlugFields;
|
IDictionary<string, PlugFieldAttribute> xPlugFields;
|
||||||
if (mPlugManager.PlugFields.TryGetValue(aType, out xPlugFields))
|
if (mPlugManager.PlugFields.TryGetValue(aType, out xPlugFields)) {
|
||||||
{
|
foreach (var xPlugField in xPlugFields) {
|
||||||
foreach (var xPlugField in xPlugFields)
|
|
||||||
{
|
|
||||||
_FieldInfo xPluggedField = null;
|
_FieldInfo xPluggedField = null;
|
||||||
if (xCurList.TryGetValue(xPlugField.Key, out xPluggedField))
|
if (xCurList.TryGetValue(xPlugField.Key, out xPluggedField)) {
|
||||||
{
|
|
||||||
// plugfield modifies an already existing field
|
// plugfield modifies an already existing field
|
||||||
|
|
||||||
// TODO: improve.
|
// TODO: improve.
|
||||||
if (xPlugField.Value.IsExternalValue)
|
if (xPlugField.Value.IsExternalValue) {
|
||||||
{
|
|
||||||
xPluggedField.IsExternalValue = true;
|
xPluggedField.IsExternalValue = true;
|
||||||
xPluggedField.FieldType = xPluggedField.FieldType.MakePointerType();
|
xPluggedField.FieldType = xPluggedField.FieldType.MakePointerType();
|
||||||
xPluggedField.Size = 4;
|
xPluggedField.Size = 4;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
xPluggedField = new _FieldInfo(xPlugField.Value.FieldId, SizeOfType(xPlugField.Value.FieldType), aType,
|
xPluggedField = new _FieldInfo(xPlugField.Value.FieldId, SizeOfType(xPlugField.Value.FieldType), aType,
|
||||||
xPlugField.Value.FieldType);
|
xPlugField.Value.FieldType);
|
||||||
aFields.Add(xPluggedField);
|
aFields.Add(xPluggedField);
|
||||||
|
|
@ -217,33 +180,26 @@ namespace Cosmos.IL2CPU
|
||||||
}
|
}
|
||||||
|
|
||||||
Type xBase = aType.GetTypeInfo().BaseType;
|
Type xBase = aType.GetTypeInfo().BaseType;
|
||||||
if (xBase != null)
|
if (xBase != null) {
|
||||||
{
|
|
||||||
DoGetFieldsInfo(xBase, aFields, includeStatic);
|
DoGetFieldsInfo(xBase, aFields, includeStatic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<_FieldInfo> GetFieldsInfo(Type aType, bool includeStatic)
|
public static List<_FieldInfo> GetFieldsInfo(Type aType, bool includeStatic) {
|
||||||
{
|
|
||||||
var xResult = new List<_FieldInfo>(16);
|
var xResult = new List<_FieldInfo>(16);
|
||||||
DoGetFieldsInfo(aType, xResult, includeStatic);
|
DoGetFieldsInfo(aType, xResult, includeStatic);
|
||||||
xResult.Reverse();
|
xResult.Reverse();
|
||||||
uint xOffset = 0;
|
uint xOffset = 0;
|
||||||
foreach (var xInfo in xResult)
|
foreach (var xInfo in xResult) {
|
||||||
{
|
if (!xInfo.IsOffsetSet && !xInfo.IsStatic) {
|
||||||
if (!xInfo.IsOffsetSet && !xInfo.IsStatic)
|
|
||||||
{
|
|
||||||
xInfo.Offset = xOffset;
|
xInfo.Offset = xOffset;
|
||||||
xOffset += xInfo.Size;
|
xOffset += xInfo.Size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var xDebugInfs = new List<FIELD_INFO>();
|
var xDebugInfs = new List<FIELD_INFO>();
|
||||||
foreach (var xInfo in xResult)
|
foreach (var xInfo in xResult) {
|
||||||
{
|
if (!xInfo.IsStatic) {
|
||||||
if (!xInfo.IsStatic)
|
xDebugInfs.Add(new FIELD_INFO() {
|
||||||
{
|
|
||||||
xDebugInfs.Add(new FIELD_INFO()
|
|
||||||
{
|
|
||||||
TYPE = xInfo.FieldType.AssemblyQualifiedName,
|
TYPE = xInfo.FieldType.AssemblyQualifiedName,
|
||||||
OFFSET = (int)xInfo.Offset,
|
OFFSET = (int)xInfo.Offset,
|
||||||
NAME = GetNameForField(xInfo),
|
NAME = GetNameForField(xInfo),
|
||||||
|
|
@ -257,24 +213,20 @@ namespace Cosmos.IL2CPU
|
||||||
return xResult;
|
return xResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GetFieldMapping(List<_FieldInfo> aFieldInfs, List<DebugInfo.Field_Map> aFieldMapping, Type aType)
|
private static void GetFieldMapping(List<_FieldInfo> aFieldInfs, List<DebugInfo.Field_Map> aFieldMapping, Type aType) {
|
||||||
{
|
|
||||||
var xFMap = new DebugInfo.Field_Map();
|
var xFMap = new DebugInfo.Field_Map();
|
||||||
xFMap.TypeName = aType.AssemblyQualifiedName;
|
xFMap.TypeName = aType.AssemblyQualifiedName;
|
||||||
foreach (var xInfo in aFieldInfs)
|
foreach (var xInfo in aFieldInfs) {
|
||||||
{
|
|
||||||
xFMap.FieldNames.Add(GetNameForField(xInfo));
|
xFMap.FieldNames.Add(GetNameForField(xInfo));
|
||||||
}
|
}
|
||||||
aFieldMapping.Add(xFMap);
|
aFieldMapping.Add(xFMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetNameForField(_FieldInfo inf)
|
private static string GetNameForField(_FieldInfo inf) {
|
||||||
{
|
|
||||||
// First we need to separate out the
|
// First we need to separate out the
|
||||||
// actual name of field from the type of the field.
|
// actual name of field from the type of the field.
|
||||||
int loc = inf.Id.IndexOf(' ');
|
int loc = inf.Id.IndexOf(' ');
|
||||||
if (loc >= 0)
|
if (loc >= 0) {
|
||||||
{
|
|
||||||
string fName = inf.Id.Substring(loc, inf.Id.Length - loc);
|
string fName = inf.Id.Substring(loc, inf.Id.Length - loc);
|
||||||
return inf.DeclaringType.AssemblyQualifiedName + fName;
|
return inf.DeclaringType.AssemblyQualifiedName + fName;
|
||||||
}
|
}
|
||||||
|
|
@ -282,8 +234,7 @@ namespace Cosmos.IL2CPU
|
||||||
return inf.Id;
|
return inf.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static uint GetStorageSize(Type aType)
|
protected static uint GetStorageSize(Type aType) {
|
||||||
{
|
|
||||||
return (from item in GetFieldsInfo(aType, false)
|
return (from item in GetFieldsInfo(aType, false)
|
||||||
where !item.IsStatic
|
where !item.IsStatic
|
||||||
orderby item.Offset descending
|
orderby item.Offset descending
|
||||||
|
|
@ -293,69 +244,55 @@ namespace Cosmos.IL2CPU
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Emits cleanup code for when an exception occurred inside a method call.
|
/// Emits cleanup code for when an exception occurred inside a method call.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void EmitExceptionCleanupAfterCall(Assembler.Assembler aAssembler, uint aReturnSize, uint aStackSizeBeforeCall, uint aTotalArgumentSizeOfMethod)
|
public static void EmitExceptionCleanupAfterCall(Assembler.Assembler aAssembler, uint aReturnSize, uint aStackSizeBeforeCall, uint aTotalArgumentSizeOfMethod) {
|
||||||
{
|
|
||||||
XS.Comment("aStackSizeBeforeCall = " + aStackSizeBeforeCall);
|
XS.Comment("aStackSizeBeforeCall = " + aStackSizeBeforeCall);
|
||||||
XS.Comment("aTotalArgumentSizeOfMethod = " + aTotalArgumentSizeOfMethod);
|
XS.Comment("aTotalArgumentSizeOfMethod = " + aTotalArgumentSizeOfMethod);
|
||||||
XS.Comment("aReturnSize = " + aReturnSize);
|
XS.Comment("aReturnSize = " + aReturnSize);
|
||||||
|
|
||||||
if (aReturnSize != 0)
|
if (aReturnSize != 0) {
|
||||||
{
|
|
||||||
// at least pop return size:
|
// at least pop return size:
|
||||||
XS.Comment("Cleanup return");
|
XS.Comment("Cleanup return");
|
||||||
|
|
||||||
// cleanup result values
|
// cleanup result values
|
||||||
for (int i = 0; i < aReturnSize / 4; i++)
|
for (int i = 0; i < aReturnSize / 4; i++) {
|
||||||
{
|
|
||||||
XS.Add(XSRegisters.ESP, 4);
|
XS.Add(XSRegisters.ESP, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aStackSizeBeforeCall > (aTotalArgumentSizeOfMethod))
|
if (aStackSizeBeforeCall > (aTotalArgumentSizeOfMethod)) {
|
||||||
{
|
if (aTotalArgumentSizeOfMethod > 0) {
|
||||||
if (aTotalArgumentSizeOfMethod > 0)
|
|
||||||
{
|
|
||||||
var xExtraStack = aStackSizeBeforeCall - aTotalArgumentSizeOfMethod;
|
var xExtraStack = aStackSizeBeforeCall - aTotalArgumentSizeOfMethod;
|
||||||
XS.Comment("Cleanup extra stack");
|
XS.Comment("Cleanup extra stack");
|
||||||
|
|
||||||
// cleanup result values
|
// cleanup result values
|
||||||
for (int i = 0; i < xExtraStack / 4; i++)
|
for (int i = 0; i < xExtraStack / 4; i++) {
|
||||||
{
|
|
||||||
XS.Add(XSRegisters.ESP, 4);
|
XS.Add(XSRegisters.ESP, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void EmitExceptionLogic(Assembler.Assembler aAssembler, _MethodInfo aMethodInfo, ILOpCode aCurrentOpCode, bool aDoTest, Action aCleanup, string aJumpTargetNoException = null)
|
public static void EmitExceptionLogic(Assembler.Assembler aAssembler, _MethodInfo aMethodInfo, ILOpCode aCurrentOpCode, bool aDoTest, Action aCleanup, string aJumpTargetNoException = null) {
|
||||||
{
|
if (aJumpTargetNoException == null) {
|
||||||
if (aJumpTargetNoException == null)
|
|
||||||
{
|
|
||||||
aJumpTargetNoException = GetLabel(aMethodInfo, aCurrentOpCode.NextPosition);
|
aJumpTargetNoException = GetLabel(aMethodInfo, aCurrentOpCode.NextPosition);
|
||||||
}
|
}
|
||||||
string xJumpTo = null;
|
string xJumpTo = null;
|
||||||
if (aCurrentOpCode != null && aCurrentOpCode.CurrentExceptionRegion != null)
|
if (aCurrentOpCode != null && aCurrentOpCode.CurrentExceptionRegion != null) {
|
||||||
{
|
|
||||||
// todo add support for nested handlers, see comment in Engine.cs
|
// todo add support for nested handlers, see comment in Engine.cs
|
||||||
//if (!((aMethodInfo.CurrentHandler.HandlerOffset < aCurrentOpOffset) || (aMethodInfo.CurrentHandler.HandlerLength + aMethodInfo.CurrentHandler.HandlerOffset) <= aCurrentOpOffset)) {
|
//if (!((aMethodInfo.CurrentHandler.HandlerOffset < aCurrentOpOffset) || (aMethodInfo.CurrentHandler.HandlerLength + aMethodInfo.CurrentHandler.HandlerOffset) <= aCurrentOpOffset)) {
|
||||||
XS.Comment(String.Format("CurrentOffset = {0}, HandlerStartOffset = {1}", aCurrentOpCode.Position,
|
XS.Comment(String.Format("CurrentOffset = {0}, HandlerStartOffset = {1}", aCurrentOpCode.Position,
|
||||||
aCurrentOpCode.CurrentExceptionRegion.HandlerOffset));
|
aCurrentOpCode.CurrentExceptionRegion.HandlerOffset));
|
||||||
if (aCurrentOpCode.CurrentExceptionRegion.HandlerOffset > aCurrentOpCode.Position)
|
if (aCurrentOpCode.CurrentExceptionRegion.HandlerOffset > aCurrentOpCode.Position) {
|
||||||
{
|
switch (aCurrentOpCode.CurrentExceptionRegion.Kind) {
|
||||||
switch (aCurrentOpCode.CurrentExceptionRegion.Kind)
|
case ExceptionRegionKind.Catch: {
|
||||||
{
|
|
||||||
case ExceptionRegionKind.Catch:
|
|
||||||
{
|
|
||||||
xJumpTo = GetLabel(aMethodInfo, aCurrentOpCode.CurrentExceptionRegion.HandlerOffset);
|
xJumpTo = GetLabel(aMethodInfo, aCurrentOpCode.CurrentExceptionRegion.HandlerOffset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ExceptionRegionKind.Finally:
|
case ExceptionRegionKind.Finally: {
|
||||||
{
|
|
||||||
xJumpTo = GetLabel(aMethodInfo, aCurrentOpCode.CurrentExceptionRegion.HandlerOffset);
|
xJumpTo = GetLabel(aMethodInfo, aCurrentOpCode.CurrentExceptionRegion.HandlerOffset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default: {
|
||||||
{
|
|
||||||
throw new Exception("ExceptionHandlerType '" + aCurrentOpCode.CurrentExceptionRegion.Kind.ToString() +
|
throw new Exception("ExceptionHandlerType '" + aCurrentOpCode.CurrentExceptionRegion.Kind.ToString() +
|
||||||
"' not supported yet!");
|
"' not supported yet!");
|
||||||
}
|
}
|
||||||
|
|
@ -363,44 +300,29 @@ namespace Cosmos.IL2CPU
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if aDoTest is true, we check ECX for exception flags
|
// if aDoTest is true, we check ECX for exception flags
|
||||||
if (!aDoTest)
|
if (!aDoTest) {
|
||||||
{
|
|
||||||
//new CPU.Call("_CODE_REQUESTED_BREAK_");
|
//new CPU.Call("_CODE_REQUESTED_BREAK_");
|
||||||
if (xJumpTo == null)
|
if (xJumpTo == null) {
|
||||||
{
|
|
||||||
Jump_Exception(aMethodInfo);
|
Jump_Exception(aMethodInfo);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
XS.Jump(xJumpTo);
|
XS.Jump(xJumpTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
XS.Test(XSRegisters.ECX, 2);
|
XS.Test(XSRegisters.ECX, 2);
|
||||||
|
|
||||||
if (aCleanup != null)
|
if (aCleanup != null) {
|
||||||
{
|
|
||||||
XS.Jump(CPU.ConditionalTestEnum.Equal, aJumpTargetNoException);
|
XS.Jump(CPU.ConditionalTestEnum.Equal, aJumpTargetNoException);
|
||||||
aCleanup();
|
aCleanup();
|
||||||
if (xJumpTo == null)
|
if (xJumpTo == null) {
|
||||||
{
|
|
||||||
XS.Jump(CPU.ConditionalTestEnum.NotEqual, GetLabel(aMethodInfo) + AppAssembler.EndOfMethodLabelNameException);
|
XS.Jump(CPU.ConditionalTestEnum.NotEqual, GetLabel(aMethodInfo) + AppAssembler.EndOfMethodLabelNameException);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
XS.Jump(CPU.ConditionalTestEnum.NotEqual, xJumpTo);
|
XS.Jump(CPU.ConditionalTestEnum.NotEqual, xJumpTo);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
if (xJumpTo == null) {
|
||||||
{
|
|
||||||
if (xJumpTo == null)
|
|
||||||
{
|
|
||||||
XS.Jump(CPU.ConditionalTestEnum.NotEqual, GetLabel(aMethodInfo) + AppAssembler.EndOfMethodLabelNameException);
|
XS.Jump(CPU.ConditionalTestEnum.NotEqual, GetLabel(aMethodInfo) + AppAssembler.EndOfMethodLabelNameException);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
XS.Jump(CPU.ConditionalTestEnum.NotEqual, xJumpTo);
|
XS.Jump(CPU.ConditionalTestEnum.NotEqual, xJumpTo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -408,16 +330,12 @@ namespace Cosmos.IL2CPU
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected static void DoNullReferenceCheck(Assembler.Assembler assembler, bool debugEnabled, int stackOffsetToCheck)
|
protected static void DoNullReferenceCheck(Assembler.Assembler assembler, bool debugEnabled, int stackOffsetToCheck) {
|
||||||
{
|
if (stackOffsetToCheck != SignedAlign(stackOffsetToCheck, 4)) {
|
||||||
if (stackOffsetToCheck != SignedAlign(stackOffsetToCheck, 4))
|
|
||||||
{
|
|
||||||
throw new Exception("Stack offset not aligned!");
|
throw new Exception("Stack offset not aligned!");
|
||||||
}
|
}
|
||||||
if (debugEnabled)
|
if (debugEnabled) {
|
||||||
{
|
//if (!CompilerEngine.UseGen3Kernel) {
|
||||||
if (!CompilerEngine.UseGen3Kernel)
|
|
||||||
{
|
|
||||||
XS.Compare(XSRegisters.ESP, 0, destinationDisplacement: (int)stackOffsetToCheck);
|
XS.Compare(XSRegisters.ESP, 0, destinationDisplacement: (int)stackOffsetToCheck);
|
||||||
XS.Jump(CPU.ConditionalTestEnum.NotEqual, ".AfterNullCheck");
|
XS.Jump(CPU.ConditionalTestEnum.NotEqual, ".AfterNullCheck");
|
||||||
XS.ClearInterruptFlag();
|
XS.ClearInterruptFlag();
|
||||||
|
|
@ -425,31 +343,27 @@ namespace Cosmos.IL2CPU
|
||||||
XS.Call(".NullCheck_GetCurrAddress");
|
XS.Call(".NullCheck_GetCurrAddress");
|
||||||
XS.Label(".NullCheck_GetCurrAddress");
|
XS.Label(".NullCheck_GetCurrAddress");
|
||||||
XS.Pop(XSRegisters.EAX);
|
XS.Pop(XSRegisters.EAX);
|
||||||
new CPU.Mov
|
new CPU.Mov {
|
||||||
{
|
|
||||||
DestinationRef = ElementReference.New("DebugStub_CallerEIP"),
|
DestinationRef = ElementReference.New("DebugStub_CallerEIP"),
|
||||||
DestinationIsIndirect = true,
|
DestinationIsIndirect = true,
|
||||||
SourceReg = CPU.RegistersEnum.EAX
|
SourceReg = CPU.RegistersEnum.EAX
|
||||||
};
|
};
|
||||||
XS.Call("DebugStub_SendNullReferenceOccurred");
|
XS.Call("DebugStub_SendNullReferenceOccurred");
|
||||||
}
|
//}
|
||||||
XS.Halt();
|
XS.Halt();
|
||||||
XS.Label(".AfterNullCheck");
|
XS.Label(".AfterNullCheck");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static _FieldInfo ResolveField(Type aDeclaringType, string aField, bool aOnlyInstance)
|
public static _FieldInfo ResolveField(Type aDeclaringType, string aField, bool aOnlyInstance) {
|
||||||
{
|
|
||||||
var xFields = GetFieldsInfo(aDeclaringType, !aOnlyInstance);
|
var xFields = GetFieldsInfo(aDeclaringType, !aOnlyInstance);
|
||||||
var xFieldInfo = (from item in xFields
|
var xFieldInfo = (from item in xFields
|
||||||
where item.Id == aField
|
where item.Id == aField
|
||||||
&& (!aOnlyInstance || item.IsStatic == false)
|
&& (!aOnlyInstance || item.IsStatic == false)
|
||||||
select item).SingleOrDefault();
|
select item).SingleOrDefault();
|
||||||
if (xFieldInfo == null)
|
if (xFieldInfo == null) {
|
||||||
{
|
|
||||||
Console.WriteLine("Following fields have been found on '{0}'", aDeclaringType.FullName);
|
Console.WriteLine("Following fields have been found on '{0}'", aDeclaringType.FullName);
|
||||||
foreach (var xField in xFields)
|
foreach (var xField in xFields) {
|
||||||
{
|
|
||||||
Console.WriteLine("\t'{0}'", xField.Id);
|
Console.WriteLine("\t'{0}'", xField.Id);
|
||||||
}
|
}
|
||||||
throw new Exception(string.Format("Field '{0}' not found on type '{1}'", aField, aDeclaringType.FullName));
|
throw new Exception(string.Format("Field '{0}' not found on type '{1}'", aField, aDeclaringType.FullName));
|
||||||
|
|
@ -457,15 +371,12 @@ namespace Cosmos.IL2CPU
|
||||||
return xFieldInfo;
|
return xFieldInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void CopyValue(XSRegisters.Register32 destination, int destinationDisplacement, XSRegisters.Register32 source, int sourceDisplacement, uint size)
|
protected static void CopyValue(XSRegisters.Register32 destination, int destinationDisplacement, XSRegisters.Register32 source, int sourceDisplacement, uint size) {
|
||||||
{
|
for (int i = 0; i < (size / 4); i++) {
|
||||||
for (int i = 0; i < (size / 4); i++)
|
|
||||||
{
|
|
||||||
XS.Set(XSRegisters.EAX, source, sourceDisplacement: sourceDisplacement + (i * 4));
|
XS.Set(XSRegisters.EAX, source, sourceDisplacement: sourceDisplacement + (i * 4));
|
||||||
XS.Set(destination, XSRegisters.EAX, destinationDisplacement: destinationDisplacement + (i * 4));
|
XS.Set(destination, XSRegisters.EAX, destinationDisplacement: destinationDisplacement + (i * 4));
|
||||||
}
|
}
|
||||||
switch (size % 4)
|
switch (size % 4) {
|
||||||
{
|
|
||||||
case 1:
|
case 1:
|
||||||
XS.Set(XSRegisters.AL, source, sourceDisplacement: (int)(sourceDisplacement + ((size / 4) * 4)));
|
XS.Set(XSRegisters.AL, source, sourceDisplacement: (int)(sourceDisplacement + ((size / 4) * 4)));
|
||||||
XS.Set(destination, XSRegisters.AL, destinationDisplacement: (int)(destinationDisplacement + ((size / 4) * 4)));
|
XS.Set(destination, XSRegisters.AL, destinationDisplacement: (int)(destinationDisplacement + ((size / 4) * 4)));
|
||||||
|
|
@ -482,64 +393,51 @@ namespace Cosmos.IL2CPU
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compat shim
|
// Compat shim
|
||||||
public static bool TypeIsReferenceType(Type aType)
|
public static bool TypeIsReferenceType(Type aType) {
|
||||||
{
|
|
||||||
return TypeIsReferenceType(aType.GetTypeInfo());
|
return TypeIsReferenceType(aType.GetTypeInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TypeIsReferenceType(TypeInfo aType)
|
private static bool TypeIsReferenceType(TypeInfo aType) {
|
||||||
{
|
|
||||||
return !aType.IsValueType && !aType.IsPointer && !aType.IsByRef;
|
return !aType.IsValueType && !aType.IsPointer && !aType.IsByRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsIntegerSigned(Type aType)
|
public static bool IsIntegerSigned(Type aType) {
|
||||||
{
|
|
||||||
return aType.FullName == "System.SByte" || aType.FullName == "System.Int16" || aType.FullName == "System.Int32" || aType.FullName == "System.Int64";
|
return aType.FullName == "System.SByte" || aType.FullName == "System.Int16" || aType.FullName == "System.Int32" || aType.FullName == "System.Int64";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsIntegralType(Type type)
|
public static bool IsIntegralType(Type type) {
|
||||||
{
|
|
||||||
return type == typeof(byte) || type == typeof(sbyte) || type == typeof(ushort) || type == typeof(short)
|
return type == typeof(byte) || type == typeof(sbyte) || type == typeof(ushort) || type == typeof(short)
|
||||||
|| type == typeof(int) || type == typeof(uint) || type == typeof(long) || type == typeof(ulong)
|
|| type == typeof(int) || type == typeof(uint) || type == typeof(long) || type == typeof(ulong)
|
||||||
|| type == typeof(char) || type == typeof(IntPtr) || type == typeof(UIntPtr);
|
|| type == typeof(char) || type == typeof(IntPtr) || type == typeof(UIntPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsIntegralTypeOrPointer(Type type)
|
public static bool IsIntegralTypeOrPointer(Type type) {
|
||||||
{
|
|
||||||
return IsIntegralType(type) || type.IsPointer || type.IsByRef;
|
return IsIntegralType(type) || type.IsPointer || type.IsByRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsPointer(Type aPointer)
|
public static bool IsPointer(Type aPointer) {
|
||||||
{
|
|
||||||
return aPointer.IsPointer || aPointer.IsByRef || aPointer == typeof(IntPtr) || aPointer == typeof(UIntPtr);
|
return aPointer.IsPointer || aPointer.IsByRef || aPointer == typeof(IntPtr) || aPointer == typeof(UIntPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compat shim.
|
// Compat shim.
|
||||||
public static uint SizeOfType(Type aType)
|
public static uint SizeOfType(Type aType) {
|
||||||
{
|
|
||||||
return SizeOfType(aType.GetTypeInfo());
|
return SizeOfType(aType.GetTypeInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static uint SizeOfType(TypeInfo aType)
|
private static uint SizeOfType(TypeInfo aType) {
|
||||||
{
|
if (aType == null) {
|
||||||
if (aType == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("aType");
|
throw new ArgumentNullException("aType");
|
||||||
}
|
}
|
||||||
if (aType.IsPointer || aType.IsByRef)
|
if (aType.IsPointer || aType.IsByRef) {
|
||||||
{
|
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
if (aType.FullName == "System.Void")
|
if (aType.FullName == "System.Void") {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (TypeIsReferenceType(aType))
|
if (TypeIsReferenceType(aType)) {
|
||||||
{
|
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
switch (aType.FullName)
|
switch (aType.FullName) {
|
||||||
{
|
|
||||||
case "System.Char":
|
case "System.Char":
|
||||||
return 2;
|
return 2;
|
||||||
case "System.Byte":
|
case "System.Byte":
|
||||||
|
|
@ -573,8 +471,7 @@ namespace Cosmos.IL2CPU
|
||||||
case "System.DateTime":
|
case "System.DateTime":
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
if (aType.FullName != null && aType.FullName.EndsWith("*"))
|
if (aType.FullName != null && aType.FullName.EndsWith("*")) {
|
||||||
{
|
|
||||||
// pointer
|
// pointer
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
@ -583,15 +480,12 @@ namespace Cosmos.IL2CPU
|
||||||
//if (xTypeSpec != null) {
|
//if (xTypeSpec != null) {
|
||||||
// return 4;
|
// return 4;
|
||||||
//}
|
//}
|
||||||
if (aType.IsEnum)
|
if (aType.IsEnum) {
|
||||||
{
|
|
||||||
return SizeOfType(aType.GetField("value__").FieldType);
|
return SizeOfType(aType.GetField("value__").FieldType);
|
||||||
}
|
}
|
||||||
if (aType.IsValueType)
|
if (aType.IsValueType) {
|
||||||
{
|
|
||||||
var xSla = aType.StructLayoutAttribute;
|
var xSla = aType.StructLayoutAttribute;
|
||||||
if ((xSla != null) && (xSla.Size > 0))
|
if ((xSla != null) && (xSla.Size > 0)) {
|
||||||
{
|
|
||||||
return (uint)xSla.Size;
|
return (uint)xSla.Size;
|
||||||
}
|
}
|
||||||
return (uint)(from item in GetFieldsInfo(aType.AsType(), false)
|
return (uint)(from item in GetFieldsInfo(aType.AsType(), false)
|
||||||
|
|
@ -600,8 +494,7 @@ namespace Cosmos.IL2CPU
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static bool TypeIsFloat(Type type)
|
protected static bool TypeIsFloat(Type type) {
|
||||||
{
|
|
||||||
return type == typeof(float) || type == typeof(double);
|
return type == typeof(float) || type == typeof(double);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue