Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ILUtils v1.0.5
plugins/ILUtils.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using ILUtils.HarmonyXtensions; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("DBJ")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("BepInEx Transpiler Tools")] [assembly: AssemblyFileVersion("1.0.5.0")] [assembly: AssemblyInformationalVersion("1.0.5+b9c52bafc41047e18d94bbefe22084e94b3c02dd")] [assembly: AssemblyProduct("ILUtils")] [assembly: AssemblyTitle("com.github.decibillyjoel.ILUtils")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/DecibillyJoel/ILUtils")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.5.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } internal static class LCMProjectInfo { public const string PROJECT_GUID = "com.github.decibillyjoel.ILUtils"; public const string PROJECT_NAME = "ILUtils"; public const string PROJECT_VERSION = "1.0.5"; } namespace ILUtils2.Plugin { [BepInPlugin("com.github.decibillyjoel.ILUtils", "ILUtils", "1.0.5")] public class Plugin : BaseUnityPlugin { public static readonly string PLUGIN_GUID = "com.github.decibillyjoel.ILUtils"; public static readonly string PLUGIN_NAME = "ILUtils"; public static readonly string PLUGIN_VERSION = "1.0.5"; public static Plugin Instance { get; private set; } = null; public static void Log(LogLevel level, object data) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) ((BaseUnityPlugin)Instance).Logger.Log(level, data); } public static void LogFatal(object data) { ((BaseUnityPlugin)Instance).Logger.LogFatal(data); } public static void LogError(object data) { ((BaseUnityPlugin)Instance).Logger.LogError(data); } public static void LogWarning(object data) { ((BaseUnityPlugin)Instance).Logger.LogWarning(data); } public static void LogMessage(object data) { ((BaseUnityPlugin)Instance).Logger.LogMessage(data); } public static void LogInfo(object data) { ((BaseUnityPlugin)Instance).Logger.LogInfo(data); } public static void LogDebug(object data) { ((BaseUnityPlugin)Instance).Logger.LogDebug(data); } private void Awake() { Instance = this; LogInfo("Plugin " + PLUGIN_NAME + " is loaded!"); } } } namespace ILUtils { public static class ILPatterns { public static int? StackSizeDelta(StackBehaviour stackBehaviour) { switch (stackBehaviour) { case StackBehaviour.Pop0: return 0; case StackBehaviour.Pop1: return -1; case StackBehaviour.Pop1_pop1: return -2; case StackBehaviour.Popi: return -1; case StackBehaviour.Popi_pop1: return -2; case StackBehaviour.Popi_popi: return -2; case StackBehaviour.Popi_popi8: return -2; case StackBehaviour.Popi_popi_popi: return -3; case StackBehaviour.Popi_popr4: return -2; case StackBehaviour.Popi_popr8: return -2; case StackBehaviour.Popref: return -1; case StackBehaviour.Popref_pop1: return -2; case StackBehaviour.Popref_popi: return -2; case StackBehaviour.Popref_popi_popi: return -3; case StackBehaviour.Popref_popi_popi8: return -3; case StackBehaviour.Popref_popi_popr4: return -3; case StackBehaviour.Popref_popi_popr8: return -3; case StackBehaviour.Popref_popi_popref: return -3; case StackBehaviour.Push0: return 0; case StackBehaviour.Push1: return 1; case StackBehaviour.Push1_push1: return 2; case StackBehaviour.Pushi: return 1; case StackBehaviour.Pushi8: return 1; case StackBehaviour.Pushr4: return 1; case StackBehaviour.Pushr8: return 1; case StackBehaviour.Pushref: return 1; case StackBehaviour.Popref_popi_pop1: return -3; case StackBehaviour.Varpop: case StackBehaviour.Varpush: return null; default: throw new ArgumentOutOfRangeException(string.Format("[{0}.{1}.{2}] [{3}] is an invalid value", "ILUtils", "ILPatterns", "StackSizeDelta", stackBehaviour)); } } public static int? StackSizeDelta(OpCode opCode, object operand) { if (opCode == OpCodes.Calli) { return null; } if (opCode.FlowControl == FlowControl.Call) { MethodInfo methodInfo = operand as MethodInfo; if (methodInfo == null) { return null; } int num = -methodInfo.GetParameters().Count(); if (opCode != OpCodes.Newobj && methodInfo.CallingConvention.HasFlag(CallingConventions.HasThis) && !methodInfo.CallingConvention.HasFlag(CallingConventions.ExplicitThis)) { num--; } if (opCode == OpCodes.Newobj || methodInfo.ReturnType != typeof(void)) { num++; } return num; } int? num2 = StackSizeDelta(opCode.StackBehaviourPush); int? num3 = StackSizeDelta(opCode.StackBehaviourPop); if (!num2.HasValue || !num3.HasValue) { return null; } return num2 + num3; } public static int? StackSizeDelta(CodeInstruction code) { return StackSizeDelta(code.opcode, code.operand); } public static bool EmptiesStack(OpCode opcode) { FlowControl flowControl = opcode.FlowControl; if (flowControl == FlowControl.Branch || (uint)(flowControl - 7) <= 1u) { return true; } return false; } public static bool EmptiesStack(CodeInstruction code) { return EmptiesStack(code.opcode); } public static Func<CodeInstruction, int, bool> NextEmptyStack(int startSize = 0) { return delegate(CodeInstruction code, int index) { if (EmptiesStack(code)) { return true; } int num = StackSizeDelta(code) ?? throw new ArgumentException(string.Format("[{0}.{1}.{2}] Encountered uncountable instruction [{3}] {4}", "ILUtils", "ILPatterns", "NextEmptyStack", index, code)); return (startSize += num) == 0; }; } } public class ILStepper { public readonly List<CodeInstruction> Instructions; public int CurrentIndex; public readonly ILGenerator Generator; public readonly Dictionary<int, LocalVariableInfo> Locals; public readonly Dictionary<int, Label> Labels; public CodeInstruction CurrentInstruction => Instructions[CurrentIndex]; public OpCode CurrentOpCode => CurrentInstruction.opcode; public object? CurrentOperand => CurrentInstruction.operand; public ILStepper(IEnumerable<CodeInstruction> codes, ILGenerator generator, MethodBase original, int index = 0) { Instructions = codes.ToList(); CurrentIndex = index; Generator = generator; Locals = (from code in Instructions select code.operand as LocalVariableInfo into local where local != null select local).Distinct().ToDictionary((LocalVariableInfo local) => local.LocalIndex, (LocalVariableInfo local) => local); Labels = Instructions.SelectMany((CodeInstruction code) => code.labels).Distinct().ToDictionary((Label label) => label.GetHashCode(), (Label label) => label); CollectionExtensions.DoIf<LocalVariableInfo>((IEnumerable<LocalVariableInfo>)original.GetMethodBody().LocalVariables, (Func<LocalVariableInfo, bool>)((LocalVariableInfo local) => !Locals.ContainsKey(local.LocalIndex)), (Action<LocalVariableInfo>)delegate(LocalVariableInfo local) { Locals.Add(local.LocalIndex, local); }); Instructions.ForEach(delegate(CodeInstruction code) { TrySetLocal(code, code); }); } public Label DeclareLabel() { Label label = Generator.DefineLabel(); Labels.Add(label.GetHashCode(), label); return label; } public LocalVariableInfo DeclareLocal(Type type, bool pinned = false) { LocalVariableInfo localVariableInfo = Generator.DeclareLocal(type, pinned); Locals.Add(localVariableInfo.LocalIndex, localVariableInfo); return localVariableInfo; } public LocalVariableInfo? TryGetLocal(int localIndex) { if (!Locals.TryGetValue(localIndex, out LocalVariableInfo value)) { return null; } return value; } public LocalVariableInfo? TryGetLocal(CodeInstruction codeWithLocal) { if (!CodeInstructionExtensions.IsLdloc(codeWithLocal, (LocalBuilder)null) && !CodeInstructionExtensions.IsStloc(codeWithLocal, (LocalBuilder)null)) { return null; } return TryGetLocal(codeWithLocal.LocalIndex()); } public LocalVariableInfo GetLocal(int localIndex, string errorMessage = "No such local variable!") { return TryGetLocal(localIndex) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}] | {4}", "ILUtils", "ILStepper", "GetLocal", localIndex, errorMessage)); } public LocalVariableInfo GetLocal(CodeInstruction codeWithLocal, string errorMessage = "No such local variable!") { return TryGetLocal(codeWithLocal) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}] | {4}", "ILUtils", "ILStepper", "GetLocal", codeWithLocal, errorMessage)); } public LocalVariableInfo? TrySetLocal(CodeInstruction code, LocalVariableInfo local) { CodeInstruction val; if (CodeInstructionExtensions.IsLdloc(code, (LocalBuilder)null)) { val = CodeInstructionPolyfills.LoadLocal(local, code.opcode == OpCodes.Ldloca || code.opcode == OpCodes.Ldloca_S); } else { if (!CodeInstructionExtensions.IsStloc(code, (LocalBuilder)null)) { return null; } val = CodeInstructionPolyfills.StoreLocal(local); } code.opcode = val.opcode; code.operand = val.operand; return local; } public LocalVariableInfo? TrySetLocal(CodeInstruction code, int localIndex) { LocalVariableInfo localVariableInfo = TryGetLocal(localIndex); if (localVariableInfo == null) { return null; } return TrySetLocal(code, localVariableInfo); } public LocalVariableInfo? TrySetLocal(CodeInstruction code, CodeInstruction codeWithLocal) { LocalVariableInfo localVariableInfo = TryGetLocal(codeWithLocal); if (localVariableInfo == null) { return null; } return TrySetLocal(code, localVariableInfo); } public LocalVariableInfo SetLocal(CodeInstruction code, LocalVariableInfo local, string errorMessage = "Could not set local!") { return TrySetLocal(code, local) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}] | {5}", "ILUtils", "ILStepper", "SetLocal", code, local, errorMessage)); } public LocalVariableInfo SetLocal(CodeInstruction code, int localIndex, string errorMessage = "Could not set local!") { return TrySetLocal(code, localIndex) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}] | {5}", "ILUtils", "ILStepper", "SetLocal", code, localIndex, errorMessage)); } public LocalVariableInfo SetLocal(CodeInstruction code, CodeInstruction codeWithLocal, string errorMessage = "Could not set local!") { return TrySetLocal(code, codeWithLocal) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}] | {5}", "ILUtils", "ILStepper", "SetLocal", code, codeWithLocal, errorMessage)); } public int? TryFindIL(Func<CodeInstruction, int, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false) { index = (index ?? CurrentIndex) + offset + (reverse ? (-1) : 0); while (index >= 0 && index < Instructions.Count) { if (searchCondition(Instructions[index.Value], index.Value)) { return index; } index += ((!reverse) ? 1 : (-1)); } return null; } public int? TryFindIL(Func<CodeInstruction, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false) { Func<CodeInstruction, bool> searchCondition2 = searchCondition; return TryFindIL((CodeInstruction code, int index) => searchCondition2(code), index, offset, reverse); } public int FindIL(Func<CodeInstruction, int, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false, string errorMessage = "Not found!") { int valueOrDefault = index.GetValueOrDefault(); if (!index.HasValue) { valueOrDefault = CurrentIndex; index = valueOrDefault; } return TryFindIL(searchCondition, index, offset, reverse) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}, {5} ({6})] | {7}", "ILUtils", "ILStepper", "FindIL", searchCondition, index, reverse, reverse ? "reverse" : "forward", errorMessage)); } public int FindIL(Func<CodeInstruction, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false, string errorMessage = "Not found!") { int valueOrDefault = index.GetValueOrDefault(); if (!index.HasValue) { valueOrDefault = CurrentIndex; index = valueOrDefault; } return TryFindIL(searchCondition, index, offset, reverse) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}, {5} ({6})] | {7}", "ILUtils", "ILStepper", "FindIL", searchCondition, index, reverse, reverse ? "reverse" : "forward", errorMessage)); } public int? TryGotoIL(Func<CodeInstruction, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false) { index = TryFindIL(searchCondition, index, offset, reverse); CurrentIndex = index ?? CurrentIndex; return index; } public int? TryGotoIL(Func<CodeInstruction, int, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false) { index = TryFindIL(searchCondition, index, offset, reverse); CurrentIndex = index ?? CurrentIndex; return index; } public int GotoIL(Func<CodeInstruction, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false, string errorMessage = "Not found!") { int valueOrDefault = index.GetValueOrDefault(); if (!index.HasValue) { valueOrDefault = CurrentIndex; index = valueOrDefault; } return CurrentIndex = TryFindIL(searchCondition, index, offset, reverse) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}, {5} ({6})] | {7}", "ILUtils", "ILStepper", "GotoIL", searchCondition, index, reverse, reverse ? "reverse" : "forward", errorMessage)); } public int GotoIL(Func<CodeInstruction, int, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false, string errorMessage = "Not found!") { int valueOrDefault = index.GetValueOrDefault(); if (!index.HasValue) { valueOrDefault = CurrentIndex; index = valueOrDefault; } return CurrentIndex = TryFindIL(searchCondition, index, offset, reverse) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}, {5} ({6})] | {7}", "ILUtils", "ILStepper", "GotoIL", searchCondition, index, reverse, reverse ? "reverse" : "forward", errorMessage)); } public int? TryFindIndex(int? index = null, int offset = 0, int leftBoundOffset = 0, int rightBoundOffset = 1) { index = (index ?? CurrentIndex) + offset; if (index < leftBoundOffset || index > Instructions.Count - 1 + rightBoundOffset) { return null; } return index; } public int FindIndex(int? index = null, int offset = 0, int leftBoundOffset = 0, int rightBoundOffset = 1, string errorMessage = "Out of bounds!") { int valueOrDefault = index.GetValueOrDefault(); if (!index.HasValue) { valueOrDefault = CurrentIndex; index = valueOrDefault; } return TryFindIndex(index, offset, leftBoundOffset, rightBoundOffset) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3} ({4} + {5}), {6} (0 + {7}), {8} ({9} + {10})] | {11}", "ILUtils", "ILStepper", "FindIndex", index + offset, index, offset, leftBoundOffset, leftBoundOffset, Instructions.Count - 1 + rightBoundOffset, Instructions.Count - 1, rightBoundOffset, errorMessage)); } public int? TryGotoIndex(int? index = null, int offset = 0, int leftBoundOffset = 0, int rightBoundOffset = 1) { index = TryFindIndex(index, offset, leftBoundOffset, rightBoundOffset); CurrentIndex = index ?? CurrentIndex; return index; } public int GotoIndex(int? index = null, int offset = 0, int leftBoundOffset = 0, int rightBoundOffset = 1, string errorMessage = "Out of bounds!") { int valueOrDefault = index.GetValueOrDefault(); if (!index.HasValue) { valueOrDefault = CurrentIndex; index = valueOrDefault; } return CurrentIndex = TryFindIndex(index, offset, leftBoundOffset, rightBoundOffset) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3} ({4} + {5}), {6} (0 + {7}), {8} ({9} + {10})] | {11}", "ILUtils", "ILStepper", "GotoIndex", index + offset, index, offset, leftBoundOffset, leftBoundOffset, Instructions.Count - 1 + rightBoundOffset, Instructions.Count - 1, rightBoundOffset, errorMessage)); } public List<CodeInstruction>? TryInsertIL(List<CodeInstruction> codeRange, int? index = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true) { index = TryFindIndex(index); if (!index.HasValue) { return null; } codeRange = ((IEnumerable<CodeInstruction>)codeRange).Select((Func<CodeInstruction, CodeInstruction>)((CodeInstruction code) => new CodeInstruction(code))).ToList(); if (index < Instructions.Count && codeRange.Count > 0) { if (pinLabels) { CodeInstructionExtensions.MoveLabelsTo(Instructions[index.Value], codeRange[0]); } if (pinBlocks) { CodeInstructionExtensions.MoveBlocksTo(Instructions[index.Value], codeRange[0]); } } Instructions.InsertRange(index.Value, codeRange); if (shiftCurrentIndex && CurrentIndex >= index) { CurrentIndex += codeRange.Count; } return codeRange; } public List<CodeInstruction>? TryInsertIL(CodeInstruction? code, int? index = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true) { return TryInsertIL((code != null) ? new List<CodeInstruction>(1) { code } : new List<CodeInstruction>(), index, shiftCurrentIndex, pinLabels, pinBlocks); } public List<CodeInstruction> InsertIL(List<CodeInstruction> codeRange, int? index = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!") { int valueOrDefault = index.GetValueOrDefault(); if (!index.HasValue) { valueOrDefault = CurrentIndex; index = valueOrDefault; } return TryInsertIL(codeRange, index, shiftCurrentIndex, pinLabels, pinBlocks) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}, {5} ({6})] | {7}", "ILUtils", "ILStepper", "InsertIL", codeRange, index, shiftCurrentIndex, shiftCurrentIndex ? "shift current index" : "dont shift current index", errorMessage)); } public List<CodeInstruction> InsertIL(CodeInstruction? code, int? index = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!") { int valueOrDefault = index.GetValueOrDefault(); if (!index.HasValue) { valueOrDefault = CurrentIndex; index = valueOrDefault; } return TryInsertIL((code != null) ? new List<CodeInstruction>(1) { code } : new List<CodeInstruction>(), index, shiftCurrentIndex, pinLabels, pinBlocks) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}, {5} ({6})] | {7}", "ILUtils", "ILStepper", "InsertIL", code, index, shiftCurrentIndex, shiftCurrentIndex ? "shift current index" : "dont shift current index", errorMessage)); } public List<CodeInstruction>? TryRemoveIL(int? startIndex = null, int? endIndex = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true) { startIndex = TryFindIndex(startIndex); endIndex = TryFindIndex(endIndex); if (!startIndex.HasValue || !endIndex.HasValue) { return null; } if (startIndex > endIndex) { int? num = endIndex; endIndex = startIndex; startIndex = num; } if (endIndex >= Instructions.Count) { return null; } int num2 = endIndex.Value - startIndex.Value; List<CodeInstruction> range = Instructions.GetRange(startIndex.Value, num2); Instructions.RemoveRange(startIndex.Value, num2); if (startIndex < Instructions.Count) { range.ForEach(delegate(CodeInstruction code) { if (pinLabels) { CodeInstructionExtensions.MoveLabelsFrom(Instructions[startIndex.Value], code); } if (pinBlocks) { CodeInstructionExtensions.MoveBlocksFrom(Instructions[startIndex.Value], code); } }); } if (shiftCurrentIndex && CurrentIndex > startIndex) { CurrentIndex = Math.Max(startIndex.Value, CurrentIndex - num2); } return range; } public List<CodeInstruction> RemoveIL(int? startIndex = null, int? endIndex = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!") { int valueOrDefault = startIndex.GetValueOrDefault(); if (!startIndex.HasValue) { valueOrDefault = CurrentIndex; startIndex = valueOrDefault; } valueOrDefault = endIndex.GetValueOrDefault(); if (!endIndex.HasValue) { valueOrDefault = CurrentIndex; endIndex = valueOrDefault; } return TryRemoveIL(startIndex, endIndex, shiftCurrentIndex, pinLabels, pinBlocks) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}, {5} ({6})] | {7}", "ILUtils", "ILStepper", "RemoveIL", startIndex, endIndex, shiftCurrentIndex, shiftCurrentIndex ? "shift current index" : "dont shift current index", errorMessage)); } public List<CodeInstruction>? TryGetIL(int? startIndex = null, int? endIndex = null) { startIndex = TryFindIndex(startIndex); endIndex = TryFindIndex(endIndex); if (!startIndex.HasValue || !endIndex.HasValue) { return null; } if (startIndex > endIndex) { int? num = endIndex; endIndex = startIndex; startIndex = num; } if (endIndex >= Instructions.Count) { return null; } int count = endIndex.Value - startIndex.Value; return Instructions.GetRange(startIndex.Value, count); } public List<CodeInstruction> GetIL(int? startIndex = null, int? endIndex = null, string errorMessage = "Out of bounds!") { int valueOrDefault = startIndex.GetValueOrDefault(); if (!startIndex.HasValue) { valueOrDefault = CurrentIndex; startIndex = valueOrDefault; } valueOrDefault = endIndex.GetValueOrDefault(); if (!endIndex.HasValue) { valueOrDefault = CurrentIndex; endIndex = valueOrDefault; } return TryGetIL(startIndex, endIndex) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}] | {5}", "ILUtils", "ILStepper", "GetIL", startIndex, endIndex, errorMessage)); } public List<Label>? TryMoveAllLabels(List<CodeInstruction> sourceCodeRange, List<CodeInstruction> destinationCodeRange) { List<CodeInstruction> destinationCodeRange2 = destinationCodeRange; if (sourceCodeRange.Count != destinationCodeRange2.Count) { return null; } return sourceCodeRange.SelectMany(delegate(CodeInstruction sourceCode, int sourceCodeIndex) { List<Label> list = CodeInstructionExtensions.ExtractLabels(sourceCode); destinationCodeRange2[sourceCodeIndex].labels.AddRange(list); return list; }).ToList(); } public List<Label>? TryMoveAllLabels(List<CodeInstruction> sourceCodeRange, CodeInstruction destinationCode) { return TryMoveAllLabels(sourceCodeRange, Enumerable.Repeat<CodeInstruction>(destinationCode, sourceCodeRange.Count).ToList()); } public List<Label> MoveAllLabels(List<CodeInstruction> sourceCodeRange, List<CodeInstruction> destinationCodeRange, string errorMessage = "Source and destination instruction count don't match!") { return TryMoveAllLabels(sourceCodeRange, destinationCodeRange) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}] | {5}", "ILUtils", "ILStepper", "MoveAllLabels", sourceCodeRange, destinationCodeRange, errorMessage)); } public List<Label> MoveAllLabels(List<CodeInstruction> sourceCodeRange, CodeInstruction destinationCode, string errorMessage = "Source and destination instruction count don't match!") { return TryMoveAllLabels(sourceCodeRange, Enumerable.Repeat<CodeInstruction>(destinationCode, sourceCodeRange.Count).ToList()) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {{{4}, ...}}] | {5}", "ILUtils", "ILStepper", "MoveAllLabels", sourceCodeRange, destinationCode, errorMessage)); } public List<Label>? TryShiftAllLabels(int? startIndex = null, int? endIndex = null, int shiftBy = 1) { List<CodeInstruction> list = TryGetIL(startIndex, endIndex); if (list == null) { return null; } int? startIndex2 = TryFindIndex(startIndex, shiftBy); int? endIndex2 = TryFindIndex(endIndex, shiftBy); if (!startIndex2.HasValue || !endIndex2.HasValue) { return null; } List<CodeInstruction> list2 = TryGetIL(startIndex2, endIndex2); if (list2 == null) { return null; } return TryMoveAllLabels(list, list2); } public List<Label> ShiftAllLabels(int? startIndex = null, int? endIndex = null, int shiftBy = 1, string errorMessage = "Source and/or destination instructions out of bounds!") { int valueOrDefault = startIndex.GetValueOrDefault(); if (!startIndex.HasValue) { valueOrDefault = CurrentIndex; startIndex = valueOrDefault; } valueOrDefault = endIndex.GetValueOrDefault(); if (!endIndex.HasValue) { valueOrDefault = CurrentIndex; endIndex = valueOrDefault; } return TryShiftAllLabels(startIndex, endIndex) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}, {5} ({6} + {7}), {8} ({9} + {10})] | {11}", "ILUtils", "ILStepper", "ShiftAllLabels", startIndex, endIndex, startIndex + shiftBy, startIndex, shiftBy, endIndex + shiftBy, endIndex, shiftBy, errorMessage)); } public List<ExceptionBlock>? TryMoveAllBlocks(List<CodeInstruction> sourceCodeRange, List<CodeInstruction> destinationCodeRange) { List<CodeInstruction> destinationCodeRange2 = destinationCodeRange; if (sourceCodeRange.Count != destinationCodeRange2.Count) { return null; } return sourceCodeRange.SelectMany(delegate(CodeInstruction sourceCode, int sourceCodeIndex) { List<ExceptionBlock> list = CodeInstructionExtensions.ExtractBlocks(sourceCode); destinationCodeRange2[sourceCodeIndex].blocks.AddRange(list); return list; }).ToList(); } public List<ExceptionBlock>? TryMoveAllBlocks(List<CodeInstruction> sourceCodeRange, CodeInstruction destinationCode) { return TryMoveAllBlocks(sourceCodeRange, Enumerable.Repeat<CodeInstruction>(destinationCode, sourceCodeRange.Count).ToList()); } public List<ExceptionBlock> MoveAllBlocks(List<CodeInstruction> sourceCodeRange, List<CodeInstruction> destinationCodeRange, string errorMessage = "Source and destination instruction count don't match!") { return TryMoveAllBlocks(sourceCodeRange, destinationCodeRange) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}] | {5}", "ILUtils", "ILStepper", "MoveAllBlocks", sourceCodeRange, destinationCodeRange, errorMessage)); } public List<ExceptionBlock> MoveAllBlocks(List<CodeInstruction> sourceCodeRange, CodeInstruction destinationCode, string errorMessage = "Source and destination instruction count don't match!") { return TryMoveAllBlocks(sourceCodeRange, Enumerable.Repeat<CodeInstruction>(destinationCode, sourceCodeRange.Count).ToList()) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {{{4}, ...}}] | {5}", "ILUtils", "ILStepper", "MoveAllBlocks", sourceCodeRange, destinationCode, errorMessage)); } public List<ExceptionBlock>? TryShiftAllBlocks(int? startIndex = null, int? endIndex = null, int shiftBy = 1) { List<CodeInstruction> list = TryGetIL(startIndex, endIndex); if (list == null) { return null; } int? startIndex2 = TryFindIndex(startIndex, shiftBy); int? endIndex2 = TryFindIndex(endIndex, shiftBy); if (!startIndex2.HasValue || !endIndex2.HasValue) { return null; } List<CodeInstruction> list2 = TryGetIL(startIndex2, endIndex2); if (list2 == null) { return null; } return TryMoveAllBlocks(list, list2); } public List<ExceptionBlock> ShiftAllBlocks(int? startIndex = null, int? endIndex = null, int shiftBy = 1, string errorMessage = "Source and/or destination instructions out of bounds!") { int valueOrDefault = startIndex.GetValueOrDefault(); if (!startIndex.HasValue) { valueOrDefault = CurrentIndex; startIndex = valueOrDefault; } valueOrDefault = endIndex.GetValueOrDefault(); if (!endIndex.HasValue) { valueOrDefault = CurrentIndex; endIndex = valueOrDefault; } return TryShiftAllBlocks(startIndex, endIndex) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}, {5} ({6} + {7}), {8} ({9} + {10})] | {11}", "ILUtils", "ILStepper", "ShiftAllBlocks", startIndex, endIndex, startIndex + shiftBy, startIndex, shiftBy, endIndex + shiftBy, endIndex, shiftBy, errorMessage)); } public List<Label> ExtractAllLabels(List<CodeInstruction> codeRange) { return codeRange.SelectMany((CodeInstruction code) => CodeInstructionExtensions.ExtractLabels(code)).ToList(); } public List<Label>? TryExtractAllLabels(int? startIndex = null, int? endIndex = null) { List<CodeInstruction> list = TryGetIL(startIndex, endIndex); if (list == null) { return null; } return ExtractAllLabels(list); } public List<Label> ExtractAllLabels(int? startIndex = null, int? endIndex = null, string errorMessage = "Out of bounds!") { int valueOrDefault = startIndex.GetValueOrDefault(); if (!startIndex.HasValue) { valueOrDefault = CurrentIndex; startIndex = valueOrDefault; } return TryExtractAllLabels(startIndex, endIndex) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}] | {5}", "ILUtils", "ILStepper", "ExtractAllLabels", startIndex, endIndex, errorMessage)); } public List<Label> ExtractAllBlocks(List<CodeInstruction> codeRange) { return codeRange.SelectMany((CodeInstruction code) => CodeInstructionExtensions.ExtractLabels(code)).ToList(); } public List<Label>? TryExtractAllBlocks(int? startIndex = null, int? endIndex = null) { List<CodeInstruction> list = TryGetIL(startIndex, endIndex); if (list == null) { return null; } return ExtractAllBlocks(list); } public List<Label> ExtractAllBlocks(int? startIndex = null, int? endIndex = null, string errorMessage = "Out of bounds!") { int valueOrDefault = startIndex.GetValueOrDefault(); if (!startIndex.HasValue) { valueOrDefault = CurrentIndex; startIndex = valueOrDefault; } valueOrDefault = endIndex.GetValueOrDefault(); if (!endIndex.HasValue) { valueOrDefault = CurrentIndex; endIndex = valueOrDefault; } return TryExtractAllBlocks(startIndex, endIndex) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}] | {5}", "ILUtils", "ILStepper", "ExtractAllBlocks", startIndex, endIndex, errorMessage)); } public List<CodeInstruction>? TryShiftIL(int? startIndex = null, int? endIndex = null, int shiftBy = 1, bool shiftCurrentIndex = true) { startIndex = TryFindIndex(startIndex); endIndex = TryFindIndex(endIndex); if (!startIndex.HasValue || !endIndex.HasValue) { return null; } if (startIndex > endIndex) { int? num = endIndex; endIndex = startIndex; startIndex = num; } if (endIndex >= Instructions.Count) { return null; } int num2 = endIndex.Value - startIndex.Value; int? index = TryFindIndex(startIndex, shiftBy, 0, -num2 + 1); if (!index.HasValue) { return null; } if (shiftCurrentIndex && CurrentIndex >= startIndex && CurrentIndex < endIndex) { CurrentIndex += shiftBy; shiftCurrentIndex = false; } string errorMessage = string.Format("[{0}.{1}.{2}] [{3}, {4}, {5} ({6} + {7}), {8} ({9} + {10})] Somehow calculated invalid parameters. This should never happen!", "ILUtils", "ILStepper", "TryShiftIL", startIndex, endIndex, startIndex + shiftBy, startIndex, shiftBy, endIndex + shiftBy, endIndex, shiftBy); List<CodeInstruction> codeRange = RemoveIL(startIndex, endIndex, shiftCurrentIndex, pinLabels: false, pinBlocks: false, errorMessage); return InsertIL(codeRange, index, shiftCurrentIndex, pinLabels: false, pinBlocks: false, errorMessage); } public List<CodeInstruction> ShiftIL(int? startIndex = null, int? endIndex = null, int shiftBy = 1, bool shiftCurrentIndex = true, string errorMessage = "Source and/or destination instructions out of bounds!") { int valueOrDefault = startIndex.GetValueOrDefault(); if (!startIndex.HasValue) { valueOrDefault = CurrentIndex; startIndex = valueOrDefault; } valueOrDefault = endIndex.GetValueOrDefault(); if (!endIndex.HasValue) { valueOrDefault = CurrentIndex; endIndex = valueOrDefault; } return TryShiftIL(startIndex, endIndex, shiftBy, shiftCurrentIndex) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}, {5} ({6} + {7}), {8} ({9} + {10})] | {11}", "ILUtils", "ILStepper", "ShiftIL", startIndex, endIndex, startIndex + shiftBy, startIndex, shiftBy, endIndex + shiftBy, endIndex, shiftBy, errorMessage)); } public List<CodeInstruction>? TryOverwriteIL(List<CodeInstruction> codeRange, int? index = null, bool pinLabels = true, bool pinBlocks = true) { int valueOrDefault = index.GetValueOrDefault(); if (!index.HasValue) { valueOrDefault = CurrentIndex; index = valueOrDefault; } List<CodeInstruction> removedIL = TryRemoveIL(index, index + codeRange.Count(), shiftCurrentIndex: false, pinLabels: false, pinBlocks: false); if (removedIL == null) { return null; } codeRange = codeRange.Select(delegate(CodeInstruction code, int i) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown code = new CodeInstruction(code); if (pinLabels) { CodeInstructionExtensions.MoveLabelsTo(removedIL[i], code); } if (pinBlocks) { CodeInstructionExtensions.MoveBlocksTo(removedIL[i], code); } return code; }).ToList(); return TryInsertIL(codeRange, index, shiftCurrentIndex: false, pinLabels: false, pinBlocks: false); } public List<CodeInstruction>? TryOverwriteIL(CodeInstruction? code, int? index = null, bool pinLabels = true, bool pinBlocks = true) { return TryOverwriteIL((code != null) ? new List<CodeInstruction>(1) { code } : new List<CodeInstruction>(), index, pinLabels, pinBlocks); } public List<CodeInstruction> OverwriteIL(List<CodeInstruction> codeRange, int? index = null, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!") { int valueOrDefault = index.GetValueOrDefault(); if (!index.HasValue) { valueOrDefault = CurrentIndex; index = valueOrDefault; } return TryOverwriteIL(codeRange, index, pinLabels, pinBlocks) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}, {5} ({6} + {7})] | {8}", "ILUtils", "ILStepper", "OverwriteIL", codeRange, index, index + codeRange.Count(), index, codeRange.Count(), errorMessage)); } public List<CodeInstruction> OverwriteIL(CodeInstruction? code, int? index = null, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!") { int valueOrDefault = index.GetValueOrDefault(); if (!index.HasValue) { valueOrDefault = CurrentIndex; index = valueOrDefault; } return TryOverwriteIL((code != null) ? new List<CodeInstruction>(1) { code } : new List<CodeInstruction>(), index, pinLabels, pinBlocks) ?? throw new Exception(string.Format("[{0}.{1}.{2}] [{3}, {4}, {5} ({6} + {7})] | {8}", "ILUtils", "ILStepper", "OverwriteIL", code, index, index + ((code != null) ? 1 : 0), index, (code != null) ? 1 : 0, errorMessage)); } } } namespace ILUtils.HarmonyXtensions { public static class CodeInstructionPolyfills { public static readonly OpCode[] ARGUMENTED_LOCAL_INSTRUCTS = new OpCode[6] { OpCodes.Ldloc, OpCodes.Stloc, OpCodes.Ldloca, OpCodes.Ldloc_S, OpCodes.Stloc_S, OpCodes.Ldloca_S }; public static readonly OpCode[] LOAD_FIELD_INSTRUCTS = new OpCode[4] { OpCodes.Ldfld, OpCodes.Ldsfld, OpCodes.Ldflda, OpCodes.Ldsflda }; public static readonly OpCode[] STORE_FIELD_INSTRUCTS = new OpCode[2] { OpCodes.Stfld, OpCodes.Stsfld }; public static bool IsValid(this OpCode code) { return code.Size > 0; } public static CodeInstruction Call(Type type, string name, Type[]? parameters = null, Type[]? generics = null) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(type, name, parameters, generics) ?? throw new ArgumentException($"No method found for type={type}, name={name}, parameters={GeneralExtensions.Description(parameters)}, generics={GeneralExtensions.Description(generics)}"); return new CodeInstruction(OpCodes.Call, (object)methodInfo); } public static bool Calls(this CodeInstruction codeInstruction, Type type, string name, Type[]? parameters = null, Type[]? generics = null) { MethodInfo methodInfo = AccessTools.Method(type, name, parameters, generics) ?? throw new ArgumentException($"No method found for type={type}, name={name}, parameters={GeneralExtensions.Description(parameters)}, generics={GeneralExtensions.Description(generics)}"); return CodeInstructionExtensions.Calls(codeInstruction, methodInfo); } public static CodeInstruction Call(string typeColonMethodname, Type[]? parameters = null, Type[]? generics = null) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeColonMethodname, parameters, generics) ?? throw new ArgumentException("No method found for " + typeColonMethodname + ", parameters=" + GeneralExtensions.Description(parameters) + ", generics=" + GeneralExtensions.Description(generics)); return new CodeInstruction(OpCodes.Call, (object)methodInfo); } public static bool Calls(this CodeInstruction codeInstruction, string typeColonMethodname, Type[]? parameters = null, Type[]? generics = null) { MethodInfo methodInfo = AccessTools.Method(typeColonMethodname, parameters, generics) ?? throw new ArgumentException("No method found for " + typeColonMethodname + ", parameters=" + GeneralExtensions.Description(parameters) + ", generics=" + GeneralExtensions.Description(generics)); return CodeInstructionExtensions.Calls(codeInstruction, methodInfo); } public static CodeInstruction Call(Expression<Action> expression) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo(expression)); } public static CodeInstruction Call<T>(Expression<Action<T>> expression) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo<T>(expression)); } public static CodeInstruction Call<T, TResult>(Expression<Func<T, TResult>> expression) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo<T, TResult>(expression)); } public static CodeInstruction Call(LambdaExpression expression) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo(expression)); } public static CodeInstruction CallClosure<T>(T closure) where T : Delegate { return Transpilers.EmitDelegate<T>(closure); } public static CodeInstruction CallConstructor(Type type, Type[]? parameters = null, bool searchForStatic = false) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown ConstructorInfo constructorInfo = AccessTools.Constructor(type, parameters, searchForStatic) ?? throw new ArgumentException($"No constructor found for type={type}, parameters={GeneralExtensions.Description(parameters)}, searchForStatic={searchForStatic}"); return new CodeInstruction(OpCodes.Newobj, (object)constructorInfo); } public static CodeInstruction LoadField(Type type, string name, bool useAddress = false) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown FieldInfo fieldInfo = AccessTools.Field(type, name) ?? throw new ArgumentException($"No field found for {type} and {name}"); return new CodeInstruction((!useAddress) ? (fieldInfo.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld) : (fieldInfo.IsStatic ? OpCodes.Ldsflda : OpCodes.Ldflda), (object)fieldInfo); } public static CodeInstruction StoreField(Type type, string name) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown FieldInfo fieldInfo = AccessTools.Field(type, name) ?? throw new ArgumentException($"No field found for {type} and {name}"); return new CodeInstruction(fieldInfo.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, (object)fieldInfo); } public static bool LoadsField(this CodeInstruction codeInstruction, Type type, string name, bool byAddress = false) { FieldInfo fieldInfo = AccessTools.DeclaredField(type, name); if (fieldInfo != null) { return CodeInstructionExtensions.LoadsField(codeInstruction, fieldInfo, byAddress); } return false; } public static bool StoresField(this CodeInstruction codeInstruction, Type type, string name) { FieldInfo fieldInfo = AccessTools.DeclaredField(type, name); if (fieldInfo != null) { return CodeInstructionExtensions.StoresField(codeInstruction, fieldInfo); } return false; } public static int LocalIndex(this CodeInstruction code) { if (code.opcode == OpCodes.Ldloc_0 || code.opcode == OpCodes.Stloc_0) { return 0; } if (code.opcode == OpCodes.Ldloc_1 || code.opcode == OpCodes.Stloc_1) { return 1; } if (code.opcode == OpCodes.Ldloc_2 || code.opcode == OpCodes.Stloc_2) { return 2; } if (code.opcode == OpCodes.Ldloc_3 || code.opcode == OpCodes.Stloc_3) { return 3; } if (ARGUMENTED_LOCAL_INSTRUCTS.Contains(code.opcode)) { int? num = (code.operand as LocalVariableInfo)?.LocalIndex; return Convert.ToInt32(num.HasValue ? ((object)num.GetValueOrDefault()) : code.operand); } throw new ArgumentException("Instruction is not a load or store", "code"); } public static CodeInstruction LoadLocal(int index, bool useAddress = false) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown if (useAddress) { if (index < 256) { return new CodeInstruction(OpCodes.Ldloca_S, (object)Convert.ToByte(index)); } return new CodeInstruction(OpCodes.Ldloca, (object)index); } if (index < 256) { return (CodeInstruction)(index switch { 0 => (object)new CodeInstruction(OpCodes.Ldloc_0, (object)null), 1 => (object)new CodeInstruction(OpCodes.Ldloc_1, (object)null), 2 => (object)new CodeInstruction(OpCodes.Ldloc_2, (object)null), 3 => (object)new CodeInstruction(OpCodes.Ldloc_3, (object)null), _ => (object)new CodeInstruction(OpCodes.Ldloc_S, (object)Convert.ToByte(index)), }); } return new CodeInstruction(OpCodes.Ldloc, (object)index); } public static CodeInstruction LoadLocal(LocalVariableInfo local, bool useAddress = false) { return LoadLocal(local.LocalIndex, useAddress); } public static CodeInstruction StoreLocal(int index) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown if (index < 256) { return (CodeInstruction)(index switch { 0 => (object)new CodeInstruction(OpCodes.Stloc_0, (object)null), 1 => (object)new CodeInstruction(OpCodes.Stloc_1, (object)null), 2 => (object)new CodeInstruction(OpCodes.Stloc_2, (object)null), 3 => (object)new CodeInstruction(OpCodes.Stloc_3, (object)null), _ => (object)new CodeInstruction(OpCodes.Stloc_S, (object)Convert.ToByte(index)), }); } return new CodeInstruction(OpCodes.Stloc, (object)index); } public static CodeInstruction StoreLocal(LocalVariableInfo local) { return StoreLocal(local.LocalIndex); } public static bool LoadsLocal(this CodeInstruction code, LocalVariableInfo? local = null) { if (CodeInstructionExtensions.IsLdloc(code, (LocalBuilder)null)) { if (local != null) { return code.LocalIndex() == local.LocalIndex; } return true; } return false; } public static bool LoadsLocal(this CodeInstruction code, int index) { if (CodeInstructionExtensions.IsLdloc(code, (LocalBuilder)null)) { return code.LocalIndex() == index; } return false; } public static bool StoresLocal(this CodeInstruction code, LocalVariableInfo? local = null) { if (CodeInstructionExtensions.IsStloc(code, (LocalBuilder)null)) { if (local != null) { return code.LocalIndex() == local.LocalIndex; } return true; } return false; } public static bool StoresLocal(this CodeInstruction code, int index) { if (CodeInstructionExtensions.IsStloc(code, (LocalBuilder)null)) { return code.LocalIndex() == index; } return false; } public static CodeInstruction LoadArgument(int index, bool useAddress = false) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown if (useAddress) { if (index >= 256) { return new CodeInstruction(OpCodes.Ldarga, (object)index); } return new CodeInstruction(OpCodes.Ldarga_S, (object)Convert.ToByte(index)); } if (index != 0) { if (index != 1) { if (index != 2) { if (index != 3) { if (index >= 256) { return new CodeInstruction(OpCodes.Ldarg, (object)index); } return new CodeInstruction(OpCodes.Ldarg_S, (object)Convert.ToByte(index)); } return new CodeInstruction(OpCodes.Ldarg_3, (object)null); } return new CodeInstruction(OpCodes.Ldarg_2, (object)null); } return new CodeInstruction(OpCodes.Ldarg_1, (object)null); } return new CodeInstruction(OpCodes.Ldarg_0, (object)null); } public static int ArgumentIndex(this CodeInstruction code) { if (code.opcode == OpCodes.Ldarg_0) { return 0; } if (code.opcode == OpCodes.Ldarg_1) { return 1; } if (code.opcode == OpCodes.Ldarg_2) { return 2; } if (code.opcode == OpCodes.Ldarg_3) { return 3; } if (code.opcode == OpCodes.Ldarg_S || code.opcode == OpCodes.Ldarg) { return Convert.ToInt32(code.operand); } if (code.opcode == OpCodes.Starg_S || code.opcode == OpCodes.Starg) { return Convert.ToInt32(code.operand); } if (code.opcode == OpCodes.Ldarga_S || code.opcode == OpCodes.Ldarga) { return Convert.ToInt32(code.operand); } throw new ArgumentException("Instruction is not a load or store", "code"); } public static CodeInstruction StoreArgument(int index) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (index >= 256) { return new CodeInstruction(OpCodes.Starg, (object)index); } return new CodeInstruction(OpCodes.Starg_S, (object)Convert.ToByte(index)); } public static bool LoadsString(this CodeInstruction code, string str) { if (code.opcode != OpCodes.Ldstr) { return false; } string text = Convert.ToString(code.operand); return text == str; } public static CodeInstruction LoadConstant(sbyte number) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown return (CodeInstruction)(number switch { -1 => (object)new CodeInstruction(OpCodes.Ldc_I4_M1, (object)null), 0 => (object)new CodeInstruction(OpCodes.Ldc_I4_0, (object)null), 1 => (object)new CodeInstruction(OpCodes.Ldc_I4_1, (object)null), 2 => (object)new CodeInstruction(OpCodes.Ldc_I4_2, (object)null), 3 => (object)new CodeInstruction(OpCodes.Ldc_I4_3, (object)null), 4 => (object)new CodeInstruction(OpCodes.Ldc_I4_4, (object)null), 5 => (object)new CodeInstruction(OpCodes.Ldc_I4_5, (object)null), 6 => (object)new CodeInstruction(OpCodes.Ldc_I4_6, (object)null), 7 => (object)new CodeInstruction(OpCodes.Ldc_I4_7, (object)null), 8 => (object)new CodeInstruction(OpCodes.Ldc_I4_8, (object)null), _ => (object)new CodeInstruction(OpCodes.Ldc_I4_S, (object)number), }); } public static CodeInstruction LoadConstant(int number) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown if (number >= -128 && number <= 127) { return LoadConstant(Convert.ToSByte(number)); } return new CodeInstruction(OpCodes.Ldc_I4, (object)number); } public static CodeInstruction LoadConstant(long number) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return new CodeInstruction(OpCodes.Ldc_I8, (object)number); } public static CodeInstruction LoadConstant(Enum e) { return (CodeInstruction)(e.GetTypeCode() switch { TypeCode.Int64 => LoadConstant(Convert.ToInt64(e)), TypeCode.SByte => LoadConstant(Convert.ToSByte(e)), _ => LoadConstant(Convert.ToInt32(e)), }); } public static CodeInstruction[] LoadLongOptimally(long number) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown if (number >= -128) { if (number <= 127) { return (CodeInstruction[])(object)new CodeInstruction[2] { LoadConstant(Convert.ToSByte(number)), new CodeInstruction(OpCodes.Conv_I8, (object)null) }; } if (number <= int.MaxValue) { goto IL_0047; } } else if (number >= int.MinValue) { goto IL_0047; } return (CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Ldc_I8, (object)number) }; IL_0047: return (CodeInstruction[])(object)new CodeInstruction[2] { LoadConstant(Convert.ToInt32(number)), new CodeInstruction(OpCodes.Conv_I8, (object)null) }; } public static CodeInstruction[] LoadEnumOptimally(Enum e) { return e.GetTypeCode() switch { TypeCode.Int64 => LoadLongOptimally(Convert.ToInt64(e)), TypeCode.SByte => (CodeInstruction[])(object)new CodeInstruction[1] { LoadConstant(Convert.ToSByte(e)) }, _ => (CodeInstruction[])(object)new CodeInstruction[1] { LoadConstant(Convert.ToInt32(e)) }, }; } public static CodeInstruction LoadString(string str) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown return new CodeInstruction(OpCodes.Ldstr, (object)str); } public static CodeInstruction LoadNull() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown return new CodeInstruction(OpCodes.Ldnull, (object)null); } public static bool LoadsNull(this CodeInstruction code) { return object.Equals(code.opcode, OpCodes.Ldnull); } public static bool LoadsProperty(this CodeInstruction code, PropertyInfo property) { return CodeInstructionExtensions.Calls(code, property.GetGetMethod(nonPublic: true)); } public static bool LoadsProperty(this CodeInstruction code, Type type, string name) { PropertyInfo propertyInfo = AccessTools.DeclaredProperty(type, name); if (propertyInfo != null) { return code.LoadsProperty(propertyInfo); } return false; } public static bool StoresProperty(this CodeInstruction code, PropertyInfo property) { return CodeInstructionExtensions.Calls(code, property.GetSetMethod(nonPublic: true)); } public static bool StoresProperty(this CodeInstruction code, Type type, string name) { PropertyInfo propertyInfo = AccessTools.DeclaredProperty(type, name); if (propertyInfo != null) { return code.StoresProperty(propertyInfo); } return false; } public static CodeInstruction LoadProperty(PropertyInfo property) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return new CodeInstruction(OpCodes.Call, (object)property.GetGetMethod(nonPublic: true)); } public static CodeInstruction LoadProperty(Type type, string name) { PropertyInfo property = AccessTools.Property(type, name) ?? throw new ArgumentException($"No property found for type={type}, name={name}"); return LoadProperty(property); } public static CodeInstruction StoreProperty(PropertyInfo property) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return new CodeInstruction(OpCodes.Call, (object)property.GetSetMethod(nonPublic: true)); } public static CodeInstruction StoreProperty(Type type, string name) { PropertyInfo property = AccessTools.Property(type, name) ?? throw new ArgumentException($"No property found for type={type}, name={name}"); return StoreProperty(property); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }