mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-21 13:28:41 +00:00
279 lines
10 KiB
C#
279 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
using CPU = Indy.IL2CPU.Assembler;
|
|
using CPUx86 = Indy.IL2CPU.Assembler.X86;
|
|
using Indy.IL2CPU.Assembler;
|
|
using Indy.IL2CPU.IL.X86.CustomImplementations.System;
|
|
|
|
namespace Indy.IL2CPU.IL.X86
|
|
{
|
|
public class X86OpCodeMap : OpCodeMap
|
|
{
|
|
protected override Type GetMethodHeaderOp()
|
|
{
|
|
return typeof(X86MethodHeaderOp);
|
|
}
|
|
|
|
protected override Type GetMethodFooterOp()
|
|
{
|
|
return typeof(X86MethodFooterOp);
|
|
}
|
|
|
|
protected override Type GetInitVmtImplementationOp()
|
|
{
|
|
return typeof(X86InitVmtImplementationOp);
|
|
}
|
|
|
|
protected override Assembly ImplementationAssembly
|
|
{
|
|
get
|
|
{
|
|
return typeof(X86OpCodeMap).Assembly;
|
|
}
|
|
}
|
|
|
|
protected override Type GetMainEntryPointOp()
|
|
{
|
|
return typeof(X86MainEntryPointOp);
|
|
}
|
|
|
|
protected override Type GetPInvokeMethodBodyOp()
|
|
{
|
|
return typeof(X86PInvokeMethodBodyOp);
|
|
}
|
|
|
|
protected override Type GetCustomMethodImplementationProxyOp()
|
|
{
|
|
return typeof(X86CustomMethodImplementationProxyOp);
|
|
}
|
|
|
|
protected override Type GetCustomMethodImplementationOp()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
public override IList<Assembly> GetPlugAssemblies()
|
|
{
|
|
IList<Assembly> xResult = base.GetPlugAssemblies();
|
|
xResult.Add(typeof(X86OpCodeMap).Assembly);
|
|
return xResult;
|
|
}
|
|
|
|
public override bool HasCustomAssembleImplementation(MethodInformation aMethodInfo, bool aInMetalMode)
|
|
{
|
|
switch (aMethodInfo.LabelName)
|
|
{
|
|
case "System_Object__System_Threading_Interlocked_CompareExchange_System_Object___System_Object__System_Object_":
|
|
{
|
|
return true;
|
|
}
|
|
case "System_Int32__System_Threading_Interlocked_CompareExchange_System_Int32___System_Int32__System_Int32_":
|
|
{
|
|
return true;
|
|
}
|
|
case "System_String___System_String_FastAllocateString___System_Int32___":
|
|
{
|
|
return true;
|
|
}
|
|
case "System_Void___System_EventHandler_Invoke___System_Object__System_EventArgs___":
|
|
{
|
|
return true;
|
|
}
|
|
case "System_IntPtr___System_Delegate_GetInvokeMethod____":
|
|
{
|
|
return true;
|
|
}
|
|
case "System_IntPtr__System_Delegate_GetMulticastInvoke__":
|
|
{
|
|
return true;
|
|
}
|
|
case "System_MulticastDelegate___System_Delegate_InternalAllocLike___System_Delegate___":
|
|
{
|
|
return true;
|
|
}
|
|
default:
|
|
{
|
|
// we need special treatment for delegate constructors, which have an Object,IntPtr param list
|
|
if (ObjectUtilities.IsDelegate(aMethodInfo.Method.DeclaringType))
|
|
{
|
|
if (aMethodInfo.LabelName.EndsWith("__ctor_System_Object__System_IntPtr_"))
|
|
{
|
|
return true;
|
|
}
|
|
if (aMethodInfo.Method.Name == "Invoke")
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return base.HasCustomAssembleImplementation(aMethodInfo, aInMetalMode);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static readonly MethodBase InvokeMulticastRef = typeof(MulticastDelegateImpl).GetMethod("InvokeMulticast", BindingFlags.Public | BindingFlags.Static);
|
|
public override void ScanCustomAssembleImplementation(MethodInformation aMethod, bool aInMetalMode)
|
|
{
|
|
base.ScanCustomAssembleImplementation(aMethod, aInMetalMode);
|
|
if (ObjectUtilities.IsDelegate(aMethod.Method.DeclaringType))
|
|
{
|
|
if (aMethod.LabelName.EndsWith("__ctor_System_Object__System_IntPtr_"))
|
|
{
|
|
//for (int i = 0; i < aMethodInfo.Arguments.Length; i++) {
|
|
// Op.Ldarg(aAssembler, aMethodInfo.Arguments[i]);
|
|
//}
|
|
//new Call(CustomImplementations.System.EventHandlerImplRefs.CtorRef) {
|
|
// Assembler = aAssembler
|
|
//}.Assemble();
|
|
Engine.QueueMethod(CustomImplementations.System.EventHandlerImplRefs.CtorRef);
|
|
Engine.QueueMethod(aMethod.TypeInfo.TypeDef.GetMethod("Invoke"));
|
|
return;
|
|
}
|
|
if (aMethod.Method.Name == "Invoke")
|
|
{
|
|
Engine.QueueMethod(InvokeMulticastRef);
|
|
Engine.QueueMethod(typeof(MulticastDelegate).GetMethod("GetInvocationList"));
|
|
Engine.QueueMethod(typeof(Delegate).GetMethod("GetInvocationList"));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
public override void DoCustomAssembleImplementation(bool aInMetalMode, Indy.IL2CPU.Assembler.Assembler aAssembler, MethodInformation aMethodInfo)
|
|
{
|
|
switch (aMethodInfo.LabelName)
|
|
{
|
|
case "System_Object__System_Threading_Interlocked_CompareExchange_System_Object___System_Object__System_Object_":
|
|
{
|
|
Assemble_System_Threading_Interlocked_CompareExchange__Object(aAssembler, aMethodInfo);
|
|
break;
|
|
}
|
|
case "System_Int32__System_Threading_Interlocked_CompareExchange_System_Int32___System_Int32__System_Int32_":
|
|
{
|
|
Assemble_System_Threading_Interlocked_CompareExchange__Object(aAssembler, aMethodInfo);
|
|
break;
|
|
}
|
|
case "System_IntPtr__System_Delegate_GetMulticastInvoke__":
|
|
{
|
|
//IL.X86.Op.Ldarg(aAssembler, aMethodInfo.Arguments[0]);
|
|
|
|
Engine.QueueMethod(InvokeMulticastRef);
|
|
new CPUx86.Push(Label.GenerateLabelName(InvokeMulticastRef));
|
|
break;
|
|
}
|
|
case "System_MulticastDelegate___System_Delegate_InternalAllocLike___System_Delegate___":
|
|
{
|
|
break;
|
|
}
|
|
default:
|
|
if (ObjectUtilities.IsDelegate(aMethodInfo.Method.DeclaringType))
|
|
{
|
|
if (aMethodInfo.LabelName.EndsWith("__ctor_System_Object__System_IntPtr_"))
|
|
{
|
|
//for (int i = 0; i < aMethodInfo.Arguments.Length; i++) {
|
|
// Op.Ldarg(aAssembler, aMethodInfo.Arguments[i]);
|
|
//}
|
|
//new Call(CustomImplementations.System.EventHandlerImplRefs.CtorRef) {
|
|
// Assembler = aAssembler
|
|
//}.Assemble();
|
|
var xOp = new X86CustomMethodImplementationProxyOp(null, aMethodInfo);
|
|
xOp.Assembler = aAssembler;
|
|
xOp.ProxiedMethod = CustomImplementations.System.EventHandlerImplRefs.CtorRef;
|
|
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$$"]);
|
|
if (xDelegateMethodInfo.ReturnType != typeof(void))
|
|
{
|
|
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0]);
|
|
new CPUx86.Pushd("1");
|
|
aAssembler.StackContents.Push(new StackContent(4));
|
|
Stfld.Stfld(aAssembler, aMethodInfo.TypeInfo, aMethodInfo.TypeInfo.Fields["$$ReturnsValue$$"]);
|
|
}
|
|
break;
|
|
}
|
|
if (aMethodInfo.Method.Name == "Invoke")
|
|
{
|
|
// param 0 is instance of eventhandler
|
|
// param 1 is sender
|
|
// param 2 is eventargs
|
|
new Label(".LoadTargetObject");
|
|
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0]);
|
|
//Ldarg.Ldfld(aAssembler, aMethodInfo.TypeInfo, "System.Object System.Delegate._target");
|
|
//new Label(".LoadMethodParams");
|
|
//for (int i = 1; i < aMethodInfo.Arguments.Length; i++) {
|
|
// Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[i]);
|
|
//}
|
|
//new Label(".LoadMethodPointer");
|
|
//Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0]);
|
|
//Ldarg.Ldfld(aAssembler, aMethodInfo.TypeInfo, "System.IntPtr System.Delegate._methodPtr");
|
|
//new CPUx86.Pop("eax");
|
|
//new CPUx86.Call(CPUx86.Registers.EAX);
|
|
//new CPUx86.Add("esp",
|
|
// "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.Move("esp", "ebp");
|
|
break;
|
|
}
|
|
}
|
|
base.DoCustomAssembleImplementation(aInMetalMode, aAssembler, aMethodInfo);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static void Assemble_System_Threading_Interlocked_CompareExchange__Object(Assembler.Assembler aAssembler, MethodInformation aMethodInfo)
|
|
{
|
|
//arguments:
|
|
// 0: location
|
|
// 1: value
|
|
// 2: comparand
|
|
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[2]);
|
|
new CPUx86.Pop(CPUx86.Registers.EAX);
|
|
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[1]);
|
|
new CPUx86.Pop(CPUx86.Registers.EDX);
|
|
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0]);
|
|
new CPUx86.Pop(CPUx86.Registers.ECX);
|
|
new CPUx86.Pushd(CPUx86.Registers.AtECX);
|
|
new CPUx86.Pop(CPUx86.Registers.ECX);
|
|
new CPUx86.CmpXchg(CPUx86.Registers.ECX, CPUx86.Registers.EDX);
|
|
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0]);
|
|
new CPUx86.Pop(CPUx86.Registers.EAX);
|
|
new CPUx86.Move(CPUx86.Registers.EAX, CPUx86.Registers.ECX);
|
|
new CPUx86.Pushd(CPUx86.Registers.EAX);
|
|
}
|
|
|
|
public override void EmitOpDebugHeader(Indy.IL2CPU.Assembler.Assembler aAssembler, uint aOpId, string aOpLabel)
|
|
{
|
|
new CPUx86.Call("DebugPoint__");
|
|
}
|
|
|
|
public override void PreProcess(Indy.IL2CPU.Assembler.Assembler mAssembler)
|
|
{
|
|
base.PreProcess(mAssembler);
|
|
RegisterAllUtilityMethods(Engine.QueueMethod);
|
|
Engine.QueueMethod(EventHandlerImplRefs.CtorRef);
|
|
Engine.QueueMethod(InvokeMulticastRef);
|
|
var xGetInvocationListMethod = typeof(MulticastDelegate).GetMethod("GetInvocationList");
|
|
Engine.QueueMethod(xGetInvocationListMethod);
|
|
xGetInvocationListMethod = typeof(Delegate).GetMethod("GetInvocationList");
|
|
Engine.QueueMethod(xGetInvocationListMethod);
|
|
}
|
|
}
|
|
}
|