ReflectedMethodInfo allows non-public type names.
MsilInstructionExtensions to make life easier
This commit is contained in:
@@ -12,6 +12,6 @@
|
||||
<rules>
|
||||
<logger name="*" minlevel="Info" writeTo="main, console" />
|
||||
<logger name="Chat" minlevel="Info" writeTo="chat" />
|
||||
<logger name="Torch.Managers.PatchManager.*" minlevel="Trace" writeTo="patch"/>
|
||||
<!--<logger name="Torch.Managers.PatchManager.*" minlevel="Trace" writeTo="patch"/>-->
|
||||
</rules>
|
||||
</nlog>
|
@@ -7,6 +7,7 @@ using System.Reflection.Emit;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using NLog;
|
||||
using Torch.Managers.PatchManager.MSIL;
|
||||
using Torch.Managers.PatchManager.Transpile;
|
||||
using Torch.Utils;
|
||||
|
||||
@@ -147,7 +148,7 @@ namespace Torch.Managers.PatchManager
|
||||
target.EmitComment("Prefixes End");
|
||||
|
||||
target.EmitComment("Original Begin");
|
||||
MethodTranspiler.Transpile(_method, Transpilers, target, labelAfterOriginalContent);
|
||||
MethodTranspiler.Transpile(_method, (type) => new MsilLocal(target.DeclareLocal(type)), Transpilers, target, labelAfterOriginalContent);
|
||||
target.EmitComment("Original End");
|
||||
|
||||
target.MarkLabel(labelAfterOriginalContent);
|
||||
|
49
Torch/Managers/PatchManager/MSIL/MsilArgument.cs
Normal file
49
Torch/Managers/PatchManager/MSIL/MsilArgument.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Torch.Managers.PatchManager.MSIL
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents metadata about a method's parameter
|
||||
/// </summary>
|
||||
public class MsilArgument
|
||||
{
|
||||
/// <summary>
|
||||
/// The positon of this argument. Note, if the method is static, index 0 is the instance.
|
||||
/// </summary>
|
||||
public int Position { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of this parameter, or null if unknown.
|
||||
/// </summary>
|
||||
public Type Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of this parameter, or null if unknown.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
internal MsilArgument(ParameterInfo local)
|
||||
{
|
||||
Position = (((MethodBase)local.Member).IsStatic ? 0 : 1) + local.Position;
|
||||
Type = local.ParameterType;
|
||||
Name = local.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an empty argument reference with the given position.
|
||||
/// </summary>
|
||||
/// <param name="position">The argument's position</param>
|
||||
public MsilArgument(int position)
|
||||
{
|
||||
Position = position;
|
||||
Type = null;
|
||||
Name = null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -67,7 +67,7 @@ namespace Torch.Managers.PatchManager.MSIL
|
||||
if (OpCode.Name.IndexOf("loc", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
Operand = new MsilOperandInline.MsilOperandLocal(this);
|
||||
else
|
||||
Operand = new MsilOperandInline.MsilOperandParameter(this);
|
||||
Operand = new MsilOperandInline.MsilOperandArgument(this);
|
||||
break;
|
||||
case OperandType.ShortInlineI:
|
||||
Operand = OpCode == OpCodes.Ldc_I4_S
|
||||
@@ -193,66 +193,6 @@ namespace Torch.Managers.PatchManager.MSIL
|
||||
private static Func<OpCode, int> _stackChange;
|
||||
#pragma warning restore 169
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets an instruction that represents the inverse of this load or store instruction.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <example>
|
||||
/// new MsilInstruction(OpCodes.Ldloc_0).StoreLoadInverse().OpCode == OpCodes.Stloc_0
|
||||
/// </example>
|
||||
/// </remarks>
|
||||
/// <returns>Inverse</returns>
|
||||
public MsilInstruction StoreLoadInverse()
|
||||
{
|
||||
if (OpCode == OpCodes.Ldloc)
|
||||
return new MsilInstruction(OpCodes.Stloc).InlineValue(
|
||||
((MsilOperandInline<LocalVariableInfo>)Operand).Value);
|
||||
if (OpCode == OpCodes.Ldloc_S)
|
||||
return new MsilInstruction(OpCodes.Stloc_S).InlineValue(
|
||||
((MsilOperandInline<LocalVariableInfo>)Operand).Value);
|
||||
if (OpCode == OpCodes.Ldloc_0)
|
||||
return new MsilInstruction(OpCodes.Stloc_0);
|
||||
if (OpCode == OpCodes.Ldloc_1)
|
||||
return new MsilInstruction(OpCodes.Stloc_1);
|
||||
if (OpCode == OpCodes.Ldloc_2)
|
||||
return new MsilInstruction(OpCodes.Stloc_2);
|
||||
if (OpCode == OpCodes.Ldloc_3)
|
||||
return new MsilInstruction(OpCodes.Stloc_3);
|
||||
|
||||
if (OpCode == OpCodes.Stloc)
|
||||
return new MsilInstruction(OpCodes.Ldloc).InlineValue(
|
||||
((MsilOperandInline<LocalVariableInfo>)Operand).Value);
|
||||
if (OpCode == OpCodes.Stloc_S)
|
||||
return new MsilInstruction(OpCodes.Ldloc_S).InlineValue(
|
||||
((MsilOperandInline<LocalVariableInfo>)Operand).Value);
|
||||
if (OpCode == OpCodes.Stloc_0)
|
||||
return new MsilInstruction(OpCodes.Ldloc_0);
|
||||
if (OpCode == OpCodes.Stloc_1)
|
||||
return new MsilInstruction(OpCodes.Ldloc_1);
|
||||
if (OpCode == OpCodes.Stloc_2)
|
||||
return new MsilInstruction(OpCodes.Ldloc_2);
|
||||
if (OpCode == OpCodes.Stloc_3)
|
||||
return new MsilInstruction(OpCodes.Ldloc_3);
|
||||
|
||||
if (OpCode == OpCodes.Ldarg)
|
||||
return new MsilInstruction(OpCodes.Starg).InlineValue(
|
||||
((MsilOperandInline<ParameterInfo>)Operand).Value);
|
||||
if (OpCode == OpCodes.Ldarg_S)
|
||||
return new MsilInstruction(OpCodes.Starg_S).InlineValue(
|
||||
((MsilOperandInline<ParameterInfo>)Operand).Value);
|
||||
// TODO Ldarg_0 etc
|
||||
|
||||
if (OpCode == OpCodes.Starg)
|
||||
return new MsilInstruction(OpCodes.Ldarg).InlineValue(
|
||||
((MsilOperandInline<ParameterInfo>)Operand).Value);
|
||||
if (OpCode == OpCodes.Starg_S)
|
||||
return new MsilInstruction(OpCodes.Ldarg_S).InlineValue(
|
||||
((MsilOperandInline<ParameterInfo>)Operand).Value);
|
||||
|
||||
throw new ArgumentException($"Can't invert the instruction {this}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Estimates the stack delta for this instruction.
|
||||
/// </summary>
|
||||
|
202
Torch/Managers/PatchManager/MSIL/MsilInstructionExtensions.cs
Normal file
202
Torch/Managers/PatchManager/MSIL/MsilInstructionExtensions.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Torch.Managers.PatchManager.MSIL
|
||||
{
|
||||
/// <summary>
|
||||
/// Various methods to make composing MSIL easier
|
||||
/// </summary>
|
||||
public static class MsilInstructionExtensions
|
||||
{
|
||||
#region Local Utils
|
||||
/// <summary>
|
||||
/// Is this instruction a local load-by-value instruction.
|
||||
/// </summary>
|
||||
public static bool IsLocalLoad(this MsilInstruction me)
|
||||
{
|
||||
return me.OpCode == OpCodes.Ldloc || me.OpCode == OpCodes.Ldloc_S || me.OpCode == OpCodes.Ldloc_0 ||
|
||||
me.OpCode == OpCodes.Ldloc_1 || me.OpCode == OpCodes.Ldloc_2 || me.OpCode == OpCodes.Ldloc_3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is this instruction a local load-by-reference instruction.
|
||||
/// </summary>
|
||||
public static bool IsLocalLoadByRef(this MsilInstruction me)
|
||||
{
|
||||
return me.OpCode == OpCodes.Ldloca || me.OpCode == OpCodes.Ldloca_S;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is this instruction a local store instruction.
|
||||
/// </summary>
|
||||
public static bool IsLocalStore(this MsilInstruction me)
|
||||
{
|
||||
return me.OpCode == OpCodes.Stloc || me.OpCode == OpCodes.Stloc_S || me.OpCode == OpCodes.Stloc_0 ||
|
||||
me.OpCode == OpCodes.Stloc_1 || me.OpCode == OpCodes.Stloc_2 || me.OpCode == OpCodes.Stloc_3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For a local referencing opcode, get the local it is referencing.
|
||||
/// </summary>
|
||||
public static MsilLocal GetReferencedLocal(this MsilInstruction me)
|
||||
{
|
||||
if (me.Operand is MsilOperandInline.MsilOperandLocal mol)
|
||||
return mol.Value;
|
||||
if (me.OpCode == OpCodes.Stloc_0 || me.OpCode == OpCodes.Ldloc_0)
|
||||
return new MsilLocal(0);
|
||||
if (me.OpCode == OpCodes.Stloc_1 || me.OpCode == OpCodes.Ldloc_1)
|
||||
return new MsilLocal(1);
|
||||
if (me.OpCode == OpCodes.Stloc_2 || me.OpCode == OpCodes.Ldloc_2)
|
||||
return new MsilLocal(2);
|
||||
if (me.OpCode == OpCodes.Stloc_3 || me.OpCode == OpCodes.Ldloc_3)
|
||||
return new MsilLocal(3);
|
||||
throw new ArgumentException($"Can't get referenced local in instruction {me}");
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets an instruction representing a load-by-value from the given local.
|
||||
/// </summary>
|
||||
/// <param name="local">Local to load</param>
|
||||
/// <returns>Loading instruction</returns>
|
||||
public static MsilInstruction AsValueLoad(this MsilLocal local)
|
||||
{
|
||||
switch (local.Index)
|
||||
{
|
||||
case 0:
|
||||
return new MsilInstruction(OpCodes.Ldloc_0);
|
||||
case 1:
|
||||
return new MsilInstruction(OpCodes.Ldloc_1);
|
||||
case 2:
|
||||
return new MsilInstruction(OpCodes.Ldloc_2);
|
||||
case 3:
|
||||
return new MsilInstruction(OpCodes.Ldloc_3);
|
||||
default:
|
||||
return new MsilInstruction(local.Index < 0xFF ? OpCodes.Ldloc_S : OpCodes.Ldloc).InlineValue(local);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an instruction representing a store-by-value to the given local.
|
||||
/// </summary>
|
||||
/// <param name="local">Local to write to</param>
|
||||
/// <returns>Loading instruction</returns>
|
||||
public static MsilInstruction AsValueStore(this MsilLocal local)
|
||||
{
|
||||
switch (local.Index)
|
||||
{
|
||||
case 0:
|
||||
return new MsilInstruction(OpCodes.Stloc_0);
|
||||
case 1:
|
||||
return new MsilInstruction(OpCodes.Stloc_1);
|
||||
case 2:
|
||||
return new MsilInstruction(OpCodes.Stloc_2);
|
||||
case 3:
|
||||
return new MsilInstruction(OpCodes.Stloc_3);
|
||||
default:
|
||||
return new MsilInstruction(local.Index < 0xFF ? OpCodes.Stloc_S : OpCodes.Stloc).InlineValue(local);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an instruction representing a load-by-reference from the given local.
|
||||
/// </summary>
|
||||
/// <param name="local">Local to load</param>
|
||||
/// <returns>Loading instruction</returns>
|
||||
public static MsilInstruction AsReferenceLoad(this MsilLocal local)
|
||||
{
|
||||
return new MsilInstruction(local.Index < 0xFF ? OpCodes.Ldloca_S : OpCodes.Ldloca).InlineValue(local);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Argument Utils
|
||||
/// <summary>
|
||||
/// Is this instruction an argument load-by-value instruction.
|
||||
/// </summary>
|
||||
public static bool IsArgumentLoad(this MsilInstruction me)
|
||||
{
|
||||
return me.OpCode == OpCodes.Ldarg || me.OpCode == OpCodes.Ldarg_S || me.OpCode == OpCodes.Ldarg_0 ||
|
||||
me.OpCode == OpCodes.Ldarg_1 || me.OpCode == OpCodes.Ldarg_2 || me.OpCode == OpCodes.Ldarg_3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is this instruction an argument load-by-reference instruction.
|
||||
/// </summary>
|
||||
public static bool IsArgumentLoadByRef(this MsilInstruction me)
|
||||
{
|
||||
return me.OpCode == OpCodes.Ldarga || me.OpCode == OpCodes.Ldarga_S;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is this instruction an argument store instruction.
|
||||
/// </summary>
|
||||
public static bool IsArgumentStore(this MsilInstruction me)
|
||||
{
|
||||
return me.OpCode == OpCodes.Starg || me.OpCode == OpCodes.Starg_S;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For an argument referencing opcode, get the index of the local it is referencing.
|
||||
/// </summary>
|
||||
public static MsilArgument GetReferencedArgument(this MsilInstruction me)
|
||||
{
|
||||
if (me.Operand is MsilOperandInline.MsilOperandArgument mol)
|
||||
return mol.Value;
|
||||
if (me.OpCode == OpCodes.Ldarg_0)
|
||||
return new MsilArgument(0);
|
||||
if (me.OpCode == OpCodes.Ldarg_1)
|
||||
return new MsilArgument(1);
|
||||
if (me.OpCode == OpCodes.Ldarg_2)
|
||||
return new MsilArgument(2);
|
||||
if (me.OpCode == OpCodes.Ldarg_3)
|
||||
return new MsilArgument(3);
|
||||
throw new ArgumentException($"Can't get referenced argument in instruction {me}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an instruction representing a load-by-value from the given argument.
|
||||
/// </summary>
|
||||
/// <param name="argument">argument to load</param>
|
||||
/// <returns>Load instruction</returns>
|
||||
public static MsilInstruction AsValueLoad(this MsilArgument argument)
|
||||
{
|
||||
switch (argument.Position)
|
||||
{
|
||||
case 0:
|
||||
return new MsilInstruction(OpCodes.Ldarg_0);
|
||||
case 1:
|
||||
return new MsilInstruction(OpCodes.Ldarg_1);
|
||||
case 2:
|
||||
return new MsilInstruction(OpCodes.Ldarg_2);
|
||||
case 3:
|
||||
return new MsilInstruction(OpCodes.Ldarg_3);
|
||||
default:
|
||||
return new MsilInstruction(argument.Position < 0xFF ? OpCodes.Ldarg_S : OpCodes.Ldarg).InlineValue(argument);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an instruction representing a store-by-value to the given argument.
|
||||
/// </summary>
|
||||
/// <param name="argument">argument to write to</param>
|
||||
/// <returns>Store instruction</returns>
|
||||
public static MsilInstruction AsValueStore(this MsilArgument argument)
|
||||
{
|
||||
return new MsilInstruction(argument.Position < 0xFF ? OpCodes.Starg_S : OpCodes.Starg).InlineValue(argument);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an instruction representing a load-by-reference from the given argument.
|
||||
/// </summary>
|
||||
/// <param name="argument">argument to load</param>
|
||||
/// <returns>Reference load instruction</returns>
|
||||
public static MsilInstruction AsReferenceLoad(this MsilArgument argument)
|
||||
{
|
||||
return new MsilInstruction(argument.Position < 0xFF ? OpCodes.Ldarga_S : OpCodes.Ldarga).InlineValue(argument);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
56
Torch/Managers/PatchManager/MSIL/MsilLocal.cs
Normal file
56
Torch/Managers/PatchManager/MSIL/MsilLocal.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Torch.Managers.PatchManager.MSIL
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents metadata about a method's local
|
||||
/// </summary>
|
||||
public class MsilLocal
|
||||
{
|
||||
/// <summary>
|
||||
/// The index of this local.
|
||||
/// </summary>
|
||||
public int Index { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of this local, or null if unknown.
|
||||
/// </summary>
|
||||
public Type Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of this local, or null if unknown.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
internal MsilLocal(LocalBuilder local)
|
||||
{
|
||||
Index = local.LocalIndex;
|
||||
Type = local.LocalType;
|
||||
Name = null;
|
||||
}
|
||||
|
||||
internal MsilLocal(LocalVariableInfo local)
|
||||
{
|
||||
Index = local.LocalIndex;
|
||||
Type = local.LocalType;
|
||||
Name = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an empty local reference with the given index.
|
||||
/// </summary>
|
||||
/// <param name="index">The local's index</param>
|
||||
public MsilLocal(int index)
|
||||
{
|
||||
Index = index;
|
||||
Type = null;
|
||||
Name = null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -209,11 +209,11 @@ namespace Torch.Managers.PatchManager.MSIL
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inline parameter reference
|
||||
/// Inline argument reference
|
||||
/// </summary>
|
||||
public class MsilOperandParameter : MsilOperandInline<ParameterInfo>
|
||||
public class MsilOperandArgument : MsilOperandInline<MsilArgument>
|
||||
{
|
||||
internal MsilOperandParameter(MsilInstruction instruction) : base(instruction)
|
||||
internal MsilOperandArgument(MsilInstruction instruction) : base(instruction)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -225,20 +225,19 @@ namespace Torch.Managers.PatchManager.MSIL
|
||||
: reader.ReadUInt16();
|
||||
if (paramID == 0 && !context.Method.IsStatic)
|
||||
throw new ArgumentException("Haven't figured out how to ldarg with the \"this\" argument");
|
||||
Value = context.Method.GetParameters()[paramID - (context.Method.IsStatic ? 0 : 1)];
|
||||
Value = new MsilArgument(context.Method.GetParameters()[paramID - (context.Method.IsStatic ? 0 : 1)]);
|
||||
}
|
||||
|
||||
internal override void Emit(LoggingIlGenerator generator)
|
||||
{
|
||||
var methodInfo = Value.Member as MethodBase;
|
||||
generator.Emit(Instruction.OpCode, Value.Position + (methodInfo != null && methodInfo.IsStatic ? 0 : 1));
|
||||
generator.Emit(Instruction.OpCode, Value.Position);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inline local variable reference
|
||||
/// </summary>
|
||||
public class MsilOperandLocal : MsilOperandInline<LocalVariableInfo>
|
||||
public class MsilOperandLocal : MsilOperandInline<MsilLocal>
|
||||
{
|
||||
internal MsilOperandLocal(MsilInstruction instruction) : base(instruction)
|
||||
{
|
||||
@@ -247,15 +246,15 @@ namespace Torch.Managers.PatchManager.MSIL
|
||||
internal override void Read(MethodContext context, BinaryReader reader)
|
||||
{
|
||||
Value =
|
||||
context.Method.GetMethodBody().LocalVariables[
|
||||
new MsilLocal(context.Method.GetMethodBody().LocalVariables[
|
||||
Instruction.OpCode.OperandType == OperandType.ShortInlineVar
|
||||
? reader.ReadByte()
|
||||
: reader.ReadUInt16()];
|
||||
: reader.ReadUInt16()]);
|
||||
}
|
||||
|
||||
internal override void Emit(LoggingIlGenerator generator)
|
||||
{
|
||||
generator.Emit(Instruction.OpCode, Value.LocalIndex);
|
||||
generator.Emit(Instruction.OpCode, Value.Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -11,7 +11,7 @@ namespace Torch.Managers.PatchManager.Transpile
|
||||
{
|
||||
public static readonly Logger _log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
internal static void Transpile(MethodBase baseMethod, IEnumerable<MethodInfo> transpilers, LoggingIlGenerator output, Label? retLabel)
|
||||
internal static void Transpile(MethodBase baseMethod, Func<Type, MsilLocal> localCreator, IEnumerable<MethodInfo> transpilers, LoggingIlGenerator output, Label? retLabel)
|
||||
{
|
||||
var context = new MethodContext(baseMethod);
|
||||
context.Read();
|
||||
@@ -20,8 +20,23 @@ namespace Torch.Managers.PatchManager.Transpile
|
||||
// _log.Trace(context.ToHumanMsil);
|
||||
|
||||
var methodContent = (IEnumerable<MsilInstruction>)context.Instructions;
|
||||
foreach (var transpiler in transpilers)
|
||||
methodContent = (IEnumerable<MsilInstruction>)transpiler.Invoke(null, new object[] { methodContent });
|
||||
foreach (MethodInfo transpiler in transpilers)
|
||||
{
|
||||
var paramList = new List<object>();
|
||||
foreach (var parameter in transpiler.GetParameters())
|
||||
{
|
||||
if (parameter.Name.Equals("__methodBody"))
|
||||
paramList.Add(baseMethod.GetMethodBody());
|
||||
else if (parameter.Name.Equals("__localCreator"))
|
||||
paramList.Add(localCreator);
|
||||
else if (parameter.ParameterType == typeof(IEnumerable<MsilInstruction>))
|
||||
paramList.Add(methodContent);
|
||||
else
|
||||
throw new ArgumentException(
|
||||
$"Bad transpiler parameter type {parameter.ParameterType.FullName} {parameter.Name}");
|
||||
}
|
||||
methodContent = (IEnumerable<MsilInstruction>)transpiler.Invoke(null, paramList.ToArray());
|
||||
}
|
||||
methodContent = FixBranchAndReturn(methodContent, retLabel);
|
||||
foreach (var k in methodContent)
|
||||
k.Emit(output);
|
||||
|
@@ -165,7 +165,10 @@
|
||||
<Compile Include="Managers\PatchManager\EmitExtensions.cs" />
|
||||
<Compile Include="Managers\PatchManager\MSIL\ITokenResolver.cs" />
|
||||
<Compile Include="Managers\PatchManager\MSIL\MsilInstruction.cs" />
|
||||
<Compile Include="Managers\PatchManager\MSIL\MsilInstructionExtensions.cs" />
|
||||
<Compile Include="Managers\PatchManager\MSIL\MsilLabel.cs" />
|
||||
<Compile Include="Managers\PatchManager\MSIL\MsilArgument.cs" />
|
||||
<Compile Include="Managers\PatchManager\MSIL\MsilLocal.cs" />
|
||||
<Compile Include="Managers\PatchManager\MSIL\MsilOperand.cs" />
|
||||
<Compile Include="Managers\PatchManager\MSIL\MsilOperandBrTarget.cs" />
|
||||
<Compile Include="Managers\PatchManager\MSIL\MsilOperandInline.cs" />
|
||||
|
@@ -74,6 +74,16 @@ namespace Torch.Utils
|
||||
/// Expected parameters of this method, or null if any parameters are accepted.
|
||||
/// </summary>
|
||||
public Type[] Parameters { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Assembly qualified names of <see cref="Parameters"/>
|
||||
/// </summary>
|
||||
public string[] ParameterNames
|
||||
{
|
||||
get => Parameters.Select(x => x.AssemblyQualifiedName).ToArray();
|
||||
set => Parameters = value?.Select(x => x == null ? null : Type.GetType(x)).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expected return type of this method, or null if any return type is accepted.
|
||||
/// </summary>
|
||||
|
Reference in New Issue
Block a user