[Add] FishNet
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
using MonoFN.Cecil;
|
||||
using MonoFN.Cecil.Cil;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FishNet.CodeGenerating.Helping.Extension
|
||||
{
|
||||
internal static class ILProcessorExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a debug log for text without any conditions.
|
||||
/// </summary>
|
||||
public static List<Instruction> DebugLog(this ILProcessor processor, CodegenSession session, string txt)
|
||||
{
|
||||
List<Instruction> insts = new();
|
||||
insts.Add(processor.Create(OpCodes.Ldstr, txt));
|
||||
insts.Add(processor.Create(OpCodes.Call, session.GetClass<GeneralHelper>().Debug_LogCommon_MethodRef));
|
||||
return insts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a debug log for vd without any conditions.
|
||||
/// </summary>
|
||||
public static List<Instruction> DebugLog(this ILProcessor processor, CodegenSession session, VariableDefinition vd)
|
||||
{
|
||||
List<Instruction> insts = new();
|
||||
insts.Add(processor.Create(OpCodes.Ldloc, vd));
|
||||
insts.Add(processor.Create(OpCodes.Box, vd.VariableType));
|
||||
insts.Add(processor.Create(OpCodes.Call, session.GetClass<GeneralHelper>().Debug_LogCommon_MethodRef));
|
||||
return insts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a debug log for vd without any conditions.
|
||||
/// </summary>
|
||||
public static List<Instruction> DebugLog(this ILProcessor processor, CodegenSession session, FieldDefinition fd, bool loadArg0)
|
||||
{
|
||||
List<Instruction> insts = new();
|
||||
if (loadArg0)
|
||||
insts.Add(processor.Create(OpCodes.Ldarg_0));
|
||||
insts.Add(processor.Create(OpCodes.Ldfld, fd));
|
||||
insts.Add(processor.Create(OpCodes.Box, fd.FieldType));
|
||||
insts.Add(processor.Create(OpCodes.Call, session.GetClass<GeneralHelper>().Debug_LogCommon_MethodRef));
|
||||
return insts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a debug log for pd without any conditions.
|
||||
/// </summary>
|
||||
public static List<Instruction> DebugLog(this ILProcessor processor, CodegenSession session, ParameterDefinition pd)
|
||||
{
|
||||
List<Instruction> insts = new();
|
||||
insts.Add(processor.Create(OpCodes.Ldloc, pd));
|
||||
insts.Add(processor.Create(OpCodes.Box, pd.ParameterType));
|
||||
insts.Add(processor.Create(OpCodes.Call, session.GetClass<GeneralHelper>().Debug_LogCommon_MethodRef));
|
||||
return insts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes Ret if the last instruction.
|
||||
/// </summary>
|
||||
/// <returns>True if ret was removed.</returns>
|
||||
public static bool RemoveEndRet(this ILProcessor processor)
|
||||
{
|
||||
int instCount = processor.Body.Instructions.Count;
|
||||
if (instCount == 0)
|
||||
return false;
|
||||
|
||||
if (processor.Body.Instructions[instCount - 1].OpCode == OpCodes.Ret)
|
||||
{
|
||||
processor.Body.Instructions.RemoveAt(instCount - 1);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// Creates a debug log for mr without any conditions.
|
||||
///// </summary>
|
||||
// public static void DebugLog(this ILProcessor processor, MethodReference mr)
|
||||
// {
|
||||
// processor.Emit(OpCodes.Call, mr);
|
||||
// processor.Emit(OpCodes.Box, mr.ReturnType);
|
||||
// processor.Emit(OpCodes.Call, base.GetClass<GeneralHelper>().Debug_LogCommon_MethodRef);
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Inserts instructions at the beginning.
|
||||
/// </summary>
|
||||
/// <param name = "processor"></param>
|
||||
/// <param name = "instructions"></param>
|
||||
public static void InsertAt(this ILProcessor processor, int target, List<Instruction> instructions)
|
||||
{
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
processor.Body.Instructions.Insert(i + target, instructions[i]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts instructions at the beginning.
|
||||
/// </summary>
|
||||
/// <param name = "processor"></param>
|
||||
/// <param name = "instructions"></param>
|
||||
public static void InsertFirst(this ILProcessor processor, List<Instruction> instructions)
|
||||
{
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
processor.Body.Instructions.Insert(i, instructions[i]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts instructions at the end while also moving Ret down.
|
||||
/// </summary>
|
||||
/// <param name = "processor"></param>
|
||||
/// <param name = "instructions"></param>
|
||||
public static void InsertLast(this ILProcessor processor, List<Instruction> instructions)
|
||||
{
|
||||
bool retRemoved = false;
|
||||
int startingCount = processor.Body.Instructions.Count;
|
||||
// Remove ret if it exist and add it back in later.
|
||||
if (startingCount > 0)
|
||||
{
|
||||
if (processor.Body.Instructions[startingCount - 1].OpCode == OpCodes.Ret)
|
||||
{
|
||||
processor.Body.Instructions.RemoveAt(startingCount - 1);
|
||||
retRemoved = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Instruction inst in instructions)
|
||||
processor.Append(inst);
|
||||
|
||||
// Add ret back if it was removed.
|
||||
if (retRemoved)
|
||||
processor.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts instructions before target.
|
||||
/// </summary>
|
||||
/// <param name = "processor"></param>
|
||||
/// <param name = "instructions"></param>
|
||||
public static void InsertBefore(this ILProcessor processor, Instruction target, List<Instruction> instructions)
|
||||
{
|
||||
int index = processor.Body.Instructions.IndexOf(target);
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
processor.Body.Instructions.Insert(index + i, instructions[i]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds instructions to the end of processor.
|
||||
/// </summary>
|
||||
/// <param name = "processor"></param>
|
||||
/// <param name = "instructions"></param>
|
||||
public static void Add(this ILProcessor processor, List<Instruction> instructions)
|
||||
{
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
processor.Body.Instructions.Add(instructions[i]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts instructions before returns. Only works on void types.
|
||||
/// </summary>
|
||||
/// <param name = "processor"></param>
|
||||
/// <param name = "instructions"></param>
|
||||
public static void InsertBeforeReturns(this ILProcessor processor, CodegenSession session, List<Instruction> instructions)
|
||||
{
|
||||
if (processor.Body.Method.ReturnType.FullName != session.Module.TypeSystem.Void.FullName)
|
||||
{
|
||||
session.LogError($"Cannot insert instructions before returns on {processor.Body.Method.FullName} because it does not return void.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Insert at the end of the method
|
||||
* and get the first instruction that was inserted.
|
||||
* Any returns or breaks which would exit the method
|
||||
* will jump to this instruction instead. */
|
||||
processor.InsertLast(instructions);
|
||||
Instruction startInst = processor.Body.Instructions[processor.Body.Instructions.Count - instructions.Count];
|
||||
|
||||
// Look for anything that jumps to rets.
|
||||
for (int i = 0; i < processor.Body.Instructions.Count; i++)
|
||||
{
|
||||
Instruction inst = processor.Body.Instructions[i];
|
||||
if (inst.Operand is Instruction operInst)
|
||||
{
|
||||
if (operInst.OpCode == OpCodes.Ret)
|
||||
inst.Operand = startInst;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user