Files
SPT-Server-Build/Libraries/SPTarkov.Reflection/CodeWrapper/CodeGenerator.cs
T
2025-07-28 19:39:29 +00:00

95 lines
2.7 KiB
C#

using System.Reflection.Emit;
using HarmonyLib;
namespace SPTarkov.Reflection.CodeWrapper;
/// <summary>
/// Helper class to generate IL code for transpilers
/// </summary>
public class CodeGenerator
{
public static List<CodeInstruction> GenerateInstructions(List<Code> codes)
{
var list = new List<CodeInstruction>();
foreach (Code code in codes)
{
list.Add(ParseCode(code));
}
return list;
}
private static CodeInstruction ParseCode(Code code)
{
if (!code.HasOperand)
{
return new CodeInstruction(code.OpCode) { labels = GetLabelList(code) };
}
if (code.OpCode == OpCodes.Ldfld || code.OpCode == OpCodes.Ldflda || code.OpCode == OpCodes.Stfld)
{
return new CodeInstruction(code.OpCode, AccessTools.Field(code.CallerType, code.OperandTarget as string))
{
labels = GetLabelList(code),
};
}
if (code.OpCode == OpCodes.Call || code.OpCode == OpCodes.Callvirt)
{
return new CodeInstruction(code.OpCode, AccessTools.Method(code.CallerType, code.OperandTarget as string, code.Parameters))
{
labels = GetLabelList(code),
};
}
if (code.OpCode == OpCodes.Box)
{
return new CodeInstruction(code.OpCode, code.CallerType) { labels = GetLabelList(code) };
}
if (
code.OpCode == OpCodes.Br
|| code.OpCode == OpCodes.Brfalse
|| code.OpCode == OpCodes.Brtrue
|| code.OpCode == OpCodes.Brtrue_S
|| code.OpCode == OpCodes.Brfalse_S
|| code.OpCode == OpCodes.Br_S
)
{
return new CodeInstruction(code.OpCode, code.OperandTarget) { labels = GetLabelList(code) };
}
if (code.OpCode == OpCodes.Ldftn)
{
return new CodeInstruction(code.OpCode, AccessTools.Method(code.CallerType, code.OperandTarget as string, code.Parameters))
{
labels = GetLabelList(code),
};
}
if (code.OpCode == OpCodes.Newobj)
{
return new CodeInstruction(
code.OpCode,
code.CallerType.GetConstructors().FirstOrDefault(x => x.GetParameters().Length == code.Parameters.Length)
)
{
labels = GetLabelList(code),
};
}
throw new ArgumentException($"Code with OpCode {code.OpCode.ToString()} is not supported.");
}
private static List<Label> GetLabelList(Code code)
{
if (code.GetLabel() == null)
{
return [];
}
return [(Label)code.GetLabel()];
}
}