mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-24 12:35:31 +00:00
Multicast delegates
This commit is contained in:
parent
2b2ca11fd4
commit
cf7d99acb7
15 changed files with 247 additions and 99 deletions
|
|
@ -5,9 +5,9 @@ using System.Text;
|
||||||
|
|
||||||
namespace Indy.IL2CPU.Assembler.X86 {
|
namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
[OpCode(0xFFFFFFFF, "rep movsb")]
|
[OpCode(0xFFFFFFFF, "rep movsb")]
|
||||||
public class RepeatMovsd: Instruction {
|
public class RepeatMovsb: Instruction {
|
||||||
//public readonly string Destination;
|
//public readonly string Destination;
|
||||||
public RepeatMovsd() {
|
public RepeatMovsb() {
|
||||||
// Destination = aDestination;
|
// Destination = aDestination;
|
||||||
}
|
}
|
||||||
//public override string ToString() {
|
//public override string ToString() {
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ namespace Indy.IL2CPU.IL.X86.CustomImplementations.System.Assemblers {
|
||||||
new CPUx86.Move("edx", "[ebp + 0xC]");
|
new CPUx86.Move("edx", "[ebp + 0xC]");
|
||||||
new CPUx86.Multiply("edx");
|
new CPUx86.Multiply("edx");
|
||||||
new CPUx86.Move("ecx", "eax");
|
new CPUx86.Move("ecx", "eax");
|
||||||
new RepeatMovsd();
|
new RepeatMovsb();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ namespace Indy.IL2CPU.IL.X86.CustomImplementations.System.Assemblers {
|
||||||
new CPUx86.Add("edi", "eax");
|
new CPUx86.Add("edi", "eax");
|
||||||
|
|
||||||
new CPUx86.Move("ecx", "[ebp + 8]");
|
new CPUx86.Move("ecx", "[ebp + 8]");
|
||||||
new CPUx86.RepeatMovsd();
|
new CPUx86.RepeatMovsb();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Indy.IL2CPU.Plugs;
|
||||||
|
using CPUx86 = Indy.IL2CPU.Assembler.X86;
|
||||||
|
using CPU = Indy.IL2CPU.Assembler;
|
||||||
|
|
||||||
|
namespace Indy.IL2CPU.IL.X86.CustomImplementations.System.Assemblers {
|
||||||
|
public class MulticastDelegate_Invoke : AssemblerMethod, INeedsMethodInfo {
|
||||||
|
/// <summary>
|
||||||
|
/// <para>This method implements Multicast Invoke. This means that it should call all delegates
|
||||||
|
/// in the current multicast delegate. </para>
|
||||||
|
/// <para>The argument size is available in the <code>$$ArgSize$$</code> field. This value is already rounded to 4byte boundaries</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="aAssembler"></param>
|
||||||
|
public override void Assemble(Assembler.Assembler aAssembler) {
|
||||||
|
if (MethodInfo == null) {
|
||||||
|
throw new Exception("This AssemblerMethod needs MethodInfo!");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* EAX contains the GetInvocationList() array at the index at which it was last used
|
||||||
|
* EDX contains the index at which the EAX is
|
||||||
|
* EBX contains the number of items in the array
|
||||||
|
* ECX contains the argument size
|
||||||
|
*/
|
||||||
|
new CPU.Label("____DEBUG_FOR_MULTICAST___");
|
||||||
|
new CPUx86.Move("eax", "[" + MethodInfo.Arguments[0].VirtualAddresses[0] + "]");
|
||||||
|
var xGetInvocationListMethod = typeof(MulticastDelegate).GetMethod("GetInvocationList");
|
||||||
|
new CPUx86.Push("eax");
|
||||||
|
new CPUx86.Call(CPU.Label.GenerateLabelName(xGetInvocationListMethod));
|
||||||
|
new CPUx86.Pop("eax");
|
||||||
|
new CPUx86.Add("eax", "8");
|
||||||
|
new CPUx86.Move("ebx", "[eax]");
|
||||||
|
new CPUx86.Add("eax", "8");
|
||||||
|
new CPUx86.Move("edi", "0");
|
||||||
|
new CPUx86.Move("ecx", "[" + MethodInfo.Arguments[0].VirtualAddresses[0] + "]");
|
||||||
|
new CPUx86.Move("ecx", "[ecx + " + (MethodInfo.Arguments[0].TypeInfo.Fields["$$ArgSize$$"].Offset + 12) + "]");
|
||||||
|
|
||||||
|
new CPU.Label(".BEGIN_OF_LOOP");
|
||||||
|
new CPUx86.Compare("edx", "ebx");
|
||||||
|
new CPUx86.JumpIfEqual(".END_OF_INVOKE_");
|
||||||
|
new CPUx86.Pushad();
|
||||||
|
new CPUx86.Move("edi", "[eax]");
|
||||||
|
new CPUx86.Move("edi", "[edi + " + (MethodInfo.Arguments[0].TypeInfo.Fields["System.Object System.Delegate._target"].Offset+12) + "]");
|
||||||
|
new CPUx86.Compare("edi", "0");
|
||||||
|
new CPUx86.JumpIfZero(".NO_THIS");
|
||||||
|
new CPUx86.Push("edi");
|
||||||
|
|
||||||
|
new CPU.Label(".NO_THIS");
|
||||||
|
new CPUx86.Sub("esp", "ecx");
|
||||||
|
new CPUx86.Move("esi",
|
||||||
|
"esp");
|
||||||
|
new CPUx86.Compare("edi", "0");
|
||||||
|
new CPUx86.JumpIfZero(".NO_THIS2");
|
||||||
|
new CPUx86.Add("esi", "4");
|
||||||
|
|
||||||
|
new CPU.Label(".NO_THIS2");
|
||||||
|
new CPUx86.Move("edi", "[eax]");
|
||||||
|
new CPUx86.Move("edi", "[edi + " + (MethodInfo.Arguments[0].TypeInfo.Fields["System.IntPtr System.Delegate._methodPtr"].Offset + 12) + "]");
|
||||||
|
new CPUx86.Push("edi");
|
||||||
|
new CPUx86.Move("edi", "esp");
|
||||||
|
new CPUx86.Add("edi", "4");
|
||||||
|
// substract twice
|
||||||
|
new CPUx86.Add("esi",
|
||||||
|
"ecx");
|
||||||
|
new CPUx86.Add("esi",
|
||||||
|
"ecx");
|
||||||
|
new CPUx86.Add("esi",
|
||||||
|
"40"); // 32 for the Pushad, 16 for the method header
|
||||||
|
new CPUx86.RepeatMovsb();
|
||||||
|
new CPUx86.Pop("edi");
|
||||||
|
new CPUx86.Call("edi");
|
||||||
|
new CPUx86.Popad();
|
||||||
|
new CPUx86.Add("edx",
|
||||||
|
"1");
|
||||||
|
new CPUx86.Add("eax", "4");
|
||||||
|
new CPUx86.Jump(".BEGIN_OF_LOOP");
|
||||||
|
|
||||||
|
new CPU.Label(".END_OF_INVOKE_");
|
||||||
|
//MethodInfo.Arguments[0].
|
||||||
|
// new CPUx86.Move("ebx", "[eax + " + (MethodInfo.Arguments[0].TypeInfo.Fields["$$ArgSize$$"].Offset + 12) + "]");
|
||||||
|
|
||||||
|
//new CPUx86.Move("eax", CPUx86.Registers.
|
||||||
|
}
|
||||||
|
|
||||||
|
public MethodInformation MethodInfo
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,17 +9,21 @@ namespace Indy.IL2CPU.IL.X86.CustomImplementations.System {
|
||||||
//[PlugField(FieldId = "$$Method$$", FieldType = typeof(object))]
|
//[PlugField(FieldId = "$$Method$$", FieldType = typeof(object))]
|
||||||
//[PlugField(FieldId = "$$Object$$", FieldType = typeof(object))]
|
//[PlugField(FieldId = "$$Object$$", FieldType = typeof(object))]
|
||||||
public static class DelegateImpl {
|
public static class DelegateImpl {
|
||||||
//[PlugMethod(Signature = "System_IntPtr___System_Delegate_GetInvokeMethod____")]
|
|
||||||
//public static unsafe uint GetInvokeMethod(uint* aThis, [FieldAccess(Name = "$$Method$$")]uint aInvokeMethod) {
|
|
||||||
// //return *(aThis + 2);
|
|
||||||
// return aInvokeMethod;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public static void DoSomethingWithDelegate(Delegate aDelegate) {
|
[PlugMethod(Signature = "System_MulticastDelegate__System_Delegate_InternalAllocLike_System_Delegate_")]
|
||||||
// // fake method to have the type Delegate referenced by the assembly
|
public unsafe static uint InternalAllocLike(uint* aDelegate) {
|
||||||
// object o = aDelegate.Target;
|
uint xNeededSize = 1024; // 24 is needed fields for Multicast Delegate
|
||||||
// object o2 = o;
|
xNeededSize += 12;
|
||||||
|
uint xResultAddr = GCImplementation.AllocNewObject(xNeededSize);
|
||||||
|
byte* xResult = (byte*)xResultAddr;
|
||||||
|
byte* xDelegateAsByte = (byte*)aDelegate;
|
||||||
|
for (int i = 0; i < 1024; i++)
|
||||||
|
{
|
||||||
|
xResult[i] = xDelegateAsByte[i];
|
||||||
|
}
|
||||||
|
return xResultAddr;
|
||||||
|
}
|
||||||
|
|
||||||
//}
|
public static IntPtr GetInvokeMethod() { return IntPtr.Zero; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,9 +2,16 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Indy.IL2CPU.Plugs;
|
||||||
|
|
||||||
namespace Indy.IL2CPU.IL.X86.CustomImplementations.System {
|
namespace Indy.IL2CPU.IL.X86.CustomImplementations.System {
|
||||||
public static unsafe class MulticastDelegateImpl {
|
[Plug(Target=typeof(MulticastDelegate))]
|
||||||
|
[PlugField(FieldType=typeof(int), FieldId="$$ArgSize$$")]
|
||||||
|
public class MulticastDelegateImpl {
|
||||||
|
[PlugMethod(MethodAssembler=typeof(Assemblers.MulticastDelegate_Invoke))]
|
||||||
|
public static void InvokeMulticast(MulticastDelegate aThis)
|
||||||
|
{
|
||||||
|
throw new Exception("This method should be implemented using a MethodAssembler");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,7 @@
|
||||||
<Compile Include="CustomImplementations\System\ArrayImpl.cs" />
|
<Compile Include="CustomImplementations\System\ArrayImpl.cs" />
|
||||||
<Compile Include="CustomImplementations\System\Assemblers\Array_InternalCopy.cs" />
|
<Compile Include="CustomImplementations\System\Assemblers\Array_InternalCopy.cs" />
|
||||||
<Compile Include="CustomImplementations\System\Assemblers\Buffer_BlockCopy.cs" />
|
<Compile Include="CustomImplementations\System\Assemblers\Buffer_BlockCopy.cs" />
|
||||||
|
<Compile Include="CustomImplementations\System\Assemblers\MulticastDelegate_Invoke.cs" />
|
||||||
<Compile Include="CustomImplementations\System\Buffer.cs" />
|
<Compile Include="CustomImplementations\System\Buffer.cs" />
|
||||||
<Compile Include="CustomImplementations\System\DelegateImpl.cs" />
|
<Compile Include="CustomImplementations\System\DelegateImpl.cs" />
|
||||||
<Compile Include="CustomImplementations\System\EnumImpl.cs" />
|
<Compile Include="CustomImplementations\System\EnumImpl.cs" />
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,11 @@ namespace Indy.IL2CPU.IL.X86 {
|
||||||
|
|
||||||
public override void DoAssemble() {
|
public override void DoAssemble() {
|
||||||
string mReturnNullLabel = mThisLabel + "_ReturnNull";
|
string mReturnNullLabel = mThisLabel + "_ReturnNull";
|
||||||
new CPUx86.Move(CPUx86.Registers.EAX, CPUx86.Registers.AtESP);
|
new CPUx86.Move(CPUx86.Registers.EAX, "[esp]");
|
||||||
new CPUx86.Compare(CPUx86.Registers.EAX, "0");
|
new CPUx86.Compare(CPUx86.Registers.EAX, "0");
|
||||||
new CPUx86.JumpIfZero(mReturnNullLabel);
|
new CPUx86.JumpIfZero(mReturnNullLabel);
|
||||||
new CPUx86.Pushd(CPUx86.Registers.AtEAX);
|
new CPUx86.Pushd(CPUx86.Registers.AtEAX);
|
||||||
new CPUx86.Pushd("0" + mTypeId );
|
new CPUx86.Pushd("0x" + mTypeId.ToString("X"));
|
||||||
Assembler.StackContents.Push(new StackContent(4, typeof(object)));
|
Assembler.StackContents.Push(new StackContent(4, typeof(object)));
|
||||||
Assembler.StackContents.Push(new StackContent(4, typeof(object)));
|
Assembler.StackContents.Push(new StackContent(4, typeof(object)));
|
||||||
MethodBase xMethodIsInstance = Engine.GetMethodBase(typeof(VTablesImpl), "IsInstance", "System.Int32", "System.Int32");
|
MethodBase xMethodIsInstance = Engine.GetMethodBase(typeof(VTablesImpl), "IsInstance", "System.Int32", "System.Int32");
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Reflection;
|
||||||
using CPU = Indy.IL2CPU.Assembler;
|
using CPU = Indy.IL2CPU.Assembler;
|
||||||
using CPUx86 = Indy.IL2CPU.Assembler.X86;
|
using CPUx86 = Indy.IL2CPU.Assembler.X86;
|
||||||
using Indy.IL2CPU.Assembler;
|
using Indy.IL2CPU.Assembler;
|
||||||
|
using Indy.IL2CPU.IL.X86.CustomImplementations.System;
|
||||||
|
|
||||||
namespace Indy.IL2CPU.IL.X86 {
|
namespace Indy.IL2CPU.IL.X86 {
|
||||||
public class X86OpCodeMap: OpCodeMap {
|
public class X86OpCodeMap: OpCodeMap {
|
||||||
|
|
@ -51,10 +52,11 @@ namespace Indy.IL2CPU.IL.X86 {
|
||||||
|
|
||||||
public override bool HasCustomAssembleImplementation(MethodInformation aMethodInfo, bool aInMetalMode) {
|
public override bool HasCustomAssembleImplementation(MethodInformation aMethodInfo, bool aInMetalMode) {
|
||||||
switch (aMethodInfo.LabelName) {
|
switch (aMethodInfo.LabelName) {
|
||||||
case "System_Object___System_Threading_Interlocked_CompareExchange___System_Object___System_Object__System_Object___": {
|
case "System_Object__System_Threading_Interlocked_CompareExchange_System_Object___System_Object__System_Object_":
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case "System_Int32___System_Threading_Interlocked_CompareExchange___System_Int32___System_Int32__System_Int32___": {
|
case "System_Int32__System_Threading_Interlocked_CompareExchange_System_Int32___System_Int32__System_Int32_": {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case "System_String___System_String_FastAllocateString___System_Int32___": {
|
case "System_String___System_String_FastAllocateString___System_Int32___": {
|
||||||
|
|
@ -66,9 +68,10 @@ namespace Indy.IL2CPU.IL.X86 {
|
||||||
case "System_IntPtr___System_Delegate_GetInvokeMethod____": {
|
case "System_IntPtr___System_Delegate_GetInvokeMethod____": {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//case "System_IntPtr___System_Delegate_GetMulticastInvoke____": {
|
case "System_IntPtr__System_Delegate_GetMulticastInvoke__":
|
||||||
// return true;
|
{
|
||||||
// }
|
return true;
|
||||||
|
}
|
||||||
case "System_MulticastDelegate___System_Delegate_InternalAllocLike___System_Delegate___": {
|
case "System_MulticastDelegate___System_Delegate_InternalAllocLike___System_Delegate___": {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -87,21 +90,27 @@ namespace Indy.IL2CPU.IL.X86 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly MethodBase InvokeMulticastRef = typeof(MulticastDelegateImpl).GetMethod("InvokeMulticast", BindingFlags.Public | BindingFlags.Static);
|
||||||
|
|
||||||
public override void DoCustomAssembleImplementation(bool aInMetalMode, Indy.IL2CPU.Assembler.Assembler aAssembler, MethodInformation aMethodInfo) {
|
public override void DoCustomAssembleImplementation(bool aInMetalMode, Indy.IL2CPU.Assembler.Assembler aAssembler, MethodInformation aMethodInfo) {
|
||||||
switch (aMethodInfo.LabelName) {
|
switch (aMethodInfo.LabelName) {
|
||||||
case "System_Object___System_Threading_Interlocked_CompareExchange___System_Object___System_Object__System_Object___": {
|
case "System_Object__System_Threading_Interlocked_CompareExchange_System_Object___System_Object__System_Object_":
|
||||||
|
{
|
||||||
Assemble_System_Threading_Interlocked_CompareExchange__Object(aAssembler, aMethodInfo);
|
Assemble_System_Threading_Interlocked_CompareExchange__Object(aAssembler, aMethodInfo);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "System_Int32___System_Threading_Interlocked_CompareExchange___System_Int32___System_Int32__System_Int32___": {
|
case "System_Int32__System_Threading_Interlocked_CompareExchange_System_Int32___System_Int32__System_Int32_": {
|
||||||
Assemble_System_Threading_Interlocked_CompareExchange__Object(aAssembler, aMethodInfo);
|
Assemble_System_Threading_Interlocked_CompareExchange__Object(aAssembler, aMethodInfo);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//case "System_IntPtr___System_Delegate_GetMulticastInvoke____": {
|
case "System_IntPtr__System_Delegate_GetMulticastInvoke__":
|
||||||
// Engine.QueueMethod(CustomImplementations.System.EventHandlerImplRefs.MulticastInvokeRef);
|
{
|
||||||
// new CPUx86.Push(CPU.Label.GenerateLabelName(CustomImplementations.System.EventHandlerImplRefs.MulticastInvokeRef));
|
//IL.X86.Op.Ldarg(aAssembler, aMethodInfo.Arguments[0]);
|
||||||
// break;
|
|
||||||
// }
|
Engine.QueueMethod(InvokeMulticastRef);
|
||||||
|
new CPUx86.Push(Label.GenerateLabelName(InvokeMulticastRef));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "System_MulticastDelegate___System_Delegate_InternalAllocLike___System_Delegate___": {
|
case "System_MulticastDelegate___System_Delegate_InternalAllocLike___System_Delegate___": {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -118,6 +127,18 @@ namespace Indy.IL2CPU.IL.X86 {
|
||||||
xOp.Assembler = aAssembler;
|
xOp.Assembler = aAssembler;
|
||||||
xOp.ProxiedMethod = CustomImplementations.System.EventHandlerImplRefs.CtorRef;
|
xOp.ProxiedMethod = CustomImplementations.System.EventHandlerImplRefs.CtorRef;
|
||||||
xOp.Assemble();
|
xOp.Assemble();
|
||||||
|
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0]);
|
||||||
|
//
|
||||||
|
var xInvokeMethod = aMethodInfo.TypeInfo.TypeDef.GetMethod("Invoke");
|
||||||
|
var xDelegateMethodInfo = Engine.GetMethodInfo(xInvokeMethod, xInvokeMethod, xInvokeMethod.Name, aMethodInfo.TypeInfo, aMethodInfo.DebugMode);
|
||||||
|
int xArgSize = (from item in xDelegateMethodInfo.Arguments
|
||||||
|
select item.Size + (item.Size % 4 == 0
|
||||||
|
? 0
|
||||||
|
: (4 - (item.Size % 4)))).Take(xDelegateMethodInfo.Arguments.Length).Sum();
|
||||||
|
new CPUx86.Push((xArgSize-4).ToString());
|
||||||
|
new CPU.Label(".SetArgSize");
|
||||||
|
aAssembler.StackContents.Push(new StackContent(4));
|
||||||
|
Stfld.Stfld(aAssembler, aMethodInfo.TypeInfo, aMethodInfo.TypeInfo.Fields["$$ArgSize$$"]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (aMethodInfo.Method.Name == "Invoke") {
|
if (aMethodInfo.Method.Name == "Invoke") {
|
||||||
|
|
@ -126,18 +147,25 @@ namespace Indy.IL2CPU.IL.X86 {
|
||||||
// param 2 is eventargs
|
// param 2 is eventargs
|
||||||
new Label(".LoadTargetObject");
|
new Label(".LoadTargetObject");
|
||||||
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0]);
|
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0]);
|
||||||
Ldarg.Ldfld(aAssembler, aMethodInfo.TypeInfo, "System.Object System.Delegate._target");
|
//Ldarg.Ldfld(aAssembler, aMethodInfo.TypeInfo, "System.Object System.Delegate._target");
|
||||||
new Label(".LoadMethodParams");
|
//new Label(".LoadMethodParams");
|
||||||
for (int i = 1; i < aMethodInfo.Arguments.Length; i++) {
|
//for (int i = 1; i < aMethodInfo.Arguments.Length; i++) {
|
||||||
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[i]);
|
// Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[i]);
|
||||||
}
|
//}
|
||||||
new Label(".LoadMethodPointer");
|
//new Label(".LoadMethodPointer");
|
||||||
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0]);
|
//Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0]);
|
||||||
Ldarg.Ldfld(aAssembler, aMethodInfo.TypeInfo, "System.IntPtr System.Delegate._methodPtr");
|
//Ldarg.Ldfld(aAssembler, aMethodInfo.TypeInfo, "System.IntPtr System.Delegate._methodPtr");
|
||||||
new CPUx86.Pop("eax");
|
//new CPUx86.Pop("eax");
|
||||||
new CPUx86.Call(CPUx86.Registers.EAX);
|
//new CPUx86.Call(CPUx86.Registers.EAX);
|
||||||
new CPUx86.Add("esp",
|
//new CPUx86.Add("esp",
|
||||||
"4");
|
// "4");
|
||||||
|
Engine.QueueMethod(InvokeMulticastRef);
|
||||||
|
new CPUx86.Call(Label.GenerateLabelName(InvokeMulticastRef));
|
||||||
|
var xGetInvocationListMethod = typeof(MulticastDelegate).GetMethod("GetInvocationList");
|
||||||
|
Engine.QueueMethod(xGetInvocationListMethod);
|
||||||
|
xGetInvocationListMethod = typeof(Delegate).GetMethod("GetInvocationList");
|
||||||
|
Engine.QueueMethod(xGetInvocationListMethod);
|
||||||
|
|
||||||
// new CPUx86.Pop(CPUx86.Registers.EAX);
|
// new CPUx86.Pop(CPUx86.Registers.EAX);
|
||||||
//new CPUx86.Move("esp", "ebp");
|
//new CPUx86.Move("esp", "ebp");
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
12
source/Indy.IL2CPU.IL/INeedsMethodInfo.cs
Normal file
12
source/Indy.IL2CPU.IL/INeedsMethodInfo.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Indy.IL2CPU.IL {
|
||||||
|
public interface INeedsMethodInfo {
|
||||||
|
MethodInformation MethodInfo {
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -64,6 +64,7 @@
|
||||||
<Compile Include="Extensions.cs" />
|
<Compile Include="Extensions.cs" />
|
||||||
<Compile Include="ILReader.cs" />
|
<Compile Include="ILReader.cs" />
|
||||||
<Compile Include="ILReader.Utilities.cs" />
|
<Compile Include="ILReader.Utilities.cs" />
|
||||||
|
<Compile Include="INeedsMethodInfo.cs" />
|
||||||
<Compile Include="InitVmtImplementationOp.cs" />
|
<Compile Include="InitVmtImplementationOp.cs" />
|
||||||
<Compile Include="MainEntryPointOp.cs" />
|
<Compile Include="MainEntryPointOp.cs" />
|
||||||
<Compile Include="MethodFooterOp.cs" />
|
<Compile Include="MethodFooterOp.cs" />
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ namespace Indy.IL2CPU.IL {
|
||||||
int aOffset,
|
int aOffset,
|
||||||
KindEnum aKind,
|
KindEnum aKind,
|
||||||
bool aIsReferenceType,
|
bool aIsReferenceType,
|
||||||
|
TypeInformation aTypeInfo,
|
||||||
Type aArgumentType) {
|
Type aArgumentType) {
|
||||||
mSize = aSize;
|
mSize = aSize;
|
||||||
mVirtualAddresses = new string[mSize / 4];
|
mVirtualAddresses = new string[mSize / 4];
|
||||||
|
|
@ -51,6 +52,7 @@ namespace Indy.IL2CPU.IL {
|
||||||
mArgumentType = aArgumentType;
|
mArgumentType = aArgumentType;
|
||||||
mIsReferenceType = aIsReferenceType;
|
mIsReferenceType = aIsReferenceType;
|
||||||
mOffset = -1;
|
mOffset = -1;
|
||||||
|
TypeInfo = aTypeInfo;
|
||||||
Offset = aOffset;
|
Offset = aOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,6 +126,8 @@ namespace Indy.IL2CPU.IL {
|
||||||
mArgumentType = value;
|
mArgumentType = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly TypeInformation TypeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodInformation(string aLabelName,
|
public MethodInformation(string aLabelName,
|
||||||
|
|
|
||||||
|
|
@ -90,28 +90,19 @@ namespace Indy.IL2CPU.IL {
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void DoCustomAssembleImplementation(bool aInMetalMode, Assembler.Assembler aAssembler, MethodInformation aMethodInfo) {
|
public virtual void DoCustomAssembleImplementation(bool aInMetalMode, Assembler.Assembler aAssembler, MethodInformation aMethodInfo) {
|
||||||
PlugMethodAttribute xAttrib = (PlugMethodAttribute)aMethodInfo.Method.GetCustomAttributes(typeof(PlugMethodAttribute), true).Cast<PlugMethodAttribute>().FirstOrDefault();
|
PlugMethodAttribute xAttrib = aMethodInfo.Method.GetCustomAttributes(typeof(PlugMethodAttribute), true).Cast<PlugMethodAttribute>().FirstOrDefault();
|
||||||
if (xAttrib != null) {
|
if (xAttrib != null) {
|
||||||
Type xAssemblerType = xAttrib.MethodAssembler;
|
Type xAssemblerType = xAttrib.MethodAssembler;
|
||||||
if (xAssemblerType != null) {
|
if (xAssemblerType != null) {
|
||||||
AssemblerMethod xAssembler = (AssemblerMethod)Activator.CreateInstance(xAssemblerType);
|
var xAssembler = (AssemblerMethod)Activator.CreateInstance(xAssemblerType);
|
||||||
|
var xNeedsMethodInfo = xAssembler as INeedsMethodInfo;
|
||||||
|
if (xNeedsMethodInfo != null) {
|
||||||
|
xNeedsMethodInfo.MethodInfo = aMethodInfo; }
|
||||||
xAssembler.Assemble(aAssembler);
|
xAssembler.Assemble(aAssembler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Type GetType(Assembly aAssembly, string aType) {
|
|
||||||
string xActualTypeName = aType;
|
|
||||||
if (xActualTypeName.Contains("<") && xActualTypeName.Contains(">")) {
|
|
||||||
xActualTypeName = xActualTypeName.Substring(0, xActualTypeName.IndexOf("<"));
|
|
||||||
}
|
|
||||||
Type xResult = aAssembly.GetType(aType, false);
|
|
||||||
if (xResult != null) {
|
|
||||||
return xResult;
|
|
||||||
}
|
|
||||||
throw new Exception("Type '" + aType + "' not found in assembly '" + aAssembly + "'!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void PostProcess(Assembler.Assembler aAssembler) {
|
public virtual void PostProcess(Assembler.Assembler aAssembler) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -578,8 +578,7 @@ namespace Indy.IL2CPU {
|
||||||
if (xTD.BaseType == null) {
|
if (xTD.BaseType == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (xMethod.IsVirtual && !xMethod.IsConstructor &&
|
if (xMethod.IsVirtual && !xMethod.IsConstructor) {
|
||||||
!xMethod.IsFinal) {
|
|
||||||
Type xCurrentInspectedType = xTD.BaseType;
|
Type xCurrentInspectedType = xTD.BaseType;
|
||||||
ParameterInfo[] xParams = xMethod.GetParameters();
|
ParameterInfo[] xParams = xMethod.GetParameters();
|
||||||
Type[] xMethodParams = new Type[xParams.Length];
|
Type[] xMethodParams = new Type[xParams.Length];
|
||||||
|
|
@ -639,8 +638,7 @@ namespace Indy.IL2CPU {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
aCurrentInspectedType = aCurrentInspectedType.BaseType;
|
aCurrentInspectedType = aCurrentInspectedType.BaseType;
|
||||||
MethodBase xFoundMethod = aCurrentInspectedType.GetMethod(aMethod.Name,
|
MethodBase xFoundMethod = aCurrentInspectedType.GetMethod(aMethod.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, Type.DefaultBinder, aMethodParams, new ParameterModifier[0]);
|
||||||
aMethodParams);
|
|
||||||
ParameterInfo[] xParams = xFoundMethod.GetParameters();
|
ParameterInfo[] xParams = xFoundMethod.GetParameters();
|
||||||
bool xContinue = true;
|
bool xContinue = true;
|
||||||
for (int i = 0; i < xParams.Length; i++) {
|
for (int i = 0; i < xParams.Length; i++) {
|
||||||
|
|
@ -654,7 +652,12 @@ namespace Indy.IL2CPU {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (xFoundMethod != null) {
|
if (xFoundMethod != null) {
|
||||||
if (xFoundMethod.IsVirtual == aMethod.IsVirtual && xFoundMethod.IsPrivate == false && xFoundMethod.IsPublic == aMethod.IsPublic && xFoundMethod.IsFamily == aMethod.IsFamily && xFoundMethod.IsFamilyAndAssembly == aMethod.IsFamilyAndAssembly && xFoundMethod.IsFamilyOrAssembly == aMethod.IsFamilyOrAssembly &&
|
if (xFoundMethod.IsVirtual == aMethod.IsVirtual &&
|
||||||
|
xFoundMethod.IsPrivate == false &&
|
||||||
|
xFoundMethod.IsPublic == aMethod.IsPublic &&
|
||||||
|
xFoundMethod.IsFamily == aMethod.IsFamily &&
|
||||||
|
xFoundMethod.IsFamilyAndAssembly == aMethod.IsFamilyAndAssembly &&
|
||||||
|
xFoundMethod.IsFamilyOrAssembly == aMethod.IsFamilyOrAssembly &&
|
||||||
xFoundMethod.IsFinal == false) {
|
xFoundMethod.IsFinal == false) {
|
||||||
xBaseMethod = xFoundMethod;
|
xBaseMethod = xFoundMethod;
|
||||||
}
|
}
|
||||||
|
|
@ -1445,6 +1448,7 @@ namespace Indy.IL2CPU {
|
||||||
xCurOffset,
|
xCurOffset,
|
||||||
xKind,
|
xKind,
|
||||||
!xParamDef.ParameterType.IsValueType,
|
!xParamDef.ParameterType.IsValueType,
|
||||||
|
GetTypeInfo(xParamDef.ParameterType),
|
||||||
xParamDef.ParameterType);
|
xParamDef.ParameterType);
|
||||||
xCurOffset += xArgSize;
|
xCurOffset += xArgSize;
|
||||||
}
|
}
|
||||||
|
|
@ -1454,6 +1458,7 @@ namespace Indy.IL2CPU {
|
||||||
xCurOffset,
|
xCurOffset,
|
||||||
MethodInformation.Argument.KindEnum.In,
|
MethodInformation.Argument.KindEnum.In,
|
||||||
!aCurrentMethodForArguments.DeclaringType.IsValueType,
|
!aCurrentMethodForArguments.DeclaringType.IsValueType,
|
||||||
|
GetTypeInfo(aCurrentMethodForArguments.DeclaringType),
|
||||||
aCurrentMethodForArguments.DeclaringType);
|
aCurrentMethodForArguments.DeclaringType);
|
||||||
} else {
|
} else {
|
||||||
ParameterInfo[] xParameters = aCurrentMethodForArguments.GetParameters();
|
ParameterInfo[] xParameters = aCurrentMethodForArguments.GetParameters();
|
||||||
|
|
@ -1477,6 +1482,7 @@ namespace Indy.IL2CPU {
|
||||||
xCurOffset,
|
xCurOffset,
|
||||||
xKind,
|
xKind,
|
||||||
!xParamDef.ParameterType.IsValueType,
|
!xParamDef.ParameterType.IsValueType,
|
||||||
|
GetTypeInfo(xParamDef.ParameterType),
|
||||||
xParamDef.ParameterType);
|
xParamDef.ParameterType);
|
||||||
xCurOffset += xArgSize;
|
xCurOffset += xArgSize;
|
||||||
}
|
}
|
||||||
|
|
@ -1509,7 +1515,7 @@ namespace Indy.IL2CPU {
|
||||||
out aObjectStorageSize);
|
out aObjectStorageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GetTypeFieldInfoImpl(Dictionary<string, TypeInformation.Field> aTypeFields,
|
private static void GetTypeFieldInfoImpl(List<KeyValuePair<string, TypeInformation.Field>> aTypeFields,
|
||||||
Type aType,
|
Type aType,
|
||||||
ref int aObjectStorageSize) {
|
ref int aObjectStorageSize) {
|
||||||
Type xActualType = aType;
|
Type xActualType = aType;
|
||||||
|
|
@ -1522,7 +1528,8 @@ namespace Indy.IL2CPU {
|
||||||
item.Value);
|
item.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (FieldInfo xField in aType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) {
|
foreach (FieldInfo xField in aType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly))
|
||||||
|
{
|
||||||
if (xField.IsStatic) {
|
if (xField.IsStatic) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -1557,9 +1564,9 @@ namespace Indy.IL2CPU {
|
||||||
xFieldSize = GetFieldStorageSize(xFieldType);
|
xFieldSize = GetFieldStorageSize(xFieldType);
|
||||||
}
|
}
|
||||||
//}
|
//}
|
||||||
if (aTypeFields.ContainsKey(xFieldId)) {
|
if ((from item in aTypeFields
|
||||||
continue;
|
where item.Key == xFieldId
|
||||||
}
|
select item).Count() > 0) { continue; }
|
||||||
int xOffset = aObjectStorageSize;
|
int xOffset = aObjectStorageSize;
|
||||||
FieldOffsetAttribute xOffsetAttrib = xField.GetCustomAttributes(typeof(FieldOffsetAttribute),
|
FieldOffsetAttribute xOffsetAttrib = xField.GetCustomAttributes(typeof(FieldOffsetAttribute),
|
||||||
true).FirstOrDefault() as FieldOffsetAttribute;
|
true).FirstOrDefault() as FieldOffsetAttribute;
|
||||||
|
|
@ -1569,13 +1576,13 @@ namespace Indy.IL2CPU {
|
||||||
aObjectStorageSize += xFieldSize;
|
aObjectStorageSize += xFieldSize;
|
||||||
xOffset = -1;
|
xOffset = -1;
|
||||||
}
|
}
|
||||||
aTypeFields.Add(xField.GetFullName(),
|
aTypeFields.Insert(0, new KeyValuePair<string,TypeInformation.Field>(xField.GetFullName(),
|
||||||
new TypeInformation.Field(xFieldSize,
|
new TypeInformation.Field(xFieldSize,
|
||||||
xFieldType.IsClass && !xFieldType.IsValueType,
|
xFieldType.IsClass && !xFieldType.IsValueType,
|
||||||
xFieldType,
|
xFieldType,
|
||||||
(xPlugFieldAttr != null && xPlugFieldAttr.IsExternalValue)) {
|
(xPlugFieldAttr != null && xPlugFieldAttr.IsExternalValue)) {
|
||||||
Offset = xOffset
|
Offset = xOffset
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
while (xCurrentPlugFieldList.Count > 0) {
|
while (xCurrentPlugFieldList.Count > 0) {
|
||||||
var xItem = xCurrentPlugFieldList.Values.First();
|
var xItem = xCurrentPlugFieldList.Values.First();
|
||||||
|
|
@ -1594,11 +1601,11 @@ namespace Indy.IL2CPU {
|
||||||
}
|
}
|
||||||
int xOffset = aObjectStorageSize;
|
int xOffset = aObjectStorageSize;
|
||||||
aObjectStorageSize += xFieldSize;
|
aObjectStorageSize += xFieldSize;
|
||||||
aTypeFields.Add(xItem.FieldId,
|
aTypeFields.Insert(0, new KeyValuePair<string,TypeInformation.Field>(xItem.FieldId,
|
||||||
new TypeInformation.Field(xFieldSize,
|
new TypeInformation.Field(xFieldSize,
|
||||||
xFieldType.IsClass && !xFieldType.IsValueType,
|
xFieldType.IsClass && !xFieldType.IsValueType,
|
||||||
xFieldType,
|
xFieldType,
|
||||||
xItem.IsExternalValue));
|
xItem.IsExternalValue)));
|
||||||
}
|
}
|
||||||
if (aType.FullName != "System.Object" &&
|
if (aType.FullName != "System.Object" &&
|
||||||
aType.BaseType != null) {
|
aType.BaseType != null) {
|
||||||
|
|
@ -1611,7 +1618,7 @@ namespace Indy.IL2CPU {
|
||||||
|
|
||||||
public static Dictionary<string, TypeInformation.Field> GetTypeFieldInfo(Type aType,
|
public static Dictionary<string, TypeInformation.Field> GetTypeFieldInfo(Type aType,
|
||||||
out int aObjectStorageSize) {
|
out int aObjectStorageSize) {
|
||||||
Dictionary<string, TypeInformation.Field> xTypeFields = new Dictionary<string, TypeInformation.Field>();
|
var xTypeFields = new List<KeyValuePair<string, TypeInformation.Field>>();
|
||||||
aObjectStorageSize = 0;
|
aObjectStorageSize = 0;
|
||||||
GetTypeFieldInfoImpl(xTypeFields,
|
GetTypeFieldInfoImpl(xTypeFields,
|
||||||
aType,
|
aType,
|
||||||
|
|
@ -1619,8 +1626,8 @@ namespace Indy.IL2CPU {
|
||||||
if (aType.IsExplicitLayout) {
|
if (aType.IsExplicitLayout) {
|
||||||
var xStructLayout = aType.StructLayoutAttribute;
|
var xStructLayout = aType.StructLayoutAttribute;
|
||||||
if (xStructLayout.Size == 0) {
|
if (xStructLayout.Size == 0) {
|
||||||
aObjectStorageSize = (from item in xTypeFields.Values
|
aObjectStorageSize = (from item in xTypeFields
|
||||||
let xSize = item.Offset + item.Size
|
let xSize = item.Value.Offset + item.Value.Size
|
||||||
orderby xSize
|
orderby xSize
|
||||||
select xSize).FirstOrDefault();
|
select xSize).FirstOrDefault();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1629,10 +1636,9 @@ namespace Indy.IL2CPU {
|
||||||
}
|
}
|
||||||
int xOffset = 0;
|
int xOffset = 0;
|
||||||
Dictionary<string, TypeInformation.Field> xResult = new Dictionary<string, TypeInformation.Field>();
|
Dictionary<string, TypeInformation.Field> xResult = new Dictionary<string, TypeInformation.Field>();
|
||||||
foreach (var item in xTypeFields.Reverse()) {
|
foreach (var item in xTypeFields) {
|
||||||
var xItem = item.Value;
|
var xItem = item.Value;
|
||||||
if (item.Value.Offset ==
|
if (item.Value.Offset == -1) {
|
||||||
-1) {
|
|
||||||
xItem.Offset = xOffset;
|
xItem.Offset = xOffset;
|
||||||
xOffset += xItem.Size;
|
xOffset += xItem.Size;
|
||||||
}
|
}
|
||||||
|
|
@ -1700,6 +1706,7 @@ namespace Indy.IL2CPU {
|
||||||
if (mCurrent == null) {
|
if (mCurrent == null) {
|
||||||
throw new Exception("ERROR: No Current Engine found!");
|
throw new Exception("ERROR: No Current Engine found!");
|
||||||
}
|
}
|
||||||
|
if (aMethod == null) { System.Diagnostics.Debugger.Break(); }
|
||||||
if (!aMethod.IsStatic) {
|
if (!aMethod.IsStatic) {
|
||||||
RegisterType(aMethod.DeclaringType);
|
RegisterType(aMethod.DeclaringType);
|
||||||
}
|
}
|
||||||
|
|
@ -1739,8 +1746,12 @@ namespace Indy.IL2CPU {
|
||||||
aType.GetArrayRank() != 1) {
|
aType.GetArrayRank() != 1) {
|
||||||
throw new Exception("Multidimensional arrays are not yet supported!");
|
throw new Exception("Multidimensional arrays are not yet supported!");
|
||||||
}
|
}
|
||||||
|
if (aType.IsArray) { aType = typeof(Array); }
|
||||||
|
else
|
||||||
|
{
|
||||||
aType = aType.GetElementType();
|
aType = aType.GetElementType();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Type xFoundItem = mCurrent.mTypes.FirstOrDefault(x => x.FullName.Equals(aType.FullName));
|
Type xFoundItem = mCurrent.mTypes.FirstOrDefault(x => x.FullName.Equals(aType.FullName));
|
||||||
if (xFoundItem == null) {
|
if (xFoundItem == null) {
|
||||||
mCurrent.mTypes.Add(aType);
|
mCurrent.mTypes.Add(aType);
|
||||||
|
|
|
||||||
|
|
@ -20,33 +20,29 @@ namespace MatthijsTest
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public static void GetResumeAndResume(ref uint aSuspend)
|
|
||||||
{
|
|
||||||
aSuspend = 0;
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
public static int GetValue() {
|
|
||||||
return 5; }
|
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
Console.Clear();
|
Console.Clear();
|
||||||
Console.WriteLine("Kernel started!");
|
Console.WriteLine("Kernel started!");
|
||||||
int xTest = 987;
|
Console.WriteLine("Starting doing tests");
|
||||||
IntPtr xPtr = (IntPtr)xTest;
|
DoIt();
|
||||||
xTest = (int)xPtr;
|
Console.WriteLine("Done");
|
||||||
Console.Write("Value: ");
|
|
||||||
Console.Write(xTest.ToString());
|
|
||||||
Console.WriteLine();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ITest {
|
public class TestType { public void DoIt(object sender, EventArgs e) { Console.WriteLine("Writeline from an instance method!"); } }
|
||||||
void DoMessage();}
|
|
||||||
|
|
||||||
public class TestImpl : ITest {
|
public static void DoIt()
|
||||||
public void DoMessage() {
|
{
|
||||||
Console.WriteLine("Message from interface member");
|
EventHandler xEvent = WriteMessage1;
|
||||||
|
var xType = new TestType();
|
||||||
|
xEvent += xType.DoIt;
|
||||||
|
xEvent += WriteMessage2;
|
||||||
|
xEvent(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void WriteMessage1(object sender, EventArgs e) { Console.WriteLine("Message 1"); }
|
||||||
|
public static void WriteMessage2(object sender, EventArgs e) { Console.WriteLine("Message 2"); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue