Some more ops are working now. Still working on the VTables support. Next Op to implement is Switch

This commit is contained in:
mterwoord_cp 2007-09-26 09:12:43 +00:00
parent 0f7c09b534
commit 1ea78b247f
21 changed files with 243 additions and 58 deletions

View file

@ -64,6 +64,7 @@
<Compile Include="JumpIfZero.cs" />
<Compile Include="Move.cs" />
<Compile Include="Multiply.cs" />
<Compile Include="Neg.cs" />
<Compile Include="Noop.cs" />
<Compile Include="Pop.cs" />
<Compile Include="Popd.cs" />

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Indy.IL2CPU.Assembler.X86 {
[OpCode(0xFFFFFFFF, "neg")]
public class Neg: Instruction {
private string mDestination;
public Neg(string aDestination) {
mDestination = aDestination;
}
public override string ToString() {
return "neg " + mDestination;
}
}
}

View file

@ -19,17 +19,21 @@ namespace Indy.IL2CPU.IL.X86 {
throw new Exception("Couldn't determine Type!");
}
mTheSize = Engine.GetFieldStorageSize(xTypeRef);
if (mTheSize != 4) {
throw new Exception("Storage size not supported yet!");
if(((mTheSize/4)*4) != mTheSize) {
throw new Exception("Incorrect Datasize. ( ((mTheSize / 4) * 4) === mTheSize should evaluate to true!");
}
Engine.RegisterType(Engine.GetDefinitionFromTypeReference(xTypeRef));
}
public override void DoAssemble() {
Pushd("0" + mTheSize.ToString("X").ToUpper() + "h");
Pushd("0" + (mTheSize + ObjectImpl.FieldDataOffset).ToString("X").ToUpper() + "h");
Call(new Label(RuntimeEngineRefs.Heap_AllocNewObjectRef).Name);
Pushd("eax");
Move(Assembler, "dword [eax + 4]", "0" + InstanceTypeEnum.NormalObject.ToString("X") + "h");
for (int i = 0; i < (mTheSize / 4); i++ ) {
Pop("edx");
Move(Assembler, "dword [eax + 0" + (ObjectImpl.FieldDataOffset + (i * 4)).ToString("X") + "h]", "edx");
}
Pushd("eax");
}
}
}

View file

@ -2,16 +2,42 @@ using System;
using System.IO;
using Mono.Cecil;
using Mono.Cecil.Cil;
using CPU = Indy.IL2CPU.Assembler.X86;
using CPU = Indy.IL2CPU.Assembler;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Castclass, false)]
public class Castclass: Op {
private int mTypeId;
private string mThisLabel;
private string mNextOpLabel;
public Castclass(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
TypeReference xType = aInstruction.Operand as TypeReference;
if(xType==null) {
throw new Exception("Unable to determine Type!");
}
TypeDefinition xTypeDef = Engine.GetDefinitionFromTypeReference(xType);
mTypeId = Engine.RegisterType(xTypeDef);
mThisLabel = GetInstructionLabel(aInstruction);
mNextOpLabel = GetInstructionLabel(aInstruction.Next);
}
public override void DoAssemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
// todo: throw an exception when the class does not support the cast!
string mReturnNullLabel = mThisLabel + "_ReturnNull";
Pop("eax");
Compare("eax", "0");
JumpIfZero(mReturnNullLabel);
Pushd("[eax]", "0" + mTypeId + "h");
MethodDefinition xMethodIsInstance = Engine.GetMethodDefinition(Engine.GetTypeDefinition("", "Indy.IL2CPU.VTablesImpl"), "IsInstance", "System.Int32", "System.Int32");
Engine.QueueMethod(xMethodIsInstance);
Call(new CPU.Label(xMethodIsInstance).Name);
Compare("eax", "0");
JumpIfEquals(mReturnNullLabel);
Pushd("eax");
JumpAlways(mNextOpLabel);
Label(mReturnNullLabel);
Pushd("0");
}
}
}

View file

@ -11,7 +11,7 @@ namespace Indy.IL2CPU.IL.X86 {
: base(aInstruction, aMethodInfo) {
}
public override void DoAssemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
// todo: implement correct truncating
}
}
}

View file

@ -11,7 +11,7 @@ namespace Indy.IL2CPU.IL.X86 {
: base(aInstruction, aMethodInfo) {
}
public override void DoAssemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
// todo: implement correct truncating
}
}
}

View file

@ -11,7 +11,7 @@ namespace Indy.IL2CPU.IL.X86 {
: base(aInstruction, aMethodInfo) {
}
public override void DoAssemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
// todo: implement correct conversion
}
}
}

View file

@ -11,7 +11,7 @@ namespace Indy.IL2CPU.IL.X86 {
: base(aInstruction, aMethodInfo) {
}
public override void DoAssemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
// todo: implement correct conversion
}
}
}

View file

@ -11,7 +11,7 @@ namespace Indy.IL2CPU.IL.X86 {
: base(aInstruction, aMethodInfo) {
}
public override void DoAssemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
// todo: implement correct truncating
}
}
}

View file

@ -11,7 +11,7 @@ namespace Indy.IL2CPU.IL.X86 {
: base(aInstruction, aMethodInfo) {
}
public override void DoAssemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
// todo: implement correct truncating
}
}
}

View file

@ -2,16 +2,41 @@ using System;
using System.IO;
using Mono.Cecil;
using Mono.Cecil.Cil;
using CPU = Indy.IL2CPU.Assembler.X86;
using CPU = Indy.IL2CPU.Assembler;
using CPUx86 = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Isinst)]
public class Isinst: Op {
private int mTypeId;
private string mThisLabel;
private string mNextOpLabel;
public Isinst(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
TypeReference xType = aInstruction.Operand as TypeReference;
if(xType==null) {
throw new Exception("Unable to determine Type!");
}
TypeDefinition xTypeDef = Engine.GetDefinitionFromTypeReference(xType);
mTypeId = Engine.RegisterType(xTypeDef);
mThisLabel = GetInstructionLabel(aInstruction);
mNextOpLabel = GetInstructionLabel(aInstruction.Next);
}
public override void DoAssemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
string mReturnNullLabel = mThisLabel + "_ReturnNull";
Pop("eax");
Compare("eax", "0");
JumpIfZero(mReturnNullLabel);
Pushd("[eax]", "0" + mTypeId + "h");
MethodDefinition xMethodIsInstance = Engine.GetMethodDefinition(Engine.GetTypeDefinition("", "Indy.IL2CPU.VTablesImpl"), "IsInstance", "System.Int32", "System.Int32");
Engine.QueueMethod(xMethodIsInstance);
Call(new CPU.Label(xMethodIsInstance).Name);
Compare("eax", "0");
JumpIfEquals(mReturnNullLabel);
Pushd("eax");
JumpAlways(mNextOpLabel);
Label(mReturnNullLabel);
Pushd("0");
}
}
}

View file

@ -15,8 +15,8 @@ namespace Indy.IL2CPU.IL.X86 {
}
string xFieldId = xField.ToString();
TypeInformation.Field xTheField;
uint xStorageSize;
xTheField = Engine.GetTypeFieldInfo(Engine.GetDefinitionFromTypeReference(xField.DeclaringType), out xStorageSize)[xFieldId];
uint xStorageSize;
xTheField = Engine.GetTypeFieldInfo(Engine.GetDefinitionFromTypeReference(xField.DeclaringType), out xStorageSize)[xFieldId];
RelativeAddress = xTheField.RelativeAddress;
FieldSize = xTheField.Size;
if (FieldSize != 4) {

View file

@ -12,14 +12,20 @@ namespace Indy.IL2CPU.IL.X86 {
public Ldtoken(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
FieldDefinition xFieldDef = aInstruction.Operand as FieldDefinition;
if (xFieldDef == null) {
throw new Exception("Unsupported Token type!");
if (xFieldDef != null) {
if (!xFieldDef.IsStatic) {
throw new Exception("Nonstatic field-backed tokens not supported yet!");
}
Engine.QueueStaticField(xFieldDef);
mTokenAddress = DataMember.GetStaticFieldName(xFieldDef);
return;
}
if (!xFieldDef.IsStatic) {
throw new Exception("Nonstatic field-backed tokens not supported yet!");
TypeReference xTypeRef = aInstruction.Operand as TypeReference;
if(xTypeRef!=null) {
mTokenAddress = "0" + Engine.RegisterType(Engine.GetDefinitionFromTypeReference(xTypeRef)).ToString("X") + "h";
return;
}
Engine.QueueStaticField(xFieldDef);
mTokenAddress=DataMember.GetStaticFieldName(xFieldDef);
throw new Exception("Token type not supported yet!");
}
public override void DoAssemble() {

View file

@ -11,7 +11,9 @@ namespace Indy.IL2CPU.IL.X86 {
: base(aInstruction, aMethodInfo) {
}
public override void DoAssemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
Pop("eax");
Assembler.Add(new CPU.Neg("eax"));
Pushd("eax");
}
}
}

View file

@ -2,16 +2,41 @@ using System;
using System.IO;
using Mono.Cecil;
using Mono.Cecil.Cil;
using CPU = Indy.IL2CPU.Assembler.X86;
using CPU = Indy.IL2CPU.Assembler;
using CPUx86 = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Unbox)]
public class Unbox: Op {
private int mTypeId;
private string mThisLabel;
private string mNextOpLabel;
public Unbox(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
TypeReference xType = aInstruction.Operand as TypeReference;
if(xType==null) {
throw new Exception("Unable to determine Type!");
}
TypeDefinition xTypeDef = Engine.GetDefinitionFromTypeReference(xType);
mTypeId = Engine.RegisterType(xTypeDef);
mThisLabel = GetInstructionLabel(aInstruction);
mNextOpLabel = GetInstructionLabel(aInstruction.Next);
}
public override void DoAssemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
string mReturnNullLabel = mThisLabel + "_ReturnNull";
Pop("eax");
Compare("eax", "0");
JumpIfZero(mReturnNullLabel);
Pushd("[eax]", "0" + mTypeId + "h");
MethodDefinition xMethodIsInstance = Engine.GetMethodDefinition(Engine.GetTypeDefinition("", "Indy.IL2CPU.VTablesImpl"), "IsInstance", "System.Int32", "System.Int32");
Engine.QueueMethod(xMethodIsInstance);
Call(new CPU.Label(xMethodIsInstance).Name);
Compare("eax", "0");
JumpIfEquals(mReturnNullLabel);
Pushd("eax");
JumpAlways(mNextOpLabel);
Label(mReturnNullLabel);
Pushd("0");
}
}
}

View file

@ -6,12 +6,9 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Unbox_Any)]
public class Unbox_Any: Op {
public class Unbox_Any: Unbox {
public Unbox_Any(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
}
public override void DoAssemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
}
}
}

View file

@ -45,9 +45,6 @@ namespace Indy.IL2CPU.IL {
}
CallProxiedMethod();
DoQueueMethod(ProxiedMethod);
if (MethodInfo.HasReturnValue) {
Ldloc(0);
}
}
}
}

View file

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Indy.IL2CPU.CustomImplementation.System {
public static class EnvironmentImpl {
[MethodAlias(Name = "System.Environment.GetResourceFromDefault(System.String)")]
public static string GetResourceFromDefault(string aResource) {
return aResource;
}
}
}

View file

@ -117,6 +117,7 @@ namespace Indy.IL2CPU {
IL.Op.QueueMethod += QueueMethod;
IL.Op.QueueStaticField += QueueStaticField;
try {
mTypes.Add(GetTypeDefinition("mscorlib", "System.Object"));
mMethods.Add(RuntimeEngineRefs.InitializeApplicationRef, false);
mMethods.Add(RuntimeEngineRefs.FinalizeApplicationRef, false);
mMethods.Add(mCrawledAssembly.EntryPoint, false);
@ -131,7 +132,14 @@ namespace Indy.IL2CPU {
}
mAssembler.Add(new Assembler.X86.Call(new Label(RuntimeEngineRefs.FinalizeApplicationRef).Name));
ProcessAllMethods();
ScanForMethodToIncludeForVMT();
do {
int xOldCount = mMethods.Count;
ScanForMethodToIncludeForVMT();
ProcessAllMethods();
if (xOldCount == mMethods.Count) {
break;
}
} while (true);
ProcessAllStaticFields();
} finally {
mAssembler.Flush();
@ -145,15 +153,26 @@ namespace Indy.IL2CPU {
}
private void ScanForMethodToIncludeForVMT() {
for (int i = mMethods.Count - 1; i >= 0; i--) {
MethodDefinition xCurrentInspectedMethod = mMethods.Keys[i];
TypeDefinition xCurrentType = GetDefinitionFromTypeReference(xCurrentInspectedMethod.DeclaringType);
List<TypeDefinition> xCheckedTypes = new List<TypeDefinition>();
foreach (MethodDefinition xMethod in mMethods.Keys) {
if (xMethod.IsStatic) {
continue;
}
TypeDefinition xCurrentType = GetDefinitionFromTypeReference(xMethod.DeclaringType);
if (!xCheckedTypes.Contains(xCurrentType, mTypesEqualityComparer)) {
xCheckedTypes.Add(xCurrentType);
}
}
foreach (TypeDefinition xType in mTypes) {
if (!xCheckedTypes.Contains(xType, mTypesEqualityComparer)) {
xCheckedTypes.Add(xType);
}
}
for (int i = 0; i < xCheckedTypes.Count; i++) {
TypeDefinition xCurrentType = xCheckedTypes[i];
while (xCurrentType != null) {
foreach (MethodDefinition xCurrentMethod in xCurrentType.Methods) {
if (xCurrentMethod.IsAbstract || xCurrentMethod.Overrides.Count > 0) {
QueueMethod(xCurrentMethod);
continue;
}
if (!xCheckedTypes.Contains(xCurrentType, mTypesEqualityComparer)) {
xCheckedTypes.Add(xCurrentType);
}
if (xCurrentType.FullName == "System.Object") {
break;
@ -161,6 +180,15 @@ namespace Indy.IL2CPU {
xCurrentType = GetDefinitionFromTypeReference(xCurrentType.BaseType);
}
}
foreach (TypeDefinition xTD in xCheckedTypes) {
foreach (MethodDefinition xMethod in xTD.Methods) {
if (!xMethod.IsStatic) {
if (xMethod.IsVirtual || xMethod.Overrides.Count > 0) {
QueueMethod(xMethod);
}
}
}
}
}
public static MethodDefinition GetDefinitionFromMethodReference(MethodReference aRef) {
@ -177,15 +205,19 @@ namespace Indy.IL2CPU {
}
public static TypeDefinition GetDefinitionFromTypeReference(TypeReference aRef) {
if (aRef == null) {
throw new ArgumentNullException("aRef");
}
if (mCurrent == null) {
throw new Exception("No Current engine found!");
}
TypeDefinition xTempResult = aRef as TypeDefinition;
if (xTempResult != null) {
return xTempResult;
}
if (aRef.FullName.Contains("modreq")) {
aRef = aRef.GetOriginalType();
}
if (aRef.FullName.EndsWith("[]")) {
return GetTypeDefinition(aRef.Module.Assembly.Name.Name, aRef.FullName.Substring(0, aRef.FullName.Length - 2));
}
AssemblyNameReference xAssemblyNameReference = aRef.Scope as AssemblyNameReference;
if (xAssemblyNameReference != null) {
AssemblyDefinition xReferencedFieldAssembly;
@ -200,6 +232,12 @@ namespace Indy.IL2CPU {
if (xReferencedType != null) {
return xReferencedType;
}
if (aRef.FullName.EndsWith("[]")) {
xReferencedType = xModule.Types[aRef.FullName.Substring(0, aRef.FullName.Length - 2)];
if (xReferencedType != null) {
return xReferencedType;
}
}
}
}
} else {
@ -209,6 +247,12 @@ namespace Indy.IL2CPU {
if (xReferencedType != null) {
return xReferencedType;
}
if (aRef.FullName.EndsWith("[]")) {
xReferencedType = xReferencedModule.Types[aRef.FullName.Substring(0, aRef.FullName.Length - 2)];
if (xReferencedType != null) {
return xReferencedType;
}
}
} else {
mCurrent.OnDebugLog("Error: Unhandled scope: " + aRef.Scope == null ? "**NULL**" : aRef.Scope.GetType().FullName);
}
@ -228,13 +272,13 @@ namespace Indy.IL2CPU {
}
switch (aType.FullName) {
case "System.Char":
return 2;
return 4;
case "System.Byte":
case "System.SByte":
return 1;
return 4;
case "System.UInt16":
case "System.Int16":
return 2;
return 4;
case "System.UInt32":
case "System.Int32":
return 4;
@ -245,8 +289,20 @@ namespace Indy.IL2CPU {
case "System.UIntPtr":
case "System.IntPtr":
return 4;
case "System.Boolean":
return 4;
case "System.Single":
return 4;
case "System.Double":
return 8;
case "System.Decimal":
return 16;
case "System.Guid":
return 16;
case "System.DateTime":
return 8; // todo: check for correct size
}
throw new Exception("Unable to determine ValueType size!");
throw new Exception("Unable to determine ValueType size! (Type = " + aType.FullName + ")");
}
private void ProcessAllStaticFields() {
@ -458,8 +514,6 @@ namespace Indy.IL2CPU {
}
public static SortedList<string, TypeInformation.Field> GetTypeFieldInfo(MethodDefinition aCurrentMethod, out uint aObjectStorageSize) {
SortedList<string, TypeInformation.Field> xTypeFields = new SortedList<string, TypeInformation.Field>();
aObjectStorageSize = ObjectImpl.FieldDataOffset;
TypeDefinition xCurrentInspectedType = GetDefinitionFromTypeReference(aCurrentMethod.DeclaringType);
return GetTypeFieldInfo(xCurrentInspectedType, out aObjectStorageSize);
}
@ -483,7 +537,7 @@ namespace Indy.IL2CPU {
xTypeFields.Add(xField.ToString(), new TypeInformation.Field(aObjectStorageSize, xFieldSize));
aObjectStorageSize += xFieldSize;
}
if (aType.FullName != "System.Object") {
if (aType.FullName != "System.Object" && aType.BaseType != null) {
aType = GetDefinitionFromTypeReference(aType.BaseType);
} else {
break;
@ -596,13 +650,16 @@ namespace Indy.IL2CPU {
/// <param name="aType"></param>
/// <returns></returns>
public static int RegisterType(TypeDefinition aType) {
if (aType == null) {
throw new ArgumentNullException("aType");
}
if (mCurrent == null) {
throw new Exception("ERROR: No Current Engine found!");
}
TypeDefinition xFoundItem = mCurrent.mTypes.FirstOrDefault(x => x.FullName.Equals(aType.FullName));
if (xFoundItem == null) {
mCurrent.mTypes.Add(aType);
if (aType.FullName != "System.Object") {
if (aType.FullName != "System.Object" && aType.BaseType != null) {
TypeDefinition xCurInspectedType = GetDefinitionFromTypeReference(aType.BaseType);
RegisterType(xCurInspectedType);
}

View file

@ -77,6 +77,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="CustomImplementation\System\ArrayImpl.cs" />
<Compile Include="CustomImplementation\System\EnvironmentImpl.cs" />
<Compile Include="CustomImplementation\System\StringImpl.cs" />
<Compile Include="VTablesImpl.cs" />
</ItemGroup>

View file

@ -5,12 +5,26 @@ using System.Text;
namespace Indy.IL2CPU {
public static class VTablesImpl {
// method VTable, indexed by the type
/// <summary>
/// This array contains a list of types in the first dimension and a list
/// of method indexes in the second dimension.
/// </summary>
private static IntPtr[][] mMethods;
public struct VTable {
public int TypeIdentifier;
public int BaseTypeIdentifier;
public int[] MethodIndexes;
public int[] MethodAddresses;
}
private static VTable[] mTypes;
public static bool IsInstance(int aObjectType, int aDesiredObjectType) {
int xCurrentType = aObjectType;
if (aObjectType == 0) {
return true;
}
do {
if (xCurrentType == aDesiredObjectType) {
return true;
}
xCurrentType = mTypes[xCurrentType].BaseTypeIdentifier;
} while (xCurrentType != 0);
return false;
}
}
}