VTable is getting emitted now. There are some issues with the generated code. ie, doesn't work at all....

This commit is contained in:
mterwoord_cp 2007-09-27 17:46:17 +00:00
parent 3df87b10ec
commit edd9ada479
5 changed files with 165 additions and 11 deletions

View file

@ -1,14 +1,46 @@
using System;
using System.IO;
using System.Linq;
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.Callvirt, false)]
public class Callvirt: Call {
public Callvirt(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
public class Callvirt: Op {
private int mMethodIdentifier;
private string mThisAddress;
private bool mHasReturn;
private string mNormalAddress;
public Callvirt(Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
MethodReference xMethod = aInstruction.Operand as MethodReference;
if (xMethod == null) {
throw new Exception("Unable to determine Method!");
}
if (!aMethodInfo.IsInstanceMethod) {
mNormalAddress = new CPU.Label(xMethod).Name;
mHasReturn = !xMethod.ReturnType.ReturnType.FullName.StartsWith("System.Void");
return;
}
mMethodIdentifier = Engine.GetMethodIdentifier(Engine.GetDefinitionFromMethodReference(xMethod));
mThisAddress = aMethodInfo.Arguments[0].VirtualAddress;
mHasReturn = !xMethod.ReturnType.ReturnType.FullName.StartsWith("System.Void");
}
public override void DoAssemble() {
if (!String.IsNullOrEmpty(mNormalAddress)) {
Call(mNormalAddress);
} else {
Ldarg(Assembler, mThisAddress);
Pop("eax");
Pushd("[eax]");
Call(new CPU.Label(VTablesImplRefs.GetMethodAddressForTypeRef).Name);
Call("eax");
}
if (mHasReturn) {
Pushd("eax");
}
}
}
}

View file

@ -127,6 +127,7 @@ namespace Indy.IL2CPU {
mMethods.Add(mCrawledAssembly.EntryPoint, false);
// initialize the runtime engine
mAssembler.Add(
new Assembler.X86.Call("____INIT__VMT____"),
new Assembler.X86.Call(new Label(RuntimeEngineRefs.InitializeApplicationRef).Name),
new Assembler.X86.Call(new Label(mCrawledAssembly.EntryPoint).Name));
if (mCrawledAssembly.EntryPoint.ReturnType.ReturnType.FullName.StartsWith("System.Void", StringComparison.InvariantCultureIgnoreCase)) {
@ -144,11 +145,8 @@ namespace Indy.IL2CPU {
break;
}
} while (true);
GenerateVMT();
ProcessAllStaticFields();
Console.WriteLine("All Registered Types:");
foreach (TypeDefinition xTypeDef in mTypes) {
Console.WriteLine("\t{0}", xTypeDef.FullName);
}
} finally {
mAssembler.Flush();
IL.Op.QueueMethod -= QueueMethod;
@ -160,6 +158,61 @@ namespace Indy.IL2CPU {
}
}
private void GenerateVMT() {
// todo: abstract this code generation out to IL.* implementation
mAssembler.Add(new Label("____INIT__VMT____"));
mAssembler.Add(new Pushd("0" + mTypes.Count.ToString("X") + "h"));
mAssembler.Add(new Call(new Label(VTablesImplRefs.LoadTypeTableRef).Name));
for (int i = 0; i < mTypes.Count; i++) {
TypeDefinition xType = mTypes[i];
List<MethodDefinition> xEmittedMethods = new List<MethodDefinition>();
foreach (MethodDefinition xMethod in xType.Methods) {
if (mMethods.ContainsKey(xMethod)) {
xEmittedMethods.Add(xMethod);
}
}
foreach (MethodDefinition xCtor in xType.Constructors) {
if (mMethods.ContainsKey(xCtor)) {
xEmittedMethods.Add(xCtor);
}
}
mAssembler.Add(new Pushd("0" + i.ToString("X") + "h"));
int? xBaseIndex = null;
if (xType.BaseType == null) {
for (int t = 0; t < mTypes.Count; t++) {
if (mTypes[t].BaseType == null && mTypes[t].FullName == xType.FullName) {
xBaseIndex = t;
break;
}
}
} else {
for (int t = 0; t < mTypes.Count; t++) {
if (mTypes[t].BaseType == null) {
continue;
}
if (mTypes[t].BaseType.FullName == xType.BaseType.FullName && mTypes[t].FullName == xType.FullName) {
xBaseIndex = t;
break;
}
}
}
if (xBaseIndex == null) {
throw new Exception("Base type not found!");
}
mAssembler.Add(new Pushd("0" + xBaseIndex.Value.ToString("X") + "h"));
mAssembler.Add(new Pushd("0" + xEmittedMethods.Count.ToString("X") + "h"));
mAssembler.Add(new Call(new Label(VTablesImplRefs.SetTypeInfoRef).Name));
for (int j = 0; j < xEmittedMethods.Count; j++) {
MethodDefinition xMethod = xEmittedMethods[j];
mAssembler.Add(new Pushd("0" + i.ToString("X") + "h"));
mAssembler.Add(new Pushd("0" + j.ToString("X") + "h"));
mAssembler.Add(new Pushd("0" + mMethods.IndexOfKey(mMethods.Keys.First(x => x.GetFullName() == xMethod.GetFullName())).ToString("X") + "h"));
mAssembler.Add(new Pushd(new Label(xMethod).Name));
mAssembler.Add(new Call(new Label(VTablesImplRefs.SetMethodInfoRef).Name));
}
}
}
private void ScanForMethodToIncludeForVMT() {
List<TypeDefinition> xCheckedTypes = new List<TypeDefinition>();
foreach (MethodDefinition xMethod in mMethods.Keys) {
@ -532,11 +585,11 @@ namespace Indy.IL2CPU {
where !mMethods[item]
select item).FirstOrDefault()) != null) {
OnDebugLog(LogSeverityEnum.Informational, "Processing method '{0}'", xCurrentMethod.GetFullName());
if(xCurrentMethod.IsAbstract) {
if (xCurrentMethod.IsAbstract) {
mMethods[xCurrentMethod] = true;
continue;
}
string xMethodName = new Label(xCurrentMethod).Name;
string xMethodName = new Label(xCurrentMethod).Name;
foreach (CustomAttribute xAttrib in xCurrentMethod.CustomAttributes) {
if (xAttrib.Constructor.DeclaringType.FullName == typeof(MethodAliasAttribute).FullName) {
//xMethodName = (string)xAttrib.Fields["Name"];
@ -815,6 +868,11 @@ namespace Indy.IL2CPU {
}
}
public static int GetMethodIdentifier(MethodDefinition aMethod) {
QueueMethod(aMethod);
return mCurrent.mMethods.IndexOfKey(aMethod);
}
public static int RegisterTypeRef(TypeReference aTypeRef) {
if (aTypeRef == null) {
throw new ArgumentNullException("aTypeRef");

View file

@ -82,6 +82,7 @@
<Compile Include="CustomImplementation\System\StringImpl.cs" />
<Compile Include="CustomImplementation\System\RuntimeType.cs" />
<Compile Include="VTablesImpl.cs" />
<Compile Include="VTablesImplRefs.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View file

@ -6,7 +6,6 @@ using System.Text;
namespace Indy.IL2CPU {
public static class VTablesImpl {
public struct VTable {
public int TypeIdentifier;
public int BaseTypeIdentifier;
public int[] MethodIndexes;
public int[] MethodAddresses;
@ -26,5 +25,30 @@ namespace Indy.IL2CPU {
} while (xCurrentType != 0);
return false;
}
public static void LoadTypeTable(int aTypeCount) {
mTypes = new VTable[aTypeCount];
}
public static void SetTypeInfo(int aType, int aBaseType, int aMethodCount) {
mTypes[aType].BaseTypeIdentifier = aBaseType;
mTypes[aType].MethodIndexes = new int[aMethodCount];
mTypes[aType].MethodAddresses = new int[aMethodCount];
}
public static void SetMethodInfo(int aType, int aMethodIndex, int aMethodIdentifier, int aMethodAddress) {
mTypes[aType].MethodIndexes[aMethodIndex] = aMethodIdentifier;
mTypes[aType].MethodAddresses[aMethodIndex] = aMethodAddress;
}
public static int GetMethodAddressForType(int aType, int aMethodIndex) {
VTable xTable = mTypes[aType];
for(int i = 0; i <xTable.MethodIndexes.Length; i++) {
if(xTable.MethodIndexes[i] == aMethodIndex) {
return xTable.MethodAddresses[i];
}
}
return 0;
}
}
}

View file

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Mono.Cecil;
namespace Indy.IL2CPU {
public static class VTablesImplRefs {
public static readonly AssemblyDefinition RuntimeAssemblyDef;
public static readonly MethodDefinition LoadTypeTableRef;
public static readonly MethodDefinition SetTypeInfoRef;
public static readonly MethodDefinition SetMethodInfoRef;
public static readonly MethodDefinition GetMethodAddressForTypeRef;
static VTablesImplRefs() {
RuntimeAssemblyDef = AssemblyFactory.GetAssembly(typeof(VTablesImpl).Assembly.Location);
TypeDefinition xType = null;
foreach (ModuleDefinition xMod in RuntimeAssemblyDef.Modules) {
if (xMod.Types.Contains(typeof(VTablesImpl).FullName)) {
xType = xMod.Types[typeof(VTablesImpl).FullName];
break;
}
}
if (xType == null) {
throw new Exception("RuntimeEngine type not found!");
}
foreach (FieldInfo xField in typeof(VTablesImplRefs).GetFields()) {
if (xField.Name.EndsWith("Ref")) {
MethodDefinition xTempMethod = xType.Methods.GetMethod(xField.Name.Substring(0, xField.Name.Length - "Ref".Length)).FirstOrDefault();
if (xTempMethod == null) {
throw new Exception("Method '" + xField.Name.Substring(0, xField.Name.Length - "Ref".Length) + "' not found on RuntimeEngine!");
}
xField.SetValue(null, xTempMethod);
}
}
}
}
}