mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 20:39:01 +00:00
VTable is getting emitted now. There are some issues with the generated code. ie, doesn't work at all....
This commit is contained in:
parent
3df87b10ec
commit
edd9ada479
5 changed files with 165 additions and 11 deletions
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
39
source/Indy.IL2CPU/VTablesImplRefs.cs
Normal file
39
source/Indy.IL2CPU/VTablesImplRefs.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue